Compare commits
1 Commits
d7d8fc4b5e
...
3.0
Author | SHA1 | Date | |
---|---|---|---|
9a2ade1857 |
4
.gitignore
vendored
4
.gitignore
vendored
@ -54,11 +54,11 @@ Temporary Items
|
|||||||
|
|
||||||
# TheTempusProject Specific
|
# TheTempusProject Specific
|
||||||
.htaccess
|
.htaccess
|
||||||
|
app/config/*
|
||||||
!app/config/constants.php
|
!app/config/constants.php
|
||||||
uploads/images/*
|
uploads/images/*
|
||||||
logs/*
|
logs/*
|
||||||
.vscode/
|
.vscode/
|
||||||
mail.log
|
mail.log
|
||||||
vendor/canary/logs/*
|
vendor/canary/logs/*
|
||||||
.env
|
docker/.env
|
||||||
components/*
|
|
||||||
|
@ -1,74 +0,0 @@
|
|||||||
stages:
|
|
||||||
- prepare
|
|
||||||
- build
|
|
||||||
- test
|
|
||||||
- update
|
|
||||||
- deploy
|
|
||||||
|
|
||||||
variables:
|
|
||||||
TIMEZONE: "America/New_York" # For the system in general
|
|
||||||
DATE_TIMEZONE: ${TIMEZONE} # For PHP
|
|
||||||
|
|
||||||
GIT_DEPTH: 1
|
|
||||||
GITLAB_API_URL: ${CI_API_V4_URL}
|
|
||||||
TARGET_BRANCH: ${CI_COMMIT_REF_NAME} # This is the branch chosen in the `Pipeline Schedule`
|
|
||||||
TARGET_REMOTE: "https://${GITLAB_USERNAME}:${GITLAB_ACCESS_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_NAMESPACE}/${CI_PROJECT_NAME}.git"
|
|
||||||
|
|
||||||
# These could/should be overridden in an extending job:
|
|
||||||
UPDATE_BRANCH_PREFIX: "update_PHP_deps_" # Used for the update branch name, it will be followed by the datetime
|
|
||||||
GIT_USER: "DependBot" # Used for the update commit
|
|
||||||
GIT_EMAIL: "webmaster@thetempusproject.com" # Used for the update commit
|
|
||||||
GITLAB_USERNAME: "root" # Used for pushing the new branch and opening the MR
|
|
||||||
GITLAB_ACCESS_TOKEN: "glpat-PKEmivGtBfbz4DVPdhzk" # Used for pushing the new branch and opening the MR
|
|
||||||
MERGE_IF_SUCCESSFUL: "true" # Set to true, to merge automatically if the pipeline succeeds
|
|
||||||
SECONDS_BETWEEN_POOLING: 10 # Nbr of seconds between checking if the MR pipeline is successful, so then it will merge
|
|
||||||
JOB_GIT_FLAGS: ""
|
|
||||||
JOB_CURL_FLAGS: ""
|
|
||||||
JOB_COMPOSER_FLAGS: ""
|
|
||||||
|
|
||||||
composer_update:
|
|
||||||
stage: update
|
|
||||||
rules:
|
|
||||||
- if: '$CI_COMMIT_BRANCH == "main"'
|
|
||||||
image: composer:latest
|
|
||||||
interruptible: true # allows to stop the job if a newer pipeline starts, saving resources and allowing new jobs to start because job concurrency is limited
|
|
||||||
script:
|
|
||||||
- git ${JOB_GIT_FLAGS} fetch origin ${TARGET_BRANCH}
|
|
||||||
- git ${JOB_GIT_FLAGS} checkout ${TARGET_BRANCH}
|
|
||||||
- git reset --hard origin/main
|
|
||||||
- git pull --allow-unrelated-histories
|
|
||||||
- export DATE_TIME="$(date '+%Y%m%d%H%M%S')"
|
|
||||||
- export MR_BRANCH="${UPDATE_BRANCH_PREFIX}${DATE_TIME}"
|
|
||||||
- git ${JOB_GIT_FLAGS} checkout -b "${MR_BRANCH}"
|
|
||||||
- composer update ${JOB_COMPOSER_FLAGS}
|
|
||||||
- if [ "$(git diff)" == "" ]; then echo "No updates needed!"; exit 0; fi
|
|
||||||
- export TITLE="Update PHP dependencies [${DATE_TIME}]"
|
|
||||||
- git ${JOB_GIT_FLAGS} commit -a -m "${TITLE}"
|
|
||||||
- git ${JOB_GIT_FLAGS} push "${TARGET_REMOTE}" "${MR_BRANCH}"
|
|
||||||
artifacts:
|
|
||||||
paths:
|
|
||||||
- vendor/
|
|
||||||
cache:
|
|
||||||
key: ${CI_COMMIT_REF_SLUG}
|
|
||||||
paths:
|
|
||||||
- vendor/
|
|
||||||
|
|
||||||
prepare:
|
|
||||||
stage: prepare
|
|
||||||
script:
|
|
||||||
- echo "Preparing environment..."
|
|
||||||
|
|
||||||
build:
|
|
||||||
stage: build
|
|
||||||
script:
|
|
||||||
- echo "Building the project..."
|
|
||||||
|
|
||||||
test:
|
|
||||||
stage: test
|
|
||||||
script:
|
|
||||||
- echo "Running tests..."
|
|
||||||
|
|
||||||
deploy:
|
|
||||||
stage: deploy
|
|
||||||
script:
|
|
||||||
- echo "Deploying the project..."
|
|
8
LICENSE
8
LICENSE
@ -1,10 +1,6 @@
|
|||||||
Copyright (c) 2024-present Joey Kimsey
|
MIT License
|
||||||
|
|
||||||
Portions of this software are licensed as follows:
|
Copyright (c) 2024 Joey Kimsey
|
||||||
|
|
||||||
* All content residing under the "app/" directory of this repository, excluding "app/plugins/"; is licensed under "Creative Commons: CC BY-SA 4.0 license".
|
|
||||||
* All third party components incorporated into The Tempus Project Software including plugins are licensed under the original license provided by the owner of the applicable component.
|
|
||||||
* Content outside of the above mentioned directories or restrictions above is available under the "MIT Expat" license as defined below.
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -372,9 +372,3 @@ What is my goal here?
|
|||||||
|
|
||||||
I would like to play Dungeons and Dragons once a week with my friends. In an ideal world, I would DM this game and spend all week building tools for us to use that I then put on a website which sells memberships to other players so they can use the tools too.
|
I would like to play Dungeons and Dragons once a week with my friends. In an ideal world, I would DM this game and spend all week building tools for us to use that I then put on a website which sells memberships to other players so they can use the tools too.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
i need to be able to name models in camel case, this shit is getting crazy. Find whatever prevents this and fix it
|
|
@ -1,8 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* app/classes/api_controller.php
|
* app/classes/admin_controller.php
|
||||||
*
|
*
|
||||||
* This is the base api controller. Every other api controller should
|
* This is the base admin controller. Every other admin controller should
|
||||||
* extend this class.
|
* extend this class.
|
||||||
*
|
*
|
||||||
* @version 3.0
|
* @version 3.0
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* app/classes/config.php
|
* classes/config.php
|
||||||
*
|
*
|
||||||
* This class handles all the hard-coded configurations.
|
* This class handles all the hard-coded configurations.
|
||||||
*
|
*
|
||||||
* @version 3.0
|
* @version 3.0
|
||||||
* @author Joey Kimsey <Joey@thetempusproject.com>
|
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||||
* @link https://TheTempusProject.com
|
* @link https://TheTempusProject.com/Core
|
||||||
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||||
*/
|
*/
|
||||||
namespace TheTempusProject\Classes;
|
namespace TheTempusProject\Classes;
|
||||||
|
|
||||||
use TheTempusProject\Houdini\Classes\Forms;
|
use TheTempusProject\Houdini\Classes\Forms;
|
||||||
use TheTempusProject\Canary\Bin\Canary as Debug;
|
use TheTempusProject\Canary\Canary as Debug;
|
||||||
use TheTempusProject\Bedrock\Functions\Check;
|
use TheTempusProject\Bedrock\Functions\Check;
|
||||||
use TheTempusProject\Bedrock\Functions\Input;
|
use TheTempusProject\Bedrock\Functions\Input;
|
||||||
use TheTempusProject\Bedrock\Classes\Config as BedrockConfig;
|
use TheTempusProject\Bedrock\Classes\Config as BedrockConfig;
|
||||||
|
@ -13,12 +13,11 @@ namespace TheTempusProject\Classes;
|
|||||||
|
|
||||||
use TheTempusProject\Bedrock\Classes\Controller as BedrockController;
|
use TheTempusProject\Bedrock\Classes\Controller as BedrockController;
|
||||||
use TheTempusProject\Houdini\Classes\Template;
|
use TheTempusProject\Houdini\Classes\Template;
|
||||||
use TheTempusProject\Bedrock\Classes\Pagination;
|
use TheTempusProject\Houdini\Classes\Pagination;
|
||||||
use TheTempusProject\TheTempusProject as App;
|
use TheTempusProject\TheTempusProject as App;
|
||||||
use TheTempusProject\Models\User;
|
use TheTempusProject\Models\User;
|
||||||
use TheTempusProject\Models\Sessions;
|
use TheTempusProject\Models\Sessions;
|
||||||
use TheTempusProject\Bedrock\Functions\Token;
|
use TheTempusProject\Bedrock\Functions\Token;
|
||||||
use TheTempusProject\Houdini\Classes\Components;
|
|
||||||
|
|
||||||
class Controller extends BedrockController {
|
class Controller extends BedrockController {
|
||||||
public static $user;
|
public static $user;
|
||||||
|
@ -13,7 +13,7 @@ namespace TheTempusProject\Classes;
|
|||||||
|
|
||||||
use TheTempusProject\Bedrock\Classes\DatabaseModel as BedrockDatabaseModel;
|
use TheTempusProject\Bedrock\Classes\DatabaseModel as BedrockDatabaseModel;
|
||||||
use TheTempusProject\Bedrock\Functions\Check;
|
use TheTempusProject\Bedrock\Functions\Check;
|
||||||
use TheTempusProject\Canary\Bin\Canary as Debug;
|
use TheTempusProject\Canary\Canary as Debug;
|
||||||
use TheTempusProject\Models\Log;
|
use TheTempusProject\Models\Log;
|
||||||
|
|
||||||
class DatabaseModel extends BedrockDatabaseModel {
|
class DatabaseModel extends BedrockDatabaseModel {
|
||||||
|
@ -14,7 +14,7 @@ namespace TheTempusProject\Classes;
|
|||||||
use TheTempusProject\Houdini\Classes\Template;
|
use TheTempusProject\Houdini\Classes\Template;
|
||||||
use TheTempusProject\Houdini\Classes\Views;
|
use TheTempusProject\Houdini\Classes\Views;
|
||||||
use TheTempusProject\Hermes\Functions\Route as Routes;
|
use TheTempusProject\Hermes\Functions\Route as Routes;
|
||||||
use TheTempusProject\Canary\Bin\Canary as Debug;
|
use TheTempusProject\Canary\Canary as Debug;
|
||||||
|
|
||||||
class Email {
|
class Email {
|
||||||
private static $header = null;
|
private static $header = null;
|
||||||
|
@ -15,20 +15,12 @@
|
|||||||
namespace TheTempusProject\Classes;
|
namespace TheTempusProject\Classes;
|
||||||
|
|
||||||
use TheTempusProject\Bedrock\Functions\Check;
|
use TheTempusProject\Bedrock\Functions\Check;
|
||||||
use TheTempusProject\Canary\Bin\Canary as Debug;
|
use TheTempusProject\Canary\Canary as Debug;
|
||||||
use TheTempusProject\Bedrock\Functions\Input;
|
|
||||||
use TheTempusProject\Models\User;
|
|
||||||
use TheTempusProject\Classes\Forms;
|
|
||||||
use TheTempusProject\Bedrock\Classes\Database;
|
|
||||||
|
|
||||||
class Forms extends Check {
|
class Forms extends Check {
|
||||||
private static $formHandlers = [];
|
private static $formHandlers = [];
|
||||||
private static $initialized = false;
|
|
||||||
|
|
||||||
public static function check( $formName ) {
|
public static function check( $formName ) {
|
||||||
if ( self::$initialized !== true ) {
|
|
||||||
self::initHandlers();
|
|
||||||
}
|
|
||||||
if ( empty( self::$formHandlers[ $formName ] ) ) {
|
if ( empty( self::$formHandlers[ $formName ] ) ) {
|
||||||
Debug::error( "Form not found: $formName" );
|
Debug::error( "Form not found: $formName" );
|
||||||
return false;
|
return false;
|
||||||
@ -82,530 +74,4 @@ class Forms extends Check {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds these functions to the form list.
|
|
||||||
*/
|
|
||||||
public function __construct() {
|
|
||||||
if ( self::$initialized === true ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
self::initHandlers();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static function initHandlers() {
|
|
||||||
self::addHandler( 'passwordResetCode', __CLASS__, 'passwordResetCode' );
|
|
||||||
self::addHandler( 'createRoute', __CLASS__, 'createRoute' );
|
|
||||||
self::addHandler( 'editRoute', __CLASS__, 'editRoute' );
|
|
||||||
self::addHandler( 'register', __CLASS__, 'register' );
|
|
||||||
self::addHandler( 'createUser', __CLASS__, 'createUser' );
|
|
||||||
self::addHandler( 'editUser', __CLASS__, 'editUser' );
|
|
||||||
self::addHandler( 'login', __CLASS__, 'login' );
|
|
||||||
self::addHandler( 'changeEmail', __CLASS__, 'changeEmail' );
|
|
||||||
self::addHandler( 'changePassword', __CLASS__, 'changePassword' );
|
|
||||||
self::addHandler( 'passwordReset', __CLASS__, 'passwordReset' );
|
|
||||||
self::addHandler( 'emailConfirmation', __CLASS__, 'emailConfirmation' );
|
|
||||||
self::addHandler( 'confirmationResend', __CLASS__, 'confirmationResend' );
|
|
||||||
self::addHandler( 'replyMessage', __CLASS__, 'replyMessage' );
|
|
||||||
self::addHandler( 'newMessage', __CLASS__, 'newMessage' );
|
|
||||||
self::addHandler( 'userPrefs', __CLASS__, 'userPrefs' );
|
|
||||||
self::addHandler( 'newGroup', __CLASS__, 'newGroup' );
|
|
||||||
self::addHandler( 'editGroup', __CLASS__, 'editGroup' );
|
|
||||||
self::addHandler( 'install', __CLASS__, 'install' );
|
|
||||||
self::addHandler( 'installStart', __CLASS__, 'install', [ 'start' ] );
|
|
||||||
self::addHandler( 'installAgreement', __CLASS__, 'install', [ 'agreement' ] );
|
|
||||||
self::addHandler( 'installCheck', __CLASS__, 'install', [ 'check' ] );
|
|
||||||
self::addHandler( 'installConfigure', __CLASS__, 'install', [ 'configure' ] );
|
|
||||||
self::addHandler( 'installRouting', __CLASS__, 'install', [ 'routing' ] );
|
|
||||||
self::addHandler( 'installModels', __CLASS__, 'install', [ 'models' ] );
|
|
||||||
self::addHandler( 'installPlugins', __CLASS__, 'install', [ 'plugins' ] );
|
|
||||||
self::addHandler( 'installResources', __CLASS__, 'install', [ 'resources' ] );
|
|
||||||
self::addHandler( 'installAdminUser', __CLASS__, 'install', [ 'adminUser' ] );
|
|
||||||
self::$initialized = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validates the installer forms.
|
|
||||||
*
|
|
||||||
* @return {bool}
|
|
||||||
*/
|
|
||||||
public static function install( $page = '' ) {
|
|
||||||
// if ( !self::token() ) {
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
switch ( $page ) {
|
|
||||||
case 'configure':
|
|
||||||
if ( ! Input::exists( 'submit' ) ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( !Database::check( Input::post( 'dbHost' ), Input::post( 'dbName' ), Input::post( 'dbUsername' ), Input::post( 'dbPassword' ) ) ) {
|
|
||||||
self::addUserError( 'DB connection error.' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
case 'adminUser':
|
|
||||||
if ( !self::checkUsername( Input::post( 'newUsername' ) ) ) {
|
|
||||||
self::addUserError( 'Invalid username.' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( !self::password( Input::post( 'userPassword' ) ) ) {
|
|
||||||
self::addUserError( 'Invalid password.' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( Input::post( 'userPassword' ) !== Input::post( 'userPassword2' ) ) {
|
|
||||||
self::addUserError( 'Passwords do not match.' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( Input::post( 'userEmail' ) !== Input::post( 'userEmail2' ) ) {
|
|
||||||
self::addUserError( 'Emails do not match.' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
case 'check':
|
|
||||||
if ( !self::uploads() ) {
|
|
||||||
self::addUserError( 'Uploads are disabled.' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( !self::php() ) {
|
|
||||||
self::addUserError( 'PHP version is too old.' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( !self::phpExtensions() ) {
|
|
||||||
self::addUserError( 'PHP extensions are missing.' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( !self::sessions() ) {
|
|
||||||
self::addUserError( 'There is an error with Sessions.' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( !self::mail() ) {
|
|
||||||
self::addUserError( 'PHP mail is not enabled.' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( !self::safe() ) {
|
|
||||||
self::addUserError( 'Safe mode is enabled.' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( ! Input::exists( 'submit' ) ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
case 'start':
|
|
||||||
case 'agreement':
|
|
||||||
case 'routing':
|
|
||||||
case 'models':
|
|
||||||
case 'plugins':
|
|
||||||
case 'resources':
|
|
||||||
if ( ! Input::exists( 'submit' ) ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validates the password re-send form.
|
|
||||||
*
|
|
||||||
* @return {bool}
|
|
||||||
*/
|
|
||||||
public static function passwordResetCode() {
|
|
||||||
if ( !self::token() ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validates the route creation form.
|
|
||||||
*
|
|
||||||
* @return {bool}
|
|
||||||
*/
|
|
||||||
public static function createRoute() {
|
|
||||||
if ( !Input::exists( 'redirect_type' ) ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( 'external' == Input::post( 'redirect_type' ) && !self::url( Input::post( 'forwarded_url' ) ) ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( !self::token() ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validates the route edit form.
|
|
||||||
*
|
|
||||||
* @return {bool}
|
|
||||||
*/
|
|
||||||
public static function editRoute() {
|
|
||||||
if ( !Input::exists( 'redirect_type' ) ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( 'external' == Input::post( 'redirect_type' ) && !self::url( Input::post( 'forwarded_url' ) ) ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( !self::token() ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validates the user creation form.
|
|
||||||
*
|
|
||||||
* @return {bool}
|
|
||||||
*/
|
|
||||||
public static function createUser() {
|
|
||||||
$user = new User;
|
|
||||||
if ( !$user->checkUsername( Input::post( 'username' ) ) ) {
|
|
||||||
self::addUserError( 'Invalid username.' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( !self::password( Input::post( 'password' ) ) ) {
|
|
||||||
self::addUserError( 'Invalid password.' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( !self::email( Input::post( 'email' ) ) ) {
|
|
||||||
self::addUserError( 'Invalid Email.' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( !$user->noEmailExists( Input::post( 'email' ) ) ) {
|
|
||||||
self::addUserError( 'A user with that email is already registered.' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( Input::post( 'password' ) !== Input::post( 'password2' ) ) {
|
|
||||||
self::addUserError( 'Passwords do not match.' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( Input::post( 'email' ) !== Input::post( 'email2' ) ) {
|
|
||||||
self::addUserError( 'Emails do not match.' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( !Input::post( 'groupSelect' ) ) {
|
|
||||||
self::addUserError( 'You must select a group for the new user.' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( !self::token() ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validates the user edit form.
|
|
||||||
*
|
|
||||||
* @return {bool}
|
|
||||||
*/
|
|
||||||
public static function editUser() {
|
|
||||||
$user = new User;
|
|
||||||
if ( !$user->checkUsername( Input::post( 'username' ) ) ) {
|
|
||||||
self::addUserError( 'Invalid username.' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( Input::exists( 'password' ) ) {
|
|
||||||
if ( !self::password( Input::post( 'password' ) ) ) {
|
|
||||||
self::addUserError( 'Invalid password.' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( Input::post( 'password' ) !== Input::post( 'password2' ) ) {
|
|
||||||
self::addUserError( 'Passwords do not match.' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( !self::email( Input::post( 'email' ) ) ) {
|
|
||||||
self::addUserError( 'Invalid Email.' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( !Input::post( 'groupSelect' ) ) {
|
|
||||||
self::addUserError( 'You must select a group for the new user.' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( !self::token() ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validates the user registration form.
|
|
||||||
*
|
|
||||||
* @return {bool}
|
|
||||||
*/
|
|
||||||
public static function register() {
|
|
||||||
$user = new User;
|
|
||||||
if ( !self::checkUsername( Input::post( 'username' ) ) ) {
|
|
||||||
self::addUserError( 'Invalid username.' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( !self::password( Input::post( 'password' ) ) ) {
|
|
||||||
self::addUserError( 'Invalid password.' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( !self::email( Input::post( 'email' ) ) ) {
|
|
||||||
self::addUserError( 'Invalid Email.' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( !$user->noEmailExists( Input::post( 'email' ) ) ) {
|
|
||||||
self::addUserError( 'A user with that email is already registered.' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( Input::post( 'password' ) !== Input::post( 'password2' ) ) {
|
|
||||||
self::addUserError( 'Passwords do not match.' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( Input::post( 'email' ) !== Input::post( 'email2' ) ) {
|
|
||||||
self::addUserError( 'Emails do not match.' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( Input::post( 'terms' ) != '1' ) {
|
|
||||||
self::addUserError( 'You must agree to the terms of service.' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( !self::token() ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validates the user login form.
|
|
||||||
*
|
|
||||||
* @return {bool}
|
|
||||||
*/
|
|
||||||
public static function login() {
|
|
||||||
if ( !self::checkUsername( Input::post( 'username' ) ) ) {
|
|
||||||
self::addUserError( 'Invalid username.' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( !self::password( Input::post( 'password' ) ) ) {
|
|
||||||
self::addUserError( 'Invalid password.' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( !self::token() ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validates the email change form.
|
|
||||||
*
|
|
||||||
* @return {bool}
|
|
||||||
*/
|
|
||||||
public static function changeEmail() {
|
|
||||||
if ( !self::email( Input::post( 'email' ) ) ) {
|
|
||||||
self::addUserError( 'Invalid Email.' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( Input::post( 'email' ) !== Input::post( 'email2' ) ) {
|
|
||||||
self::addUserError( 'Emails do not match.' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( !self::token() ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validates the password change form.
|
|
||||||
*
|
|
||||||
* @return {bool}
|
|
||||||
*/
|
|
||||||
public static function changePassword() {
|
|
||||||
if ( !self::password( Input::post( 'password' ) ) ) {
|
|
||||||
self::addUserError( 'Invalid password.' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( Input::post( 'password' ) !== Input::post( 'password2' ) ) {
|
|
||||||
self::addUserError( 'Passwords do not match.' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( !self::token() ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validates the password reset form.
|
|
||||||
*
|
|
||||||
* @return {bool}
|
|
||||||
*/
|
|
||||||
public static function passwordReset() {
|
|
||||||
if ( !self::password( Input::post( 'password' ) ) ) {
|
|
||||||
self::addUserError( 'Invalid password.' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( Input::post( 'password' ) !== Input::post( 'password2' ) ) {
|
|
||||||
self::addUserError( 'Passwords do not match.' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( !self::token() ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validates the email confirmation re-send form.
|
|
||||||
*
|
|
||||||
* @return {bool}
|
|
||||||
*/
|
|
||||||
public static function emailConfirmation() {
|
|
||||||
if ( !Input::exists( 'confirmationCode' ) ) {
|
|
||||||
self::addUserError( 'No confirmation code provided.' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( !self::token() ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validates the email confirmation re-send form.
|
|
||||||
*
|
|
||||||
* @return {bool}
|
|
||||||
*/
|
|
||||||
public static function confirmationResend() {
|
|
||||||
if ( !Input::exists( 'resendConfirmation' ) ) {
|
|
||||||
self::addUserError( 'Confirmation not provided.' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( !self::token() ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validates the reply message form.
|
|
||||||
*
|
|
||||||
* @return {bool}
|
|
||||||
*/
|
|
||||||
public static function replyMessage() {
|
|
||||||
if ( !Input::exists( 'message' ) ) {
|
|
||||||
self::addUserError( 'Reply cannot be empty.' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( !Input::exists( 'messageID' ) ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( !self::token() ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validates the new message form.
|
|
||||||
*
|
|
||||||
* @return {bool}
|
|
||||||
*/
|
|
||||||
public static function newMessage() {
|
|
||||||
if ( !Input::exists( 'toUser' ) ) {
|
|
||||||
self::addUserError( 'You must specify a user to send the message to.' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( !Input::exists( 'subject' ) ) {
|
|
||||||
self::addUserError( 'You must have a subject for your message.' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( !Input::exists( 'message' ) ) {
|
|
||||||
self::addUserError( 'No message entered.' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( !self::token() ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validates the user preferences form.
|
|
||||||
*
|
|
||||||
* @return {bool}
|
|
||||||
*/
|
|
||||||
public static function userPrefs() {
|
|
||||||
// @todo make this a real check
|
|
||||||
if ( !Input::exists( 'timeFormat' ) ) {
|
|
||||||
self::addUserError( 'You must specify timeFormat' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( !Input::exists( 'pageLimit' ) ) {
|
|
||||||
self::addUserError( 'You must specify pageLimit' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( !Input::exists( 'gender' ) ) {
|
|
||||||
self::addUserError( 'You must specify gender' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( !Input::exists( 'dateFormat' ) ) {
|
|
||||||
self::addUserError( 'You must specify dateFormat' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( !Input::exists( 'timezone' ) ) {
|
|
||||||
self::addUserError( 'You must specify timezone' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( !Input::exists( 'updates' ) ) {
|
|
||||||
self::addUserError( 'You must specify updates' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( !Input::exists( 'newsletter' ) ) {
|
|
||||||
self::addUserError( 'You must specify newsletter' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( !self::token() ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validates the group creation form.
|
|
||||||
*
|
|
||||||
* @return {bool}
|
|
||||||
*/
|
|
||||||
public static function newGroup() {
|
|
||||||
if ( !Input::exists( 'name' ) ) {
|
|
||||||
self::addUserError( 'You must specify a name' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( !self::dataTitle( Input::exists( 'name' ) ) ) {
|
|
||||||
self::addUserError( 'invalid group name' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( !self::token() ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validates the group edit form.
|
|
||||||
*
|
|
||||||
* @return {bool}
|
|
||||||
*/
|
|
||||||
public static function editGroup() {
|
|
||||||
if ( !Input::exists( 'name' ) ) {
|
|
||||||
self::addUserError( 'You must specify a name' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( !self::dataTitle( Input::exists( 'name' ) ) ) {
|
|
||||||
self::addUserError( 'invalid group name' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ( !self::token() ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ namespace TheTempusProject\Classes;
|
|||||||
use TheTempusProject\Bedrock\Functions\Check;
|
use TheTempusProject\Bedrock\Functions\Check;
|
||||||
use TheTempusProject\Bedrock\Functions\Code;
|
use TheTempusProject\Bedrock\Functions\Code;
|
||||||
use TheTempusProject\Bedrock\Functions\Cookie;
|
use TheTempusProject\Bedrock\Functions\Cookie;
|
||||||
use TheTempusProject\Canary\Bin\Canary as Debug;
|
use TheTempusProject\Canary\Canary as Debug;
|
||||||
use TheTempusProject\Hermes\Functions\Redirect;
|
use TheTempusProject\Hermes\Functions\Redirect;
|
||||||
use TheTempusProject\Hermes\Functions\Route as Routes;
|
use TheTempusProject\Hermes\Functions\Route as Routes;
|
||||||
use TheTempusProject\Bedrock\Functions\Session;
|
use TheTempusProject\Bedrock\Functions\Session;
|
||||||
@ -266,7 +266,6 @@ class Installer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function getModelInfo( $filename, $folder = '' ) {
|
public function getModelInfo( $filename, $folder = '' ) {
|
||||||
Debug::debug( 'getModelInfo filename: ' . $filename . ', folder: ' . $folder);
|
|
||||||
$object = self::emptyModule( 'model', $folder, $filename );
|
$object = self::emptyModule( 'model', $folder, $filename );
|
||||||
|
|
||||||
if ( ! class_exists( $object->class ) ) {
|
if ( ! class_exists( $object->class ) ) {
|
||||||
@ -327,7 +326,7 @@ class Installer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ( empty( $module_data->class_object ) ) {
|
if ( empty( $module_data->class_object ) ) {
|
||||||
self::$errors[] = [ 'errorInfo' => 'installPlugin: class_object not found: ' . $module_data->class ];
|
self::$errors[] = [ 'errorInfo' => 'Class not found: ' . $module_data->class ];
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -364,7 +363,7 @@ class Installer {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$errors[] = [ 'errorInfo' => $module_data['name'] . " Plugin has been installed." ];
|
$errors[] = [ 'errorInfo' => $module_data['name'] . " has been installed." ];
|
||||||
self::$errors = array_merge( self::$errors, $errors );
|
self::$errors = array_merge( self::$errors, $errors );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -374,7 +373,7 @@ class Installer {
|
|||||||
$errors = [];
|
$errors = [];
|
||||||
|
|
||||||
if ( empty( $module_data->class_object ) ) {
|
if ( empty( $module_data->class_object ) ) {
|
||||||
self::$errors[] = [ 'errorInfo' => 'uninstallPlugin: class_object not found: ' . $module_data->class ];
|
self::$errors[] = [ 'errorInfo' => 'Class not found: ' . $module_data->class ];
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -394,7 +393,7 @@ class Installer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$this->removeModule( $module_data->name, true );
|
$this->removeModule( $module_data->name, true );
|
||||||
$errors[] = [ 'errorInfo' => $module_data->name . " Plugin has been uninstalled." ];
|
$errors[] = [ 'errorInfo' => $module_data->name . " has been installed." ];
|
||||||
self::$errors = array_merge( self::$errors, $errors );
|
self::$errors = array_merge( self::$errors, $errors );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -409,7 +408,7 @@ class Installer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ( empty( $module_data->class_object ) ) {
|
if ( empty( $module_data->class_object ) ) {
|
||||||
self::$errors[] = [ 'errorInfo' => 'installModel class_object not found: ' . $module_data->class ];
|
self::$errors[] = [ 'errorInfo' => 'Class not found: ' . $module_data->class ];
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -466,7 +465,7 @@ class Installer {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$errors[] = [ 'errorInfo' => $module_data['name'] . " model has been installed." ];
|
$errors[] = [ 'errorInfo' => $module_data['name'] . " has been installed." ];
|
||||||
self::$errors = array_merge( self::$errors, $errors );
|
self::$errors = array_merge( self::$errors, $errors );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -476,7 +475,7 @@ class Installer {
|
|||||||
$errors = [];
|
$errors = [];
|
||||||
|
|
||||||
if ( empty( $module_data->class_object ) ) {
|
if ( empty( $module_data->class_object ) ) {
|
||||||
self::$errors[] = [ 'errorInfo' => 'uninstallModel: class_object not found: ' . $module_data->class ];
|
self::$errors[] = [ 'errorInfo' => 'Class not found: ' . $module_data->class ];
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -500,7 +499,7 @@ class Installer {
|
|||||||
|
|
||||||
// exclude any flags we don't have a matric map for
|
// exclude any flags we don't have a matric map for
|
||||||
if ( empty( $module_data->class_object->$matrix ) ) {
|
if ( empty( $module_data->class_object->$matrix ) ) {
|
||||||
Debug::warn( "$flag_type does not have a proper matrix map and cannot be uninstalled." );
|
Debug::warn( "$flag_type does not have a proper matrix map and cannot be installed." );
|
||||||
$module_data->$flag_type = INSTALL_STATUS_NOT_FOUND;
|
$module_data->$flag_type = INSTALL_STATUS_NOT_FOUND;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -513,7 +512,7 @@ class Installer {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$errors[] = [ 'errorInfo' => $module_data->name . " model has been uninstalled." ];
|
$errors[] = [ 'errorInfo' => $module_data->name . " has been uninstalled." ];
|
||||||
self::$errors = array_merge( self::$errors, $errors );
|
self::$errors = array_merge( self::$errors, $errors );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
*/
|
*/
|
||||||
namespace TheTempusProject\Classes;
|
namespace TheTempusProject\Classes;
|
||||||
|
|
||||||
use TheTempusProject\Canary\Bin\Canary as Debug;
|
use TheTempusProject\Canary\Canary as Debug;
|
||||||
use TheTempusProject\Bedrock\Functions\Check;
|
use TheTempusProject\Bedrock\Functions\Check;
|
||||||
use TheTempusProject\Houdini\Classes\Forms;
|
use TheTempusProject\Houdini\Classes\Forms;
|
||||||
use TheTempusProject\Bedrock\Functions\Input;
|
use TheTempusProject\Bedrock\Functions\Input;
|
||||||
|
@ -14,7 +14,7 @@ namespace TheTempusProject\Classes;
|
|||||||
use TheTempusProject\Houdini\Classes\Navigation;
|
use TheTempusProject\Houdini\Classes\Navigation;
|
||||||
use TheTempusProject\Houdini\Classes\Filters;
|
use TheTempusProject\Houdini\Classes\Filters;
|
||||||
use TheTempusProject\TheTempusProject as App;
|
use TheTempusProject\TheTempusProject as App;
|
||||||
use TheTempusProject\Canary\Bin\Canary as Debug;
|
use TheTempusProject\Canary\Canary as Debug;
|
||||||
use TheTempusProject\Bedrock\Classes\Database;
|
use TheTempusProject\Bedrock\Classes\Database;
|
||||||
|
|
||||||
class Plugin {
|
class Plugin {
|
||||||
|
@ -13,7 +13,7 @@ namespace TheTempusProject\Classes;
|
|||||||
|
|
||||||
use TheTempusProject\Houdini\Classes\Issues;
|
use TheTempusProject\Houdini\Classes\Issues;
|
||||||
use TheTempusProject\Houdini\Classes\Forms;
|
use TheTempusProject\Houdini\Classes\Forms;
|
||||||
use TheTempusProject\Canary\Bin\Canary as Debug;
|
use TheTempusProject\Canary\Canary as Debug;
|
||||||
use TheTempusProject\Bedrock\Functions\Check;
|
use TheTempusProject\Bedrock\Functions\Check;
|
||||||
use TheTempusProject\Bedrock\Functions\Upload;
|
use TheTempusProject\Bedrock\Functions\Upload;
|
||||||
use TheTempusProject\Bedrock\Functions\Input;
|
use TheTempusProject\Bedrock\Functions\Input;
|
||||||
|
@ -1,312 +0,0 @@
|
|||||||
{
|
|
||||||
"main":
|
|
||||||
{
|
|
||||||
"logo":
|
|
||||||
{
|
|
||||||
"type": "file",
|
|
||||||
"pretty": "Site Logo (Used mostly in emails)",
|
|
||||||
"default": "images/logo.png",
|
|
||||||
"value": "images/logo.png"
|
|
||||||
},
|
|
||||||
"name":
|
|
||||||
{
|
|
||||||
"type": "text",
|
|
||||||
"pretty": "Site Name",
|
|
||||||
"default": "TTP Example",
|
|
||||||
"value": "TableTop Elite"
|
|
||||||
},
|
|
||||||
"template":
|
|
||||||
{
|
|
||||||
"type": "text",
|
|
||||||
"pretty": "Default Site Template",
|
|
||||||
"default": "default",
|
|
||||||
"value": "default"
|
|
||||||
},
|
|
||||||
"tokenEnabled":
|
|
||||||
{
|
|
||||||
"type": "radio",
|
|
||||||
"pretty": "Enable CSRF Token for all forms.",
|
|
||||||
"default": true,
|
|
||||||
"value": true
|
|
||||||
},
|
|
||||||
"loginLimit":
|
|
||||||
{
|
|
||||||
"type": "text",
|
|
||||||
"pretty": "Maximum Login Attempts per hour",
|
|
||||||
"default": 5,
|
|
||||||
"value": "5"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"uploads":
|
|
||||||
{
|
|
||||||
"files":
|
|
||||||
{
|
|
||||||
"type": "radio",
|
|
||||||
"pretty": "Enable File Uploads",
|
|
||||||
"default": true,
|
|
||||||
"value": true
|
|
||||||
},
|
|
||||||
"images":
|
|
||||||
{
|
|
||||||
"type": "radio",
|
|
||||||
"pretty": "Enable Image Uploads",
|
|
||||||
"default": true,
|
|
||||||
"value": true
|
|
||||||
},
|
|
||||||
"maxFileSize":
|
|
||||||
{
|
|
||||||
"type": "text",
|
|
||||||
"pretty": "Maximum File Size",
|
|
||||||
"default": 5000000,
|
|
||||||
"value": "5000000"
|
|
||||||
},
|
|
||||||
"maxImageSize":
|
|
||||||
{
|
|
||||||
"type": "text",
|
|
||||||
"pretty": "Maximum Image Size",
|
|
||||||
"default": 500000,
|
|
||||||
"value": "500000"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"database":
|
|
||||||
{
|
|
||||||
"dbMaxQuery":
|
|
||||||
{
|
|
||||||
"type": "text",
|
|
||||||
"pretty": "Maximum results per query",
|
|
||||||
"default": 100,
|
|
||||||
"protected": true,
|
|
||||||
"value": 100
|
|
||||||
},
|
|
||||||
"dbEnabled":
|
|
||||||
{
|
|
||||||
"type": "radio",
|
|
||||||
"pretty": "Database Enabled",
|
|
||||||
"default": true,
|
|
||||||
"protected": true,
|
|
||||||
"value": true
|
|
||||||
},
|
|
||||||
"dbHost":
|
|
||||||
{
|
|
||||||
"type": "text",
|
|
||||||
"pretty": "Database Host (IE: http://localhost:3306)",
|
|
||||||
"default": "127.0.0.1",
|
|
||||||
"protected": true,
|
|
||||||
"value": "194.195.208.99"
|
|
||||||
},
|
|
||||||
"dbName":
|
|
||||||
{
|
|
||||||
"type": "text",
|
|
||||||
"pretty": "Database Name",
|
|
||||||
"default": "ttp-example",
|
|
||||||
"protected": true,
|
|
||||||
"value": "tte-com"
|
|
||||||
},
|
|
||||||
"dbPassword":
|
|
||||||
{
|
|
||||||
"type": "text",
|
|
||||||
"pretty": "Database Password",
|
|
||||||
"default": "",
|
|
||||||
"protected": true,
|
|
||||||
"value": "lsVb#$D74816"
|
|
||||||
},
|
|
||||||
"dbPrefix":
|
|
||||||
{
|
|
||||||
"type": "text",
|
|
||||||
"pretty": "Database table Prefix",
|
|
||||||
"default": "TTP_",
|
|
||||||
"protected": true,
|
|
||||||
"value": "TTP_"
|
|
||||||
},
|
|
||||||
"dbUsername":
|
|
||||||
{
|
|
||||||
"type": "text",
|
|
||||||
"pretty": "Database Username",
|
|
||||||
"default": "root",
|
|
||||||
"protected": true,
|
|
||||||
"value": "joeyk"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"group":
|
|
||||||
{
|
|
||||||
"defaultGroup":
|
|
||||||
{
|
|
||||||
"type": "customSelect",
|
|
||||||
"pretty": "The Default Group for new registrations.",
|
|
||||||
"default": 5,
|
|
||||||
"value": 5
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"logging":
|
|
||||||
{
|
|
||||||
"admin":
|
|
||||||
{
|
|
||||||
"type": "radio",
|
|
||||||
"pretty": "Enable Admin Action Logging.",
|
|
||||||
"default": true,
|
|
||||||
"value": true
|
|
||||||
},
|
|
||||||
"errors":
|
|
||||||
{
|
|
||||||
"type": "radio",
|
|
||||||
"pretty": "Enable Error Logging",
|
|
||||||
"default": true,
|
|
||||||
"value": true
|
|
||||||
},
|
|
||||||
"logins":
|
|
||||||
{
|
|
||||||
"type": "radio",
|
|
||||||
"pretty": "Enable Login Logging",
|
|
||||||
"default": true,
|
|
||||||
"value": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"bugreports":
|
|
||||||
{
|
|
||||||
"enabled":
|
|
||||||
{
|
|
||||||
"type": "radio",
|
|
||||||
"pretty": "Enable Bug reporting.",
|
|
||||||
"default": true,
|
|
||||||
"value": true
|
|
||||||
},
|
|
||||||
"sendEmail":
|
|
||||||
{
|
|
||||||
"type": "radio",
|
|
||||||
"pretty": "Email the user after submitting.",
|
|
||||||
"default": true,
|
|
||||||
"value": true
|
|
||||||
},
|
|
||||||
"emailTemplate":
|
|
||||||
{
|
|
||||||
"type": "text",
|
|
||||||
"pretty": "Email Template",
|
|
||||||
"default": "BugReportEmail",
|
|
||||||
"value": "BugReportEmail"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"bugtracker":
|
|
||||||
{
|
|
||||||
"enabled":
|
|
||||||
{
|
|
||||||
"type": "radio",
|
|
||||||
"pretty": "Enable Bug tracking.",
|
|
||||||
"default": true,
|
|
||||||
"value": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"calendar":
|
|
||||||
{
|
|
||||||
"enabled":
|
|
||||||
{
|
|
||||||
"type": "radio",
|
|
||||||
"pretty": "Enable Calendar.",
|
|
||||||
"default": true,
|
|
||||||
"value": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"chat":
|
|
||||||
{
|
|
||||||
"enabled":
|
|
||||||
{
|
|
||||||
"type": "radio",
|
|
||||||
"pretty": "Enable Chat.",
|
|
||||||
"default": true,
|
|
||||||
"value": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"dice":
|
|
||||||
{
|
|
||||||
"enabled":
|
|
||||||
{
|
|
||||||
"type": "radio",
|
|
||||||
"pretty": "Enable dice usage.",
|
|
||||||
"default": true,
|
|
||||||
"value": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"dnd":
|
|
||||||
{
|
|
||||||
"enabled":
|
|
||||||
{
|
|
||||||
"type": "radio",
|
|
||||||
"pretty": "Enable D&D plugin.",
|
|
||||||
"default": true,
|
|
||||||
"value": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"feedback":
|
|
||||||
{
|
|
||||||
"enabled":
|
|
||||||
{
|
|
||||||
"type": "radio",
|
|
||||||
"pretty": "Enable User Feedback.",
|
|
||||||
"default": true,
|
|
||||||
"value": true
|
|
||||||
},
|
|
||||||
"sendEmail":
|
|
||||||
{
|
|
||||||
"type": "radio",
|
|
||||||
"pretty": "Email the user after submitting.",
|
|
||||||
"default": false,
|
|
||||||
"value": false
|
|
||||||
},
|
|
||||||
"emailTemplate":
|
|
||||||
{
|
|
||||||
"type": "text",
|
|
||||||
"pretty": "Email Template",
|
|
||||||
"default": "feedbackEmail",
|
|
||||||
"value": "feedbackEmail"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"initiativeTracker":
|
|
||||||
{
|
|
||||||
"enabled":
|
|
||||||
{
|
|
||||||
"type": "radio",
|
|
||||||
"pretty": "Enable tracker usage.",
|
|
||||||
"default": true,
|
|
||||||
"value": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"npcGeneration":
|
|
||||||
{
|
|
||||||
"enabled":
|
|
||||||
{
|
|
||||||
"type": "radio",
|
|
||||||
"pretty": "Enable NPC-Generator usage.",
|
|
||||||
"default": true,
|
|
||||||
"value": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"rng":
|
|
||||||
{
|
|
||||||
"enabled":
|
|
||||||
{
|
|
||||||
"type": "radio",
|
|
||||||
"pretty": "Enable rng usage.",
|
|
||||||
"default": true,
|
|
||||||
"value": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"tablefinder":
|
|
||||||
{
|
|
||||||
"enabled":
|
|
||||||
{
|
|
||||||
"type": "radio",
|
|
||||||
"pretty": "Enable the table finder.",
|
|
||||||
"default": true,
|
|
||||||
"value": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"timers":
|
|
||||||
{
|
|
||||||
"enabled":
|
|
||||||
{
|
|
||||||
"type": "radio",
|
|
||||||
"pretty": "Enable timer usage.",
|
|
||||||
"default": true,
|
|
||||||
"value": true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1 +0,0 @@
|
|||||||
{"main":{"logo":{"value":"images\/logo.png"},"name":{"value":"Table-Top Elite"},"loginLimit":{"type":"text","pretty":"Maximum Login Attempts per hour","default":5,"value":5}},"database":{"dbMaxQuery":{"value":100},"dbEnabled":{"value":true},"dbHost":{"value":"194.195.208.99"},"dbName":{"value":"tte-com"},"dbPassword":{"value":"lsVb#$D74816"},"dbPrefix":{"value":"TTP_"},"dbUsername":{"value":"joeyk"}}}
|
|
@ -1,17 +1,19 @@
|
|||||||
<?php
|
<?php
|
||||||
|
if ( ! defined( 'APP_SPACE' ) ) {
|
||||||
define( 'APP_SPACE', 'TheTempusProject' );
|
define( 'APP_SPACE', 'TheTempusProject' );
|
||||||
|
}
|
||||||
if ( ! defined( 'APP_ROOT_DIRECTORY' ) ) {
|
if ( ! defined( 'APP_ROOT_DIRECTORY' ) ) {
|
||||||
define( 'APP_ROOT_DIRECTORY', dirname( __DIR__ ) . DIRECTORY_SEPARATOR ); // need to verify
|
define( 'APP_ROOT_DIRECTORY', dirname( __DIR__ ) . DIRECTORY_SEPARATOR ); // need to verify
|
||||||
}
|
}
|
||||||
define( 'APP_DIRECTORY', APP_ROOT_DIRECTORY . 'app' . DIRECTORY_SEPARATOR );
|
if ( ! defined( 'CONFIG_DIRECTORY' ) ) {
|
||||||
|
define( 'CONFIG_DIRECTORY', APP_ROOT_DIRECTORY . 'app' . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR );
|
||||||
|
}
|
||||||
// Directories
|
// Directories
|
||||||
|
define( 'APP_DIRECTORY', APP_ROOT_DIRECTORY . 'app' . DIRECTORY_SEPARATOR );
|
||||||
define( 'CSS_DIRECTORY', APP_ROOT_DIRECTORY . 'css' . DIRECTORY_SEPARATOR );
|
define( 'CSS_DIRECTORY', APP_ROOT_DIRECTORY . 'css' . DIRECTORY_SEPARATOR );
|
||||||
define( 'IMAGE_DIRECTORY', APP_ROOT_DIRECTORY . 'images' . DIRECTORY_SEPARATOR );
|
define( 'IMAGE_DIRECTORY', APP_ROOT_DIRECTORY . 'images' . DIRECTORY_SEPARATOR );
|
||||||
define( 'JAVASCRIPT_DIRECTORY', APP_ROOT_DIRECTORY . 'js' . DIRECTORY_SEPARATOR );
|
define( 'JAVASCRIPT_DIRECTORY', APP_ROOT_DIRECTORY . 'js' . DIRECTORY_SEPARATOR );
|
||||||
define( 'HTACCESS_LOCATION', APP_ROOT_DIRECTORY . '.htaccess' );
|
define( 'HTACCESS_LOCATION', APP_ROOT_DIRECTORY . '.htaccess' );
|
||||||
if ( ! defined( 'CONFIG_DIRECTORY' ) ) {
|
|
||||||
define( 'CONFIG_DIRECTORY', APP_DIRECTORY . 'config' . DIRECTORY_SEPARATOR );
|
|
||||||
}
|
|
||||||
define( 'PLUGIN_DIRECTORY', APP_DIRECTORY . 'plugins' . DIRECTORY_SEPARATOR );
|
define( 'PLUGIN_DIRECTORY', APP_DIRECTORY . 'plugins' . DIRECTORY_SEPARATOR );
|
||||||
define( 'MODEL_DIRECTORY', APP_DIRECTORY . 'models' . DIRECTORY_SEPARATOR );
|
define( 'MODEL_DIRECTORY', APP_DIRECTORY . 'models' . DIRECTORY_SEPARATOR );
|
||||||
define( 'CONTROLLER_DIRECTORY', APP_DIRECTORY . 'controllers' . DIRECTORY_SEPARATOR );
|
define( 'CONTROLLER_DIRECTORY', APP_DIRECTORY . 'controllers' . DIRECTORY_SEPARATOR );
|
||||||
@ -43,8 +45,6 @@ if ( ! defined( 'CONFIG_DIRECTORY' ) ) {
|
|||||||
// Cookies
|
// Cookies
|
||||||
define( 'DEFAULT_COOKIE_PREFIX', 'TP_');
|
define( 'DEFAULT_COOKIE_PREFIX', 'TP_');
|
||||||
// Debug
|
// Debug
|
||||||
|
|
||||||
define( 'CANARY_DEBUG_DIRECTORY', APP_ROOT_DIRECTORY . 'logs' . DIRECTORY_SEPARATOR );
|
|
||||||
define( 'CANARY_DEBUG_LEVEL_ERROR', 'error' );
|
define( 'CANARY_DEBUG_LEVEL_ERROR', 'error' );
|
||||||
define( 'CANARY_DEBUG_LEVEL_WARN', 'warn' );
|
define( 'CANARY_DEBUG_LEVEL_WARN', 'warn' );
|
||||||
define( 'CANARY_DEBUG_LEVEL_INFO', 'info' );
|
define( 'CANARY_DEBUG_LEVEL_INFO', 'info' );
|
||||||
@ -59,9 +59,7 @@ if ( ! defined( 'CONFIG_DIRECTORY' ) ) {
|
|||||||
define( 'CANARY_DEBUG_TO_CONSOLE', false );
|
define( 'CANARY_DEBUG_TO_CONSOLE', false );
|
||||||
define( 'CANARY_DEBUG_TO_FILE', true );
|
define( 'CANARY_DEBUG_TO_FILE', true );
|
||||||
// Directories
|
// Directories
|
||||||
if ( ! defined( 'VENDOR_DIRECTORY' ) ) {
|
|
||||||
define( 'VENDOR_DIRECTORY', APP_ROOT_DIRECTORY . 'vendor' . DIRECTORY_SEPARATOR );
|
define( 'VENDOR_DIRECTORY', APP_ROOT_DIRECTORY . 'vendor' . DIRECTORY_SEPARATOR );
|
||||||
}
|
|
||||||
if ( is_dir( VENDOR_DIRECTORY . 'thetempusproject' )) {
|
if ( is_dir( VENDOR_DIRECTORY . 'thetempusproject' )) {
|
||||||
define( 'TP_VENDOR_DIRECTORY', VENDOR_DIRECTORY . 'thetempusproject' . DIRECTORY_SEPARATOR );
|
define( 'TP_VENDOR_DIRECTORY', VENDOR_DIRECTORY . 'thetempusproject' . DIRECTORY_SEPARATOR );
|
||||||
} elseif ( is_dir( VENDOR_DIRECTORY . 'TheTempusProject' )) {
|
} elseif ( is_dir( VENDOR_DIRECTORY . 'TheTempusProject' )) {
|
||||||
@ -133,14 +131,5 @@ if ( ! defined( 'CONFIG_DIRECTORY' ) ) {
|
|||||||
define( 'DEFAULT_SESSION_PREFIX', 'TP_' );
|
define( 'DEFAULT_SESSION_PREFIX', 'TP_' );
|
||||||
// Token
|
// Token
|
||||||
define( 'DEFAULT_TOKEN_NAME', 'TP_SESSION_TOKEN' );
|
define( 'DEFAULT_TOKEN_NAME', 'TP_SESSION_TOKEN' );
|
||||||
|
|
||||||
# Bugsnag
|
|
||||||
define( 'BUGSNAG_API_KEY', '88045bdc058de51139ac1a47dcd5694b' );
|
|
||||||
// define( 'BUGSNAG_API_KEY', 'cb94acd2a46160589b37cbaad0c61047' );
|
|
||||||
|
|
||||||
# Recaptcha
|
|
||||||
|
|
||||||
# Google Analytics
|
|
||||||
|
|
||||||
# Tell the app; all constants have been loaded
|
# Tell the app; all constants have been loaded
|
||||||
define( 'TEMPUS_PROJECT_CONSTANTS_LOADED', true );
|
define( 'TEMPUS_PROJECT_CONSTANTS_LOADED', true );
|
||||||
|
File diff suppressed because one or more lines are too long
@ -1 +0,0 @@
|
|||||||
{"adminAccess":{"pretty":"Access Administrator Areas","default":false},"addRoute":{"pretty":"Add Custom Routes","default":false},"uploadImages":{"pretty":"Upload images (such as avatars)","default":false},"bugReport":{"pretty":"Can Submit Bug Reports","default":false},"bugTrack":{"pretty":"Can Track Bugs","default":false},"useCalendar":{"pretty":"Can use the calendar feature","default":false},"createEvents":{"pretty":"Can add events to calendars","default":false},"chat":{"pretty":"Can use chat","default":false},"modAccess":{"pretty":"Access Moderator Areas","default":false},"dice":{"pretty":"Can use dice","default":true},"canCreateCharacters":{"pretty":"Can use the character creator","default":true},"canCreateClasses":{"pretty":"Can add Classes.","default":true},"canCreateItems":{"pretty":"Can add Items","default":true},"canCreateMonsters":{"pretty":"Can add Monsters","default":true},"canCreateRaces":{"pretty":"Can add Races","default":true},"canCreateSkills":{"pretty":"Can add Skills","default":true},"canCreateSourceBooks":{"pretty":"Can add SourceBooks","default":true},"canCreateSpells":{"pretty":"Can add Spells","default":true},"feedback":{"pretty":"Can Submit Feedback","default":false},"uploadFiles":{"pretty":"Can upload files","default":false},"useInitiativeTracker":{"pretty":"Can use the tracker","default":true},"memberAccess":{"pretty":"Access Member Areas","default":false},"controlMemberships":{"pretty":"User can Access and Control user memberships.","default":false},"sendMessages":{"pretty":"Can send Messages","default":false},"sendNotifications":{"pretty":"Can send notifications","default":false},"suggest":{"pretty":"Can create suggestions","default":false},"redirects":{"pretty":"Can modify redirects","default":false},"useTableFinder":{"pretty":"Can use the table finder","default":true},"timers":{"pretty":"Can use timers","default":true}}
|
|
@ -1 +0,0 @@
|
|||||||
{"adminAccess":{"pretty":"Access Administrator Areas","default":false},"addRoute":{"pretty":"Add Custom Routes","default":false},"uploadImages":{"pretty":"Upload images (such as avatars)","default":false},"bugReport":{"pretty":"Can Submit Bug Reports","default":false},"bugTrack":{"pretty":"Can Track Bugs","default":false},"useCalendar":{"pretty":"Can use the calendar feature","default":false},"createEvents":{"pretty":"Can add events to calendars","default":false},"chat":{"pretty":"Can use chat","default":false},"modAccess":{"pretty":"Access Moderator Areas","default":false},"dice":{"pretty":"Can use dice","default":true},"canCreateCharacters":{"pretty":"Can use the character creator","default":true},"canCreateClasses":{"pretty":"Can add Classes.","default":true},"canCreateItems":{"pretty":"Can add Items","default":true},"canCreateMonsters":{"pretty":"Can add Monsters","default":true},"canCreateRaces":{"pretty":"Can add Races","default":true},"canCreateSkills":{"pretty":"Can add Skills","default":true},"canCreateSourceBooks":{"pretty":"Can add SourceBooks","default":true},"canCreateSpells":{"pretty":"Can add Spells","default":true},"feedback":{"pretty":"Can Submit Feedback","default":false},"uploadFiles":{"pretty":"Can upload files","default":false},"useInitiativeTracker":{"pretty":"Can use the tracker","default":true},"memberAccess":{"pretty":"Access Member Areas","default":false},"controlMemberships":{"pretty":"User can Access and Control user memberships.","default":false},"sendMessages":{"pretty":"Can send Messages","default":false},"sendNotifications":{"pretty":"Can send notifications","default":false},"suggest":{"pretty":"Can create suggestions","default":false},"redirects":{"pretty":"Can modify redirects","default":false},"useTableFinder":{"pretty":"Can use the table finder","default":true},"timers":{"pretty":"Can use timers","default":true}}
|
|
@ -1 +0,0 @@
|
|||||||
{"gender":{"pretty":"Gender","type":"select","default":"unspecified","options":["male","female","other","unspecified"],"avatar":"\/var\/www\/tabletopelite.com\/images\/defaultAvatar.png"},"newsletter":{"pretty":"Receive our Newsletter?","type":"checkbox","default":"true","avatar":"\/var\/www\/tabletopelite.com\/images\/defaultAvatar.png","options":null},"avatar":{"pretty":"Avatar","type":"file","default":"images\/defaultAvatar.png","avatar":"\/var\/www\/tabletopelite.com\/images\/defaultAvatar.png","options":null},"timezone":{"pretty":"Timezone","type":"timezone","default":"America\/New_York","avatar":"\/var\/www\/tabletopelite.com\/images\/defaultAvatar.png","options":null},"dateFormat":{"pretty":"Date Format","type":"select","default":"F j, Y","options":{"1-8-1991":"n-j-Y","8-1-1991":"j-n-Y","01-08-1991":"m-d-Y","08-01-1991":"d-m-Y","January 8, 1991":"F-j-Y","8 January, 1991":"j-F-Y","January 08, 1991":"F-d-Y","08 January, 1991":"d-F-Y","Jan 8, 1991":"M-j-Y","8 Jan 1991":"j-M-Y","Jan 08, 1991":"M-d-Y","08 Jan 1991":"d-M-Y"},"avatar":"\/var\/www\/tabletopelite.com\/images\/defaultAvatar.png"},"timeFormat":{"pretty":"Time Format","type":"select","default":"g:i:s A","options":{"3:33:33 AM":"g:i:s A","03:33:33 AM":"h:i:s A","3:33:33 am":"g:i:s a","03:33:33 am":"h:i:s a","3:33:33 (military)":"G:i:s","03:33:33 (military)":"H:i:s"},"avatar":"\/var\/www\/tabletopelite.com\/images\/defaultAvatar.png"},"pageLimit":{"pretty":"Items Displayed Per Page","type":"select","default":"10","options":["10","15","20","25","50"],"avatar":"\/var\/www\/tabletopelite.com\/images\/defaultAvatar.png"},"calendarPreference":{"pretty":"Default Calendar View","type":"select","default":"byMonth","options":{"Daily":"byDay","Weekly":"byWeek","Monthly":"byMonth","Yearly":"byYear","All Events":"events"},"avatar":"\/var\/www\/tabletopelite.com\/images\/defaultAvatar.png"},"weekStart":{"pretty":"First day of the week for the Calendar","type":"select","default":"sunday","options":{"Sunday":"6","Monday":"7"},"avatar":"\/var\/www\/tabletopelite.com\/images\/defaultAvatar.png"}}
|
|
@ -1 +0,0 @@
|
|||||||
{"gender":{"pretty":"Gender","type":"select","default":"unspecified","options":["male","female","other","unspecified"],"avatar":"\/var\/www\/tabletopelite.com\/images\/defaultAvatar.png"},"newsletter":{"pretty":"Receive our Newsletter?","type":"checkbox","default":"true","avatar":"\/var\/www\/tabletopelite.com\/images\/defaultAvatar.png","options":null},"avatar":{"pretty":"Avatar","type":"file","default":"images\/defaultAvatar.png","avatar":"\/var\/www\/tabletopelite.com\/images\/defaultAvatar.png","options":null},"timezone":{"pretty":"Timezone","type":"timezone","default":"America\/New_York","avatar":"\/var\/www\/tabletopelite.com\/images\/defaultAvatar.png","options":null},"dateFormat":{"pretty":"Date Format","type":"select","default":"F j, Y","options":{"1-8-1991":"n-j-Y","8-1-1991":"j-n-Y","01-08-1991":"m-d-Y","08-01-1991":"d-m-Y","January 8, 1991":"F-j-Y","8 January, 1991":"j-F-Y","January 08, 1991":"F-d-Y","08 January, 1991":"d-F-Y","Jan 8, 1991":"M-j-Y","8 Jan 1991":"j-M-Y","Jan 08, 1991":"M-d-Y","08 Jan 1991":"d-M-Y"},"avatar":"\/var\/www\/tabletopelite.com\/images\/defaultAvatar.png"},"timeFormat":{"pretty":"Time Format","type":"select","default":"g:i:s A","options":{"3:33:33 AM":"g:i:s A","03:33:33 AM":"h:i:s A","3:33:33 am":"g:i:s a","03:33:33 am":"h:i:s a","3:33:33 (military)":"G:i:s","03:33:33 (military)":"H:i:s"},"avatar":"\/var\/www\/tabletopelite.com\/images\/defaultAvatar.png"},"pageLimit":{"pretty":"Items Displayed Per Page","type":"select","default":"10","options":["10","15","20","25","50"],"avatar":"\/var\/www\/tabletopelite.com\/images\/defaultAvatar.png"},"calendarPreference":{"pretty":"Default Calendar View","type":"select","default":"byMonth","options":{"Daily":"byDay","Weekly":"byWeek","Monthly":"byMonth","Yearly":"byYear","All Events":"events"},"avatar":"\/var\/www\/tabletopelite.com\/images\/defaultAvatar.png"},"weekStart":{"pretty":"First day of the week for the Calendar","type":"select","default":"sunday","options":{"Sunday":"6","Monday":"7"},"avatar":"\/var\/www\/tabletopelite.com\/images\/defaultAvatar.png"}}
|
|
@ -39,7 +39,7 @@ class Admin extends AdminController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function index() {
|
public function index() {
|
||||||
return Views::view( 'admin.logs.admin_list', self::$log->listPaginated( 'admin' ) );
|
return Views::view( 'admin.logs.admin_list', self::$log->list( 'admin' ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
public function view( $id = null ) {
|
public function view( $id = null ) {
|
||||||
|
@ -59,6 +59,6 @@ class Composer extends AdminController {
|
|||||||
$out[] = (object) $versionsInstalled[ $name ];
|
$out[] = (object) $versionsInstalled[ $name ];
|
||||||
}
|
}
|
||||||
|
|
||||||
Views::view( 'admin.modules.composer.dependencies', $out );
|
Views::view( 'admin.dependencies', $out );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@ class Errors extends AdminController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function index() {
|
public function index() {
|
||||||
return Views::view( 'admin.logs.error_list', self::$log->listPaginated( 'error' ) );
|
return Views::view( 'admin.logs.error_list', self::$log->list( 'error' ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
public function view( $id = null ) {
|
public function view( $id = null ) {
|
||||||
|
@ -95,7 +95,7 @@ class Groups extends AdminController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function index( $data = null ) {
|
public function index( $data = null ) {
|
||||||
Views::view( 'admin.groups.list', self::$group->listPaginated() );
|
Views::view( 'admin.groups.list', self::$group->list() );
|
||||||
}
|
}
|
||||||
|
|
||||||
public function listmembers( $data = null ) {
|
public function listmembers( $data = null ) {
|
||||||
|
@ -39,7 +39,7 @@ class Logins extends AdminController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function index() {
|
public function index() {
|
||||||
return Views::view( 'admin.logs.login_list', self::$log->listPaginated( 'login' ) );
|
return Views::view( 'admin.logs.login_list', self::$log->list( 'login' ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
public function view( $id = null ) {
|
public function view( $id = null ) {
|
||||||
|
@ -26,8 +26,8 @@ class Logs extends AdminController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function index( $data = null ) {
|
public function index( $data = null ) {
|
||||||
Views::view( 'admin.logs.error_list', self::$log->listPaginated( 'error' ) );
|
Views::view( 'admin.logs.error_list', self::$log->list( 'error' ) );
|
||||||
Views::view( 'admin.logs.admin_list', self::$log->listPaginated( 'admin' ) );
|
Views::view( 'admin.logs.admin_list', self::$log->list( 'admin' ) );
|
||||||
Views::view( 'admin.logs.login_list', self::$log->listPaginated( 'login' ) );
|
Views::view( 'admin.logs.login_list', self::$log->list( 'login' ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,7 +56,7 @@ class Plugins extends AdminController {
|
|||||||
if ( !Input::exists( 'installHash' ) ) {
|
if ( !Input::exists( 'installHash' ) ) {
|
||||||
return Views::view( 'admin.modules.plugins.enable' );
|
return Views::view( 'admin.modules.plugins.enable' );
|
||||||
}
|
}
|
||||||
if ( ! Plugin::enable( $name ) ) {
|
if ( !Plugin::enable( $name ) ) {
|
||||||
Session::flash( 'error', 'There was an error enabling the plugin.' );
|
Session::flash( 'error', 'There was an error enabling the plugin.' );
|
||||||
} else {
|
} else {
|
||||||
Session::flash( 'success', 'Plugin has been enabled.' );
|
Session::flash( 'success', 'Plugin has been enabled.' );
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
*/
|
*/
|
||||||
namespace TheTempusProject\Controllers\Admin;
|
namespace TheTempusProject\Controllers\Admin;
|
||||||
|
|
||||||
use TheTempusProject\Classes\Forms as TTPForms;
|
use TheTempusProject\TTPForms;
|
||||||
use TheTempusProject\Houdini\Classes\Views;
|
use TheTempusProject\Houdini\Classes\Views;
|
||||||
use TheTempusProject\Houdini\Classes\Issues;
|
use TheTempusProject\Houdini\Classes\Issues;
|
||||||
use TheTempusProject\Houdini\Classes\Navigation;
|
use TheTempusProject\Houdini\Classes\Navigation;
|
||||||
@ -88,7 +88,7 @@ class Routes extends AdminController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function index() {
|
public function index() {
|
||||||
return Views::view( 'admin.routes.list', self::$routes->listPaginated() );
|
return Views::view( 'admin.routes.list', self::$routes->list() );
|
||||||
}
|
}
|
||||||
|
|
||||||
public function view( $id = null ) {
|
public function view( $id = null ) {
|
||||||
|
@ -140,7 +140,7 @@ class Users extends AdminController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function index() {
|
public function index() {
|
||||||
Views::view( 'admin.users.list', self::$user->listPaginated() );
|
Views::view( 'admin.users.list', self::$user->userList() );
|
||||||
}
|
}
|
||||||
|
|
||||||
public function view( $id = null ) {
|
public function view( $id = null ) {
|
||||||
|
@ -30,7 +30,7 @@ class Users extends ApiController {
|
|||||||
$response = 'No user found.';
|
$response = 'No user found.';
|
||||||
} else {
|
} else {
|
||||||
$responseType = 'data';
|
$responseType = 'data';
|
||||||
$response = $user->ID;
|
$response = $user;
|
||||||
}
|
}
|
||||||
Views::view( 'api.response', ['response' => json_encode( [ $responseType => $response ], true )]);
|
Views::view( 'api.response', ['response' => json_encode( [ $responseType => $response ], true )]);
|
||||||
}
|
}
|
||||||
|
@ -29,11 +29,6 @@ class Home extends Controller {
|
|||||||
self::$title = '{SITENAME}';
|
self::$title = '{SITENAME}';
|
||||||
self::$pageDescription = 'This is the homepage of your new Tempus Project Installation. Thank you for installing. find more info at https://thetempusproject.com';
|
self::$pageDescription = 'This is the homepage of your new Tempus Project Installation. Thank you for installing. find more info at https://thetempusproject.com';
|
||||||
Views::view( 'index' );
|
Views::view( 'index' );
|
||||||
|
|
||||||
Template::addHeader( 'Access-Control-Allow-Origin: *');
|
|
||||||
$bugsnag = \Bugsnag\Client::make( BUGSNAG_API_KEY );
|
|
||||||
\Bugsnag\Handler::register($bugsnag);
|
|
||||||
$bugsnag->notifyException(new \RuntimeException("Test error"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function login() {
|
public function login() {
|
||||||
|
@ -217,7 +217,7 @@ pre {
|
|||||||
color: #000;
|
color: #000;
|
||||||
background-color: #FFF;
|
background-color: #FFF;
|
||||||
}
|
}
|
||||||
#carousel-home {
|
#carousel-example-generic {
|
||||||
margin-bottom: 30px;
|
margin-bottom: 30px;
|
||||||
}
|
}
|
||||||
.col-centered {
|
.col-centered {
|
||||||
|
542
app/functions/forms.php
Normal file
542
app/functions/forms.php
Normal file
@ -0,0 +1,542 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* app/functions/forms.php
|
||||||
|
*
|
||||||
|
* This class is used in conjunction with TheTempusProject\Bedrock\Classes\Check
|
||||||
|
* to house complete form verification. You can utilize the error reporting
|
||||||
|
* to easily define exactly what feedback you would like to give.
|
||||||
|
*
|
||||||
|
* @version 3.0
|
||||||
|
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||||
|
* @link https://TheTempusProject.com
|
||||||
|
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||||
|
*/
|
||||||
|
namespace TheTempusProject;
|
||||||
|
|
||||||
|
use TheTempusProject\Bedrock\Functions\Input;
|
||||||
|
use TheTempusProject\Bedrock\Functions\Check;
|
||||||
|
use TheTempusProject\Models\User;
|
||||||
|
use TheTempusProject\Classes\Forms;
|
||||||
|
use TheTempusProject\Bedrock\Classes\Database;
|
||||||
|
|
||||||
|
class TTPForms extends Forms {
|
||||||
|
/**
|
||||||
|
* Adds these functions to the form list.
|
||||||
|
*/
|
||||||
|
public function __construct() {
|
||||||
|
self::addHandler( 'passwordResetCode', __CLASS__, 'passwordResetCode' );
|
||||||
|
self::addHandler( 'createRoute', __CLASS__, 'createRoute' );
|
||||||
|
self::addHandler( 'editRoute', __CLASS__, 'editRoute' );
|
||||||
|
self::addHandler( 'register', __CLASS__, 'register' );
|
||||||
|
self::addHandler( 'createUser', __CLASS__, 'createUser' );
|
||||||
|
self::addHandler( 'editUser', __CLASS__, 'editUser' );
|
||||||
|
self::addHandler( 'login', __CLASS__, 'login' );
|
||||||
|
self::addHandler( 'changeEmail', __CLASS__, 'changeEmail' );
|
||||||
|
self::addHandler( 'changePassword', __CLASS__, 'changePassword' );
|
||||||
|
self::addHandler( 'passwordReset', __CLASS__, 'passwordReset' );
|
||||||
|
self::addHandler( 'emailConfirmation', __CLASS__, 'emailConfirmation' );
|
||||||
|
self::addHandler( 'confirmationResend', __CLASS__, 'confirmationResend' );
|
||||||
|
self::addHandler( 'replyMessage', __CLASS__, 'replyMessage' );
|
||||||
|
self::addHandler( 'newMessage', __CLASS__, 'newMessage' );
|
||||||
|
self::addHandler( 'userPrefs', __CLASS__, 'userPrefs' );
|
||||||
|
self::addHandler( 'newGroup', __CLASS__, 'newGroup' );
|
||||||
|
self::addHandler( 'editGroup', __CLASS__, 'editGroup' );
|
||||||
|
self::addHandler( 'install', __CLASS__, 'install' );
|
||||||
|
self::addHandler( 'installStart', __CLASS__, 'install', [ 'start' ] );
|
||||||
|
self::addHandler( 'installAgreement', __CLASS__, 'install', [ 'agreement' ] );
|
||||||
|
self::addHandler( 'installCheck', __CLASS__, 'install', [ 'check' ] );
|
||||||
|
self::addHandler( 'installConfigure', __CLASS__, 'install', [ 'configure' ] );
|
||||||
|
self::addHandler( 'installRouting', __CLASS__, 'install', [ 'routing' ] );
|
||||||
|
self::addHandler( 'installModels', __CLASS__, 'install', [ 'models' ] );
|
||||||
|
self::addHandler( 'installPlugins', __CLASS__, 'install', [ 'plugins' ] );
|
||||||
|
self::addHandler( 'installResources', __CLASS__, 'install', [ 'resources' ] );
|
||||||
|
self::addHandler( 'installAdminUser', __CLASS__, 'install', [ 'adminUser' ] );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates the installer forms.
|
||||||
|
*
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
public static function install( $page = '' ) {
|
||||||
|
// if ( !self::token() ) {
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
switch ( $page ) {
|
||||||
|
case 'configure':
|
||||||
|
if ( ! Input::exists( 'submit' ) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !Database::check( Input::post( 'dbHost' ), Input::post( 'dbName' ), Input::post( 'dbUsername' ), Input::post( 'dbPassword' ) ) ) {
|
||||||
|
self::addUserError( 'DB connection error.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
case 'adminUser':
|
||||||
|
if ( !self::checkUsername( Input::post( 'newUsername' ) ) ) {
|
||||||
|
self::addUserError( 'Invalid username.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !self::password( Input::post( 'userPassword' ) ) ) {
|
||||||
|
self::addUserError( 'Invalid password.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( Input::post( 'userPassword' ) !== Input::post( 'userPassword2' ) ) {
|
||||||
|
self::addUserError( 'Passwords do not match.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( Input::post( 'userEmail' ) !== Input::post( 'userEmail2' ) ) {
|
||||||
|
self::addUserError( 'Emails do not match.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
case 'check':
|
||||||
|
if ( !self::uploads() ) {
|
||||||
|
self::addUserError( 'Uploads are disabled.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !self::php() ) {
|
||||||
|
self::addUserError( 'PHP version is too old.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !self::phpExtensions() ) {
|
||||||
|
self::addUserError( 'PHP extensions are missing.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !self::sessions() ) {
|
||||||
|
self::addUserError( 'There is an error with Sessions.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !self::mail() ) {
|
||||||
|
self::addUserError( 'PHP mail is not enabled.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !self::safe() ) {
|
||||||
|
self::addUserError( 'Safe mode is enabled.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( ! Input::exists( 'submit' ) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
case 'start':
|
||||||
|
case 'agreement':
|
||||||
|
case 'routing':
|
||||||
|
case 'models':
|
||||||
|
case 'plugins':
|
||||||
|
case 'resources':
|
||||||
|
if ( ! Input::exists( 'submit' ) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates the password re-send form.
|
||||||
|
*
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
public static function passwordResetCode() {
|
||||||
|
if ( !self::token() ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates the route creation form.
|
||||||
|
*
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
public static function createRoute() {
|
||||||
|
if ( !Input::exists( 'redirect_type' ) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( 'external' == Input::post( 'redirect_type' ) && !self::url( Input::post( 'forwarded_url' ) ) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !self::token() ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates the route edit form.
|
||||||
|
*
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
public static function editRoute() {
|
||||||
|
if ( !Input::exists( 'redirect_type' ) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( 'external' == Input::post( 'redirect_type' ) && !self::url( Input::post( 'forwarded_url' ) ) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !self::token() ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates the user creation form.
|
||||||
|
*
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
public static function createUser() {
|
||||||
|
$user = new User;
|
||||||
|
if ( !$user->checkUsername( Input::post( 'username' ) ) ) {
|
||||||
|
self::addUserError( 'Invalid username.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !self::password( Input::post( 'password' ) ) ) {
|
||||||
|
self::addUserError( 'Invalid password.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !self::email( Input::post( 'email' ) ) ) {
|
||||||
|
self::addUserError( 'Invalid Email.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !$user->noEmailExists( Input::post( 'email' ) ) ) {
|
||||||
|
self::addUserError( 'A user with that email is already registered.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( Input::post( 'password' ) !== Input::post( 'password2' ) ) {
|
||||||
|
self::addUserError( 'Passwords do not match.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( Input::post( 'email' ) !== Input::post( 'email2' ) ) {
|
||||||
|
self::addUserError( 'Emails do not match.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !Input::post( 'groupSelect' ) ) {
|
||||||
|
self::addUserError( 'You must select a group for the new user.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !self::token() ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates the user edit form.
|
||||||
|
*
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
public static function editUser() {
|
||||||
|
$user = new User;
|
||||||
|
if ( !$user->checkUsername( Input::post( 'username' ) ) ) {
|
||||||
|
self::addUserError( 'Invalid username.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( Input::exists( 'password' ) ) {
|
||||||
|
if ( !self::password( Input::post( 'password' ) ) ) {
|
||||||
|
self::addUserError( 'Invalid password.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( Input::post( 'password' ) !== Input::post( 'password2' ) ) {
|
||||||
|
self::addUserError( 'Passwords do not match.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( !self::email( Input::post( 'email' ) ) ) {
|
||||||
|
self::addUserError( 'Invalid Email.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !Input::post( 'groupSelect' ) ) {
|
||||||
|
self::addUserError( 'You must select a group for the new user.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !self::token() ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates the user registration form.
|
||||||
|
*
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
public static function register() {
|
||||||
|
$user = new User;
|
||||||
|
if ( !self::checkUsername( Input::post( 'username' ) ) ) {
|
||||||
|
self::addUserError( 'Invalid username.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !self::password( Input::post( 'password' ) ) ) {
|
||||||
|
self::addUserError( 'Invalid password.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !self::email( Input::post( 'email' ) ) ) {
|
||||||
|
self::addUserError( 'Invalid Email.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !$user->noEmailExists( Input::post( 'email' ) ) ) {
|
||||||
|
self::addUserError( 'A user with that email is already registered.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( Input::post( 'password' ) !== Input::post( 'password2' ) ) {
|
||||||
|
self::addUserError( 'Passwords do not match.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( Input::post( 'email' ) !== Input::post( 'email2' ) ) {
|
||||||
|
self::addUserError( 'Emails do not match.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( Input::post( 'terms' ) != '1' ) {
|
||||||
|
self::addUserError( 'You must agree to the terms of service.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !self::token() ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates the user login form.
|
||||||
|
*
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
public static function login() {
|
||||||
|
if ( !self::checkUsername( Input::post( 'username' ) ) ) {
|
||||||
|
self::addUserError( 'Invalid username.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !self::password( Input::post( 'password' ) ) ) {
|
||||||
|
self::addUserError( 'Invalid password.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !self::token() ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates the email change form.
|
||||||
|
*
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
public static function changeEmail() {
|
||||||
|
if ( !self::email( Input::post( 'email' ) ) ) {
|
||||||
|
self::addUserError( 'Invalid Email.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( Input::post( 'email' ) !== Input::post( 'email2' ) ) {
|
||||||
|
self::addUserError( 'Emails do not match.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !self::token() ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates the password change form.
|
||||||
|
*
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
public static function changePassword() {
|
||||||
|
if ( !self::password( Input::post( 'password' ) ) ) {
|
||||||
|
self::addUserError( 'Invalid password.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( Input::post( 'password' ) !== Input::post( 'password2' ) ) {
|
||||||
|
self::addUserError( 'Passwords do not match.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !self::token() ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates the password reset form.
|
||||||
|
*
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
public static function passwordReset() {
|
||||||
|
if ( !self::password( Input::post( 'password' ) ) ) {
|
||||||
|
self::addUserError( 'Invalid password.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( Input::post( 'password' ) !== Input::post( 'password2' ) ) {
|
||||||
|
self::addUserError( 'Passwords do not match.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !self::token() ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates the email confirmation re-send form.
|
||||||
|
*
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
public static function emailConfirmation() {
|
||||||
|
if ( !Input::exists( 'confirmationCode' ) ) {
|
||||||
|
self::addUserError( 'No confirmation code provided.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !self::token() ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates the email confirmation re-send form.
|
||||||
|
*
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
public static function confirmationResend() {
|
||||||
|
if ( !Input::exists( 'resendConfirmation' ) ) {
|
||||||
|
self::addUserError( 'Confirmation not provided.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !self::token() ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates the reply message form.
|
||||||
|
*
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
public static function replyMessage() {
|
||||||
|
if ( !Input::exists( 'message' ) ) {
|
||||||
|
self::addUserError( 'Reply cannot be empty.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !Input::exists( 'messageID' ) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !self::token() ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates the new message form.
|
||||||
|
*
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
public static function newMessage() {
|
||||||
|
if ( !Input::exists( 'toUser' ) ) {
|
||||||
|
self::addUserError( 'You must specify a user to send the message to.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !Input::exists( 'subject' ) ) {
|
||||||
|
self::addUserError( 'You must have a subject for your message.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !Input::exists( 'message' ) ) {
|
||||||
|
self::addUserError( 'No message entered.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !self::token() ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates the user preferences form.
|
||||||
|
*
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
public static function userPrefs() {
|
||||||
|
// @todo make this a real check
|
||||||
|
if ( !Input::exists( 'timeFormat' ) ) {
|
||||||
|
self::addUserError( 'You must specify timeFormat' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !Input::exists( 'pageLimit' ) ) {
|
||||||
|
self::addUserError( 'You must specify pageLimit' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !Input::exists( 'gender' ) ) {
|
||||||
|
self::addUserError( 'You must specify gender' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !Input::exists( 'dateFormat' ) ) {
|
||||||
|
self::addUserError( 'You must specify dateFormat' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !Input::exists( 'timezone' ) ) {
|
||||||
|
self::addUserError( 'You must specify timezone' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !Input::exists( 'updates' ) ) {
|
||||||
|
self::addUserError( 'You must specify updates' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !Input::exists( 'newsletter' ) ) {
|
||||||
|
self::addUserError( 'You must specify newsletter' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !self::token() ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates the group creation form.
|
||||||
|
*
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
public static function newGroup() {
|
||||||
|
if ( !Input::exists( 'name' ) ) {
|
||||||
|
self::addUserError( 'You must specify a name' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !self::dataTitle( Input::exists( 'name' ) ) ) {
|
||||||
|
self::addUserError( 'invalid group name' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !self::token() ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates the group edit form.
|
||||||
|
*
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
public static function editGroup() {
|
||||||
|
if ( !Input::exists( 'name' ) ) {
|
||||||
|
self::addUserError( 'You must specify a name' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !self::dataTitle( Input::exists( 'name' ) ) ) {
|
||||||
|
self::addUserError( 'invalid group name' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !self::token() ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
new TTPForms;
|
@ -11,8 +11,101 @@
|
|||||||
/**
|
/**
|
||||||
* Automatically selects/de-selects all check boxes associated with that field
|
* Automatically selects/de-selects all check boxes associated with that field
|
||||||
**/
|
**/
|
||||||
|
function checkAll(ele) {
|
||||||
|
var checkboxes = document.getElementsByTagName( 'input' );
|
||||||
|
if (ele.checked) {
|
||||||
|
test = true;
|
||||||
|
} else {
|
||||||
|
test = false;
|
||||||
|
}
|
||||||
|
for ( var i = 0; i < checkboxes.length; i++ ) {
|
||||||
|
if ( checkboxes[i].type == 'checkbox' ) {
|
||||||
|
if ( checkboxes[i].name == ele.value ) {
|
||||||
|
checkboxes[i].checked = test;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function copyAll( ele ) {
|
||||||
|
var eleName = '#' + ele;
|
||||||
|
var text = $( eleName ).text();
|
||||||
|
text = text.replaceAll( "''", "\n" ).trim();
|
||||||
|
text = text.substring( 1, text.length - 1 );
|
||||||
|
navigator.clipboard.writeText( text );
|
||||||
|
console.log( '#' + ele );
|
||||||
|
}
|
||||||
|
|
||||||
import BugsnagPerformance from '//d2wy8f7a9ursnm.cloudfront.net/v1/bugsnag-performance.min.js'
|
function insertTag( box, tag ) {
|
||||||
|
var Field = document.getElementById( box );
|
||||||
|
var currentPos = cursorPos( Field );
|
||||||
|
var val = Field.value;
|
||||||
|
var before = val.substring( 0, currentPos );
|
||||||
|
var after = val.substring( currentPos, val.length );
|
||||||
|
Field.value = before + '(' + tag + ')' + after;
|
||||||
|
}
|
||||||
|
|
||||||
BugsnagPerformance.start({ apiKey: '88045bdc058de51139ac1a47dcd5694b' });
|
function cursorPos( el ) {
|
||||||
|
if ( el.selectionStart ) {
|
||||||
|
return el.selectionStart;
|
||||||
|
} else if ( document.selection ) {
|
||||||
|
el.focus();
|
||||||
|
var r = document.selection.createRange();
|
||||||
|
if ( r == null ) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
var re = el.createTextRange(),
|
||||||
|
rc = re.duplicate();
|
||||||
|
re.moveToBookmark( r.getBookmark() );
|
||||||
|
rc.setEndPoint( 'EndToStart', re );
|
||||||
|
return rc.text.length;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRandomInt(min, max) {
|
||||||
|
const minCeiled = Math.ceil(min);
|
||||||
|
const maxFloored = Math.floor(max);
|
||||||
|
return Math.floor(Math.random() * (maxFloored - minCeiled) + minCeiled);
|
||||||
|
}
|
||||||
|
|
||||||
|
$(document).ready(function() {
|
||||||
|
$('select').each(function() {
|
||||||
|
var selectedValue = $(this).attr('value');
|
||||||
|
if (selectedValue) {
|
||||||
|
$(this).removeAttr('value');
|
||||||
|
$(this).find('option').each(function() {
|
||||||
|
if ($(this).attr('value') === selectedValue) {
|
||||||
|
$(this).prop('selected', true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// with the dynamic footer, you need to adjust the content padding to make sure the footer doesn't overlap the content
|
||||||
|
window.onload = function () {
|
||||||
|
function updateFooterPadding() {
|
||||||
|
var footer = document.querySelector('footer');
|
||||||
|
var container = document.querySelector('.container-fluid.top-pad');
|
||||||
|
if ( ! container ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// footer has no height but its children do!
|
||||||
|
var footerHeight = Array.from(footer.children).reduce((totalHeight, child) => {
|
||||||
|
return totalHeight + child.offsetHeight;
|
||||||
|
}, 0);
|
||||||
|
|
||||||
|
footerHeight += 20; // Add 20px for padding
|
||||||
|
|
||||||
|
// console.error(footerHeight);
|
||||||
|
|
||||||
|
container.style.setProperty('--footer-height', footerHeight + 'px');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update padding on initial load
|
||||||
|
updateFooterPadding();
|
||||||
|
|
||||||
|
// Update padding on window resize
|
||||||
|
window.addEventListener('resize', updateFooterPadding);
|
||||||
|
};
|
@ -12,7 +12,7 @@
|
|||||||
namespace TheTempusProject\Models;
|
namespace TheTempusProject\Models;
|
||||||
|
|
||||||
use TheTempusProject\Bedrock\Functions\Check;
|
use TheTempusProject\Bedrock\Functions\Check;
|
||||||
use TheTempusProject\Canary\Bin\Canary as Debug;
|
use TheTempusProject\Canary\Canary as Debug;
|
||||||
use TheTempusProject\Classes\Permissions;
|
use TheTempusProject\Classes\Permissions;
|
||||||
use TheTempusProject\Bedrock\Classes\Config;
|
use TheTempusProject\Bedrock\Classes\Config;
|
||||||
use TheTempusProject\Bedrock\Functions\Input;
|
use TheTempusProject\Bedrock\Functions\Input;
|
||||||
@ -257,7 +257,7 @@ class Group extends DatabaseModel {
|
|||||||
if ( $group === false ) {
|
if ( $group === false ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$members = self::$db->getPaginated( 'users', [ 'userGroup', '=', $id ] );
|
$members = self::$db->get( 'users', [ 'userGroup', '=', $id ] );
|
||||||
if ( !$members->count() ) {
|
if ( !$members->count() ) {
|
||||||
Debug::info( "list members: Could not find anyone in group: $id" );
|
Debug::info( "list members: Could not find anyone in group: $id" );
|
||||||
return false;
|
return false;
|
||||||
|
@ -13,10 +13,10 @@ namespace TheTempusProject\Models;
|
|||||||
|
|
||||||
use TheTempusProject\Bedrock\Functions\Check;
|
use TheTempusProject\Bedrock\Functions\Check;
|
||||||
use TheTempusProject\Bedrock\Classes\Config;
|
use TheTempusProject\Bedrock\Classes\Config;
|
||||||
use TheTempusProject\Canary\Classes\CustomException;
|
use TheTempusProject\Bedrock\Classes\CustomException;
|
||||||
use TheTempusProject\TheTempusProject as App;
|
use TheTempusProject\TheTempusProject as App;
|
||||||
use TheTempusProject\Classes\DatabaseModel;
|
use TheTempusProject\Classes\DatabaseModel;
|
||||||
use TheTempusProject\Canary\Bin\Canary as Debug;
|
use TheTempusProject\Canary\Canary as Debug;
|
||||||
|
|
||||||
class Log extends DatabaseModel {
|
class Log extends DatabaseModel {
|
||||||
public $tableName = 'logs';
|
public $tableName = 'logs';
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
namespace TheTempusProject\Models;
|
namespace TheTempusProject\Models;
|
||||||
|
|
||||||
use TheTempusProject\Bedrock\Functions\Check;
|
use TheTempusProject\Bedrock\Functions\Check;
|
||||||
use TheTempusProject\Canary\Bin\Canary as Debug;
|
use TheTempusProject\Canary\Canary as Debug;
|
||||||
use TheTempusProject\Classes\DatabaseModel;
|
use TheTempusProject\Classes\DatabaseModel;
|
||||||
|
|
||||||
class Routes extends DatabaseModel {
|
class Routes extends DatabaseModel {
|
||||||
|
@ -16,7 +16,7 @@ namespace TheTempusProject\Models;
|
|||||||
|
|
||||||
use TheTempusProject\Bedrock\Functions\Check;
|
use TheTempusProject\Bedrock\Functions\Check;
|
||||||
use TheTempusProject\Bedrock\Functions\Code;
|
use TheTempusProject\Bedrock\Functions\Code;
|
||||||
use TheTempusProject\Canary\Bin\Canary as Debug;
|
use TheTempusProject\Canary\Canary as Debug;
|
||||||
use TheTempusProject\Bedrock\Functions\Session;
|
use TheTempusProject\Bedrock\Functions\Session;
|
||||||
use TheTempusProject\Bedrock\Functions\Cookie;
|
use TheTempusProject\Bedrock\Functions\Cookie;
|
||||||
use TheTempusProject\Classes\DatabaseModel;
|
use TheTempusProject\Classes\DatabaseModel;
|
||||||
|
@ -16,12 +16,12 @@
|
|||||||
namespace TheTempusProject\Models;
|
namespace TheTempusProject\Models;
|
||||||
|
|
||||||
use TheTempusProject\Bedrock\Functions\Check;
|
use TheTempusProject\Bedrock\Functions\Check;
|
||||||
use TheTempusProject\Canary\Bin\Canary as Debug;
|
use TheTempusProject\Canary\Canary as Debug;
|
||||||
use TheTempusProject\Bedrock\Functions\Hash;
|
use TheTempusProject\Bedrock\Functions\Hash;
|
||||||
use TheTempusProject\Bedrock\Functions\Session;
|
use TheTempusProject\Bedrock\Functions\Session;
|
||||||
use TheTempusProject\Bedrock\Functions\Code;
|
use TheTempusProject\Bedrock\Functions\Code;
|
||||||
use TheTempusProject\Bedrock\Classes\Config;
|
use TheTempusProject\Bedrock\Classes\Config;
|
||||||
use TheTempusProject\Canary\Classes\CustomException;
|
use TheTempusProject\Bedrock\Classes\CustomException;
|
||||||
use TheTempusProject\Classes\Email;
|
use TheTempusProject\Classes\Email;
|
||||||
use TheTempusProject\Classes\DatabaseModel;
|
use TheTempusProject\Classes\DatabaseModel;
|
||||||
use TheTempusProject\Classes\Preferences;
|
use TheTempusProject\Classes\Preferences;
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
namespace TheTempusProject\Controllers;
|
namespace TheTempusProject\Controllers;
|
||||||
|
|
||||||
use TheTempusProject\Bedrock\Functions\Check;
|
use TheTempusProject\Bedrock\Functions\Check;
|
||||||
use TheTempusProject\Canary\Bin\Canary as Debug;
|
use TheTempusProject\Canary\Canary as Debug;
|
||||||
use TheTempusProject\Bedrock\Functions\Input;
|
use TheTempusProject\Bedrock\Functions\Input;
|
||||||
use TheTempusProject\Houdini\Classes\Components;
|
use TheTempusProject\Houdini\Classes\Components;
|
||||||
use TheTempusProject\Houdini\Classes\Issues;
|
use TheTempusProject\Houdini\Classes\Issues;
|
||||||
|
@ -12,19 +12,16 @@
|
|||||||
*/
|
*/
|
||||||
namespace TheTempusProject\Models;
|
namespace TheTempusProject\Models;
|
||||||
|
|
||||||
use TheTempusProject\Canary\Bin\Canary as Debug;
|
use TheTempusProject\Canary\Canary as Debug;
|
||||||
use TheTempusProject\Bedrock\Functions\Check;
|
use TheTempusProject\Bedrock\Functions\Check;
|
||||||
use TheTempusProject\Bedrock\Functions\Sanitize;
|
use TheTempusProject\Bedrock\Functions\Sanitize;
|
||||||
use TheTempusProject\Classes\DatabaseModel;
|
use TheTempusProject\Classes\DatabaseModel;
|
||||||
use TheTempusProject\TheTempusProject as App;
|
use TheTempusProject\TheTempusProject as App;
|
||||||
use TheTempusProject\Canary\Classes\CustomException;
|
use TheTempusProject\Bedrock\Classes\CustomException;
|
||||||
use TheTempusProject\Houdini\Classes\Filters;
|
use TheTempusProject\Houdini\Classes\Filters;
|
||||||
use TheTempusProject\Plugins\Comments as CommentPlugin;
|
|
||||||
use TheTempusProject\Models\Comments;
|
|
||||||
|
|
||||||
class Posts extends DatabaseModel {
|
class Posts extends DatabaseModel {
|
||||||
public $tableName = 'posts';
|
public $tableName = 'posts';
|
||||||
public static $comments = false;
|
|
||||||
|
|
||||||
public $databaseMatrix = [
|
public $databaseMatrix = [
|
||||||
[ 'author', 'int', '11' ],
|
[ 'author', 'int', '11' ],
|
||||||
@ -35,14 +32,19 @@ class Posts extends DatabaseModel {
|
|||||||
[ 'content', 'text', '' ],
|
[ 'content', 'text', '' ],
|
||||||
];
|
];
|
||||||
|
|
||||||
|
public $resourceMatrix = [
|
||||||
|
[
|
||||||
|
'title' => 'Welcome',
|
||||||
|
'content' => '<p>This is just a simple message to say thank you for installing The Tempus Project. If you have any questions you can find everything through our website <a href="https://TheTempusProject.com">here</a>.</p>',
|
||||||
|
'author' => 1,
|
||||||
|
'created' => '{time}',
|
||||||
|
'edited' => '{time}',
|
||||||
|
'draft' => 0,
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
public function __construct() {
|
public function __construct() {
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
if ( class_exists( 'TheTempusProject\Plugins\Comments' ) ) {
|
|
||||||
$comments = new CommentPlugin;
|
|
||||||
if ( $comments->checkEnabled() ) {
|
|
||||||
self::$comments = new Comments;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function newPost( $title, $post, $draft ) {
|
public function newPost( $title, $post, $draft ) {
|
||||||
@ -159,9 +161,6 @@ class Posts extends DatabaseModel {
|
|||||||
if ( isset( $params['stripHtml'] ) && $params['stripHtml'] === true ) {
|
if ( isset( $params['stripHtml'] ) && $params['stripHtml'] === true ) {
|
||||||
$instance->contentSummary = strip_tags( $instance->content );
|
$instance->contentSummary = strip_tags( $instance->content );
|
||||||
}
|
}
|
||||||
if ( self::$comments !== false ) {
|
|
||||||
$instance->commentCount = self::$comments->count( 'blog', $instance->ID );
|
|
||||||
}
|
|
||||||
$instance->content = Filters::applyOne( 'mentions.0', $instance->content, true );
|
$instance->content = Filters::applyOne( 'mentions.0', $instance->content, true );
|
||||||
$instance->content = Filters::applyOne( 'hashtags.0', $instance->content, true );
|
$instance->content = Filters::applyOne( 'hashtags.0', $instance->content, true );
|
||||||
$out[] = $instance;
|
$out[] = $instance;
|
||||||
|
@ -38,18 +38,6 @@ class Blog extends Plugin {
|
|||||||
'url' => '{ROOT_URL}blog/index',
|
'url' => '{ROOT_URL}blog/index',
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
public $resourceMatrix = [
|
|
||||||
'posts' => [
|
|
||||||
[
|
|
||||||
'title' => 'Welcome',
|
|
||||||
'content' => '<p>This is just a simple message to say thank you for installing The Tempus Project. If you have any questions you can find everything through our website <a href="https://TheTempusProject.com">here</a>.</p>',
|
|
||||||
'author' => 1,
|
|
||||||
'created' => '{time}',
|
|
||||||
'edited' => '{time}',
|
|
||||||
'draft' => 0,
|
|
||||||
],
|
|
||||||
],
|
|
||||||
];
|
|
||||||
public $posts;
|
public $posts;
|
||||||
|
|
||||||
public function __construct( $load = false ) {
|
public function __construct( $load = false ) {
|
||||||
|
402
app/plugins/bookmarks/controllers/bookmarks.php
Normal file
402
app/plugins/bookmarks/controllers/bookmarks.php
Normal file
@ -0,0 +1,402 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* app/plugins/bugreport/controllers/bugreport.php
|
||||||
|
*
|
||||||
|
* This is the bug reports controller.
|
||||||
|
*
|
||||||
|
* @package TP BugReports
|
||||||
|
* @version 3.0
|
||||||
|
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||||
|
* @link https://TheTempusProject.com
|
||||||
|
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||||
|
*/
|
||||||
|
namespace TheTempusProject\Controllers;
|
||||||
|
|
||||||
|
use TheTempusProject\Hermes\Functions\Redirect;
|
||||||
|
use TheTempusProject\Bedrock\Functions\Check;
|
||||||
|
use TheTempusProject\Bedrock\Functions\Input;
|
||||||
|
use TheTempusProject\Bedrock\Functions\Session;
|
||||||
|
use TheTempusProject\Houdini\Classes\Issues;
|
||||||
|
use TheTempusProject\Houdini\Classes\Views;
|
||||||
|
use TheTempusProject\Classes\Controller;
|
||||||
|
use TheTempusProject\Classes\Forms;
|
||||||
|
use TheTempusProject\Models\Bookmarks as Bookmark;
|
||||||
|
use TheTempusProject\Models\Folders;
|
||||||
|
use TheTempusProject\TheTempusProject as App;
|
||||||
|
use TheTempusProject\Houdini\Classes\Components;
|
||||||
|
use TheTempusProject\Houdini\Classes\Forms as HoudiniForms;
|
||||||
|
use TheTempusProject\Houdini\Classes\Navigation;
|
||||||
|
|
||||||
|
class Bookmarks extends Controller {
|
||||||
|
protected static $bookmarks;
|
||||||
|
protected static $folders;
|
||||||
|
|
||||||
|
public function __construct() {
|
||||||
|
parent::__construct();
|
||||||
|
if ( !App::$isLoggedIn ) {
|
||||||
|
Session::flash( 'notice', 'You must be logged in to create or manage bookmarks.' );
|
||||||
|
return Redirect::home();
|
||||||
|
}
|
||||||
|
self::$bookmarks = new Bookmark;
|
||||||
|
self::$folders = new Folders;
|
||||||
|
self::$title = 'Bookmarks - {SITENAME}';
|
||||||
|
self::$pageDescription = 'Add and save url bookmarks here.';
|
||||||
|
|
||||||
|
$folderTabs = Views::simpleView( 'bookmarks.nav.folderTabs' );
|
||||||
|
if ( stripos( Input::get('url'), 'bookmarks/bookmarks' ) !== false ) {
|
||||||
|
$tabsView = Navigation::activePageSelect( $folderTabs, '/bookmarks/folders/', false, true );
|
||||||
|
$userFolderTabs = Views::simpleView('bookmarks.nav.userFolderTabs', self::$folders->simpleObjectByUser(true) );
|
||||||
|
$userFolderTabsView = Navigation::activePageSelect( $userFolderTabs, Input::get( 'url' ), false, true );
|
||||||
|
} else {
|
||||||
|
$tabsView = Navigation::activePageSelect( $folderTabs, Input::get( 'url' ), false, true );
|
||||||
|
$userFolderTabsView = '';
|
||||||
|
}
|
||||||
|
Components::set( 'userFolderTabs', $userFolderTabsView );
|
||||||
|
Views::raw( $tabsView );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function index() {
|
||||||
|
$bookmarks = self::$bookmarks->noFolder();
|
||||||
|
$folders = self::$folders->byUser();
|
||||||
|
|
||||||
|
$panelArray = [];
|
||||||
|
if ( !empty( $folders ) ) {
|
||||||
|
foreach ( $folders as $folder ) {
|
||||||
|
$panel = new \stdClass();
|
||||||
|
$folderObject = new \stdClass();
|
||||||
|
$folderObject->bookmarks = self::$bookmarks->byFolder( $folder->ID );
|
||||||
|
$folderObject->ID = $folder->ID;
|
||||||
|
$folderObject->title = $folder->title;
|
||||||
|
$folderObject->color = $folder->color;
|
||||||
|
$folderObject->bookmarkListRows = Views::simpleView( 'bookmarks.components.bookmarkListRows', $folderObject->bookmarks );
|
||||||
|
$panel->panel = Views::simpleView( 'bookmarks.components.bookmarkListPanel', [$folderObject] );
|
||||||
|
$panelArray[] = $panel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Components::set( 'foldersList', Views::simpleView( 'bookmarks.folders.list', $folders ) );
|
||||||
|
Components::set( 'folderPanels', Views::simpleView( 'bookmarks.components.folderPanelList', $panelArray ) );
|
||||||
|
Components::set( 'bookmarksList', Views::simpleView( 'bookmarks.bookmarks.list', $bookmarks ) );
|
||||||
|
return Views::view( 'bookmarks.dash' );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bookmarks
|
||||||
|
*/
|
||||||
|
public function bookmark( $id = 0 ) {
|
||||||
|
$bookmark = self::$bookmarks->findById( $id );
|
||||||
|
if ( $bookmark == false ) {
|
||||||
|
Session::flash( 'error', 'Bookmark not found.' );
|
||||||
|
return Redirect::to( 'bookmarks/index' );
|
||||||
|
}
|
||||||
|
if ( $bookmark->createdBy != App::$activeUser->ID ) {
|
||||||
|
Session::flash( 'error', 'You do not have permission to modify this bookmark.' );
|
||||||
|
return Redirect::to( 'bookmarks/index' );
|
||||||
|
}
|
||||||
|
Navigation::setCrumbComponent( 'BookmarkBreadCrumbs', 'bookmarks/bookmark/' . $id );
|
||||||
|
return Views::view( 'bookmarks.bookmarks.view', $bookmark );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function bookmarks( $id = null ) {
|
||||||
|
$folder = self::$folders->findById( $id );
|
||||||
|
if ( $folder == false ) {
|
||||||
|
Session::flash( 'error', 'Folder not found.' );
|
||||||
|
return Redirect::to( 'bookmarks/index' );
|
||||||
|
}
|
||||||
|
if ( $folder->createdBy != App::$activeUser->ID ) {
|
||||||
|
Session::flash( 'error', 'You do not have permission to view this folder.' );
|
||||||
|
return Redirect::to( 'bookmarks/index' );
|
||||||
|
}
|
||||||
|
Navigation::setCrumbComponent( 'BookmarkBreadCrumbs', 'bookmarks/bookmarks/' . $id );
|
||||||
|
|
||||||
|
|
||||||
|
$bookmarks = self::$bookmarks->noFolder();
|
||||||
|
|
||||||
|
$panelArray = [];
|
||||||
|
$panel = new \stdClass();
|
||||||
|
$folderObject = new \stdClass();
|
||||||
|
$folderObject->bookmarks = self::$bookmarks->byFolder( $folder->ID );
|
||||||
|
$folderObject->ID = $folder->ID;
|
||||||
|
$folderObject->title = $folder->title;
|
||||||
|
$folderObject->color = $folder->color;
|
||||||
|
$folderObject->bookmarkListRows = Views::simpleView( 'bookmarks.components.bookmarkListRows', $folderObject->bookmarks );
|
||||||
|
$panel->panel = Views::simpleView( 'bookmarks.components.bookmarkListPanel', [$folderObject] );
|
||||||
|
$panelArray[] = $panel;
|
||||||
|
|
||||||
|
return Views::view( 'bookmarks.components.folderPanelList', $panelArray );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function createBookmark( $id = null ) {
|
||||||
|
$folderID = Input::get('folder_id') ? Input::get('folder_id') : $id;
|
||||||
|
$folderID = Input::post('folder_id') ? Input::post('folder_id') : $id;
|
||||||
|
$folderSelect = HoudiniForms::getFormFieldHtml( 'folder_id', 'Folder', 'select', $folderID, self::$folders->simpleByUser() );
|
||||||
|
Components::set( 'folderSelect', $folderSelect );
|
||||||
|
|
||||||
|
if ( ! Input::exists() ) {
|
||||||
|
return Views::view( 'bookmarks.bookmarks.create' );
|
||||||
|
}
|
||||||
|
if ( ! Forms::check( 'createBookmark' ) ) {
|
||||||
|
Issues::add( 'error', [ 'There was an error with your form.' => Check::userErrors() ] );
|
||||||
|
return Views::view( 'bookmarks.bookmarks.create' );
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = self::$bookmarks->create(
|
||||||
|
Input::post('title'),
|
||||||
|
Input::post('url'),
|
||||||
|
$folderID,
|
||||||
|
Input::post('description'),
|
||||||
|
Input::post('color'),
|
||||||
|
Input::post('privacy'),
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( ! $result ) {
|
||||||
|
Issues::add( 'error', [ 'There was an error creating your bookmark.' => Check::userErrors() ] );
|
||||||
|
return Views::view( 'bookmarks.bookmarks.create' );
|
||||||
|
}
|
||||||
|
self::$bookmarks->refreshInfo( $result );
|
||||||
|
Session::flash( 'success', 'Your Bookmark has been created.' );
|
||||||
|
Redirect::to( 'bookmarks/bookmarks/'. $folderID );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function editBookmark( $id = null ) {
|
||||||
|
$folderID = Input::exists('folder_id') ? Input::post('folder_id') : '';
|
||||||
|
|
||||||
|
$bookmark = self::$bookmarks->findById( $id );
|
||||||
|
if ( $bookmark == false ) {
|
||||||
|
Issues::add( 'error', 'Bookmark not found.' );
|
||||||
|
return Redirect::to( 'bookmarks/index' );
|
||||||
|
}
|
||||||
|
if ( $bookmark->createdBy != App::$activeUser->ID ) {
|
||||||
|
Issues::add( 'error', 'You do not have permission to modify this bookmark.' );
|
||||||
|
return Redirect::to( 'bookmarks/index' );
|
||||||
|
}
|
||||||
|
if ( empty( $folderID ) ) {
|
||||||
|
$folderID = $bookmark->folderID;
|
||||||
|
}
|
||||||
|
|
||||||
|
$folderSelect = HoudiniForms::getFormFieldHtml( 'folder_id', 'Folder', 'select', $folderID, self::$folders->simpleByUser() );
|
||||||
|
Components::set( 'folderSelect', $folderSelect );
|
||||||
|
Components::set( 'color', $bookmark->color );
|
||||||
|
|
||||||
|
if ( ! Input::exists( 'submit' ) ) {
|
||||||
|
return Views::view( 'bookmarks.bookmarks.edit', $bookmark );
|
||||||
|
}
|
||||||
|
if ( ! Forms::check( 'editBookmark' ) ) {
|
||||||
|
Issues::add( 'error', [ 'There was an error updating your bookmark.' => Check::userErrors() ] );
|
||||||
|
return Views::view( 'bookmarks.bookmarks.edit', $bookmark );
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = self::$bookmarks->update(
|
||||||
|
$id,
|
||||||
|
Input::post('title'),
|
||||||
|
Input::post('url'),
|
||||||
|
$folderID,
|
||||||
|
Input::post('description'),
|
||||||
|
Input::post('color'),
|
||||||
|
Input::post('privacy'),
|
||||||
|
);
|
||||||
|
if ( ! $result ) {
|
||||||
|
Issues::add( 'error', [ 'There was an error updating your bookmark.' => Check::userErrors() ] );
|
||||||
|
return Views::view( 'bookmarks.bookmarks.edit', $bookmark );
|
||||||
|
}
|
||||||
|
Session::flash( 'success', 'Your Bookmark has been updated.' );
|
||||||
|
Redirect::to( 'bookmarks/folders/'. $bookmark->folderID );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function deleteBookmark( $id = null ) {
|
||||||
|
$bookmark = self::$bookmarks->findById( $id );
|
||||||
|
if ( $bookmark == false ) {
|
||||||
|
Issues::add( 'error', 'Bookmark not found.' );
|
||||||
|
return $this->index();
|
||||||
|
}
|
||||||
|
if ( $bookmark->createdBy != App::$activeUser->ID ) {
|
||||||
|
Issues::add( 'error', 'You do not have permission to modify this bookmark.' );
|
||||||
|
return $this->index();
|
||||||
|
}
|
||||||
|
$result = self::$bookmarks->delete( $id );
|
||||||
|
if ( !$result ) {
|
||||||
|
Session::flash( 'error', 'There was an error deleting the bookmark(s)' );
|
||||||
|
} else {
|
||||||
|
Session::flash( 'success', 'Bookmark deleted' );
|
||||||
|
}
|
||||||
|
Redirect::to( 'bookmarks/folders/'. $bookmark->folderID );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Folders
|
||||||
|
*/
|
||||||
|
public function folders( $id = null) {
|
||||||
|
$folder = self::$folders->findById( $id );
|
||||||
|
if ( $folder == false ) {
|
||||||
|
$folders = self::$folders->byUser();
|
||||||
|
return Views::view( 'bookmarks.folders.list', $folders );
|
||||||
|
}
|
||||||
|
if ( $folder->createdBy != App::$activeUser->ID ) {
|
||||||
|
Session::flash( 'error', 'You do not have permission to view this folder.' );
|
||||||
|
return Redirect::to( 'bookmarks/index' );
|
||||||
|
}
|
||||||
|
Navigation::setCrumbComponent( 'BookmarkBreadCrumbs', 'bookmarks/folders/' . $id );
|
||||||
|
return Views::view( 'bookmarks.folders.view', $folder );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function createFolder( $id = 0 ) {
|
||||||
|
$folderID = Input::exists('folder_id') ? Input::post('folder_id') : $id;
|
||||||
|
$folders = self::$folders->simpleByUser();
|
||||||
|
if ( ! empty( $folders ) ) {
|
||||||
|
$folderSelect = HoudiniForms::getFormFieldHtml( 'folder_id', 'Folder', 'select', $folderID, $folders );
|
||||||
|
} else {
|
||||||
|
$folderSelect = '';
|
||||||
|
}
|
||||||
|
Components::set( 'folderSelect', $folderSelect );
|
||||||
|
if ( ! Input::exists() ) {
|
||||||
|
return Views::view( 'bookmarks.folders.create' );
|
||||||
|
}
|
||||||
|
if ( ! Forms::check( 'createFolder' ) ) {
|
||||||
|
Issues::add( 'error', [ 'There was an error creating your folder.' => Check::userErrors() ] );
|
||||||
|
return Views::view( 'bookmarks.folders.create' );
|
||||||
|
}
|
||||||
|
$folder = self::$folders->create( Input::post('title'), $folderID, Input::post('description'), Input::post('color'), Input::post('privacy') );
|
||||||
|
if ( ! $folder ) {
|
||||||
|
return Views::view( 'bookmarks.folders.create' );
|
||||||
|
}
|
||||||
|
Session::flash( 'success', 'Your Folder has been created.' );
|
||||||
|
Redirect::to( 'bookmarks/folders' );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function editFolder( $id = null ) {
|
||||||
|
$folder = self::$folders->findById( $id );
|
||||||
|
|
||||||
|
if ( $folder == false ) {
|
||||||
|
Issues::add( 'error', 'Folder not found.' );
|
||||||
|
return $this->index();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( $folder->createdBy != App::$activeUser->ID ) {
|
||||||
|
Issues::add( 'error', 'You do not have permission to modify this folder.' );
|
||||||
|
return $this->index();
|
||||||
|
}
|
||||||
|
$folderID = ( false === Input::exists('folder_id') ) ? $folder->ID : Input::post('folder_id');
|
||||||
|
|
||||||
|
$folderSelect = HoudiniForms::getFormFieldHtml( 'folder_id', 'Folder', 'select', $folderID, self::$folders->simpleByUser() );
|
||||||
|
Components::set( 'folderSelect', $folderSelect );
|
||||||
|
Components::set( 'color', $folder->color );
|
||||||
|
|
||||||
|
if ( ! Input::exists( 'submit' ) ) {
|
||||||
|
return Views::view( 'bookmarks.folders.edit', $folder );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !Forms::check( 'editFolder' ) ) {
|
||||||
|
Issues::add( 'error', [ 'There was an error editing your folder.' => Check::userErrors() ] );
|
||||||
|
return Views::view( 'bookmarks.folders.edit', $folder );
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = self::$folders->update( $id, Input::post('title'), $folderID, Input::post('description'), Input::post('color'), Input::post('privacy') );
|
||||||
|
if ( !$result ) {
|
||||||
|
Issues::add( 'error', [ 'There was an error updating your folder.' => Check::userErrors() ] );
|
||||||
|
return Views::view( 'bookmarks.folders.edit', $folder );
|
||||||
|
}
|
||||||
|
Session::flash( 'success', 'Your Folder has been updated.' );
|
||||||
|
Redirect::to( 'bookmarks/folders/'. $folder->ID );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function deleteFolder( $id = null ) {
|
||||||
|
$folder = self::$folders->findById( $id );
|
||||||
|
if ( $folder == false ) {
|
||||||
|
Issues::add( 'error', 'Folder not found.' );
|
||||||
|
return $this->index();
|
||||||
|
}
|
||||||
|
if ( $folder->createdBy != App::$activeUser->ID ) {
|
||||||
|
Issues::add( 'error', 'You do not have permission to modify this folder.' );
|
||||||
|
return $this->index();
|
||||||
|
}
|
||||||
|
$results = self::$bookmarks->deleteByFolder( $id );
|
||||||
|
$result = self::$folders->delete( $id );
|
||||||
|
if ( !$result ) {
|
||||||
|
Session::flash( 'error', 'There was an error deleting the folder(s)' );
|
||||||
|
} else {
|
||||||
|
Session::flash( 'success', 'Folder deleted' );
|
||||||
|
}
|
||||||
|
Redirect::to( 'bookmarks/folders' );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Functionality
|
||||||
|
*/
|
||||||
|
public function hideBookmark( $id = null ) {
|
||||||
|
$bookmark = self::$bookmarks->findById( $id );
|
||||||
|
if ( $bookmark == false ) {
|
||||||
|
Session::flash( 'error', 'Bookmark not found.' );
|
||||||
|
return Redirect::to( 'bookmarks/index' );
|
||||||
|
}
|
||||||
|
if ( $bookmark->createdBy != App::$activeUser->ID ) {
|
||||||
|
Session::flash( 'error', 'You do not have permission to modify this bookmark.' );
|
||||||
|
return Redirect::to( 'bookmarks/index' );
|
||||||
|
}
|
||||||
|
self::$bookmarks->hide( $id );
|
||||||
|
Session::flash( 'success', 'Bookmark hidden.' );
|
||||||
|
return Redirect::to( 'bookmarks/index' );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function archiveBookmark( $id = null ) {
|
||||||
|
$bookmark = self::$bookmarks->findById( $id );
|
||||||
|
if ( $bookmark == false ) {
|
||||||
|
Session::flash( 'error', 'Bookmark not found.' );
|
||||||
|
return Redirect::to( 'bookmarks/index' );
|
||||||
|
}
|
||||||
|
if ( $bookmark->createdBy != App::$activeUser->ID ) {
|
||||||
|
Session::flash( 'error', 'You do not have permission to modify this bookmark.' );
|
||||||
|
return Redirect::to( 'bookmarks/index' );
|
||||||
|
}
|
||||||
|
self::$bookmarks->archive( $id );
|
||||||
|
Session::flash( 'success', 'Bookmark archived.' );
|
||||||
|
return Redirect::to( 'bookmarks/index' );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function showBookmark( $id = null ) {
|
||||||
|
$bookmark = self::$bookmarks->findById( $id );
|
||||||
|
if ( $bookmark == false ) {
|
||||||
|
Session::flash( 'error', 'Bookmark not found.' );
|
||||||
|
return Redirect::to( 'bookmarks/index' );
|
||||||
|
}
|
||||||
|
if ( $bookmark->createdBy != App::$activeUser->ID ) {
|
||||||
|
Session::flash( 'error', 'You do not have permission to modify this bookmark.' );
|
||||||
|
return Redirect::to( 'bookmarks/index' );
|
||||||
|
}
|
||||||
|
self::$bookmarks->show( $id );
|
||||||
|
Session::flash( 'success', 'Bookmark shown.' );
|
||||||
|
return Redirect::to( 'bookmarks/index' );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function unarchiveBookmark( $id = null ) {
|
||||||
|
$bookmark = self::$bookmarks->findById( $id );
|
||||||
|
if ( $bookmark == false ) {
|
||||||
|
Session::flash( 'error', 'Bookmark not found.' );
|
||||||
|
return Redirect::to( 'bookmarks/index' );
|
||||||
|
}
|
||||||
|
if ( $bookmark->createdBy != App::$activeUser->ID ) {
|
||||||
|
Session::flash( 'error', 'You do not have permission to modify this bookmark.' );
|
||||||
|
return Redirect::to( 'bookmarks/index' );
|
||||||
|
}
|
||||||
|
self::$bookmarks->unarchive( $id );
|
||||||
|
Session::flash( 'success', 'Bookmark un-archived.' );
|
||||||
|
return Redirect::to( 'bookmarks/index' );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function refreshBookmark( $id = null ) {
|
||||||
|
$bookmark = self::$bookmarks->findById( $id );
|
||||||
|
if ( $bookmark == false ) {
|
||||||
|
Session::flash( 'error', 'Bookmark not found.' );
|
||||||
|
return Redirect::to( 'bookmarks/index' );
|
||||||
|
}
|
||||||
|
if ( $bookmark->createdBy != App::$activeUser->ID ) {
|
||||||
|
Session::flash( 'error', 'You do not have permission to modify this bookmark.' );
|
||||||
|
return Redirect::to( 'bookmarks/index' );
|
||||||
|
}
|
||||||
|
$info = self::$bookmarks->refreshInfo( $id );
|
||||||
|
if ( false == $info ) {
|
||||||
|
Session::flash( 'error', 'Issue refreshing your bookmark.' );
|
||||||
|
return Redirect::to( 'bookmarks/bookmark/' . $bookmark->ID );
|
||||||
|
}
|
||||||
|
Session::flash( 'success', 'Bookmark data refreshed.' );
|
||||||
|
return Redirect::to( 'bookmarks/bookmark/' . $bookmark->ID );
|
||||||
|
}
|
||||||
|
}
|
122
app/plugins/bookmarks/forms.php
Normal file
122
app/plugins/bookmarks/forms.php
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* app/plugins/bookmarks/forms.php
|
||||||
|
*
|
||||||
|
* This houses all of the form checking functions for this plugin.
|
||||||
|
*
|
||||||
|
* @package TP Bookmarks
|
||||||
|
* @version 3.0
|
||||||
|
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||||
|
* @link https://TheTempusProject.com
|
||||||
|
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||||
|
*/
|
||||||
|
namespace TheTempusProject\Plugins\Bookmarks;
|
||||||
|
|
||||||
|
use TheTempusProject\Bedrock\Functions\Input;
|
||||||
|
use TheTempusProject\Bedrock\Functions\Check;
|
||||||
|
use TheTempusProject\Classes\Forms;
|
||||||
|
|
||||||
|
class BookmarksForms extends Forms {
|
||||||
|
/**
|
||||||
|
* Adds these functions to the form list.
|
||||||
|
*/
|
||||||
|
public function __construct() {
|
||||||
|
self::addHandler( 'createBookmark', __CLASS__, 'createBookmark' );
|
||||||
|
self::addHandler( 'createFolder', __CLASS__, 'createFolder' );
|
||||||
|
self::addHandler( 'editBookmark', __CLASS__, 'editBookmark' );
|
||||||
|
self::addHandler( 'editFolder', __CLASS__, 'editFolder' );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function createBookmark() {
|
||||||
|
// if ( ! Input::exists( 'title' ) ) {
|
||||||
|
// Check::addUserError( 'You must include a title.' );
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
if ( ! Input::exists( 'url' ) ) {
|
||||||
|
Check::addUserError( 'You must include a url.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// if ( ! Input::exists( 'color' ) ) {
|
||||||
|
// Check::addUserError( 'You must include a color.' );
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
// if ( ! Input::exists( 'privacy' ) ) {
|
||||||
|
// Check::addUserError( 'You must include a privacy.' );
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
// if ( !self::token() ) {
|
||||||
|
// Check::addUserError( 'token - comment out later.' );
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function createFolder() {
|
||||||
|
if ( ! Input::exists( 'title' ) ) {
|
||||||
|
Check::addUserError( 'You must include a title.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// if ( ! Input::exists( 'color' ) ) {
|
||||||
|
// Check::addUserError( 'You must include a color.' );
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
// if ( ! Input::exists( 'privacy' ) ) {
|
||||||
|
// Check::addUserError( 'You must include a privacy.' );
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
// if ( ! self::token() ) {
|
||||||
|
// Check::addUserError( 'token - comment out later.' );
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function editBookmark() {
|
||||||
|
// if ( ! Input::exists( 'title' ) ) {
|
||||||
|
// Check::addUserError( 'You must include a title.' );
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
if ( ! Input::exists( 'url' ) ) {
|
||||||
|
Check::addUserError( 'You must include a url.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// if ( ! Input::exists( 'color' ) ) {
|
||||||
|
// Check::addUserError( 'You must include a color.' );
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
// if ( ! Input::exists( 'privacy' ) ) {
|
||||||
|
// Check::addUserError( 'You must include a privacy.' );
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
// if ( !self::token() ) {
|
||||||
|
// Check::addUserError( 'token - comment out later.' );
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function editFolder() {
|
||||||
|
if ( ! Input::exists( 'submit' ) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( ! Input::exists( 'title' ) ) {
|
||||||
|
Check::addUserError( 'You must include a title.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// if ( ! Input::exists( 'color' ) ) {
|
||||||
|
// Check::addUserError( 'You must include a color.' );
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
// if ( ! Input::exists( 'privacy' ) ) {
|
||||||
|
// Check::addUserError( 'You must include a privacy.' );
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
// if ( !self::token() ) {
|
||||||
|
// Check::addUserError( 'token - comment out later.' );
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
new BookmarksForms;
|
149
app/plugins/bookmarks/models/bookmarkViews.php
Normal file
149
app/plugins/bookmarks/models/bookmarkViews.php
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* app/plugins/bookmarks/models/bookmarkViews.php
|
||||||
|
*
|
||||||
|
* This class is used for the manipulation of the bookmark_views database table.
|
||||||
|
*
|
||||||
|
* @package TP Bookmarks
|
||||||
|
* @version 3.0
|
||||||
|
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||||
|
* @link https://TheTempusProject.com
|
||||||
|
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||||
|
*/
|
||||||
|
namespace TheTempusProject\Models;
|
||||||
|
|
||||||
|
use TheTempusProject\Bedrock\Classes\Config;
|
||||||
|
use TheTempusProject\Bedrock\Functions\Check;
|
||||||
|
use TheTempusProject\Canary\Canary as Debug;
|
||||||
|
use TheTempusProject\Classes\DatabaseModel;
|
||||||
|
use TheTempusProject\TheTempusProject as App;
|
||||||
|
use TheTempusProject\Houdini\Classes\Filters;
|
||||||
|
use TheTempusProject\Bedrock\Classes\CustomException;
|
||||||
|
|
||||||
|
class BookmarkViews extends DatabaseModel {
|
||||||
|
public $tableName = 'bookmark_views';
|
||||||
|
public $databaseMatrix = [
|
||||||
|
[ 'title', 'varchar', '256' ],
|
||||||
|
[ 'description', 'text', '' ],
|
||||||
|
[ 'privacy', 'varchar', '48' ],
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[ 'createdBy', 'int', '11' ],
|
||||||
|
[ 'createdAt', 'int', '11' ],
|
||||||
|
[ 'updatedAt', 'int', '11' ],
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The model constructor.
|
||||||
|
*/
|
||||||
|
public function __construct() {
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function create( $title, $description = '', $privacy = 'private' ) {
|
||||||
|
if ( ! Check::dataTitle( $title ) ) {
|
||||||
|
Debug::info( 'Views: illegal title.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$fields = [
|
||||||
|
'title' => $title,
|
||||||
|
'description' => $description,
|
||||||
|
'privacy' => $privacy,
|
||||||
|
'createdBy' => App::$activeUser->ID,
|
||||||
|
'createdAt' => time(),
|
||||||
|
];
|
||||||
|
if ( ! self::$db->insert( $this->tableName, $fields ) ) {
|
||||||
|
new CustomException( 'viewCreate' );
|
||||||
|
Debug::error( "Views: not created " . var_export($fields,true) );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return self::$db->lastId();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update( $id, $title, $description = '', $privacy = 'private' ) {
|
||||||
|
if ( !Check::id( $id ) ) {
|
||||||
|
Debug::info( 'Views: illegal ID.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !Check::dataTitle( $title ) ) {
|
||||||
|
Debug::info( 'Views: illegal title.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$fields = [
|
||||||
|
'title' => $title,
|
||||||
|
'description' => $description,
|
||||||
|
'privacy' => $privacy,
|
||||||
|
];
|
||||||
|
if ( !self::$db->update( $this->tableName, $id, $fields ) ) {
|
||||||
|
new CustomException( 'viewUpdate' );
|
||||||
|
Debug::error( "Views: $id not updated: $fields" );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function byUser( $limit = null ) {
|
||||||
|
$whereClause = ['createdBy', '=', App::$activeUser->ID];
|
||||||
|
if ( empty( $limit ) ) {
|
||||||
|
$views = self::$db->get( $this->tableName, $whereClause );
|
||||||
|
} else {
|
||||||
|
$views = self::$db->get( $this->tableName, $whereClause, 'ID', 'DESC', [0, $limit] );
|
||||||
|
}
|
||||||
|
if ( !$views->count() ) {
|
||||||
|
Debug::info( 'No Views found.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return $this->filter( $views->results() );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getName( $id ) {
|
||||||
|
$views = self::findById( $id );
|
||||||
|
if (false == $views) {
|
||||||
|
return 'unknown';
|
||||||
|
}
|
||||||
|
return $views->title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function simpleByUser() {
|
||||||
|
$whereClause = ['createdBy', '=', App::$activeUser->ID];
|
||||||
|
$views = self::$db->get( $this->tableName, $whereClause );
|
||||||
|
if ( !$views->count() ) {
|
||||||
|
Debug::warn( 'Could not find any Views' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$views = $views->results();
|
||||||
|
$out = [];
|
||||||
|
foreach ( $views as $view ) {
|
||||||
|
$out[ $view->title ] = $view->ID;
|
||||||
|
}
|
||||||
|
return $out;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function simpleObjectByUser() {
|
||||||
|
$whereClause = ['createdBy', '=', App::$activeUser->ID];
|
||||||
|
$views = self::$db->get( $this->tableName, $whereClause );
|
||||||
|
if ( !$views->count() ) {
|
||||||
|
Debug::warn( 'Could not find any Views' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$views = $views->results();
|
||||||
|
$out = [];
|
||||||
|
foreach ( $views as $view ) {
|
||||||
|
$obj = new \stdClass();
|
||||||
|
$obj->title = $view->title;
|
||||||
|
$obj->ID = $view->ID;
|
||||||
|
$out[] = $obj;
|
||||||
|
}
|
||||||
|
return $out;
|
||||||
|
}
|
||||||
|
}
|
705
app/plugins/bookmarks/models/bookmarks.php
Normal file
705
app/plugins/bookmarks/models/bookmarks.php
Normal file
@ -0,0 +1,705 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* app/plugins/bookmarks/models/bookmarks.php
|
||||||
|
*
|
||||||
|
* This class is used for the manipulation of the bookmarks database table.
|
||||||
|
*
|
||||||
|
* @package TP Bookmarks
|
||||||
|
* @version 3.0
|
||||||
|
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||||
|
* @link https://TheTempusProject.com
|
||||||
|
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||||
|
*/
|
||||||
|
namespace TheTempusProject\Models;
|
||||||
|
|
||||||
|
use TheTempusProject\Bedrock\Classes\Config;
|
||||||
|
use TheTempusProject\Bedrock\Functions\Check;
|
||||||
|
use TheTempusProject\Canary\Canary as Debug;
|
||||||
|
use TheTempusProject\Classes\DatabaseModel;
|
||||||
|
use TheTempusProject\TheTempusProject as App;
|
||||||
|
use TheTempusProject\Houdini\Classes\Filters;
|
||||||
|
use TheTempusProject\Bedrock\Classes\CustomException;
|
||||||
|
|
||||||
|
class Bookmarks extends DatabaseModel {
|
||||||
|
public $tableName = 'bookmarks';
|
||||||
|
public $linkTypes = [
|
||||||
|
'Open in New Tab' => 'external',
|
||||||
|
'Open in Same Tab' => 'internal',
|
||||||
|
];
|
||||||
|
|
||||||
|
public $databaseMatrix = [
|
||||||
|
[ 'title', 'varchar', '256' ],
|
||||||
|
[ 'url', 'text', '' ],
|
||||||
|
[ 'color', 'varchar', '48' ],
|
||||||
|
[ 'privacy', 'varchar', '48' ],
|
||||||
|
[ 'folderID', 'int', '11' ],
|
||||||
|
[ 'description', 'text', '' ],
|
||||||
|
[ 'createdBy', 'int', '11' ],
|
||||||
|
[ 'createdAt', 'int', '11' ],
|
||||||
|
[ 'meta', 'text', '' ],
|
||||||
|
[ 'icon', 'text', '' ],
|
||||||
|
[ 'archivedAt', 'int', '11' ],
|
||||||
|
[ 'refreshedAt', 'int', '11' ],
|
||||||
|
[ 'hiddenAt', 'int', '11' ],
|
||||||
|
[ 'order', 'int', '11' ],
|
||||||
|
[ 'linkType', 'varchar', '32' ],
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The model constructor.
|
||||||
|
*/
|
||||||
|
public function __construct() {
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function create( $title, $url, $folderID = 0, $description = '', $color = 'default', $privacy = 'private', $type = 'external' ) {
|
||||||
|
$fields = [
|
||||||
|
'title' => $title,
|
||||||
|
'url' => $url,
|
||||||
|
'description' => $description,
|
||||||
|
'color' => $color,
|
||||||
|
'privacy' => $privacy,
|
||||||
|
'createdBy' => App::$activeUser->ID,
|
||||||
|
'createdAt' => time(),
|
||||||
|
];
|
||||||
|
if ( !empty( $folderID ) ) {
|
||||||
|
$fields['folderID'] = $folderID;
|
||||||
|
} else {
|
||||||
|
$fields['folderID'] = null;
|
||||||
|
}
|
||||||
|
if ( ! self::$db->insert( $this->tableName, $fields ) ) {
|
||||||
|
new CustomException( 'bookmarkCreate' );
|
||||||
|
Debug::error( "Bookmarks: not created " . var_export($fields,true) );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return self::$db->lastId();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update( $id, $title, $url, $folderID = 0, $description = '', $color = 'default', $privacy = 'private', $type = 'external', $order = 0 ) {
|
||||||
|
if ( !Check::id( $id ) ) {
|
||||||
|
Debug::info( 'Bookmarks: illegal ID.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$fields = [
|
||||||
|
'title' => $title,
|
||||||
|
'url' => $url,
|
||||||
|
'description' => $description,
|
||||||
|
'color' => $color,
|
||||||
|
'privacy' => $privacy,
|
||||||
|
// 'linkType' => $type,
|
||||||
|
// 'order' => $order,
|
||||||
|
];
|
||||||
|
if ( !empty( $folderID ) ) {
|
||||||
|
$fields['folderID'] = $folderID;
|
||||||
|
}
|
||||||
|
if ( !self::$db->update( $this->tableName, $id, $fields ) ) {
|
||||||
|
new CustomException( 'bookmarkUpdate' );
|
||||||
|
Debug::error( "Bookmarks: $id not updated" );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function byUser( $limit = null ) {
|
||||||
|
$whereClause = ['createdBy', '=', App::$activeUser->ID];
|
||||||
|
if ( empty( $limit ) ) {
|
||||||
|
$bookmarks = self::$db->get( $this->tableName, $whereClause );
|
||||||
|
} else {
|
||||||
|
$bookmarks = self::$db->get( $this->tableName, $whereClause, 'ID', 'DESC', [0, $limit] );
|
||||||
|
}
|
||||||
|
if ( !$bookmarks->count() ) {
|
||||||
|
Debug::info( 'No Bookmarks found.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return $this->filter( $bookmarks->results() );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function byFolder( $id, $limit = null ) {
|
||||||
|
$whereClause = ['createdBy', '=', App::$activeUser->ID, 'AND'];
|
||||||
|
|
||||||
|
$whereClause = array_merge( $whereClause, [ 'folderID', '=', $id ] );
|
||||||
|
if ( empty( $limit ) ) {
|
||||||
|
$bookmarks = self::$db->get( $this->tableName, $whereClause );
|
||||||
|
} else {
|
||||||
|
$bookmarks = self::$db->get( $this->tableName, $whereClause, 'ID', 'DESC', [0, $limit] );
|
||||||
|
}
|
||||||
|
if ( !$bookmarks->count() ) {
|
||||||
|
Debug::info( 'No Bookmarks found.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return $this->filter( $bookmarks->results() );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function noFolder( $id = 0, $limit = 10 ) {
|
||||||
|
$whereClause = ['createdBy', '=', App::$activeUser->ID, 'AND'];
|
||||||
|
if ( !empty( $id ) ) {
|
||||||
|
$whereClause = array_merge( $whereClause, ['folderID', '!=', $id] );
|
||||||
|
} else {
|
||||||
|
$whereClause = array_merge( $whereClause, [ 'folderID', 'IS', null] );
|
||||||
|
}
|
||||||
|
if ( empty( $limit ) ) {
|
||||||
|
$bookmarks = self::$db->get( $this->tableName, $whereClause );
|
||||||
|
} else {
|
||||||
|
$bookmarks = self::$db->get( $this->tableName, $whereClause, 'ID', 'DESC', [ 0, $limit ] );
|
||||||
|
}
|
||||||
|
if ( !$bookmarks->count() ) {
|
||||||
|
Debug::info( 'No Bookmarks found.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return $this->filter( $bookmarks->results() );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getName( $id ) {
|
||||||
|
$bookmarks = self::findById( $id );
|
||||||
|
if (false == $bookmarks) {
|
||||||
|
return 'unknown';
|
||||||
|
}
|
||||||
|
return $bookmarks->title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getColor( $id ) {
|
||||||
|
$bookmarks = self::findById( $id );
|
||||||
|
if (false == $bookmarks) {
|
||||||
|
return 'default';
|
||||||
|
}
|
||||||
|
return $bookmarks->color;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function simpleByUser() {
|
||||||
|
$whereClause = ['createdBy', '=', App::$activeUser->ID];
|
||||||
|
$bookmarks = self::$db->get( $this->tableName, $whereClause );
|
||||||
|
if ( !$bookmarks->count() ) {
|
||||||
|
Debug::warn( 'Could not find any bookmarks' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$bookmarks = $bookmarks->results();
|
||||||
|
$out = [];
|
||||||
|
foreach ( $bookmarks as $bookmarks ) {
|
||||||
|
$out[ $bookmarks->title ] = $bookmarks->ID;
|
||||||
|
}
|
||||||
|
return $out;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function simpleObjectByUser() {
|
||||||
|
$whereClause = ['createdBy', '=', App::$activeUser->ID];
|
||||||
|
$bookmarks = self::$db->get( $this->tableName, $whereClause );
|
||||||
|
if ( !$bookmarks->count() ) {
|
||||||
|
Debug::warn( 'Could not find any bookmarks' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$bookmarks = $bookmarks->results();
|
||||||
|
$out = [];
|
||||||
|
foreach ( $bookmarks as $bookmarks ) {
|
||||||
|
$obj = new \stdClass();
|
||||||
|
$obj->title = $bookmarks->title;
|
||||||
|
$obj->ID = $bookmarks->ID;
|
||||||
|
$out[] = $obj;
|
||||||
|
}
|
||||||
|
return $out;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function deleteByFolder( $folderID ) {
|
||||||
|
$whereClause = [ 'createdBy', '=', App::$activeUser->ID, 'AND' ];
|
||||||
|
$whereClause = array_merge( $whereClause, [ 'folderID', '=', $folderID ] );
|
||||||
|
$bookmarks = self::$db->get( $this->tableName, $whereClause );
|
||||||
|
if ( ! $bookmarks->count() ) {
|
||||||
|
Debug::info( 'No ' . $this->tableName . ' data found.' );
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
foreach( $bookmarks->results() as $bookmark ) {
|
||||||
|
$this->delete( $bookmark->ID );
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function resolveShortenedUrl( $url ) {
|
||||||
|
$ch = curl_init($url);
|
||||||
|
|
||||||
|
// Set curl options
|
||||||
|
curl_setopt($ch, CURLOPT_NOBODY, true); // We don't need the body
|
||||||
|
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); // Follow redirects
|
||||||
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // Return the response
|
||||||
|
curl_setopt($ch, CURLOPT_TIMEOUT, 30); // Set a timeout
|
||||||
|
// curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); // Maybe sketchy?
|
||||||
|
// Maybe sketchy?
|
||||||
|
// curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); // Disable SSL host verification
|
||||||
|
// curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // Disable SSL peer verification
|
||||||
|
// curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1_2);
|
||||||
|
|
||||||
|
// added to support the regex site
|
||||||
|
// curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
|
||||||
|
|
||||||
|
// =
|
||||||
|
// curl_setopt($ch, CURLOPT_SSL_CIPHER_LIST, 'AES256+EECDH:AES256+EDH' );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Execute curl
|
||||||
|
$response = curl_exec( $ch );
|
||||||
|
|
||||||
|
// Check if there was an error
|
||||||
|
if ( curl_errno( $ch ) ) {
|
||||||
|
|
||||||
|
|
||||||
|
// Get error details
|
||||||
|
$errorCode = curl_errno($ch);
|
||||||
|
$errorMessage = curl_error($ch);
|
||||||
|
// Log or display the error details
|
||||||
|
dv('cURL Error: ' . $errorMessage . ' (Error Code: ' . $errorCode . ')');
|
||||||
|
|
||||||
|
curl_close($ch);
|
||||||
|
// return $url; // Return the original URL if there was an error
|
||||||
|
|
||||||
|
|
||||||
|
$url = rtrim( $url, '/' );
|
||||||
|
$ch2 = curl_init($url);
|
||||||
|
curl_setopt($ch2, CURLOPT_NOBODY, true); // We don't need the body
|
||||||
|
curl_setopt($ch2, CURLOPT_FOLLOWLOCATION, true); // Follow redirects
|
||||||
|
curl_setopt($ch2, CURLOPT_RETURNTRANSFER, true); // Return the response
|
||||||
|
curl_setopt($ch2, CURLOPT_TIMEOUT, 5); // Set a timeout
|
||||||
|
curl_exec($ch2);
|
||||||
|
|
||||||
|
if ( curl_errno( $ch2 ) ) {
|
||||||
|
|
||||||
|
}
|
||||||
|
curl_close( $ch );
|
||||||
|
return $url;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the effective URL (the final destination after redirects)
|
||||||
|
$finalUrl = curl_getinfo( $ch, CURLINFO_EFFECTIVE_URL );
|
||||||
|
curl_close( $ch );
|
||||||
|
|
||||||
|
return $finalUrl;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// $headers = get_headers( $url, 1 );
|
||||||
|
$headers = @get_headers($url, 1);
|
||||||
|
if ( $headers === false ) {
|
||||||
|
}
|
||||||
|
if ( isset( $headers['Location'] ) ) {
|
||||||
|
if (is_array($headers['Location'])) {
|
||||||
|
return end($headers['Location']);
|
||||||
|
} else {
|
||||||
|
return $headers['Location'];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return $url;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function filter( $data, $params = [] ) {
|
||||||
|
foreach ( $data as $instance ) {
|
||||||
|
if ( !is_object( $instance ) ) {
|
||||||
|
$instance = $data;
|
||||||
|
$end = true;
|
||||||
|
}
|
||||||
|
$base_url = $this->getBaseUrl( $instance->url );
|
||||||
|
|
||||||
|
if ( empty( $instance->icon ) ) {
|
||||||
|
$instance->iconHtml = '<i class="glyphicon glyphicon-link"></i>';
|
||||||
|
} else {
|
||||||
|
if (strpos($instance->icon, 'http') !== false) {
|
||||||
|
$instance->iconHtml = '<img src="' . $instance->icon .'" />';
|
||||||
|
} else {
|
||||||
|
$instance->iconHtml = '<img src="' . $base_url . ltrim( $instance->icon, '/' ) .'" />';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( empty( $instance->hiddenAt ) ) {
|
||||||
|
$instance->hideBtn = '
|
||||||
|
<a href="{ROOT_URL}bookmarks/hideBookmark/'.$instance->ID.'" class="btn btn-sm btn-warning" role="button">
|
||||||
|
<i class="glyphicon glyphicon-eye-open"></i>
|
||||||
|
</a>';
|
||||||
|
} else {
|
||||||
|
$instance->hideBtn = '
|
||||||
|
<a href="{ROOT_URL}bookmarks/showBookmark/'.$instance->ID.'" class="btn btn-sm btn-default" role="button">
|
||||||
|
<i class="glyphicon glyphicon-eye-open"></i>
|
||||||
|
</a>';
|
||||||
|
}
|
||||||
|
if ( empty( $instance->archivedAt ) ) {
|
||||||
|
$instance->archiveBtn = '
|
||||||
|
<a href="{ROOT_URL}bookmarks/archiveBookmark/'.$instance->ID.'" class="btn btn-sm btn-info" role="button">
|
||||||
|
<i class="glyphicon glyphicon-briefcase"></i>
|
||||||
|
</a>';
|
||||||
|
} else {
|
||||||
|
$instance->archiveBtn = '
|
||||||
|
<a href="{ROOT_URL}bookmarks/unarchiveBookmark/'.$instance->ID.'" class="btn btn-sm btn-default" role="button">
|
||||||
|
<i class="glyphicon glyphicon-briefcase"></i>
|
||||||
|
</a>';
|
||||||
|
}
|
||||||
|
if ( ! empty( $instance->refreshedAt ) && time() < ( $instance->refreshedAt + ( 60 * 10 ) ) ) {
|
||||||
|
$instance->refreshBtn = '
|
||||||
|
<a href="{ROOT_URL}bookmarks/refreshBookmark/'.$instance->ID.'" class="btn btn-sm btn-danger" role="button">
|
||||||
|
<i class="glyphicon glyphicon-refresh"></i>
|
||||||
|
</a>';
|
||||||
|
} else {
|
||||||
|
$instance->refreshBtn = '
|
||||||
|
<a href="{ROOT_URL}bookmarks/refreshBookmark/'.$instance->ID.'" class="btn btn-sm btn-success" role="button">
|
||||||
|
<i class="glyphicon glyphicon-refresh"></i>
|
||||||
|
</a>';
|
||||||
|
}
|
||||||
|
|
||||||
|
$out[] = $instance;
|
||||||
|
if ( !empty( $end ) ) {
|
||||||
|
$out = $out[0];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $out;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function hide( $id ) {
|
||||||
|
if ( !Check::id( $id ) ) {
|
||||||
|
Debug::info( 'Bookmarks: illegal ID.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$fields = [
|
||||||
|
'hiddenAt' => time(),
|
||||||
|
];
|
||||||
|
if ( !self::$db->update( $this->tableName, $id, $fields ) ) {
|
||||||
|
new CustomException( 'bookmarkUpdate' );
|
||||||
|
Debug::error( "Bookmarks: $id not updated" );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function show( $id ) {
|
||||||
|
if ( !Check::id( $id ) ) {
|
||||||
|
Debug::info( 'Bookmarks: illegal ID.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$fields = [
|
||||||
|
'hiddenAt' => 0,
|
||||||
|
];
|
||||||
|
if ( !self::$db->update( $this->tableName, $id, $fields ) ) {
|
||||||
|
new CustomException( 'bookmarkUpdate' );
|
||||||
|
Debug::error( "Bookmarks: $id not updated" );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function archive( $id ) {
|
||||||
|
if ( !Check::id( $id ) ) {
|
||||||
|
Debug::info( 'Bookmarks: illegal ID.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$fields = [
|
||||||
|
'archivedAt' => time(),
|
||||||
|
];
|
||||||
|
if ( !self::$db->update( $this->tableName, $id, $fields ) ) {
|
||||||
|
new CustomException( 'bookmarkUpdate' );
|
||||||
|
Debug::error( "Bookmarks: $id not updated" );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function unarchive( $id ) {
|
||||||
|
if ( !Check::id( $id ) ) {
|
||||||
|
Debug::info( 'Bookmarks: illegal ID.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$fields = [
|
||||||
|
'archivedAt' => 0,
|
||||||
|
];
|
||||||
|
if ( !self::$db->update( $this->tableName, $id, $fields ) ) {
|
||||||
|
new CustomException( 'bookmarkUpdate' );
|
||||||
|
Debug::error( "Bookmarks: $id not updated" );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function extractMetaTags($htmlContent) {
|
||||||
|
$doc = new \DOMDocument();
|
||||||
|
@$doc->loadHTML($htmlContent);
|
||||||
|
$metaTags = [];
|
||||||
|
foreach ($doc->getElementsByTagName('meta') as $meta) {
|
||||||
|
$name = $meta->getAttribute('name') ?: $meta->getAttribute('property');
|
||||||
|
$content = $meta->getAttribute('content');
|
||||||
|
if ($name && $content) {
|
||||||
|
$metaTags[$name] = $content;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $metaTags;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function fetchUrlData($url) {
|
||||||
|
$ch = curl_init();
|
||||||
|
|
||||||
|
// Set cURL options
|
||||||
|
curl_setopt($ch, CURLOPT_URL, $url);
|
||||||
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||||
|
curl_setopt($ch, CURLOPT_HEADER, true); // Include headers in the output
|
||||||
|
curl_setopt($ch, CURLOPT_NOBODY, false); // Include the body in the output
|
||||||
|
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); // Follow redirects
|
||||||
|
curl_setopt($ch, CURLOPT_TIMEOUT, 30); // Set a timeout
|
||||||
|
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); // Disable SSL host verification for testing
|
||||||
|
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // Disable SSL peer verification for testing
|
||||||
|
|
||||||
|
// Execute cURL request
|
||||||
|
$response = curl_exec($ch);
|
||||||
|
|
||||||
|
// Check if there was an error
|
||||||
|
if (curl_errno($ch)) {
|
||||||
|
$errorMessage = curl_error($ch);
|
||||||
|
curl_close($ch);
|
||||||
|
throw new \Exception('cURL Error: ' . $errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get HTTP status code
|
||||||
|
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||||
|
|
||||||
|
// Separate headers and body
|
||||||
|
$headerSize = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
|
||||||
|
$headers = substr($response, 0, $headerSize);
|
||||||
|
$body = substr($response, $headerSize);
|
||||||
|
|
||||||
|
curl_close($ch);
|
||||||
|
|
||||||
|
// Parse headers into an associative array
|
||||||
|
$headerLines = explode("\r\n", trim($headers));
|
||||||
|
$headerArray = [];
|
||||||
|
foreach ($headerLines as $line) {
|
||||||
|
$parts = explode(': ', $line, 2);
|
||||||
|
if (count($parts) == 2) {
|
||||||
|
$headerArray[$parts[0]] = $parts[1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
'http_code' => $httpCode,
|
||||||
|
'headers' => $headerArray,
|
||||||
|
'body' => $body,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getMetaTagsAndFavicon( $url ) {
|
||||||
|
try {
|
||||||
|
// $url = 'https://runescape.wiki';
|
||||||
|
$data = $this->fetchUrlData($url);
|
||||||
|
|
||||||
|
// iv($data);
|
||||||
|
|
||||||
|
// Get headers
|
||||||
|
$headers = $data['headers'];
|
||||||
|
iv($headers);
|
||||||
|
|
||||||
|
// Get meta tags
|
||||||
|
$metaTags = $this->extractMetaTags($data['body']);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
dv( 'Error: ' . $e->getMessage());
|
||||||
|
|
||||||
|
}
|
||||||
|
$metaInfo = [
|
||||||
|
'url' => $url,
|
||||||
|
'title' => null,
|
||||||
|
'description' => null,
|
||||||
|
'image' => null,
|
||||||
|
'favicon' => null
|
||||||
|
];
|
||||||
|
$ch = curl_init($url);
|
||||||
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||||
|
$html = curl_exec($ch);
|
||||||
|
curl_close($ch);
|
||||||
|
|
||||||
|
if ($html === false) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$meta = @get_meta_tags( $url );
|
||||||
|
|
||||||
|
$dom = new \DOMDocument('1.0', 'utf-8');
|
||||||
|
$dom->strictErrorChecking = false;
|
||||||
|
$dom->loadHTML($html, LIBXML_NOERROR);
|
||||||
|
$xml = simplexml_import_dom($dom);
|
||||||
|
$arr = $xml->xpath('//link[@rel="shortcut icon"]');
|
||||||
|
|
||||||
|
// Get the title of the page
|
||||||
|
$titles = $dom->getElementsByTagName('title');
|
||||||
|
if ($titles->length > 0) {
|
||||||
|
$metaInfo['title'] = $titles->item(0)->nodeValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the meta tags
|
||||||
|
$metaTags = $dom->getElementsByTagName('meta');
|
||||||
|
$metadata = [];
|
||||||
|
foreach ($metaTags as $meta) {
|
||||||
|
$metadata[] = [
|
||||||
|
'name' => $meta->getAttribute('name'),
|
||||||
|
'property' => $meta->getAttribute('property'),
|
||||||
|
'content' => $meta->getAttribute('content')
|
||||||
|
];
|
||||||
|
if ($meta->getAttribute('name') === 'description') {
|
||||||
|
$metaInfo['description'] = $meta->getAttribute('content');
|
||||||
|
}
|
||||||
|
if ($meta->getAttribute('itemprop') === 'image') {
|
||||||
|
$metaInfo['google_image'] = $meta->getAttribute('content');
|
||||||
|
}
|
||||||
|
if ($meta->getAttribute('property') === 'og:image') {
|
||||||
|
$metaInfo['image'] = $meta->getAttribute('content');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the link tags to find the favicon
|
||||||
|
$linkTags = $dom->getElementsByTagName('link');
|
||||||
|
$metadata['links'] = [];
|
||||||
|
foreach ($linkTags as $link) {
|
||||||
|
$metadata['links'][] = [ $link->getAttribute('rel') => $link->getAttribute('href') ];
|
||||||
|
if ( $link->getAttribute('rel') === 'icon' || $link->getAttribute('rel') === 'shortcut icon') {
|
||||||
|
$metaInfo['favicon'] = $link->getAttribute('href');
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$metaInfo['metadata'] = $metadata;
|
||||||
|
|
||||||
|
return $metaInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function retrieveInfo( $url ) {
|
||||||
|
$finalDestination = $this->resolveShortenedUrl( $url );
|
||||||
|
$info = $this->getMetaTagsAndFavicon( $finalDestination );
|
||||||
|
$base_url = $this->getBaseUrl( $finalDestination );
|
||||||
|
|
||||||
|
if ( ! empty( $info['favicon'] ) ) {
|
||||||
|
echo 'favicon exists' . PHP_EOL;
|
||||||
|
if ( stripos( $info['favicon'], 'http' ) !== false) {
|
||||||
|
echo 'favicon is full url' . PHP_EOL;
|
||||||
|
$imageUrl = $info['favicon'];
|
||||||
|
} else {
|
||||||
|
echo 'favicon is not full url' . PHP_EOL;
|
||||||
|
$imageUrl = trim( $base_url, '/' ) . '/' . ltrim( $info['favicon'], '/' );
|
||||||
|
}
|
||||||
|
if ( $this->isValidImageUrl( $imageUrl ) ) {
|
||||||
|
echo 'image is valid' . PHP_EOL;
|
||||||
|
$info['favicon'] = $imageUrl;
|
||||||
|
} else {
|
||||||
|
echo 'image is not valid' . PHP_EOL;
|
||||||
|
$base_info = $this->getMetaTagsAndFavicon( $base_url );
|
||||||
|
if ( ! empty( $base_info['favicon'] ) ) {
|
||||||
|
echo 'parent favicon exists!';
|
||||||
|
if ( stripos( $base_info['favicon'], 'http' ) !== false) {
|
||||||
|
echo 'parent favicon is full url' . PHP_EOL;
|
||||||
|
$imageUrl = $base_info['favicon'];
|
||||||
|
} else {
|
||||||
|
echo 'parent favicon is not full url' . PHP_EOL;
|
||||||
|
$imageUrl = trim( $base_url, '/' ) . '/' . ltrim( $base_info['favicon'], '/' );
|
||||||
|
}
|
||||||
|
if ( $this->isValidImageUrl( $imageUrl ) ) {
|
||||||
|
echo 'parent favicon image is valid' . PHP_EOL;
|
||||||
|
$info['favicon'] = $imageUrl;
|
||||||
|
} else {
|
||||||
|
echo 'parent favicon image is not valid' . PHP_EOL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
echo 'favicon does not exist' . PHP_EOL;
|
||||||
|
$base_info = $this->getMetaTagsAndFavicon( $base_url );
|
||||||
|
if ( ! empty( $base_info['favicon'] ) ) {
|
||||||
|
echo 'parent favicon exists!' . PHP_EOL;
|
||||||
|
if ( stripos( $base_info['favicon'], 'http' ) !== false) {
|
||||||
|
echo 'parent favicon is full url' . PHP_EOL;
|
||||||
|
$imageUrl = $base_info['favicon'];
|
||||||
|
} else {
|
||||||
|
echo 'parent favicon is not full url' . PHP_EOL;
|
||||||
|
$imageUrl = trim( $base_url, '/' ) . '/' . ltrim( $base_info['favicon'], '/' );
|
||||||
|
}
|
||||||
|
if ( $this->isValidImageUrl( $imageUrl ) ) {
|
||||||
|
echo 'parent favicon image is valid' . PHP_EOL;
|
||||||
|
$info['favicon'] = $imageUrl;
|
||||||
|
} else {
|
||||||
|
echo 'parent favicon image is not valid' . PHP_EOL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $info;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function refreshInfo( $id ) {
|
||||||
|
if ( !Check::id( $id ) ) {
|
||||||
|
Debug::info( 'Bookmarks: illegal ID.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$bookmark = self::findById( $id );
|
||||||
|
if ( $bookmark == false ) {
|
||||||
|
Debug::info( 'Bookmarks not found.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( $bookmark->createdBy != App::$activeUser->ID ) {
|
||||||
|
Debug::info( 'You do not have permission to modify this bookmark.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( time() < ( $bookmark->refreshedAt + ( 60 * 10 ) ) ) {
|
||||||
|
Debug::info( 'You may only fetch bookmarks once every 10 minutes.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$info = $this->retrieveInfo( $bookmark->url );
|
||||||
|
|
||||||
|
$fields = [
|
||||||
|
// 'refreshedAt' => time(),
|
||||||
|
];
|
||||||
|
|
||||||
|
if ( empty( $bookmark->title ) && ! empty( $info['title'] ) ) {
|
||||||
|
$fields['title'] = $info['title'];
|
||||||
|
}
|
||||||
|
if ( empty( $bookmark->description ) && ! empty( $info['description'] ) ) {
|
||||||
|
$fields['description'] = $info['description'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ( empty( $bookmark->icon ) || ! $this->isValidImageUrl( $bookmark->icon ) ) && ! empty( $info['favicon'] ) ) {
|
||||||
|
$fields['icon'] = $info['favicon'];
|
||||||
|
}
|
||||||
|
$fields['meta'] = json_encode( $info['metadata'] );
|
||||||
|
|
||||||
|
if ( !self::$db->update( $this->tableName, $id, $fields ) ) {
|
||||||
|
new CustomException( 'bookmarkUpdate' );
|
||||||
|
Debug::error( "Bookmarks: $id not updated" );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getBaseUrl ($url ) {
|
||||||
|
$parsedUrl = parse_url($url);
|
||||||
|
|
||||||
|
if (isset($parsedUrl['scheme']) && isset($parsedUrl['host'])) {
|
||||||
|
return $parsedUrl['scheme'] . '://' . $parsedUrl['host'] . '/';
|
||||||
|
} else {
|
||||||
|
return null; // URL is not valid or cannot be parsed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function isValidImageUrl($url) {
|
||||||
|
$headers = @get_headers($url);
|
||||||
|
if ($headers && strpos($headers[0], '200') !== false) {
|
||||||
|
|
||||||
|
return true;
|
||||||
|
// Further check to ensure it's an image
|
||||||
|
foreach ($headers as $header) {
|
||||||
|
if (strpos(strtolower($header), 'content-type:') !== false) {
|
||||||
|
if (strpos(strtolower($header), 'image/') !== false) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
157
app/plugins/bookmarks/models/folders.php
Normal file
157
app/plugins/bookmarks/models/folders.php
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* app/plugins/bookmarks/models/folders.php
|
||||||
|
*
|
||||||
|
* This class is used for the manipulation of the folders database table.
|
||||||
|
*
|
||||||
|
* @package TP Bookmarks
|
||||||
|
* @version 3.0
|
||||||
|
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||||
|
* @link https://TheTempusProject.com
|
||||||
|
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||||
|
*/
|
||||||
|
namespace TheTempusProject\Models;
|
||||||
|
|
||||||
|
use TheTempusProject\Bedrock\Classes\Config;
|
||||||
|
use TheTempusProject\Bedrock\Functions\Check;
|
||||||
|
use TheTempusProject\Canary\Canary as Debug;
|
||||||
|
use TheTempusProject\Classes\DatabaseModel;
|
||||||
|
use TheTempusProject\TheTempusProject as App;
|
||||||
|
use TheTempusProject\Houdini\Classes\Filters;
|
||||||
|
use TheTempusProject\Bedrock\Classes\CustomException;
|
||||||
|
|
||||||
|
class Folders extends DatabaseModel {
|
||||||
|
public $tableName = 'folders';
|
||||||
|
public $databaseMatrix = [
|
||||||
|
[ 'title', 'varchar', '256' ],
|
||||||
|
[ 'color', 'varchar', '48' ],
|
||||||
|
[ 'privacy', 'varchar', '48' ],
|
||||||
|
[ 'description', 'text', '' ],
|
||||||
|
[ 'folderID', 'int', '11' ],
|
||||||
|
[ 'createdBy', 'int', '11' ],
|
||||||
|
[ 'createdAt', 'int', '11' ],
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The model constructor.
|
||||||
|
*/
|
||||||
|
public function __construct() {
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function create( $title, $folderID = 0, $description = '', $color = 'default', $privacy = 'private' ) {
|
||||||
|
if ( ! Check::dataTitle( $title ) ) {
|
||||||
|
Debug::info( 'Folders: illegal title.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$fields = [
|
||||||
|
'title' => $title,
|
||||||
|
'description' => $description,
|
||||||
|
'color' => $color,
|
||||||
|
'privacy' => $privacy,
|
||||||
|
'createdBy' => App::$activeUser->ID,
|
||||||
|
'createdAt' => time(),
|
||||||
|
];
|
||||||
|
if ( !empty( $folderID ) ) {
|
||||||
|
$fields['folderID'] = $folderID;
|
||||||
|
}
|
||||||
|
if ( ! self::$db->insert( $this->tableName, $fields ) ) {
|
||||||
|
new CustomException( 'folderCreate' );
|
||||||
|
Debug::error( "Folders: not created " . var_export($fields,true) );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return self::$db->lastId();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update( $id, $title, $folderID = 0, $description = '', $color = 'default', $privacy = 'private' ) {
|
||||||
|
if ( !Check::id( $id ) ) {
|
||||||
|
Debug::info( 'Folders: illegal ID.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !Check::dataTitle( $title ) ) {
|
||||||
|
Debug::info( 'Folders: illegal title.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$fields = [
|
||||||
|
'title' => $title,
|
||||||
|
'description' => $description,
|
||||||
|
'color' => $color,
|
||||||
|
'privacy' => $privacy,
|
||||||
|
];
|
||||||
|
if ( !empty( $folderID ) ) {
|
||||||
|
$fields['folderID'] = $folderID;
|
||||||
|
}
|
||||||
|
if ( !self::$db->update( $this->tableName, $id, $fields ) ) {
|
||||||
|
new CustomException( 'folderUpdate' );
|
||||||
|
Debug::error( "Folders: $id not updated: $fields" );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function byUser( $limit = null ) {
|
||||||
|
$whereClause = ['createdBy', '=', App::$activeUser->ID];
|
||||||
|
if ( empty( $limit ) ) {
|
||||||
|
$folders = self::$db->get( $this->tableName, $whereClause );
|
||||||
|
} else {
|
||||||
|
$folders = self::$db->get( $this->tableName, $whereClause, 'ID', 'DESC', [0, $limit] );
|
||||||
|
}
|
||||||
|
if ( !$folders->count() ) {
|
||||||
|
Debug::info( 'No Folders found.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return $this->filter( $folders->results() );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getName( $id ) {
|
||||||
|
$folder = self::findById( $id );
|
||||||
|
if (false == $folder) {
|
||||||
|
return 'unknown';
|
||||||
|
}
|
||||||
|
return $folder->title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getColor( $id ) {
|
||||||
|
$folder = self::findById( $id );
|
||||||
|
if (false == $folder) {
|
||||||
|
return 'default';
|
||||||
|
}
|
||||||
|
return $folder->color;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function simpleByUser() {
|
||||||
|
$whereClause = ['createdBy', '=', App::$activeUser->ID];
|
||||||
|
$folders = self::$db->get( $this->tableName, $whereClause );
|
||||||
|
if ( !$folders->count() ) {
|
||||||
|
Debug::warn( 'Could not find any folders' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$folders = $folders->results();
|
||||||
|
$out = [];
|
||||||
|
$out[ 'No Folder' ] = 0;
|
||||||
|
foreach ( $folders as $folder ) {
|
||||||
|
$out[ $folder->title ] = $folder->ID;
|
||||||
|
}
|
||||||
|
return $out;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function simpleObjectByUser() {
|
||||||
|
$whereClause = ['createdBy', '=', App::$activeUser->ID];
|
||||||
|
$folders = self::$db->get( $this->tableName, $whereClause );
|
||||||
|
if ( !$folders->count() ) {
|
||||||
|
Debug::warn( 'Could not find any folders' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$folders = $folders->results();
|
||||||
|
$out = [];
|
||||||
|
foreach ( $folders as $folder ) {
|
||||||
|
$obj = new \stdClass();
|
||||||
|
$obj->title = $folder->title;
|
||||||
|
$obj->ID = $folder->ID;
|
||||||
|
$out[] = $obj;
|
||||||
|
}
|
||||||
|
return $out;
|
||||||
|
}
|
||||||
|
}
|
62
app/plugins/bookmarks/plugin.php
Normal file
62
app/plugins/bookmarks/plugin.php
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* app/plugins/bookmarks/plugin.php
|
||||||
|
*
|
||||||
|
* This houses all of the main plugin info and functionality.
|
||||||
|
*
|
||||||
|
* @package TP Bookmarks
|
||||||
|
* @version 3.0
|
||||||
|
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||||
|
* @link https://TheTempusProject.com
|
||||||
|
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||||
|
*/
|
||||||
|
namespace TheTempusProject\Plugins;
|
||||||
|
|
||||||
|
use TheTempusProject\Classes\Plugin;
|
||||||
|
use TheTempusProject\Models\Events;
|
||||||
|
use TheTempusProject\Models\Bookmarks as Bookmark;
|
||||||
|
use TheTempusProject\Models\Folders;
|
||||||
|
use TheTempusProject\Houdini\Classes\Components;
|
||||||
|
use TheTempusProject\Houdini\Classes\Template;
|
||||||
|
|
||||||
|
class Bookmarks extends Plugin {
|
||||||
|
public $pluginName = 'TP Bookmarks';
|
||||||
|
public $configName = 'bookmarks';
|
||||||
|
public $pluginAuthor = 'JoeyK';
|
||||||
|
public $pluginWebsite = 'https://TheTempusProject.com';
|
||||||
|
public $modelVersion = '1.0';
|
||||||
|
public $pluginVersion = '3.0';
|
||||||
|
public $pluginDescription = 'A simple plugin which adds a site wide bookmark system.';
|
||||||
|
public $permissionMatrix = [
|
||||||
|
'useBookmarks' => [
|
||||||
|
'pretty' => 'Can use the bookmarks feature',
|
||||||
|
'default' => false,
|
||||||
|
],
|
||||||
|
'createEvents' => [
|
||||||
|
'pretty' => 'Can add events to bookmarks',
|
||||||
|
'default' => false,
|
||||||
|
],
|
||||||
|
];
|
||||||
|
public $main_links = [
|
||||||
|
[
|
||||||
|
'text' => 'Bookmarks',
|
||||||
|
'url' => '{ROOT_URL}bookmarks/index',
|
||||||
|
'filter' => 'loggedin',
|
||||||
|
],
|
||||||
|
];
|
||||||
|
public $configMatrix = [
|
||||||
|
'enabled' => [
|
||||||
|
'type' => 'radio',
|
||||||
|
'pretty' => 'Enable Bookmarks.',
|
||||||
|
'default' => true,
|
||||||
|
],
|
||||||
|
];
|
||||||
|
public $bookmarks;
|
||||||
|
public $folders;
|
||||||
|
|
||||||
|
public function __construct( $load = false ) {
|
||||||
|
$this->bookmarks = new Bookmark;
|
||||||
|
$this->folders = new Folders;
|
||||||
|
parent::__construct( $load );
|
||||||
|
}
|
||||||
|
}
|
45
app/plugins/bookmarks/views/bookmarks/create.html
Normal file
45
app/plugins/bookmarks/views/bookmarks/create.html
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
<legend>Create Bookmark</legend>
|
||||||
|
{BookmarkBreadCrumbs}
|
||||||
|
<form action="" method="post" class="form-horizontal">
|
||||||
|
<input type="hidden" name="token" value="{TOKEN}">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="title" class="col-lg-3 control-label">Title</label>
|
||||||
|
<div class="col-lg-3">
|
||||||
|
<input type="text" class="form-control" name="title" id="title">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="url" class="col-lg-3 control-label">URL:</label>
|
||||||
|
<div class="col-lg-3">
|
||||||
|
<input type="text" class="form-control" name="url" id="url">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="description" class="col-lg-3 control-label">Description:</label>
|
||||||
|
<div class="col-lg-3">
|
||||||
|
<textarea class="form-control" name="description" maxlength="2000" rows="10" cols="50" id="description"></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{folderSelect}
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="privacy" class="col-lg-3 control-label">Privacy</label>
|
||||||
|
<div class="col-lg-3 select-container" id="colorContainer">
|
||||||
|
<select id="privacy" name="privacy" class="form-control custom-select">
|
||||||
|
<option value="private">Private</option>
|
||||||
|
<option value="public">Public</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="color" class="col-lg-3 control-label">Color</label>
|
||||||
|
<div class="col-lg-3 select-container" id="colorContainer">
|
||||||
|
{colorSelect}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="submit" class="col-lg-3 control-label"></label>
|
||||||
|
<div class="col-lg-3">
|
||||||
|
<button name="submit" value="submit" type="submit" class="btn btn-lg btn-primary center-block ">Submit</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
45
app/plugins/bookmarks/views/bookmarks/edit.html
Normal file
45
app/plugins/bookmarks/views/bookmarks/edit.html
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
<legend>Edit Bookmark</legend>
|
||||||
|
{BookmarkBreadCrumbs}
|
||||||
|
<form action="" method="post" class="form-horizontal">
|
||||||
|
<input type="hidden" name="token" value="{TOKEN}">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="title" class="col-lg-3 control-label">Title</label>
|
||||||
|
<div class="col-lg-3">
|
||||||
|
<input type="text" class="form-control" name="title" id="title" value="{title}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="url" class="col-lg-3 control-label">URL:</label>
|
||||||
|
<div class="col-lg-3">
|
||||||
|
<input type="text" class="form-control" name="url" id="url" value="{url}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="description" class="col-lg-3 control-label">Description:</label>
|
||||||
|
<div class="col-lg-3">
|
||||||
|
<textarea class="form-control" name="description" maxlength="2000" rows="10" cols="50" id="description">{description}</textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{folderSelect}
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="privacy" class="col-lg-3 control-label">Privacy</label>
|
||||||
|
<div class="col-lg-3 select-container" id="colorContainer">
|
||||||
|
<select id="privacy" name="privacy" class="form-control custom-select" value="{privacy}">
|
||||||
|
<option value="private">Private</option>
|
||||||
|
<option value="public">Public</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="color" class="col-lg-3 control-label">Color</label>
|
||||||
|
<div class="col-lg-3 select-container" id="colorContainer">
|
||||||
|
{colorSelect}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="submit" class="col-lg-3 control-label"></label>
|
||||||
|
<div class="col-lg-3">
|
||||||
|
<button name="submit" value="submit" type="submit" class="btn btn-lg btn-primary center-block ">Submit</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
37
app/plugins/bookmarks/views/bookmarks/list.html
Normal file
37
app/plugins/bookmarks/views/bookmarks/list.html
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
{BookmarkBreadCrumbs}
|
||||||
|
<table class="table table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th style="width: 75%">Bookmark</th>
|
||||||
|
<th style="width: 10%"></th>
|
||||||
|
<th style="width: 5%"></th>
|
||||||
|
<th style="width: 5%"></th>
|
||||||
|
<th style="width: 5%"></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{LOOP}
|
||||||
|
<tr>
|
||||||
|
<td style="text-align: center;">
|
||||||
|
<a href="{url}" role="button">
|
||||||
|
{title}
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
<td style="text-align: center;">
|
||||||
|
{privacy}
|
||||||
|
</td>
|
||||||
|
<td><a href="{ROOT_URL}bookmarks/bookmarks/{ID}" class="btn btn-sm btn-primary" role="button"><i class="glyphicon glyphicon-open"></i></a></td>
|
||||||
|
<td><a href="{ROOT_URL}bookmarks/editBookmark/{ID}" class="btn btn-sm btn-warning" role="button"><i class="glyphicon glyphicon-edit"></i></a></td>
|
||||||
|
<td><a href="{ROOT_URL}bookmarks/deleteBookmark/{ID}" class="btn btn-sm btn-danger" role="button"><i class="glyphicon glyphicon-trash"></i></a></td>
|
||||||
|
</tr>
|
||||||
|
{/LOOP}
|
||||||
|
{ALT}
|
||||||
|
<tr>
|
||||||
|
<td style="text-align: center;" colspan="6">
|
||||||
|
No results to show.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{/ALT}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<a href="{ROOT_URL}bookmarks/createBookmark" class="btn btn-sm btn-primary" role="button">Create</a>
|
84
app/plugins/bookmarks/views/bookmarks/view.html
Normal file
84
app/plugins/bookmarks/views/bookmarks/view.html
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
{BookmarkBreadCrumbs}<br />
|
||||||
|
<div class="container col-md-4 col-lg-4">
|
||||||
|
<div class="row">
|
||||||
|
<div class="panel panel-{color}">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<h3 class="panel-title">Bookmark</h3>
|
||||||
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<div class="row">
|
||||||
|
<div class="">
|
||||||
|
<table class="table table-user-primary">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td align="left" width="200"><b>Title</b></td>
|
||||||
|
<td align="right">{title}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td align="left" width="200"><b>URL</b></td>
|
||||||
|
<td align="right">{url}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td align="left" width="200"><b>Type</b></td>
|
||||||
|
<td align="right">{linkType}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td align="left" width="200"><b>Privacy</b></td>
|
||||||
|
<td align="right">{privacy}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td align="left" width="200"><b>Color</b></td>
|
||||||
|
<td align="right">{color}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td align="center" colspan="2"><b>Description</b></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">{description}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td align="center" colspan="2"><b>Icon</b></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">{iconHtml}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">{icon}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td align="center" colspan="2"><b>Meta</b></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">{meta}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><b>Created</b></td>
|
||||||
|
<td align="right">{DTC}{createdAt}{/DTC}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><b>Archived</b></td>
|
||||||
|
<td align="right">{DTC}{archivedAt}{/DTC}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><b>Hidden</b></td>
|
||||||
|
<td align="right">{DTC}{hiddenAt}{/DTC}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><b>Last Refreshed</b></td>
|
||||||
|
<td align="right">{DTC}{refreshedAt}{/DTC}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="panel-footer">
|
||||||
|
{refreshBtn}
|
||||||
|
{hideBtn}
|
||||||
|
{archiveBtn}
|
||||||
|
<a href="{ROOT_URL}bookmarks/editBookmark/{ID}" class="btn btn-sm btn-warning" role="button"><i class="glyphicon glyphicon-edit"></i></a>
|
||||||
|
<a href="{ROOT_URL}bookmarks/deleteBookmark/{ID}" class="btn btn-sm btn-danger" role="button"><i class="glyphicon glyphicon-trash"></i></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
@ -0,0 +1,21 @@
|
|||||||
|
<div class="panel panel-{color}">
|
||||||
|
<div class="panel-heading" data-target="#Collapse{ID}" data-toggle="collapse" aria-expanded="true" aria-controls="#Collapse{ID}">
|
||||||
|
{title}
|
||||||
|
</div>
|
||||||
|
<div id="Collapse{ID}" class="panel-collapse collapse in" style="width:100%; position: relative;" role="tabpanel" aria-expanded="true">
|
||||||
|
<div class="panel-body">
|
||||||
|
<ul class="list-group">
|
||||||
|
{bookmarkListRows}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="panel-footer">
|
||||||
|
<a href="{ROOT_URL}bookmarks/createBookmark/{ID}" class="btn btn-sm btn-success" role="button"><i class="glyphicon glyphicon-plus-sign"></i></a></td>
|
||||||
|
<span class="pull-right">
|
||||||
|
<a href="{ROOT_URL}bookmarks/bookmarks/{ID}" class="btn btn-sm btn-primary" role="button"><i class="glyphicon glyphicon-th-list"></i></a>
|
||||||
|
<a href="{ROOT_URL}bookmarks/folders/{ID}" class="btn btn-sm btn-primary" role="button"><i class="glyphicon glyphicon-info-sign"></i></a></td>
|
||||||
|
<a href="{ROOT_URL}bookmarks/editFolder/{ID}" class="btn btn-sm btn-warning" role="button"><i class="glyphicon glyphicon-edit"></i></a></td>
|
||||||
|
<a href="{ROOT_URL}bookmarks/deleteFolder/{ID}" class="btn btn-sm btn-danger" role="button"><i class="glyphicon glyphicon-trash"></i></a></td>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
18
app/plugins/bookmarks/views/components/bookmarkListRows.html
Normal file
18
app/plugins/bookmarks/views/components/bookmarkListRows.html
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
|
||||||
|
{LOOP}
|
||||||
|
<li class="list-group-item list-group-item-{color}">
|
||||||
|
<a href="{ROOT_URL}bookmarks/bookmarks/{ID}" class="btn btn-sm" role="button">{iconHtml}</a>
|
||||||
|
<a href="{url}" class="list-group"> {title}</a>
|
||||||
|
<span class="pull-right">
|
||||||
|
{hideBtn}
|
||||||
|
{archiveBtn}
|
||||||
|
<a href="{ROOT_URL}bookmarks/editBookmark/{ID}" class="btn btn-sm btn-warning" role="button"><i class="glyphicon glyphicon-edit"></i></a>
|
||||||
|
<a href="{ROOT_URL}bookmarks/deleteBookmark/{ID}" class="btn btn-sm btn-danger" role="button"><i class="glyphicon glyphicon-trash"></i></a>
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
{/LOOP}
|
||||||
|
{ALT}
|
||||||
|
<li class="list-group-item">
|
||||||
|
<a href="#" class="list-group">No Bookmarks</a>
|
||||||
|
</li>
|
||||||
|
{/ALT}
|
10
app/plugins/bookmarks/views/components/folderPanelList.html
Normal file
10
app/plugins/bookmarks/views/components/folderPanelList.html
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{LOOP}
|
||||||
|
<div class="col-xlg-6 col-lg-6 col-md-6 col-sm-6 col-xs-6">
|
||||||
|
{panel}
|
||||||
|
</div>
|
||||||
|
{/LOOP}
|
||||||
|
{ALT}
|
||||||
|
<div class="col-xlg-6 col-lg-6 col-md-6 col-sm-6 col-xs-6">
|
||||||
|
<p>no folders</p>
|
||||||
|
</div>
|
||||||
|
{/ALT}
|
16
app/plugins/bookmarks/views/dash.html
Normal file
16
app/plugins/bookmarks/views/dash.html
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
|
||||||
|
{BookmarkBreadCrumbs}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xlg-6 col-lg-6 col-md-6 col-sm-6 col-xs-6">
|
||||||
|
<legend>Unsorted Bookmarks</legend>
|
||||||
|
{bookmarksList}
|
||||||
|
</div>
|
||||||
|
<div class="col-xlg-6 col-lg-6 col-md-6 col-sm-6 col-xs-6">
|
||||||
|
<legend>Folders List</legend>
|
||||||
|
{foldersList}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<legend>Folders</legend>
|
||||||
|
<div class="row">
|
||||||
|
{folderPanels}
|
||||||
|
</div>
|
39
app/plugins/bookmarks/views/folders/create.html
Normal file
39
app/plugins/bookmarks/views/folders/create.html
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<legend>Create Folder</legend>
|
||||||
|
{BookmarkBreadCrumbs}
|
||||||
|
<form action="" method="post" class="form-horizontal">
|
||||||
|
<input type="hidden" name="token" value="{TOKEN}">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="title" class="col-lg-3 control-label">Title</label>
|
||||||
|
<div class="col-lg-3">
|
||||||
|
<input type="text" class="form-control" name="title" id="title">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="description" class="col-lg-3 control-label">Description:</label>
|
||||||
|
<div class="col-lg-3">
|
||||||
|
<textarea class="form-control" name="description" maxlength="2000" rows="10" cols="50" id="description"></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{folderSelect}
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="privacy" class="col-lg-3 control-label">Privacy</label>
|
||||||
|
<div class="col-lg-3 select-container" id="colorContainer">
|
||||||
|
<select id="privacy" name="privacy" class="form-control custom-select">
|
||||||
|
<option value="private">Private</option>
|
||||||
|
<option value="public">Public</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="color" class="col-lg-3 control-label">Color</label>
|
||||||
|
<div class="col-lg-3 select-container" id="colorContainer">
|
||||||
|
{colorSelect}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="submit" class="col-lg-3 control-label"></label>
|
||||||
|
<div class="col-lg-3">
|
||||||
|
<button name="submit" value="submit" type="submit" class="btn btn-lg btn-primary center-block ">Submit</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
39
app/plugins/bookmarks/views/folders/edit.html
Normal file
39
app/plugins/bookmarks/views/folders/edit.html
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
<legend>Edit Folder</legend>
|
||||||
|
{BookmarkBreadCrumbs}
|
||||||
|
<form action="" method="post" class="form-horizontal">
|
||||||
|
<input type="hidden" name="token" value="{TOKEN}">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="title" class="col-lg-3 control-label">Title</label>
|
||||||
|
<div class="col-lg-3">
|
||||||
|
<input type="text" class="form-control" name="title" id="title" value="{title}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="description" class="col-lg-3 control-label">Description:</label>
|
||||||
|
<div class="col-lg-3">
|
||||||
|
<textarea class="form-control" name="description" maxlength="2000" rows="10" cols="50" id="description">{description}</textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{folderSelect}
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="privacy" class="col-lg-3 control-label">Privacy</label>
|
||||||
|
<div class="col-lg-3 select-container" id="colorContainer">
|
||||||
|
<select id="privacy" name="privacy" class="form-control custom-select" value="{privacy}">
|
||||||
|
<option value="private">Private</option>
|
||||||
|
<option value="public">Public</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="color" class="col-lg-3 control-label">Color</label>
|
||||||
|
<div class="col-lg-3 select-container" id="colorContainer">
|
||||||
|
{colorSelect}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="submit" class="col-lg-3 control-label"></label>
|
||||||
|
<div class="col-lg-3">
|
||||||
|
<button name="submit" value="submit" type="submit" class="btn btn-lg btn-primary center-block ">Submit</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
33
app/plugins/bookmarks/views/folders/list.html
Normal file
33
app/plugins/bookmarks/views/folders/list.html
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
{BookmarkBreadCrumbs}
|
||||||
|
<table class="table table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th style="width: 35%">Title</th>
|
||||||
|
<th style="width: 20%">Privacy</th>
|
||||||
|
<th style="width: 30%">Description</th>
|
||||||
|
<th style="width: 5%"></th>
|
||||||
|
<th style="width: 5%"></th>
|
||||||
|
<th style="width: 5%"></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{LOOP}
|
||||||
|
<tr>
|
||||||
|
<td align="center">{title}</td>
|
||||||
|
<td align="center">{privacy}</td>
|
||||||
|
<td>{description}</td>
|
||||||
|
<td><a href="{ROOT_URL}bookmarks/folders/{ID}" class="btn btn-sm btn-primary" role="button"><i class="glyphicon glyphicon-info-sign"></i></a></td>
|
||||||
|
<td><a href="{ROOT_URL}bookmarks/editFolder/{ID}" class="btn btn-sm btn-warning" role="button"><i class="glyphicon glyphicon-edit"></i></a></td>
|
||||||
|
<td><a href="{ROOT_URL}bookmarks/deleteFolder/{ID}" class="btn btn-sm btn-danger" role="button"><i class="glyphicon glyphicon-trash"></i></a></td>
|
||||||
|
</tr>
|
||||||
|
{/LOOP}
|
||||||
|
{ALT}
|
||||||
|
<tr>
|
||||||
|
<td align="center" colspan="7">
|
||||||
|
No results to show.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{/ALT}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<a href="{ROOT_URL}bookmarks/createFolder" class="btn btn-sm btn-primary" role="button">Create</a>
|
47
app/plugins/bookmarks/views/folders/view.html
Normal file
47
app/plugins/bookmarks/views/folders/view.html
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
{BookmarkBreadCrumbs}<br />
|
||||||
|
<div class="container col-md-4 col-lg-4">
|
||||||
|
<div class="row">
|
||||||
|
<div class="panel panel-{color}">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<h3 class="panel-title">Bookmark Folder</h3>
|
||||||
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<div class="row">
|
||||||
|
<div class="">
|
||||||
|
<table class="table table-user-primary">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td align="left" width="200"><b>Title</b></td>
|
||||||
|
<td align="right">{title}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td align="left" width="200"><b>Privacy</b></td>
|
||||||
|
<td align="right">{privacy}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td align="left" width="200"><b>Color</b></td>
|
||||||
|
<td align="right">{color}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td align="center" colspan="2"><b>Description</b></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">{description}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><b>Created</b></td>
|
||||||
|
<td align="right">{DTC}{createdAt}{/DTC}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="panel-footer">
|
||||||
|
<a href="{ROOT_URL}bookmarks/bookmarks/{ID}" class="btn btn-sm btn-primary" role="button"><i class="glyphicon glyphicon-th-list"></i></a>
|
||||||
|
<a href="{ROOT_URL}bookmarks/editFolder/{ID}" class="btn btn-sm btn-warning" role="button"><i class="glyphicon glyphicon-edit"></i></a>
|
||||||
|
<a href="{ROOT_URL}bookmarks/deleteFolder/{ID}" class="btn btn-sm btn-danger" role="button"><i class="glyphicon glyphicon-trash"></i></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
5
app/plugins/bookmarks/views/nav/folderTabs.html
Normal file
5
app/plugins/bookmarks/views/nav/folderTabs.html
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<ul class="nav nav-tabs">
|
||||||
|
<li><a href="{ROOT_URL}bookmarks/index/">Dashboard</a></li>
|
||||||
|
<li><a href="{ROOT_URL}bookmarks/folders/">Folders</a></li>
|
||||||
|
</ul>
|
||||||
|
{userFolderTabs}
|
9
app/plugins/bookmarks/views/nav/userFolderTabs.html
Normal file
9
app/plugins/bookmarks/views/nav/userFolderTabs.html
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<ul class="nav nav-tabs">
|
||||||
|
<li><a href="{ROOT_URL}bookmarks/folders/">All</a></li>
|
||||||
|
{LOOP}
|
||||||
|
<li><a href="{ROOT_URL}bookmarks/bookmarks/{ID}">{title}</a></li>
|
||||||
|
{/LOOP}
|
||||||
|
{ALT}
|
||||||
|
<li></li>
|
||||||
|
{/ALT}
|
||||||
|
</ul>
|
@ -14,8 +14,8 @@ namespace TheTempusProject\Models;
|
|||||||
|
|
||||||
use TheTempusProject\Bedrock\Functions\Check;
|
use TheTempusProject\Bedrock\Functions\Check;
|
||||||
use TheTempusProject\Bedrock\Classes\Config;
|
use TheTempusProject\Bedrock\Classes\Config;
|
||||||
use TheTempusProject\Canary\Bin\Canary as Debug;
|
use TheTempusProject\Canary\Canary as Debug;
|
||||||
use TheTempusProject\Canary\Classes\CustomException;
|
use TheTempusProject\Bedrock\Classes\CustomException;
|
||||||
use TheTempusProject\Classes\DatabaseModel;
|
use TheTempusProject\Classes\DatabaseModel;
|
||||||
use TheTempusProject\Plugins\Bugreport as Plugin;
|
use TheTempusProject\Plugins\Bugreport as Plugin;
|
||||||
use TheTempusProject\TheTempusProject as App;
|
use TheTempusProject\TheTempusProject as App;
|
||||||
|
7
app/plugins/bugtracker/config/constants.php
Normal file
7
app/plugins/bugtracker/config/constants.php
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?php
|
||||||
|
# bugTracker
|
||||||
|
define( 'TRACKER_STATUS_IN_PROGRESS', 'In Progress' );
|
||||||
|
define( 'TRACKER_STATUS_TESTING', 'Needs Testing' );
|
||||||
|
define( 'TRACKER_STATUS_NEW', 'New' );
|
||||||
|
define( 'TRACKER_STATUS_FIXED', 'Fixed' );
|
||||||
|
define( 'TRACKER_STATUS_CLOSED', 'Closed' );
|
206
app/plugins/bugtracker/controllers/admin/bugtracker.php
Normal file
206
app/plugins/bugtracker/controllers/admin/bugtracker.php
Normal file
@ -0,0 +1,206 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* app/plugins/bugtracker/controllers/admin/bugtracker.php
|
||||||
|
*
|
||||||
|
* This is the Bug-Tracker admin controller.
|
||||||
|
*
|
||||||
|
* @package TP BugTracker
|
||||||
|
* @version 3.0
|
||||||
|
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||||
|
* @link https://TheTempusProject.com
|
||||||
|
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||||
|
*/
|
||||||
|
namespace TheTempusProject\Controllers\Admin;
|
||||||
|
|
||||||
|
use TheTempusProject\Bedrock\Functions\Check;
|
||||||
|
use TheTempusProject\Bedrock\Functions\Upload;
|
||||||
|
use TheTempusProject\Bedrock\Functions\Input;
|
||||||
|
use TheTempusProject\Houdini\Classes\Issues;
|
||||||
|
use TheTempusProject\Houdini\Classes\Views;
|
||||||
|
use TheTempusProject\Houdini\Classes\Navigation;
|
||||||
|
use TheTempusProject\Houdini\Classes\Components;
|
||||||
|
use TheTempusProject\Houdini\Classes\Forms as FormGen;
|
||||||
|
use TheTempusProject\Classes\AdminController;
|
||||||
|
use TheTempusProject\Classes\Forms;
|
||||||
|
use TheTempusProject\Models\Bugtracker as BugtrackerModel;
|
||||||
|
use TheTempusProject\TheTempusProject as App;
|
||||||
|
use TheTempusProject\Models\Comments;
|
||||||
|
|
||||||
|
class Bugtracker extends AdminController {
|
||||||
|
protected static $tracker;
|
||||||
|
protected static $comments;
|
||||||
|
|
||||||
|
public function __construct() {
|
||||||
|
parent::__construct();
|
||||||
|
self::$tracker = new BugtrackerModel;
|
||||||
|
self::$title = 'Admin - Bug-Tracker';
|
||||||
|
$view = Navigation::activePageSelect( 'nav.admin', '/admin/bugtracker' );
|
||||||
|
Components::set( 'ADMINNAV', $view );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function index( $data = null ) {
|
||||||
|
Views::view( 'bugtracker.admin.list', self::$tracker->list() );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function create( $data = null ) {
|
||||||
|
$form = '';
|
||||||
|
$form .= FormGen::getFormFieldHtml( 'title', 'Title', 'text', Input::post('title') );
|
||||||
|
$form .= FormGen::getFormFieldHtml( 'description', 'Description', 'block', Input::post('description') );
|
||||||
|
$form .= FormGen::getFormFieldHtml( 'bugImage', 'Screenshot', 'file', '' );
|
||||||
|
$form .= FormGen::getFormFieldHtml( 'url', 'URL (if possible)', 'text', '' );
|
||||||
|
$form .= FormGen::getFormFieldHtml( 'repeat', 'Has this happened more than once', 'radio' );
|
||||||
|
Components::set( 'TRACKER_FORM', $form );
|
||||||
|
if ( !Input::exists( 'submit' ) ) {
|
||||||
|
return Views::view( 'bugtracker.admin.create' );
|
||||||
|
}
|
||||||
|
if ( !Forms::check( 'newBugTracker' ) ) {
|
||||||
|
Issues::add( 'error', [ 'There was an error with your request.' => Check::userErrors() ] );
|
||||||
|
return Views::view( 'bugtracker.admin.create' );
|
||||||
|
}
|
||||||
|
$image = '';
|
||||||
|
if ( Input::exists( 'bugImage' ) ) {
|
||||||
|
$folder = IMAGE_UPLOAD_DIRECTORY . App::$activeUser->username . DIRECTORY_SEPARATOR;
|
||||||
|
if ( !Upload::image( 'bugImage', $folder ) ) {
|
||||||
|
Issues::add( 'error', [ 'There was an error with your upload.' => Check::systemErrors() ] );
|
||||||
|
} else {
|
||||||
|
$route = str_replace( APP_ROOT_DIRECTORY, '', $folder );
|
||||||
|
$image = $route . Upload::last();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$result = self::$tracker->create(
|
||||||
|
App::$activeUser->ID,
|
||||||
|
Input::post( 'url' ),
|
||||||
|
$image,
|
||||||
|
Input::post( 'repeat' ),
|
||||||
|
Input::post( 'description' ),
|
||||||
|
Input::post( 'title' ),
|
||||||
|
);
|
||||||
|
if ( $result ) {
|
||||||
|
Issues::add( 'success', 'Your tracker has been created.' );
|
||||||
|
return $this->index();
|
||||||
|
} else {
|
||||||
|
Issues::add( 'error', [ 'There was an unknown error submitting your data.' => Check::userErrors() ] );
|
||||||
|
return $this->index();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function edit( $data = null ) {
|
||||||
|
if ( !Input::exists( 'submit' ) ) {
|
||||||
|
$bug = self::$tracker->findById( $data );
|
||||||
|
$statusList = [
|
||||||
|
TRACKER_STATUS_IN_PROGRESS => TRACKER_STATUS_IN_PROGRESS,
|
||||||
|
TRACKER_STATUS_TESTING => TRACKER_STATUS_TESTING,
|
||||||
|
TRACKER_STATUS_NEW => TRACKER_STATUS_NEW,
|
||||||
|
TRACKER_STATUS_FIXED => TRACKER_STATUS_FIXED,
|
||||||
|
TRACKER_STATUS_CLOSED => TRACKER_STATUS_CLOSED,
|
||||||
|
];
|
||||||
|
$form = '';
|
||||||
|
$form .= FormGen::getFormFieldHtml( 'title', 'Title', 'text', $bug->title );
|
||||||
|
$form .= FormGen::getFormFieldHtml( 'description', 'Description', 'block', $bug->description );
|
||||||
|
$form .= FormGen::getFormFieldHtml( 'bugImage', 'Screenshot', 'file', $bug->image );
|
||||||
|
$form .= FormGen::getFormFieldHtml( 'url', 'Page you were on', 'text', $bug->url );
|
||||||
|
$form .= FormGen::getFormFieldHtml( 'repeat', 'Has this happened more than once', 'radio', $bug->repeatable );
|
||||||
|
$form .= FormGen::getFormFieldHtml( 'status', 'Status', 'customSelect', $bug->status, $statusList );
|
||||||
|
Components::set( 'TRACKER_FORM', $form );
|
||||||
|
return Views::view( 'bugtracker.admin.edit', $bug );
|
||||||
|
}
|
||||||
|
if ( !Forms::check( 'editBugTracker' ) ) {
|
||||||
|
Issues::add( 'error', [ 'There was an error with your form.' => Check::userErrors() ] );
|
||||||
|
return $this->index();
|
||||||
|
}
|
||||||
|
$image = '';
|
||||||
|
if ( Input::exists( 'bugImage' ) ) {
|
||||||
|
$folder = IMAGE_UPLOAD_DIRECTORY . App::$activeUser->username . DIRECTORY_SEPARATOR;
|
||||||
|
if ( !Upload::image( 'bugImage', $folder ) ) {
|
||||||
|
Issues::add( 'error', [ 'There was an error with your upload.' => Check::systemErrors() ] );
|
||||||
|
} else {
|
||||||
|
$image = $folder . Upload::last();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$tracker = self::$tracker->updateTracker(
|
||||||
|
$data,
|
||||||
|
Input::post( 'url' ),
|
||||||
|
$image,
|
||||||
|
Input::post( 'repeat' ),
|
||||||
|
Input::post( 'description' ),
|
||||||
|
Input::post( 'title' ),
|
||||||
|
Input::post( 'status' )
|
||||||
|
);
|
||||||
|
if ( true === $tracker ) {
|
||||||
|
Issues::add( 'success', 'Tracker Updated.' );
|
||||||
|
return $this->index();
|
||||||
|
}
|
||||||
|
Issues::add( 'error', 'There was an error with your request.' );
|
||||||
|
$this->index();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function view( $id = null ) {
|
||||||
|
if ( empty( self::$comments ) ) {
|
||||||
|
self::$comments = new Comments;
|
||||||
|
}
|
||||||
|
$data = self::$tracker->findById( $id );
|
||||||
|
if ( $data === false ) {
|
||||||
|
Issues::add( 'error', 'Tracker not found.' );
|
||||||
|
return $this->index();
|
||||||
|
}
|
||||||
|
if ( Input::exists( 'contentId' ) ) {
|
||||||
|
$this->comments( 'post', Input::post( 'contentId' ) );
|
||||||
|
}
|
||||||
|
if ( empty( self::$comments ) ) {
|
||||||
|
self::$comments = new Comments;
|
||||||
|
}
|
||||||
|
Components::set( 'CONTENT_ID', $id );
|
||||||
|
Components::set( 'COMMENT_TYPE', 'admin/bugtracker' );
|
||||||
|
Components::set( 'count', self::$comments->count( 'tracker', $id ) );
|
||||||
|
Components::set( 'NEWCOMMENT', Views::simpleView( 'comments.create' ) );
|
||||||
|
Components::set( 'COMMENTS', Views::simpleView( 'comments.list', self::$comments->display( 10, 'tracker', $id ) ) );
|
||||||
|
Views::view( 'bugtracker.admin.view', $data );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function delete( $data = null ) {
|
||||||
|
if ( $data == null ) {
|
||||||
|
if ( Input::exists( 'T_' ) ) {
|
||||||
|
$data = Input::post( 'T_' );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( !self::$tracker->delete( $data ) ) {
|
||||||
|
Issues::add( 'error', 'There was an error with your request.' );
|
||||||
|
} else {
|
||||||
|
Issues::add( 'success', 'Tracker has been deleted' );
|
||||||
|
}
|
||||||
|
$this->index();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function comments( $sub = null, $data = null ) {
|
||||||
|
if ( empty( self::$comments ) ) {
|
||||||
|
self::$comments = new Comments;
|
||||||
|
}
|
||||||
|
if ( empty( $sub ) || empty( $data ) ) {
|
||||||
|
Session::flash( 'error', 'Whoops, try again.' );
|
||||||
|
Redirect::to( 'admin/bugtracker' );
|
||||||
|
}
|
||||||
|
switch ( $sub ) {
|
||||||
|
case 'post':
|
||||||
|
$content = self::$tracker->findById( $data );
|
||||||
|
if ( empty( $content ) ) {
|
||||||
|
Session::flash( 'error', 'Unknown Post.' );
|
||||||
|
Redirect::to( 'admin/bugtracker' );
|
||||||
|
}
|
||||||
|
return self::$comments->formPost( 'tracker', $content, 'admin/bugtracker/view/' );
|
||||||
|
case 'edit':
|
||||||
|
$content = self::$comments->findById( $data );
|
||||||
|
if ( empty( $content ) ) {
|
||||||
|
Session::flash( 'error', 'Unknown Comment.' );
|
||||||
|
Redirect::to( 'admin/bugtracker' );
|
||||||
|
}
|
||||||
|
return self::$comments->formEdit( 'tracker', $content, 'admin/bugtracker/view/' );
|
||||||
|
case 'delete':
|
||||||
|
$content = self::$comments->findById( $data );
|
||||||
|
if ( empty( $content ) ) {
|
||||||
|
Session::flash( 'error', 'Unknown Comment.' );
|
||||||
|
Redirect::to( 'admin/bugtracker' );
|
||||||
|
}
|
||||||
|
return self::$comments->formDelete( 'tracker', $content, 'admin/bugtracker/view/' );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
92
app/plugins/bugtracker/forms.php
Normal file
92
app/plugins/bugtracker/forms.php
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* app/plugins/bugtracker/forms.php
|
||||||
|
*
|
||||||
|
* This houses all of the form checking functions for this plugin.
|
||||||
|
*
|
||||||
|
* @package TP BugTracker
|
||||||
|
* @version 3.0
|
||||||
|
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||||
|
* @link https://TheTempusProject.com
|
||||||
|
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||||
|
*/
|
||||||
|
namespace TheTempusProject\Plugins\Bugreport;
|
||||||
|
|
||||||
|
use TheTempusProject\Bedrock\Functions\Input;
|
||||||
|
use TheTempusProject\Classes\Forms;
|
||||||
|
|
||||||
|
class BugTrackerForms extends Forms {
|
||||||
|
/**
|
||||||
|
* Adds these functions to the form list.
|
||||||
|
*/
|
||||||
|
public function __construct() {
|
||||||
|
self::addHandler( 'newBugTracker', __CLASS__, 'newBugTracker' );
|
||||||
|
self::addHandler( 'editBugTracker', __CLASS__, 'editBugTracker' );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates the bug tracker create form.
|
||||||
|
*
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
public static function newBugTracker() {
|
||||||
|
if ( !empty(Input::post( 'url' )) && !self::url( Input::post( 'url' ) ) ) {
|
||||||
|
self::addUserError( 'Invalid url: <code>' . Input::post( 'url' ) . '</code>' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !self::tf( Input::post( 'repeat' ) ) ) {
|
||||||
|
self::addUserError( 'Invalid repeat value: ' . Input::post( 'repeat' ) );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !Input::exists( 'title' ) ) {
|
||||||
|
self::addUserError( 'You must specify title' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !self::dataTitle( Input::post( 'title' ) ) ) {
|
||||||
|
self::addUserError( 'Invalid title' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !Input::exists( 'description' ) ) {
|
||||||
|
self::addUserError( 'You must specify a description' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// if ( !self::token() ) {
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates the bug tracker create form.
|
||||||
|
*
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
public static function editBugTracker() {
|
||||||
|
if ( !empty(Input::post( 'url' )) && !self::url( Input::post( 'url' ) ) ) {
|
||||||
|
self::addUserError( 'Invalid url.' . Input::post( 'url' ) );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !self::tf( Input::post( 'repeat' ) ) ) {
|
||||||
|
self::addUserError( 'Invalid repeat value.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !Input::exists( 'title' ) ) {
|
||||||
|
self::addUserError( 'You must specify title' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !self::dataTitle( Input::post( 'title' ) ) ) {
|
||||||
|
self::addUserError( 'Invalid title' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !Input::exists( 'description' ) ) {
|
||||||
|
self::addUserError( 'You must specify a description' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// if ( !self::token() ) {
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
new BugTrackerForms;
|
142
app/plugins/bugtracker/models/bugtracker.php
Normal file
142
app/plugins/bugtracker/models/bugtracker.php
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* app/plugins/bugtracker/models/bugtracker.php
|
||||||
|
*
|
||||||
|
* This class is used for the manipulation of the bugs database table.
|
||||||
|
*
|
||||||
|
* @package TP BugTracker
|
||||||
|
* @version 3.0
|
||||||
|
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||||
|
* @link https://TheTempusProject.com
|
||||||
|
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||||
|
*/
|
||||||
|
namespace TheTempusProject\Models;
|
||||||
|
|
||||||
|
use TheTempusProject\Bedrock\Functions\Check;
|
||||||
|
use TheTempusProject\Bedrock\Classes\Config;
|
||||||
|
use TheTempusProject\Canary\Canary as Debug;
|
||||||
|
use TheTempusProject\Bedrock\Classes\CustomException;
|
||||||
|
use TheTempusProject\Classes\DatabaseModel;
|
||||||
|
use TheTempusProject\TheTempusProject as App;
|
||||||
|
use TheTempusProject\Plugins\Bugtracker as Plugin;
|
||||||
|
|
||||||
|
class Bugtracker extends DatabaseModel {
|
||||||
|
public $tableName = 'bugs';
|
||||||
|
public $databaseMatrix = [
|
||||||
|
[ 'userID', 'int', '11' ],
|
||||||
|
[ 'time', 'int', '10' ],
|
||||||
|
[ 'title', 'varchar', '128' ],
|
||||||
|
[ 'status', 'varchar', '64' ],
|
||||||
|
[ 'description', 'text', '' ],
|
||||||
|
[ 'image', 'varchar', '256' ],
|
||||||
|
[ 'repeatable', 'varchar', '5' ],
|
||||||
|
[ 'url', 'varchar', '256' ],
|
||||||
|
];
|
||||||
|
public $plugin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The model constructor.
|
||||||
|
*/
|
||||||
|
public function __construct() {
|
||||||
|
parent::__construct();
|
||||||
|
$this->plugin = new Plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function parses the bug reports description and
|
||||||
|
* separates it into separate keys in the array.
|
||||||
|
*
|
||||||
|
* @param array $data - The data being parsed.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function filter( $data, $params = [] ) {
|
||||||
|
foreach ( $data as $instance ) {
|
||||||
|
if ( !is_object( $instance ) ) {
|
||||||
|
$instance = $data;
|
||||||
|
$end = true;
|
||||||
|
}
|
||||||
|
$instance->submittedBy = self::$user->getUsername( $instance->userID );
|
||||||
|
$instance->repeatText = ( 'false' == $instance->repeatable ? 'no' : 'yes' );
|
||||||
|
$out[] = $instance;
|
||||||
|
if ( !empty( $end ) ) {
|
||||||
|
$out = $out[0];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs a Bug Report form.
|
||||||
|
*
|
||||||
|
* @param int $ID the user ID submitting the form
|
||||||
|
* @param string $url the url
|
||||||
|
* @param string $o_url the original url
|
||||||
|
* @param int $repeat is repeatable?
|
||||||
|
* @param string $description_ description of the event.
|
||||||
|
*
|
||||||
|
* @return null
|
||||||
|
*/
|
||||||
|
public function create( $ID, $url, $image, $repeat, $description, $title ) {
|
||||||
|
if ( !$this->plugin->checkEnabled() ) {
|
||||||
|
Debug::info( 'Bug Tracking is disabled in the config.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !Check::dataTitle( $title ) ) {
|
||||||
|
Debug::info( 'bugTracker: illegal title.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$fields = [
|
||||||
|
'userID' => App::$activeUser->ID,
|
||||||
|
'time' => time(),
|
||||||
|
'title' => $title,
|
||||||
|
'status' => TRACKER_STATUS_NEW,
|
||||||
|
'description' => $description,
|
||||||
|
'image' => $image,
|
||||||
|
'repeatable' => $repeat,
|
||||||
|
'url' => $url,
|
||||||
|
];
|
||||||
|
if ( !self::$db->insert( $this->tableName, $fields ) ) {
|
||||||
|
new CustomException( $this->tableName );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return self::$db->lastId();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function updateTracker( $ID, $url, $image, $repeat, $description, $title, $status ) {
|
||||||
|
if ( !$this->plugin->checkEnabled() ) {
|
||||||
|
Debug::info( 'Bug Tracking is disabled in the config.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( empty( self::$log ) ) {
|
||||||
|
self::$log = new Log;
|
||||||
|
}
|
||||||
|
if ( !Check::id( $ID ) ) {
|
||||||
|
Debug::info( 'bugTracker: illegal ID.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !Check::dataTitle( $title ) ) {
|
||||||
|
Debug::info( 'bugTracker: illegal title.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$fields = [
|
||||||
|
'url' => $url,
|
||||||
|
'description' => $description,
|
||||||
|
'repeatable' => $repeat,
|
||||||
|
'title' => $title,
|
||||||
|
'status' => $status,
|
||||||
|
];
|
||||||
|
if ( !empty( $image ) ) {
|
||||||
|
$fields['image'] = $image;
|
||||||
|
}
|
||||||
|
if ( !self::$db->update( $this->tableName, $ID, $fields ) ) {
|
||||||
|
new CustomException( $this->tableName );
|
||||||
|
Debug::error( "Tracker Post: $ID not updated: $fields" );
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
self::$log->admin( "Updated Tracker Post: $ID" );
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
48
app/plugins/bugtracker/plugin.php
Normal file
48
app/plugins/bugtracker/plugin.php
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* app/plugins/bugtracker/plugin.php
|
||||||
|
*
|
||||||
|
* This houses all of the main plugin info and functionality.
|
||||||
|
*
|
||||||
|
* @package TP BugTracker
|
||||||
|
* @version 3.0
|
||||||
|
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||||
|
* @link https://TheTempusProject.com
|
||||||
|
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||||
|
*/
|
||||||
|
namespace TheTempusProject\Plugins;
|
||||||
|
|
||||||
|
use ReflectionClass;
|
||||||
|
use TheTempusProject\Classes\Installer;
|
||||||
|
use TheTempusProject\Houdini\Classes\Navigation;
|
||||||
|
use TheTempusProject\Classes\Plugin;
|
||||||
|
use TheTempusProject\TheTempusProject as App;
|
||||||
|
|
||||||
|
class Bugtracker extends Plugin {
|
||||||
|
public $pluginName = 'TP BugTracker';
|
||||||
|
public $pluginAuthor = 'JoeyK';
|
||||||
|
public $pluginWebsite = 'https://TheTempusProject.com';
|
||||||
|
public $modelVersion = '1.0';
|
||||||
|
public $pluginVersion = '3.0';
|
||||||
|
public $pluginDescription = '';
|
||||||
|
public $configName = 'bugtracker';
|
||||||
|
public $configMatrix = [
|
||||||
|
'enabled' => [
|
||||||
|
'type' => 'radio',
|
||||||
|
'pretty' => 'Enable Bug tracking.',
|
||||||
|
'default' => true,
|
||||||
|
],
|
||||||
|
];
|
||||||
|
public $permissionMatrix = [
|
||||||
|
'bugTrack' => [
|
||||||
|
'pretty' => 'Can Track Bugs',
|
||||||
|
'default' => false,
|
||||||
|
],
|
||||||
|
];
|
||||||
|
public $admin_links = [
|
||||||
|
[
|
||||||
|
'text' => '<i class="fa fa-fw fa-bug"></i> Bug Tracker',
|
||||||
|
'url' => '{ROOT_URL}admin/bugtracker',
|
||||||
|
],
|
||||||
|
];
|
||||||
|
}
|
6
app/plugins/bugtracker/views/admin/create.html
Normal file
6
app/plugins/bugtracker/views/admin/create.html
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<form action="" method="post" class="form-horizontal" enctype="multipart/form-data">
|
||||||
|
<legend>Create Bug Tracker</legend>
|
||||||
|
{TRACKER_FORM}
|
||||||
|
<input type="hidden" name="token" value="{TOKEN}">
|
||||||
|
<button name="submit" value="submit" type="submit" class="btn btn-lg btn-primary center-block">Save</button><br>
|
||||||
|
</form>
|
30
app/plugins/bugtracker/views/admin/dashboard.html
Normal file
30
app/plugins/bugtracker/views/admin/dashboard.html
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
<legend>New Bugs</legend>
|
||||||
|
<table class="table table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th style="width: 20%"></th>
|
||||||
|
<th style="width: 65%"></th>
|
||||||
|
<th style="width: 5%"></th>
|
||||||
|
<th style="width: 5%"></th>
|
||||||
|
<th style="width: 5%"></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{LOOP}
|
||||||
|
<tr>
|
||||||
|
<td>{title}</td>
|
||||||
|
<td>{description}</td>
|
||||||
|
<td><a href="{ROOT_URL}admin/bugtracker/view/{ID}" class="btn btn-sm btn-primary" role="button"><i class="glyphicon glyphicon-open"></i></a></td>
|
||||||
|
<td><a href="{ROOT_URL}admin/bugtracker/edit/{ID}" class="btn btn-sm btn-warning" role="button"><i class="glyphicon glyphicon-edit"></i></a></td>
|
||||||
|
<td width="30px"><a href="{ROOT_URL}admin/bugtracker/delete/{ID}" class="btn btn-sm btn-danger" role="button"><i class="glyphicon glyphicon-trash"></i></a></td>
|
||||||
|
</tr>
|
||||||
|
{/LOOP}
|
||||||
|
{ALT}
|
||||||
|
<tr>
|
||||||
|
<td align="center" colspan="5">
|
||||||
|
No results to show.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{/ALT}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
6
app/plugins/bugtracker/views/admin/edit.html
Normal file
6
app/plugins/bugtracker/views/admin/edit.html
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<form action="" method="post" class="form-horizontal" enctype="multipart/form-data">
|
||||||
|
<legend>Edit Bug Tracker</legend>
|
||||||
|
{TRACKER_FORM}
|
||||||
|
<input type="hidden" name="token" value="{TOKEN}">
|
||||||
|
<button name="submit" value="submit" type="submit" class="btn btn-lg btn-primary center-block">Save</button><br>
|
||||||
|
</form>
|
45
app/plugins/bugtracker/views/admin/list.html
Normal file
45
app/plugins/bugtracker/views/admin/list.html
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
<legend>Bug Trackers</legend>
|
||||||
|
{PAGINATION}
|
||||||
|
<form action="{ROOT_URL}admin/bugtracker/delete" method="post">
|
||||||
|
<table class="table table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th style="width: 30%">Title</th>
|
||||||
|
<th style="width: 40%">Description</th>
|
||||||
|
<th style="width: 10%">Status</th>
|
||||||
|
<th style="width: 5%">Time Submitted</th>
|
||||||
|
<th style="width: 5%"></th>
|
||||||
|
<th style="width: 5%"></th>
|
||||||
|
<th style="width: 5%">
|
||||||
|
<INPUT type="checkbox" onchange="checkAll(this)" name="check.br" value="T_[]"/>
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{LOOP}
|
||||||
|
<tr>
|
||||||
|
<td><a href="{ROOT_URL}admin/bugtracker/view/{ID}">{title}</a></td>
|
||||||
|
<td>{description}</td>
|
||||||
|
<td>{status}</td>
|
||||||
|
<td align="center">{DTC}{time}{/DTC}</td>
|
||||||
|
<td><a href="{ROOT_URL}admin/bugtracker/edit/{ID}" class="btn btn-sm btn-warning" role="button"><i class="glyphicon glyphicon-edit"></i></a></td>
|
||||||
|
<td><a href="{ROOT_URL}admin/bugtracker/delete/{ID}" class="btn btn-sm btn-danger" role="button"><i class="glyphicon glyphicon-trash"></i></a></td>
|
||||||
|
<td>
|
||||||
|
<input type="checkbox" value="{ID}" name="T_[]">
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{/LOOP}
|
||||||
|
{ALT}
|
||||||
|
<tr>
|
||||||
|
<td align="center" colspan="7">
|
||||||
|
No results to show.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{/ALT}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<button name="submit" value="submit" type="submit" class="btn btn-sm btn-danger">Delete</button>
|
||||||
|
<a href="{ROOT_URL}admin/bugtracker/create" class="btn btn-sm btn-primary" role="button">Create</a>
|
||||||
|
</form>
|
||||||
|
<br />
|
||||||
|
<a href="{ROOT_URL}admin/bugtracker/clear">clear all</a>
|
74
app/plugins/bugtracker/views/admin/view.html
Normal file
74
app/plugins/bugtracker/views/admin/view.html
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
<div class="container">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xs-12 col-sm-12 col-md-6 col-lg-6 col-xs-offset-0 col-sm-offset-0 col-md-offset-3 col-lg-offset-3 top-pad" >
|
||||||
|
<div class="panel panel-primary">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<h3 class="panel-title">Bug Tracker</h3>
|
||||||
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<div class="row">
|
||||||
|
<div class=" col-md-12 col-lg-12 ">
|
||||||
|
<table class="table table-user-primary">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td align="center" colspan="2">Title</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">{title}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td align="center" colspan="2">Description</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">{description}</td>
|
||||||
|
</tr>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
|
<div align="center">
|
||||||
|
<a href="{ROOT_URL}{image}"><img alt="Screenshot" src="{ROOT_URL}{image}" class="img-responsive"></a>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td align="left" width="200">Status</td>
|
||||||
|
<td align="right">{status}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td align="left" width="200">ID</td>
|
||||||
|
<td align="right">{ID}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Time submitted</td>
|
||||||
|
<td align="right">{DTC}{time}{/DTC}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Submitted by</td>
|
||||||
|
<td align="right"><a href="{ROOT_URL}admin/users/view/{userID}">{submittedBy}</a></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>URL:</td>
|
||||||
|
<td align="right">{URL}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Multiple occurrences?</td>
|
||||||
|
<td align="right">{repeatText}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="panel-footer">
|
||||||
|
{ADMIN}
|
||||||
|
<a href="{ROOT_URL}admin/bugtracker/delete/{ID}" class="btn btn-md btn-danger" role="button">Delete</a>
|
||||||
|
<a href="{ROOT_URL}admin/bugtracker/edit/{ID}" class="btn btn-md btn-warning" role="button">Edit</a>
|
||||||
|
<a href="{ROOT_URL}admin/comments/tracker/{ID}" class="btn btn-md btn-primary" role="button">View Comments</a>
|
||||||
|
{/ADMIN}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{COMMENTS}
|
||||||
|
{NEWCOMMENT}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
593
app/plugins/calendar/controllers/calendar.php
Normal file
593
app/plugins/calendar/controllers/calendar.php
Normal file
@ -0,0 +1,593 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* app/plugins/calendar/controllers/calendar.php
|
||||||
|
*
|
||||||
|
* This is the calendar controller.
|
||||||
|
*
|
||||||
|
* @package TP Calendar
|
||||||
|
* @version 3.0
|
||||||
|
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||||
|
* @link https://TheTempusProject.com
|
||||||
|
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||||
|
*/
|
||||||
|
namespace TheTempusProject\Controllers;
|
||||||
|
|
||||||
|
use TheTempusProject\Bedrock\Functions\Check;
|
||||||
|
use TheTempusProject\Bedrock\Functions\Input;
|
||||||
|
use TheTempusProject\Bedrock\Functions\Session;
|
||||||
|
use TheTempusProject\Bedrock\Functions\Date;
|
||||||
|
use TheTempusProject\Classes\Controller;
|
||||||
|
use TheTempusProject\Houdini\Classes\Forms as HoudiniForms;
|
||||||
|
use TheTempusProject\Classes\Forms;
|
||||||
|
use TheTempusProject\Houdini\Classes\Issues;
|
||||||
|
use TheTempusProject\Houdini\Classes\Views;
|
||||||
|
use TheTempusProject\Houdini\Classes\Template;
|
||||||
|
use TheTempusProject\Houdini\Classes\Components;
|
||||||
|
use TheTempusProject\Hermes\Functions\Redirect;
|
||||||
|
use TheTempusProject\TheTempusProject as App;
|
||||||
|
use TheTempusProject\Models\Events;
|
||||||
|
use TheTempusProject\Models\Calendars;
|
||||||
|
use TheTempusProject\Houdini\Classes\Navigation;
|
||||||
|
|
||||||
|
class Calendar extends Controller {
|
||||||
|
protected static $events;
|
||||||
|
protected static $calendars;
|
||||||
|
protected static $defaultView;
|
||||||
|
protected static $defaultCalendar;
|
||||||
|
protected static $selectedDate;
|
||||||
|
|
||||||
|
public function __construct() {
|
||||||
|
if ( !App::$isLoggedIn ) {
|
||||||
|
Session::flash( 'notice', 'You must be logged in to create or manage calendars.' );
|
||||||
|
return Redirect::home();
|
||||||
|
}
|
||||||
|
parent::__construct();
|
||||||
|
self::$title = 'Calendar - {SITENAME}';
|
||||||
|
self::$pageDescription = 'The {SITENAME} calendar is where you can find various features for creating and managing events and schedules.';
|
||||||
|
self::$events = new Events;
|
||||||
|
self::$calendars = new Calendars;
|
||||||
|
|
||||||
|
$prefs = App::$activePrefs;
|
||||||
|
if ( ! empty( $prefs['calendarPreference'] ) ) {
|
||||||
|
$view = $prefs['calendarPreference'];
|
||||||
|
} else {
|
||||||
|
Session::flash( 'info', 'You can select a default view for this page in your user settings in the top right.' );
|
||||||
|
$view = 'byMonth';
|
||||||
|
}
|
||||||
|
self::$defaultView = $view;
|
||||||
|
self::$selectedDate = intval( strtotime( Date::determineDateInput() ) );
|
||||||
|
|
||||||
|
Template::setTemplate( 'calendar' );
|
||||||
|
|
||||||
|
// Date Dropdown
|
||||||
|
$dateDropdownView = Views::simpleView('calendar.nav.dateDropdown', Date::getDateBreakdown( self::$selectedDate ) );
|
||||||
|
Components::set( 'dateDropdown', $dateDropdownView );
|
||||||
|
|
||||||
|
// Calendar Top Tabs
|
||||||
|
$calendarTabs = Views::simpleView('calendar.nav.topTabs');
|
||||||
|
$tabsView = Navigation::activePageSelect( $calendarTabs, Input::get( 'url' ), false, true );
|
||||||
|
// must be done after top-nav gets selected
|
||||||
|
$calendarDropdown = Views::simpleView('calendar.nav.calendarDropdown', self::$calendars->simpleObjectByUser() );
|
||||||
|
$calendarDropdownView = Navigation::activePageSelect( $calendarDropdown, Input::get( 'url' ), false, true ); // add notebookID as second param
|
||||||
|
Components::set( 'calendarDropdown', $calendarDropdownView);
|
||||||
|
// must be done after dropdown gets added
|
||||||
|
Components::set( 'CalendarNav', Template::parse( $calendarTabs ) );
|
||||||
|
}
|
||||||
|
public function index() {
|
||||||
|
if ( method_exists( $this, self::$defaultView ) ) {
|
||||||
|
Redirect::to( 'calendar/'.self::$defaultView.'/' );
|
||||||
|
} else {
|
||||||
|
Redirect::to( 'calendar/byMonth/' );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Events
|
||||||
|
*/
|
||||||
|
public function event( $id = null ) {
|
||||||
|
$event = $this->findEventOrFail( $id );
|
||||||
|
Views::view( 'calendar.events.view', $event );
|
||||||
|
}
|
||||||
|
public function createEvent() {
|
||||||
|
// get the url calendar input
|
||||||
|
$newCalendar = Input::get('calendar_id') ? Input::get('calendar_id') : '';// for loading the form
|
||||||
|
$calendarSelect = HoudiniForms::getFormFieldHtml( 'calendar_id', 'Calendar', 'select', $newCalendar, self::$calendars->simpleByUser() );
|
||||||
|
Components::set( 'calendarSelect', $calendarSelect );
|
||||||
|
|
||||||
|
$repeatSelect = HoudiniForms::getFormFieldHtml( 'repeats', 'Frequency', 'select', 'none', self::$events->repeatOptions );
|
||||||
|
Components::set( 'repeatSelect', $repeatSelect );
|
||||||
|
|
||||||
|
$dateSelect = Views::simpleView( 'calendar.dateSelect', $this->getEventBreakdown( self::$selectedDate ) );
|
||||||
|
Components::set( 'dateSelect', $dateSelect );
|
||||||
|
|
||||||
|
if ( ! Input::exists() ) {
|
||||||
|
return Views::view( 'calendar.events.create' );
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Attempt to save the form data somewhat */
|
||||||
|
// get the form calendar input
|
||||||
|
$calendarID = Input::post('calendar_id') ? Input::post('calendar_id') : ''; // for submitting the form
|
||||||
|
$calendarSelect = HoudiniForms::getFormFieldHtml( 'calendar_id', 'Calendar', 'select', $calendarID, self::$calendars->simpleByUser() );
|
||||||
|
Components::set( 'calendarSelect', $calendarSelect );
|
||||||
|
|
||||||
|
$repeatSelect = HoudiniForms::getFormFieldHtml( 'repeats', 'Frequency', 'select', Input::post('repeats'), self::$events->repeatOptions );
|
||||||
|
Components::set( 'repeatSelect', $repeatSelect );
|
||||||
|
|
||||||
|
if ( ! Forms::check( 'createEvent' ) ) {
|
||||||
|
Issues::add( 'error', [ 'There was an error with your form.' => Check::userErrors() ] );
|
||||||
|
return Views::view( 'calendar.events.create' );
|
||||||
|
}
|
||||||
|
|
||||||
|
$event_id = self::$events->create(
|
||||||
|
$calendarID,
|
||||||
|
Input::post('title'),
|
||||||
|
Date::applyUtcToDate( Date::determineDateInput() ),
|
||||||
|
Input::post('description'),
|
||||||
|
Input::post('location'),
|
||||||
|
Input::post('repeats'),
|
||||||
|
Input::post('color'),
|
||||||
|
0,
|
||||||
|
);
|
||||||
|
if ( ! $event_id ) {
|
||||||
|
Issues::add( 'error', [ 'There was an error creating your event.' => Check::userErrors() ] );
|
||||||
|
return Views::view( 'calendar.events.create' );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( Input::post('repeats') != 'none' ) {
|
||||||
|
$childrens = self::$events->generateChildEvents( $event_id, true, true );
|
||||||
|
}
|
||||||
|
|
||||||
|
Session::flash( 'success', 'Your Event has been created.' );
|
||||||
|
Redirect::to( 'calendar/'.self::$defaultView.'/'. $calendarID );
|
||||||
|
}
|
||||||
|
public function editEvent( $id = null ) {
|
||||||
|
$calendar = Input::exists('calendar_id') ? Input::post('calendar_id') : '';
|
||||||
|
$event = self::$events->findById( $id );
|
||||||
|
$readableDate = date('Y-m-d H:i:s', $event->event_time);
|
||||||
|
|
||||||
|
if ( $event == false ) {
|
||||||
|
Session::flash( 'error', 'Event not found.' );
|
||||||
|
return Redirect::to( 'calendar/'.self::$defaultView.'/' );
|
||||||
|
}
|
||||||
|
if ( $event->createdBy != App::$activeUser->ID ) {
|
||||||
|
Session::flash( 'error', 'You do not have permission to modify this event.' );
|
||||||
|
return Redirect::to( 'calendar/'.self::$defaultView.'/' );
|
||||||
|
}
|
||||||
|
|
||||||
|
$repeatSelect = HoudiniForms::getFormFieldHtml( 'repeats', 'Frequency', 'select', $event->repeats, self::$events->repeatOptions );
|
||||||
|
Components::set( 'repeatSelect', $repeatSelect );
|
||||||
|
|
||||||
|
// there should be a way to do this natively
|
||||||
|
$event_at = Date::getDateBreakdown( $event->event_time, true );
|
||||||
|
|
||||||
|
// $readableDate = date('Y-m-d H:i:s', $readableDate);
|
||||||
|
$dateSelect = Views::simpleView( 'calendar.dateSelect', $event_at );
|
||||||
|
Components::set( 'dateSelect', $dateSelect );
|
||||||
|
Components::set( 'color', $event->color );
|
||||||
|
|
||||||
|
if ( ! Input::exists( 'submit' ) ) {
|
||||||
|
return Views::view( 'calendar.events.edit', $event );
|
||||||
|
}
|
||||||
|
if ( ! Forms::check( 'editEvent' ) ) {
|
||||||
|
Issues::add( 'error', [ 'There was an error updating your event.' => Check::userErrors() ] );
|
||||||
|
return Views::view( 'calendar.events.edit', $event );
|
||||||
|
}
|
||||||
|
$result = self::$events->update(
|
||||||
|
$id,
|
||||||
|
Input::post('title'),
|
||||||
|
Date::applyUtcToDate( Date::determineDateInput() ),
|
||||||
|
Input::post('description'),
|
||||||
|
Input::post('location'),
|
||||||
|
Input::post('repeats'),
|
||||||
|
Input::post('color'),
|
||||||
|
);
|
||||||
|
|
||||||
|
if ( Input::post('repeats') != 'none' && $event->parent_id == 0 ) {
|
||||||
|
$childrens = self::$events->generateChildEvents( $event->ID, true, true );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! $result ) {
|
||||||
|
Issues::add( 'error', [ 'There was an error updating your event.' => Check::userErrors() ] );
|
||||||
|
return Views::view( 'calendar.events.edit', $event->ID );
|
||||||
|
}
|
||||||
|
Session::flash( 'success', 'Your Event has been updated.' );
|
||||||
|
Redirect::to( 'calendar/'.self::$defaultView.'/'. $event->calendar_id );
|
||||||
|
}
|
||||||
|
public function deleteEvent( $id = null ) {
|
||||||
|
$event = self::$events->findById( $id );
|
||||||
|
if ( $event == false ) {
|
||||||
|
Issues::add( 'error', 'Event not found.' );
|
||||||
|
return $this->index();
|
||||||
|
}
|
||||||
|
if ( $event->createdBy != App::$activeUser->ID ) {
|
||||||
|
Issues::add( 'error', 'You do not have permission to modify this event.' );
|
||||||
|
return $this->index();
|
||||||
|
}
|
||||||
|
$result = self::$events->delete( $id );
|
||||||
|
if ( !$result ) {
|
||||||
|
Session::flash( 'error', 'There was an error deleting the event(s)' );
|
||||||
|
} else {
|
||||||
|
Session::flash( 'success', 'Event deleted' );
|
||||||
|
}
|
||||||
|
return $this->index();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calendars
|
||||||
|
*/
|
||||||
|
public function calendar( $id = null ) {
|
||||||
|
$calendar = $this->findCalendarOrFail( $id );
|
||||||
|
Views::view( 'calendar.calendar.view', $calendar );
|
||||||
|
}
|
||||||
|
public function createCalendar() {
|
||||||
|
$timezoneSelect = HoudiniForms::getTimezoneHtml( Date::getTimezone() );
|
||||||
|
Components::set( 'timezoneSelect', $timezoneSelect );
|
||||||
|
if ( ! Input::exists() ) {
|
||||||
|
return Views::view( 'calendar.calendar.create' );
|
||||||
|
}
|
||||||
|
if ( ! Forms::check( 'createCalendar' ) ) {
|
||||||
|
Issues::add( 'error', [ 'There was an error creating your calendar111.' => Check::userErrors() ] );
|
||||||
|
return Views::view( 'calendar.calendar.create' );
|
||||||
|
}
|
||||||
|
$calendar = self::$calendars->create( Input::post('title'), Input::post('description'), Input::post('timezone'), Input::post('color') );
|
||||||
|
if ( ! $calendar ) {
|
||||||
|
return Views::view( 'calendar.calendar.create' );
|
||||||
|
}
|
||||||
|
Session::flash( 'success', 'Your Calendar has been created.' );
|
||||||
|
Redirect::to( 'calendar/'.self::$defaultView.'/');
|
||||||
|
}
|
||||||
|
public function editCalendar( $id = null ) {
|
||||||
|
$calendar = $this->findCalendarOrFail( $id );
|
||||||
|
|
||||||
|
$timezoneSelect = HoudiniForms::getTimezoneHtml( Date::getTimezone() );
|
||||||
|
Components::set( 'timezoneSelect', $timezoneSelect );
|
||||||
|
Components::set( 'color', $calendar->color );
|
||||||
|
|
||||||
|
if ( ! Input::exists( 'submit' ) ) {
|
||||||
|
return Views::view( 'calendar.calendar.edit', $calendar );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( !Forms::check( 'editCalendar' ) ) {
|
||||||
|
Issues::add( 'error', [ 'There was an error editing your calendar.' => Check::userErrors() ] );
|
||||||
|
return Views::view( 'calendar.calendar.edit', $calendar );
|
||||||
|
}
|
||||||
|
$result = self::$calendars->update( $id, Input::post('title'), Input::post('description'), Input::post('timezone'), Input::post('color') );
|
||||||
|
if ( !$result ) {
|
||||||
|
Issues::add( 'error', [ 'There was an error updating your calendar.' => Check::userErrors() ] );
|
||||||
|
return Views::view( 'calendar.calendar.edit', $calendar );
|
||||||
|
}
|
||||||
|
Session::flash( 'success', 'Your Calendar has been updated.' );
|
||||||
|
Redirect::to( 'calendar/'.self::$defaultView.'/'. $calendar->ID );
|
||||||
|
}
|
||||||
|
public function deleteCalendar( $id = null ) {
|
||||||
|
$calendar = self::$calendars->findById( $id );
|
||||||
|
if ( $calendar == false ) {
|
||||||
|
Issues::add( 'error', 'Calendar not found.' );
|
||||||
|
return $this->index();
|
||||||
|
}
|
||||||
|
if ( $calendar->createdBy != App::$activeUser->ID ) {
|
||||||
|
Issues::add( 'error', 'You do not have permission to modify this calendar.' );
|
||||||
|
return $this->index();
|
||||||
|
}
|
||||||
|
$results = self::$events->deleteByCalendar( $id );
|
||||||
|
$result = self::$calendars->delete( $id );
|
||||||
|
if ( !$result ) {
|
||||||
|
Session::flash( 'error', 'There was an error deleting the calendar(s)' );
|
||||||
|
} else {
|
||||||
|
Session::flash( 'success', 'Calendar deleted' );
|
||||||
|
}
|
||||||
|
Redirect::to( 'calendar/'.self::$defaultView.'/' );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Views
|
||||||
|
*/
|
||||||
|
public function byDay( $id = 0 ) {
|
||||||
|
// Set base components
|
||||||
|
Components::set( 'currentView', __FUNCTION__ );
|
||||||
|
Components::set( 'calendarID', $id );
|
||||||
|
|
||||||
|
// Set components for next / back arrows
|
||||||
|
$nextDayMonth = date( 'M', strtotime( 'tomorrow', self::$selectedDate ) );
|
||||||
|
$nextDay = date( 'd', strtotime( 'tomorrow', self::$selectedDate ) );
|
||||||
|
$lastDayMonth = date( 'M', strtotime( 'yesterday', self::$selectedDate ) );
|
||||||
|
$lastDay = date( 'd', strtotime( 'yesterday', self::$selectedDate ) );
|
||||||
|
Components::set( 'nextDayMonth', $nextDayMonth );
|
||||||
|
Components::set( 'nextDay', $nextDay );
|
||||||
|
Components::set( 'lastDayMonth', $lastDayMonth );
|
||||||
|
Components::set( 'lastDay', $lastDay );
|
||||||
|
|
||||||
|
// Get the data
|
||||||
|
$dayArray = self::$events->dayArray( $id, self::$selectedDate );
|
||||||
|
|
||||||
|
// build the results
|
||||||
|
$selectedHour = Date::getCurrentHour();
|
||||||
|
$day = date( 'd', self::$selectedDate );
|
||||||
|
$month = date( 'M', self::$selectedDate );
|
||||||
|
$year = date( 'Y', self::$selectedDate );
|
||||||
|
$fullDay = [];
|
||||||
|
foreach ( $dayArray as $hour => $events ) {
|
||||||
|
Components::set( 'hour', $hour );
|
||||||
|
$hourCell = new \stdClass();
|
||||||
|
$hourCell->hour = $hour;
|
||||||
|
if ( $hour == $selectedHour ) {
|
||||||
|
$hourCell->hourSelected = ' hour-active';
|
||||||
|
} else {
|
||||||
|
$hourCell->hourSelected = '';
|
||||||
|
}
|
||||||
|
$hourCell->day = $day;
|
||||||
|
$hourCell->month = $month;
|
||||||
|
$hourCell->year = $year;
|
||||||
|
$hourCell->EventCells = Views::simpleView( 'calendar.nav.row', $events );
|
||||||
|
$fullDay[] = $hourCell;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calendar Top Tabs
|
||||||
|
Components::unset( 'calendarDropdown');
|
||||||
|
$calendarTabs = Views::simpleView('calendar.nav.topTabs');
|
||||||
|
$tabsView = Navigation::activePageSelect( $calendarTabs, '/calendar/byDay/', false, true );
|
||||||
|
// must be done after top-nav gets selected
|
||||||
|
$calendarDropdown = Views::simpleView('calendar.nav.calendarDropdown', self::$calendars->simpleObjectByUser() );
|
||||||
|
$calendarDropdownView = Navigation::activePageSelect( $calendarDropdown, Input::get( 'url' ), false, true ); // add notebookID as second param
|
||||||
|
Components::set( 'calendarDropdown', $calendarDropdownView);
|
||||||
|
Components::set( 'CalendarNav', Template::parse( $tabsView ) );
|
||||||
|
|
||||||
|
Components::set( 'activeDate', date( 'F d, Y', self::$selectedDate ) );
|
||||||
|
Views::view( 'calendar.byDay', $fullDay );
|
||||||
|
}
|
||||||
|
public function byWeek( $id = 0 ) {
|
||||||
|
// Set base components
|
||||||
|
Components::set( 'currentView', __FUNCTION__ );
|
||||||
|
Components::set( 'calendarID', $id );
|
||||||
|
|
||||||
|
// Set components for next / back arrows
|
||||||
|
$lastWeekMonth = date( 'M', strtotime( '-7 days', self::$selectedDate) );
|
||||||
|
$lastWeekDay = date( 'd', strtotime( '-7 days', self::$selectedDate) );
|
||||||
|
$lastWeekYear = date( 'Y', strtotime( '-7 days', self::$selectedDate) );
|
||||||
|
$nextWeekMonth = date( 'M', strtotime( '+7 days', self::$selectedDate) );
|
||||||
|
$nextWeekDay = date( 'd', strtotime( '+7 days', self::$selectedDate) );
|
||||||
|
$nextWeekYear = date( 'Y', strtotime( '+7 days', self::$selectedDate) );
|
||||||
|
Components::set( 'lastWeekMonth', $lastWeekMonth );
|
||||||
|
Components::set( 'lastWeek', $lastWeekDay );
|
||||||
|
Components::set( 'lastYear', $lastWeekYear );
|
||||||
|
Components::set( 'nextWeekMonth', $nextWeekMonth );
|
||||||
|
Components::set( 'nextWeek', $nextWeekDay );
|
||||||
|
Components::set( 'nextYear', $nextWeekYear );
|
||||||
|
|
||||||
|
// Get the data
|
||||||
|
$weekArray = self::$events->weekArray( $id, self::$selectedDate );
|
||||||
|
|
||||||
|
// build the results
|
||||||
|
$presentMonth = date( 'F', self::$selectedDate );
|
||||||
|
$presentDay = date( 'd', self::$selectedDate );
|
||||||
|
foreach ( $weekArray as $week => $days ) {
|
||||||
|
$weekFormat = [];
|
||||||
|
foreach ( $days as $day => $events ) {
|
||||||
|
if ( empty( $first ) ) {
|
||||||
|
$first = true;
|
||||||
|
if ( intval( $presentDay ) >= $day ) {
|
||||||
|
$month = date( 'F', self::$selectedDate );
|
||||||
|
} else {
|
||||||
|
$month = date( 'F', strtotime( '-7 days', self::$selectedDate ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( $day == '01' ) {
|
||||||
|
$month = date( 'F', strtotime( '+7 days', self::$selectedDate ) );
|
||||||
|
}
|
||||||
|
Components::set( 'currentMonth', $month );
|
||||||
|
Components::set( 'currentDay', $day );
|
||||||
|
$dayCell = new \stdClass();
|
||||||
|
if ( $presentDay == $day && $presentMonth == $month ) {
|
||||||
|
$dayCell->highlightedDate = ' today';
|
||||||
|
} else {
|
||||||
|
$dayCell->highlightedDate = '';
|
||||||
|
}
|
||||||
|
$dayCell->day = $day;
|
||||||
|
$dayCell->dayEventList = Views::simpleView( 'calendar.nav.cell', $events );
|
||||||
|
$weekFormat[] = $dayCell;
|
||||||
|
}
|
||||||
|
$weekView = Views::simpleView( 'calendar.nav.week', $weekFormat );
|
||||||
|
Components::set( $week . 'Element', $weekView );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calendar Top Tabs
|
||||||
|
Components::unset( 'calendarDropdown');
|
||||||
|
$calendarTabs = Views::simpleView('calendar.nav.topTabs');
|
||||||
|
$tabsView = Navigation::activePageSelect( $calendarTabs, '/calendar/byWeek/', false, true );
|
||||||
|
// must be done after top-nav gets selected
|
||||||
|
$calendarDropdown = Views::simpleView('calendar.nav.calendarDropdown', self::$calendars->simpleObjectByUser() );
|
||||||
|
$calendarDropdownView = Navigation::activePageSelect( $calendarDropdown, Input::get( 'url' ), false, true ); // add notebookID as second param
|
||||||
|
Components::set( 'calendarDropdown', $calendarDropdownView);
|
||||||
|
Components::set( 'CalendarNav', Template::parse( $tabsView ) );
|
||||||
|
|
||||||
|
Components::set( 'dateWeek', 'Week of ' . date( 'F d, Y', self::$selectedDate ) );
|
||||||
|
Views::view( 'calendar.byWeek' );
|
||||||
|
}
|
||||||
|
public function byMonth( $id = 0 ) {
|
||||||
|
// Set base components
|
||||||
|
Components::set( 'currentView', __FUNCTION__ );
|
||||||
|
Components::set( 'calendarID', $id );
|
||||||
|
|
||||||
|
// Set components for next / back arrows
|
||||||
|
$month = date( 'F', strtotime( 'first day of last month', self::$selectedDate ) );
|
||||||
|
$lastMonthYear = date( 'Y', strtotime( 'first day of last month', self::$selectedDate ) );
|
||||||
|
$nextMonth = date( 'F', strtotime( 'first day of next month', self::$selectedDate ) );
|
||||||
|
$nextMonthYear = date( 'Y', strtotime( 'first day of next month', self::$selectedDate ) );
|
||||||
|
Components::set( 'lastMonth', $month );
|
||||||
|
Components::set( 'lastMonthYear', $lastMonthYear );
|
||||||
|
Components::set( 'nextMonth', $nextMonth );
|
||||||
|
Components::set( 'nextMonthYear', $nextMonthYear );
|
||||||
|
|
||||||
|
// Get the data
|
||||||
|
$monthArray = self::$events->monthArray( $id, self::$selectedDate );
|
||||||
|
|
||||||
|
// build the results
|
||||||
|
$lastMonth = strtotime( 'last month', self::$selectedDate );
|
||||||
|
$presentMonth = date( 'F', self::$selectedDate );
|
||||||
|
$presentDay = date( 'd', self::$selectedDate );
|
||||||
|
foreach ( $monthArray as $week => $days ) {
|
||||||
|
$weekFormat = [];
|
||||||
|
foreach ( $days as $day => $events ) {
|
||||||
|
if ( $day == '01' ) {
|
||||||
|
$month = date( 'F', strtotime( '+1 month', $lastMonth ) );
|
||||||
|
$lastMonth = strtotime( '+1 month', $lastMonth) ;
|
||||||
|
}
|
||||||
|
Components::set( 'currentMonth', $month );
|
||||||
|
Components::set( 'currentDay', $day );
|
||||||
|
$dayCell = new \stdClass();
|
||||||
|
if ( $presentDay == $day && $presentMonth == $month ) {
|
||||||
|
$dayCell->highlightedDate = ' today';
|
||||||
|
} else {
|
||||||
|
$dayCell->highlightedDate = '';
|
||||||
|
}
|
||||||
|
$dayCell->day = $day;
|
||||||
|
// prevent duplicated entries for previous/next month
|
||||||
|
if ( $lastMonth < strtotime( 'this month',self::$selectedDate ) || $lastMonth == strtotime( 'next month',self::$selectedDate )) {
|
||||||
|
$events = [];
|
||||||
|
}
|
||||||
|
$dayCell->dayEventList = Views::simpleView( 'calendar.nav.cell', $events );
|
||||||
|
$weekFormat[] = $dayCell;
|
||||||
|
}
|
||||||
|
|
||||||
|
$weekView = Views::simpleView( 'calendar.nav.week', $weekFormat );
|
||||||
|
Components::set( $week . 'Element', $weekView );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calendar Top Tabs
|
||||||
|
Components::unset( 'calendarDropdown');
|
||||||
|
$calendarTabs = Views::simpleView('calendar.nav.topTabs');
|
||||||
|
$tabsView = Navigation::activePageSelect( $calendarTabs, '/calendar/byMonth/', false, true );
|
||||||
|
// must be done after top-nav gets selected
|
||||||
|
$calendarDropdown = Views::simpleView('calendar.nav.calendarDropdown', self::$calendars->simpleObjectByUser() );
|
||||||
|
$calendarDropdownView = Navigation::activePageSelect( $calendarDropdown, Input::get( 'url' ), false, true ); // add notebookID as second param
|
||||||
|
Components::set( 'calendarDropdown', $calendarDropdownView);
|
||||||
|
Components::set( 'CalendarNav', Template::parse( $tabsView ) );
|
||||||
|
|
||||||
|
Components::set( 'dateMonth', date( 'F Y', self::$selectedDate ) );
|
||||||
|
Views::view( 'calendar.byMonth' );
|
||||||
|
}
|
||||||
|
public function byYear( $id = 0 ) {
|
||||||
|
// Set base components
|
||||||
|
Components::set( 'calendarID', $id );
|
||||||
|
Components::set( 'currentView', __FUNCTION__ );
|
||||||
|
|
||||||
|
// Set components for next / back arrows
|
||||||
|
$nextYear = date( 'Y', strtotime( 'next year', self::$selectedDate ) );
|
||||||
|
$lastYear = date( 'Y', strtotime( 'last year', self::$selectedDate ) );
|
||||||
|
Components::set( 'lastYear', $lastYear );
|
||||||
|
Components::set( 'nextYear', $nextYear );
|
||||||
|
|
||||||
|
// Get the data
|
||||||
|
$eventList = self::$events->yearArray( $id, self::$selectedDate );
|
||||||
|
|
||||||
|
// Calendar Top Tabs
|
||||||
|
Components::unset( 'calendarDropdown');
|
||||||
|
$calendarTabs = Views::simpleView('calendar.nav.topTabs');
|
||||||
|
$tabsView = Navigation::activePageSelect( $calendarTabs, '/calendar/byYear/', false, true );
|
||||||
|
// must be done after top-nav gets selected
|
||||||
|
$calendarDropdown = Views::simpleView('calendar.nav.calendarDropdown', self::$calendars->simpleObjectByUser() );
|
||||||
|
$calendarDropdownView = Navigation::activePageSelect( $calendarDropdown, Input::get( 'url' ), false, true ); // add notebookID as second param
|
||||||
|
Components::set( 'calendarDropdown', $calendarDropdownView);
|
||||||
|
Components::set( 'CalendarNav', Template::parse( $tabsView ) );
|
||||||
|
|
||||||
|
Components::set( 'dateYear', date( 'Y', self::$selectedDate ) );
|
||||||
|
Views::view( 'calendar.byYear', $eventList );
|
||||||
|
}
|
||||||
|
public function events( $id = 0 ) {
|
||||||
|
Components::set( 'currentView', __FUNCTION__ );
|
||||||
|
Components::set( 'calendarID', $id );
|
||||||
|
if ( ! empty( $id ) ) {
|
||||||
|
$calendar = self::$calendars->findById( $id );
|
||||||
|
if ( $calendar == false ) {
|
||||||
|
Issues::add( 'error', 'Calendar not found.' );
|
||||||
|
return $this->index();
|
||||||
|
}
|
||||||
|
if ( $calendar->createdBy != App::$activeUser->ID ) {
|
||||||
|
Issues::add( 'error', 'You do not have permission to view this calendar.' );
|
||||||
|
return $this->index();
|
||||||
|
}
|
||||||
|
Components::set( 'calendarName', $calendar->title );
|
||||||
|
$eventList = self::$events->findByCalendar( $id );
|
||||||
|
} else {
|
||||||
|
$eventList = self::$events->userEvents( 5 );
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calendar Top Tabs
|
||||||
|
Components::unset( 'calendarDropdown');
|
||||||
|
$calendarTabs = Views::simpleView('calendar.nav.topTabs');
|
||||||
|
$tabsView = Navigation::activePageSelect( $calendarTabs, '/calendar/events/', false, true );
|
||||||
|
// must be done after top-nav gets selected
|
||||||
|
$calendarDropdown = Views::simpleView('calendar.nav.calendarDropdown', self::$calendars->simpleObjectByUser() );
|
||||||
|
$calendarDropdownView = Navigation::activePageSelect( $calendarDropdown, Input::get( 'url' ), false, true ); // add notebookID as second param
|
||||||
|
Components::set( 'calendarDropdown', $calendarDropdownView);
|
||||||
|
Components::set( 'CalendarNav', Template::parse( $tabsView ) );
|
||||||
|
|
||||||
|
Views::view( 'calendar.events.list', $eventList );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Support Functions
|
||||||
|
*/
|
||||||
|
private function findCalendarOrFail( $id = null ) {
|
||||||
|
$calendar = self::$calendars->findById( $id );
|
||||||
|
if ( $calendar == false ) {
|
||||||
|
Session::flash( 'error', 'Calendar not found.' );
|
||||||
|
Redirect::to( 'calendar/'.self::$defaultView.'/' );
|
||||||
|
}
|
||||||
|
if ( $calendar->createdBy != App::$activeUser->ID ) {
|
||||||
|
Session::flash( 'error', 'Permissions Error.' );
|
||||||
|
Redirect::to( 'calendar/'.self::$defaultView.'/' );
|
||||||
|
}
|
||||||
|
return $calendar;
|
||||||
|
}
|
||||||
|
private function findEventOrFail( $id = null ) {
|
||||||
|
$event = self::$events->findById( $id );
|
||||||
|
if ( $event == false ) {
|
||||||
|
Session::flash( 'error', 'Event not found.' );
|
||||||
|
Redirect::to( 'calendar/'.self::$defaultView.'/' );
|
||||||
|
}
|
||||||
|
if ( $event->createdBy != App::$activeUser->ID ) {
|
||||||
|
Session::flash( 'error', 'Permissions Error.' );
|
||||||
|
Redirect::to( 'calendar/'.self::$defaultView.'/' );
|
||||||
|
}
|
||||||
|
return $event;
|
||||||
|
}
|
||||||
|
private function getEventBreakdown( $start_timestamp = 0, $end_timestamp = 0, $with_timezone = false ) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
$out = new \stdClass();
|
||||||
|
if ( empty( $end_timestamp ) ) {
|
||||||
|
$out->allDay = 'true';
|
||||||
|
// $out->date = ;
|
||||||
|
// $out->time = ;
|
||||||
|
$out->endDate = $out->date;
|
||||||
|
$out->endTime = $out->time;
|
||||||
|
} else {
|
||||||
|
$out->allDay = 'false';
|
||||||
|
|
||||||
|
// $out->date = ;
|
||||||
|
// $out->time = ;
|
||||||
|
$out->endDate = $out->date;
|
||||||
|
$out->endTime = $out->time;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$timestamp = intval( $timestamp );
|
||||||
|
$init = date('Y-m-d H:i:s', $timestamp);
|
||||||
|
if ( true === $with_timezone ) {
|
||||||
|
$readableDate = self::applyTimezoneToTimestamp( $timestamp );
|
||||||
|
} else {
|
||||||
|
$readableDate = date('Y-m-d H:i:s', $timestamp);
|
||||||
|
}
|
||||||
|
$date = date( 'Y-m-d', strtotime( $readableDate ) );
|
||||||
|
$time = date( 'H:i', strtotime( $readableDate ) );
|
||||||
|
return [
|
||||||
|
'time' => $time,
|
||||||
|
'date' => $date,
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
153
app/plugins/calendar/css/calendar.css
Normal file
153
app/plugins/calendar/css/calendar.css
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
.calendar-container {
|
||||||
|
margin-left: 20px;
|
||||||
|
margin-right: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-row {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-cell {
|
||||||
|
flex: 1;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
text-align: center;
|
||||||
|
padding: 10px 0;
|
||||||
|
margin: 0 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-cell h4 {
|
||||||
|
margin: 0;
|
||||||
|
padding: 5px;
|
||||||
|
border-radius: 4px;
|
||||||
|
background-color: #f8f8f8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hour-row {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hour-body {
|
||||||
|
display: flex; /* Add this line to use flexbox */
|
||||||
|
flex-direction: row; /* Ensure the direction is row */
|
||||||
|
flex: 4;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
text-align: center;
|
||||||
|
padding: 10px 0;
|
||||||
|
margin-left: 5px;
|
||||||
|
margin-right: 5px;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hour-cell {
|
||||||
|
flex: 1;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
text-align: center;
|
||||||
|
padding: 10px 0;
|
||||||
|
margin-left: 5px;
|
||||||
|
margin-right: 5px;
|
||||||
|
align-items: center;
|
||||||
|
max-width: 250px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.today {
|
||||||
|
background-color: #5cb85c !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hour-header, .hour-footer {
|
||||||
|
flex: 0 0 10%;
|
||||||
|
background-color: #f8f8f8;
|
||||||
|
text-align: center;
|
||||||
|
padding: 10px 0;
|
||||||
|
margin: 0 5px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Adjusting the first and last cell margins to align with the container edges */
|
||||||
|
.calendar-cell:first-child {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.calendar-cell:last-child {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select-container {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
.custom-select {
|
||||||
|
/* color: red; */
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
.custom-select .white {
|
||||||
|
background-color: #ffffff;
|
||||||
|
}
|
||||||
|
.custom-select .primary {
|
||||||
|
background-color: #337ab7;
|
||||||
|
}
|
||||||
|
.custom-select .success {
|
||||||
|
background-color: #5cb85c;
|
||||||
|
}
|
||||||
|
.custom-select .info {
|
||||||
|
background-color: #5bc0de;
|
||||||
|
}
|
||||||
|
.custom-select .warning {
|
||||||
|
background-color: #f0ad4e;
|
||||||
|
}
|
||||||
|
.custom-select .danger {
|
||||||
|
background-color: #d9534f;
|
||||||
|
}
|
||||||
|
.select-container .primary {
|
||||||
|
background-color: #337ab7;
|
||||||
|
}
|
||||||
|
.select-container .white {
|
||||||
|
background-color: #ffffff;
|
||||||
|
}
|
||||||
|
.select-container .success {
|
||||||
|
background-color: #5cb85c;
|
||||||
|
}
|
||||||
|
.select-container .info {
|
||||||
|
background-color: #5bc0de;
|
||||||
|
}
|
||||||
|
.select-container .warning {
|
||||||
|
background-color: #f0ad4e;
|
||||||
|
}
|
||||||
|
.select-container .danger {
|
||||||
|
background-color: #d9534f;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dateDayContainer {
|
||||||
|
width: 250px;
|
||||||
|
display: inline-block;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dateWeekContainer {
|
||||||
|
width: 450px;
|
||||||
|
display: inline-block;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dateMonthContainer {
|
||||||
|
width: 250px;
|
||||||
|
display: inline-block;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dateYearContainer {
|
||||||
|
width: 150px;
|
||||||
|
display: inline-block;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hour-active {
|
||||||
|
background-color: #217025 !important;
|
||||||
|
/* color: #00ff0d !important; */
|
||||||
|
background-image:none;
|
||||||
|
}
|
136
app/plugins/calendar/forms.php
Normal file
136
app/plugins/calendar/forms.php
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* app/plugins/calendar/forms.php
|
||||||
|
*
|
||||||
|
* This houses all of the form checking functions for this plugin.
|
||||||
|
*
|
||||||
|
* @package TP Calendar
|
||||||
|
* @version 3.0
|
||||||
|
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||||
|
* @link https://TheTempusProject.com
|
||||||
|
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||||
|
*/
|
||||||
|
namespace TheTempusProject\Plugins\Calendar;
|
||||||
|
|
||||||
|
use TheTempusProject\Bedrock\Functions\Input;
|
||||||
|
use TheTempusProject\Bedrock\Functions\Check;
|
||||||
|
use TheTempusProject\Classes\Forms;
|
||||||
|
|
||||||
|
class CalendarForms extends Forms {
|
||||||
|
/**
|
||||||
|
* Adds these functions to the form list.
|
||||||
|
*/
|
||||||
|
public function __construct() {
|
||||||
|
self::addHandler( 'calendarSelect', __CLASS__, 'calendarSelect' );
|
||||||
|
self::addHandler( 'createEvent', __CLASS__, 'createEvent' );
|
||||||
|
self::addHandler( 'createCalendar', __CLASS__, 'createCalendar' );
|
||||||
|
self::addHandler( 'editEvent', __CLASS__, 'editEvent' );
|
||||||
|
self::addHandler( 'editCalendar', __CLASS__, 'editCalendar' );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validates the password re-send form.
|
||||||
|
*
|
||||||
|
* @return {bool}
|
||||||
|
*/
|
||||||
|
public static function calendarSelect() {
|
||||||
|
if ( ! Input::exists( 'calendar_id' ) ) {
|
||||||
|
Check::addUserError( 'You must include a title.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// if ( !self::token() ) {
|
||||||
|
// Check::addUserError( 'token - comment out later.' );
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function createEvent() {
|
||||||
|
if ( ! Input::exists( 'title' ) ) {
|
||||||
|
Check::addUserError( 'You must include a title.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( ! Input::exists( 'date' ) ) {
|
||||||
|
Check::addUserError( 'You must include a date.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( ! Input::exists( 'time' ) ) {
|
||||||
|
Check::addUserError( 'You must include a time.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( ! Input::exists( 'repeats' ) ) {
|
||||||
|
Check::addUserError( 'You must include a frequency.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( ! Input::exists( 'calendar_id' ) ) {
|
||||||
|
Check::addUserError( 'You must select a calendar.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// if ( !self::token() ) {
|
||||||
|
// Check::addUserError( 'token - comment out later.' );
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function createCalendar() {
|
||||||
|
if ( ! Input::exists( 'title' ) ) {
|
||||||
|
Check::addUserError( 'You must include a title.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( ! Input::exists( 'timezone' ) ) {
|
||||||
|
Check::addUserError( 'You must include a timezone.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// if ( ! self::token() ) {
|
||||||
|
// Check::addUserError( 'token - comment out later.' );
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function editEvent() {
|
||||||
|
if ( ! Input::exists( 'title' ) ) {
|
||||||
|
Check::addUserError( 'You must include a title.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( ! Input::exists( 'date' ) ) {
|
||||||
|
Check::addUserError( 'You must include a date.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( ! Input::exists( 'time' ) ) {
|
||||||
|
Check::addUserError( 'You must include a time.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( ! Input::exists( 'repeats' ) ) {
|
||||||
|
Check::addUserError( 'You must include a frequency.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// if ( !self::token() ) {
|
||||||
|
// Check::addUserError( 'token - comment out later.' );
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function editCalendar() {
|
||||||
|
if ( ! Input::exists( 'submit' ) ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( ! Input::exists( 'title' ) ) {
|
||||||
|
Check::addUserError( 'You must include a title.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( ! Input::exists( 'timezone' ) ) {
|
||||||
|
Check::addUserError( 'You must include a timezone.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// if ( !self::token() ) {
|
||||||
|
// Check::addUserError( 'token - comment out later.' );
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
new CalendarForms;
|
157
app/plugins/calendar/models/calendars.php
Normal file
157
app/plugins/calendar/models/calendars.php
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* app/plugins/calendar/models/events.php
|
||||||
|
*
|
||||||
|
* This class is used for the manipulation of the calendars database table.
|
||||||
|
*
|
||||||
|
* @package TP Calendar
|
||||||
|
* @version 3.0
|
||||||
|
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||||
|
* @link https://TheTempusProject.com
|
||||||
|
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||||
|
*/
|
||||||
|
namespace TheTempusProject\Models;
|
||||||
|
|
||||||
|
use TheTempusProject\Bedrock\Classes\Config;
|
||||||
|
use TheTempusProject\Bedrock\Functions\Check;
|
||||||
|
use TheTempusProject\Bedrock\Functions\Date;
|
||||||
|
use TheTempusProject\Canary\Canary as Debug;
|
||||||
|
use TheTempusProject\Classes\DatabaseModel;
|
||||||
|
use TheTempusProject\TheTempusProject as App;
|
||||||
|
use TheTempusProject\Houdini\Classes\Filters;
|
||||||
|
use TheTempusProject\Bedrock\Classes\CustomException;
|
||||||
|
|
||||||
|
class Calendars extends DatabaseModel {
|
||||||
|
public $tableName = 'calendars';
|
||||||
|
public $databaseMatrix = [
|
||||||
|
[ 'title', 'varchar', '256' ],
|
||||||
|
[ 'color', 'varchar', '48' ],
|
||||||
|
[ 'privacy', 'varchar', '48' ],
|
||||||
|
[ 'description', 'text', '' ],
|
||||||
|
[ 'createdBy', 'int', '11' ],
|
||||||
|
[ 'createdAt', 'int', '11' ],
|
||||||
|
[ 'timezone', 'varchar', '256' ],
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The model constructor.
|
||||||
|
*/
|
||||||
|
public function __construct() {
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function create( $title, $description = '', $timezone = '', $color = 'default' ) {
|
||||||
|
if ( ! Check::dataTitle( $title ) ) {
|
||||||
|
Debug::info( 'Calendars: illegal title.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( empty( $timezone ) ) {
|
||||||
|
$timezone = Date::getTimezone();
|
||||||
|
}
|
||||||
|
$fields = [
|
||||||
|
'title' => $title,
|
||||||
|
'description' => $description,
|
||||||
|
'timezone' => $timezone,
|
||||||
|
'color' => $color,
|
||||||
|
'createdBy' => App::$activeUser->ID,
|
||||||
|
'createdAt' => time(),
|
||||||
|
];
|
||||||
|
if ( ! self::$db->insert( $this->tableName, $fields ) ) {
|
||||||
|
new CustomException( 'calendarCreate' );
|
||||||
|
Debug::error( "Calendar: not created " . var_export($fields,true) );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return self::$db->lastId();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update( $id, $title, $description = '', $timezone = '', $color = 'default' ) {
|
||||||
|
if ( empty( $timezone ) ) {
|
||||||
|
$timezone = Date::getTimezone();
|
||||||
|
}
|
||||||
|
if ( !Check::id( $id ) ) {
|
||||||
|
Debug::info( 'Calendars: illegal ID.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( !Check::dataTitle( $title ) ) {
|
||||||
|
Debug::info( 'Calendars: illegal title.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$fields = [
|
||||||
|
'title' => $title,
|
||||||
|
'description' => $description,
|
||||||
|
'timezone' => $timezone,
|
||||||
|
'color' => $color,
|
||||||
|
];
|
||||||
|
if ( !self::$db->update( $this->tableName, $id, $fields ) ) {
|
||||||
|
new CustomException( 'calendarUpdate' );
|
||||||
|
Debug::error( "Calendar: $id not updated: $fields" );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function byUser( $limit = null ) {
|
||||||
|
$whereClause = ['createdBy', '=', App::$activeUser->ID];
|
||||||
|
if ( empty( $limit ) ) {
|
||||||
|
$calendars = self::$db->get( $this->tableName, $whereClause );
|
||||||
|
} else {
|
||||||
|
$calendars = self::$db->get( $this->tableName, $whereClause, 'ID', 'DESC', [0, $limit] );
|
||||||
|
}
|
||||||
|
if ( !$calendars->count() ) {
|
||||||
|
Debug::info( 'No Calendars found.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return $this->filter( $calendars->results() );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getName( $id ) {
|
||||||
|
$calendar = self::findById( $id );
|
||||||
|
if (false == $calendar) {
|
||||||
|
return 'unknown';
|
||||||
|
}
|
||||||
|
return $calendar->title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getColor( $id ) {
|
||||||
|
$calendar = self::findById( $id );
|
||||||
|
if (false == $calendar) {
|
||||||
|
return 'default';
|
||||||
|
}
|
||||||
|
return $calendar->color;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function simpleByUser() {
|
||||||
|
$whereClause = ['createdBy', '=', App::$activeUser->ID];
|
||||||
|
$calendars = self::$db->get( $this->tableName, $whereClause );
|
||||||
|
if ( !$calendars->count() ) {
|
||||||
|
Debug::warn( 'Could not find any calendars' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$calendars = $calendars->results();
|
||||||
|
$out = [];
|
||||||
|
foreach ( $calendars as &$calendar ) {
|
||||||
|
$out[ $calendar->title ] = $calendar->ID;
|
||||||
|
}
|
||||||
|
return $out;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function simpleObjectByUser() {
|
||||||
|
$whereClause = ['createdBy', '=', App::$activeUser->ID];
|
||||||
|
$calendars = self::$db->get( $this->tableName, $whereClause );
|
||||||
|
if ( !$calendars->count() ) {
|
||||||
|
Debug::warn( 'Could not find any calendars' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$calendars = $calendars->results();
|
||||||
|
$out = [];
|
||||||
|
foreach ( $calendars as &$calendar ) {
|
||||||
|
$obj = new \stdClass();
|
||||||
|
$obj->title = $calendar->title;
|
||||||
|
$obj->ID = $calendar->ID;
|
||||||
|
$out[] = $obj;
|
||||||
|
}
|
||||||
|
return $out;
|
||||||
|
}
|
||||||
|
}
|
509
app/plugins/calendar/models/events.php
Normal file
509
app/plugins/calendar/models/events.php
Normal file
@ -0,0 +1,509 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* app/plugins/calendar/models/events.php
|
||||||
|
*
|
||||||
|
* This class is used for the manipulation of the events database table.
|
||||||
|
*
|
||||||
|
* @package TP Calendar
|
||||||
|
* @version 3.0
|
||||||
|
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||||
|
* @link https://TheTempusProject.com
|
||||||
|
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||||
|
*/
|
||||||
|
namespace TheTempusProject\Models;
|
||||||
|
|
||||||
|
use TheTempusProject\Bedrock\Classes\Config;
|
||||||
|
use TheTempusProject\Bedrock\Functions\Check;
|
||||||
|
use TheTempusProject\Canary\Canary as Debug;
|
||||||
|
use TheTempusProject\Classes\DatabaseModel;
|
||||||
|
use TheTempusProject\TheTempusProject as App;
|
||||||
|
use TheTempusProject\Houdini\Classes\Filters;
|
||||||
|
use TheTempusProject\Models\Calendars;
|
||||||
|
use TheTempusProject\Bedrock\Classes\CustomException;
|
||||||
|
use TheTempusProject\Bedrock\Functions\Date;
|
||||||
|
use TheTempusProject\Houdini\Classes\Pagination;
|
||||||
|
|
||||||
|
class Events extends DatabaseModel {
|
||||||
|
public $tableName = 'events';
|
||||||
|
public $repeatOptions = [
|
||||||
|
'Does Not Repeat' => 'none',
|
||||||
|
'Every Day' => 'daily',
|
||||||
|
'Every Week' => 'weekly',
|
||||||
|
'Every Month' => 'monthly',
|
||||||
|
'Every Year' => 'yearly',
|
||||||
|
];
|
||||||
|
public $databaseMatrix = [
|
||||||
|
[ 'calendar_id', 'int', '11' ],
|
||||||
|
[ 'title', 'varchar', '256' ],
|
||||||
|
[ 'event_time', 'int', '11' ],
|
||||||
|
[ 'event_ends', 'int', '11' ],
|
||||||
|
[ 'description', 'text', '' ],
|
||||||
|
[ 'location', 'varchar', '256' ],
|
||||||
|
[ 'repeats', 'varchar', '48' ],
|
||||||
|
[ 'color', 'varchar', '48' ],
|
||||||
|
[ 'parent_id', 'int', '11' ],
|
||||||
|
[ 'createdBy', 'int', '11' ],
|
||||||
|
[ 'createdAt', 'int', '11' ],
|
||||||
|
];
|
||||||
|
protected static $calendars;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The model constructor.
|
||||||
|
*/
|
||||||
|
public function __construct() {
|
||||||
|
parent::__construct();
|
||||||
|
self::$calendars = new Calendars;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves a chat form to the db.
|
||||||
|
*
|
||||||
|
* @param string $message -contents of the chat form.
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function create( $calendar_id, $title, $event_time, $description = '', $location = '', $repeats = 'none', $color = 'default', $parent_id = 0 ) {
|
||||||
|
if ( ! Check::id( $calendar_id ) ) {
|
||||||
|
Debug::info( 'calendar event: illegal calendar ID.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$fields = [
|
||||||
|
'calendar_id' => $calendar_id,
|
||||||
|
'title' => $title,
|
||||||
|
'event_time' => $event_time,
|
||||||
|
'description' => $description,
|
||||||
|
'location' => $location,
|
||||||
|
'repeats' => $repeats,
|
||||||
|
'color' => $color,
|
||||||
|
'parent_id' => $parent_id,
|
||||||
|
'createdBy' => App::$activeUser->ID,
|
||||||
|
'createdAt' => time(),
|
||||||
|
];
|
||||||
|
if ( !self::$db->insert( $this->tableName, $fields ) ) {
|
||||||
|
Debug::info( 'Events::create - failed to insert to db' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return self::$db->lastId();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update( $id, $title, $event_time, $description = '', $location ='', $repeats = 'none', $color = 'default', $parent_id = 0, $calendar_id = '' ) {
|
||||||
|
if ( ! Check::id( $id ) ) {
|
||||||
|
Debug::info( 'calendar event: illegal ID.' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$fields = [
|
||||||
|
'title' => $title,
|
||||||
|
'event_time' => $event_time,
|
||||||
|
'description' => $description,
|
||||||
|
'location' => $location,
|
||||||
|
'repeats' => $repeats,
|
||||||
|
'color' => $color,
|
||||||
|
'parent_id' => $parent_id,
|
||||||
|
];
|
||||||
|
if ( ! self::$db->update( $this->tableName, $id, $fields ) ) {
|
||||||
|
new CustomException( 'calendarEventUpdate' );
|
||||||
|
Debug::error( "Event: $id not updated: $fields" );
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function dayArray( $calendar_id = 0, $date = 0 ) {
|
||||||
|
$whereClause = [ 'createdBy', '=', App::$activeUser->ID, 'AND' ];
|
||||||
|
if ( ! empty( $calendar_id ) ) {
|
||||||
|
$whereClause = array_merge( $whereClause, [ 'calendar_id', '=', $calendar_id, 'AND' ] );
|
||||||
|
}
|
||||||
|
|
||||||
|
$whereClause = array_merge( $whereClause, [
|
||||||
|
'event_time', '>=', Date::getDayStartTimestamp( $date, true ), 'AND',
|
||||||
|
'event_time', '<=', Date::getDayEndTimestamp( $date, true ),
|
||||||
|
] );
|
||||||
|
|
||||||
|
$events = self::$db->get( $this->tableName, $whereClause );
|
||||||
|
if ( ! $events->count() ) {
|
||||||
|
$results = [];
|
||||||
|
} else {
|
||||||
|
$results = $events->results();
|
||||||
|
}
|
||||||
|
$events = $this->sortByEventTimeHour(
|
||||||
|
$this->filter(
|
||||||
|
$results
|
||||||
|
)
|
||||||
|
);
|
||||||
|
// Generate day array
|
||||||
|
$currentDay = [];
|
||||||
|
$currentHour = Date::getDayStartTimestamp( $date );
|
||||||
|
$lastHour = Date::getDayEndTimestamp( $date );
|
||||||
|
while ( $currentHour <= $lastHour ) {
|
||||||
|
$hour = date( 'H', $currentHour );
|
||||||
|
if ( ! empty( $events[ $hour ] ) ) {
|
||||||
|
$dailyEvents = $events[ $hour ];
|
||||||
|
} else {
|
||||||
|
$dailyEvents = [];
|
||||||
|
}
|
||||||
|
$currentDay[ $hour ] = $dailyEvents;
|
||||||
|
$currentHour = strtotime('+1 hour', $currentHour);
|
||||||
|
}
|
||||||
|
return $currentDay;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function weekArray( $calendar_id = 0, $date = null ) {
|
||||||
|
$whereClause = [ 'createdBy', '=', App::$activeUser->ID, 'AND' ];
|
||||||
|
if ( ! empty( $calendar_id ) ) {
|
||||||
|
$whereClause = array_merge( $whereClause, [ 'calendar_id', '=', $calendar_id, 'AND' ] );
|
||||||
|
}
|
||||||
|
|
||||||
|
$whereClause = array_merge( $whereClause, [
|
||||||
|
'event_time', '>=', Date::getWeekStartTimestamp( $date, true ), 'AND',
|
||||||
|
'event_time', '<=', Date::getWeekEndTimestamp( $date, true ),
|
||||||
|
] );
|
||||||
|
$events = self::$db->get( $this->tableName, $whereClause );
|
||||||
|
if ( ! $events->count() ) {
|
||||||
|
$results = [];
|
||||||
|
} else {
|
||||||
|
$results = $events->results();
|
||||||
|
}
|
||||||
|
$events = $this->sortByEventTime(
|
||||||
|
$this->filter(
|
||||||
|
$results
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Generate weeks array
|
||||||
|
$output = [];
|
||||||
|
$currentWeek = [];
|
||||||
|
$currentDay = Date::getWeekStartTimestamp( $date );
|
||||||
|
$weekCounter = 1;
|
||||||
|
$dayCounter = 1;
|
||||||
|
|
||||||
|
// Re-index the array using the date derived from event_time as the key
|
||||||
|
while ( $currentDay <= Date::getWeekEndTimestamp( $date ) ) {
|
||||||
|
$month = date( 'F', $currentDay );
|
||||||
|
$dayOfMonth = date( 'd', $currentDay );
|
||||||
|
if ( ! empty( $events[ $month ][ $dayOfMonth ] ) ) {
|
||||||
|
$dailyEvents = $events[ $month ][ $dayOfMonth ];
|
||||||
|
} else {
|
||||||
|
$dailyEvents = [];
|
||||||
|
}
|
||||||
|
$currentWeek[ $dayOfMonth ] = $dailyEvents;
|
||||||
|
$currentDay = strtotime('+1 day', $currentDay);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle any remaining days in the last week
|
||||||
|
if ( ! empty( $currentWeek ) ) {
|
||||||
|
$output["week$weekCounter"] = $currentWeek;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $output;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function monthArray( $calendar_id = 0, $date = null ) {
|
||||||
|
$whereClause = [ 'createdBy', '=', App::$activeUser->ID, 'AND' ];
|
||||||
|
if ( ! empty( $calendar_id ) ) {
|
||||||
|
$whereClause = array_merge( $whereClause, [ 'calendar_id', '=', $calendar_id, 'AND' ] );
|
||||||
|
}
|
||||||
|
$whereClause = array_merge( $whereClause, [
|
||||||
|
'event_time', '>=', Date::getMonthStartTimestamp( $date, true ), 'AND',
|
||||||
|
'event_time', '<=', Date::getMonthEndTimestamp( $date, true ),
|
||||||
|
] );
|
||||||
|
|
||||||
|
$events = self::$db->get( $this->tableName, $whereClause );
|
||||||
|
if ( ! $events->count() ) {
|
||||||
|
$results = [];
|
||||||
|
} else {
|
||||||
|
$results = $events->results();
|
||||||
|
}
|
||||||
|
$events = $this->sortByEventTime(
|
||||||
|
$this->filter(
|
||||||
|
$results
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Generate weeks array
|
||||||
|
$output = [];
|
||||||
|
$currentWeek = [];
|
||||||
|
$currentDay = Date::getMonthStartTimestamp( $date );
|
||||||
|
$weekCounter = 1;
|
||||||
|
$dayCounter = 1;
|
||||||
|
|
||||||
|
// Re-index the array using the date derived from event_time as the key
|
||||||
|
while ( $currentDay <= Date::getMonthEndTimestamp( $date ) ) {
|
||||||
|
$month = date( 'F', $currentDay );
|
||||||
|
$dayOfMonth = date( 'd', $currentDay );
|
||||||
|
if ( ! empty( $events[ $month ][ $dayOfMonth ] ) ) {
|
||||||
|
$dailyEvents = $events[ $month ][ $dayOfMonth ];
|
||||||
|
} else {
|
||||||
|
$dailyEvents = [];
|
||||||
|
}
|
||||||
|
$currentWeek[$dayOfMonth] = $dailyEvents;
|
||||||
|
if (count($currentWeek) == 7) {
|
||||||
|
$output["week$weekCounter"] = $currentWeek;
|
||||||
|
$currentWeek = [];
|
||||||
|
$weekCounter++;
|
||||||
|
}
|
||||||
|
$currentDay = strtotime('+1 day', $currentDay);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle any remaining days in the last week
|
||||||
|
if ( ! empty( $currentWeek ) ) {
|
||||||
|
$output["week$weekCounter"] = $currentWeek;
|
||||||
|
}
|
||||||
|
while ( $weekCounter < 7 ) {
|
||||||
|
$output["week$weekCounter"] = [];
|
||||||
|
$weekCounter++;
|
||||||
|
}
|
||||||
|
return $output;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function yearArray( $calendar_id = 0, $date = null ) {
|
||||||
|
if ( empty( $date ) ) {
|
||||||
|
$date = time();
|
||||||
|
}
|
||||||
|
$year = date( 'Y', $date );
|
||||||
|
$firstDayUnix = date( 'U', strtotime( "Jan 1, $year" ) );
|
||||||
|
$lastDayUnix = date( 'U', strtotime( "December 31, $year" ) );
|
||||||
|
$whereClause = [ 'createdBy', '=', App::$activeUser->ID, 'AND' ];
|
||||||
|
if ( ! empty( $calendar_id ) ) {
|
||||||
|
$whereClause = array_merge( $whereClause, [ 'calendar_id', '=', $calendar_id, 'AND' ] );
|
||||||
|
}
|
||||||
|
$whereClause = array_merge( $whereClause, [
|
||||||
|
'event_time', '<=', $lastDayUnix, 'AND',
|
||||||
|
'event_time', '>=', $firstDayUnix,
|
||||||
|
] );
|
||||||
|
$events = self::$db->get( $this->tableName, $whereClause );
|
||||||
|
if ( ! $events->count() ) {
|
||||||
|
Debug::info( 'No ' . $this->tableName . ' data found.' );
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
return $this->filter( $events->results() );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function compareEventTime($a, $b) {
|
||||||
|
return $a->event_time - $b->event_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function sortByEventTimeHour( $results ) {
|
||||||
|
usort( $results, [ $this,'compareEventTime' ] );
|
||||||
|
|
||||||
|
$sortedResults = array();
|
||||||
|
foreach ( $results as $result ) {
|
||||||
|
$date = new \DateTime();
|
||||||
|
$date->setTimestamp( $result->event_time );
|
||||||
|
$timezone = new \DateTimeZone( Date::getTimezone() );
|
||||||
|
$date->setTimezone( $timezone );
|
||||||
|
$dateKey = $date->format('H');
|
||||||
|
$sortedResults[ $dateKey ][] = $result;
|
||||||
|
}
|
||||||
|
return $sortedResults;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function sortByEventTime( $results ) {
|
||||||
|
usort( $results, [ $this,'compareEventTime' ] );
|
||||||
|
|
||||||
|
$sortedResults = array();
|
||||||
|
foreach ( $results as $result ) {
|
||||||
|
$date = new \DateTime();
|
||||||
|
$date->setTimestamp( $result->event_time );
|
||||||
|
$timezone = new \DateTimeZone( Date::getTimezone() );
|
||||||
|
$date->setTimezone( $timezone );
|
||||||
|
$month = $date->format('F');
|
||||||
|
$dateKey = $date->format('d');
|
||||||
|
if ( ! isset( $sortedResults[ $month ] ) ) {
|
||||||
|
$sortedResults[ $month ] = [];
|
||||||
|
}
|
||||||
|
if ( ! isset( $sortedResults[ $month ][ $dateKey ] ) ) {
|
||||||
|
$sortedResults[ $month ][ $dateKey ] = [];
|
||||||
|
}
|
||||||
|
$sortedResults[ $month ][ $dateKey ][] = $result;
|
||||||
|
}
|
||||||
|
return $sortedResults;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function findByCalendar( $id ) {
|
||||||
|
$calendar = $this->verifyCalendar( $id );
|
||||||
|
if ( empty( $calendar ) ) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
$whereClause = [ 'createdBy', '=', App::$activeUser->ID, 'AND' ];
|
||||||
|
$whereClause = array_merge( $whereClause, [ 'calendar_id', '=', $id ] );
|
||||||
|
$events = self::$db->getPaginated( $this->tableName, $whereClause );
|
||||||
|
if ( ! $events->count() ) {
|
||||||
|
Debug::info( 'No ' . $this->tableName . ' data found.' );
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
return $this->filter( $events->results() );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function userEvents( $limit = 0 ) {
|
||||||
|
$whereClause = [ 'createdBy', '=', App::$activeUser->ID ];
|
||||||
|
$events = self::$db->getPaginated( $this->tableName, $whereClause );
|
||||||
|
if ( ! $events->count() ) {
|
||||||
|
Debug::info( 'No ' . $this->tableName . ' data found.' );
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
return $this->filter( $events->results() );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function filter( $data, $params = [] ) {
|
||||||
|
$out = [];
|
||||||
|
foreach ( $data as $instance ) {
|
||||||
|
if ( !is_object( $instance ) ) {
|
||||||
|
$instance = $data;
|
||||||
|
$end = true;
|
||||||
|
}
|
||||||
|
$instance->repeatsText = array_search('none', $this->repeatOptions);
|
||||||
|
$instance->calendarName = self::$calendars->getName( $instance->calendar_id );
|
||||||
|
if ( empty( $instance->color ) || $instance->color == 'default' || $instance->color == 'none') {
|
||||||
|
$instance->displayColor = self::$calendars->getColor( $instance->calendar_id );
|
||||||
|
} else {
|
||||||
|
$instance->displayColor = $instance->color;
|
||||||
|
}
|
||||||
|
$out[] = $instance;
|
||||||
|
if ( !empty( $end ) ) {
|
||||||
|
$out = $out[0];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $out;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function today( $limit = 0 ) {
|
||||||
|
$date = time();
|
||||||
|
$day = date('d', $date);
|
||||||
|
$month = date('M', $date);
|
||||||
|
$year = date( 'Y', $date );
|
||||||
|
$firstDayUnix = date( 'U', strtotime( "00:00:00 $day $month $year" ) );
|
||||||
|
$lastDayUnix = date( 'U', strtotime( "23:59:59 $day $month $year" ) );
|
||||||
|
$whereClause = [ 'createdBy', '=', App::$activeUser->ID, 'AND' ];
|
||||||
|
$whereClause = array_merge( $whereClause, [
|
||||||
|
'event_time', '<=', $lastDayUnix, 'AND',
|
||||||
|
'event_time', '>=', $firstDayUnix,
|
||||||
|
] );
|
||||||
|
if ( empty( $limit ) ) {
|
||||||
|
$events = self::$db->get( $this->tableName, $whereClause );
|
||||||
|
} else {
|
||||||
|
$events = self::$db->get( $this->tableName, $whereClause, 'ID', 'DESC', [0, $limit] );
|
||||||
|
}
|
||||||
|
if ( ! $events->count() ) {
|
||||||
|
Debug::info( 'No ' . $this->tableName . ' data found.' );
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
return $this->filter( $events->results() );
|
||||||
|
}
|
||||||
|
|
||||||
|
private function verifyCalendar( $calendar_id ) {
|
||||||
|
if ( ! Check::id( $calendar_id ) ) {
|
||||||
|
Debug::info( 'Invalid Calendar ID' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$calendar = self::$calendars->findById( $calendar_id );
|
||||||
|
if ( $calendar == false ) {
|
||||||
|
Debug::info( 'Calendar not found' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( $calendar->createdBy != App::$activeUser->ID ) {
|
||||||
|
Debug::info( 'You do not have permission to view this calendar' );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return $calendar;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function deleteByCalendar( $calendar_id ) {
|
||||||
|
$calendar = $this->verifyCalendar( $calendar_id );
|
||||||
|
if ( empty( $calendar ) ) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
$whereClause = [ 'createdBy', '=', App::$activeUser->ID, 'AND' ];
|
||||||
|
$whereClause = array_merge( $whereClause, [ 'calendar_id', '=', $calendar_id ] );
|
||||||
|
$events = self::$db->get( $this->tableName, $whereClause );
|
||||||
|
if ( ! $events->count() ) {
|
||||||
|
Debug::info( 'No ' . $this->tableName . ' data found.' );
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
foreach( $events->results() as $event ) {
|
||||||
|
$this->deleteByParent( $event->ID );
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function deleteByParent( $event_id ) {
|
||||||
|
$whereClause = [ 'createdBy', '=', App::$activeUser->ID, 'AND' ];
|
||||||
|
$whereClause = array_merge( $whereClause, [ 'parent_id', '=', $event_id ] );
|
||||||
|
$events = self::$db->get( $this->tableName, $whereClause );
|
||||||
|
if ( ! $events->count() ) {
|
||||||
|
Debug::info( 'No ' . $this->tableName . ' data found.' );
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
foreach( $events->results() as $event ) {
|
||||||
|
$this->delete( $event->ID );
|
||||||
|
}
|
||||||
|
// need to delete all child events accordingly
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function delete( $idArray ) {
|
||||||
|
if ( !is_array( $idArray ) ) {
|
||||||
|
$idArray = [ $idArray ];
|
||||||
|
}
|
||||||
|
return parent::delete( $idArray );
|
||||||
|
}
|
||||||
|
|
||||||
|
public function generateChildEvents( $event_id, $remove_existing_children = true, $remove_history = false ) {
|
||||||
|
$event = self::findById( $event_id );
|
||||||
|
if (empty($event)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ($event->parent_id != 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!in_array($event->repeats, $this->repeatOptions)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
$startDate = time();
|
||||||
|
$whereClause = [
|
||||||
|
'parent_id', '=', $event_id,
|
||||||
|
];
|
||||||
|
if ( $remove_history && ! $remove_existing_children) {
|
||||||
|
$whereClause = array_merge( $whereClause, [ 'AND', 'event_time', '<=', $startDate ] );
|
||||||
|
} elseif ( $remove_existing_children && ! $remove_history ) {
|
||||||
|
$whereClause = array_merge( $whereClause, [ 'AND', 'event_time', '>=', $startDate ] );
|
||||||
|
} elseif ( !$remove_existing_children && !$remove_history ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
self::$db->delete($this->tableName, $whereClause);
|
||||||
|
|
||||||
|
switch ($event->repeats) {
|
||||||
|
case 'daily':
|
||||||
|
return $this->generateEvents( $event, 'P90D' );
|
||||||
|
case 'weekly':
|
||||||
|
return $this->generateEvents( $event, 'P1W' );
|
||||||
|
case 'monthly':
|
||||||
|
return $this->generateEvents( $event, 'P1M' );
|
||||||
|
case 'yearly':
|
||||||
|
return $this->generateEvents( $event, 'P1Y' );
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function generateEvents( $event, $interval, $years = 2 ) {
|
||||||
|
$endDate = strtotime('+'.$years.' years');
|
||||||
|
$interval = new \DateInterval( $interval );
|
||||||
|
$period = new \DatePeriod(new \DateTime('@' . $event->event_time), $interval, new \DateTime('@' . $endDate));
|
||||||
|
foreach ($period as $date) {
|
||||||
|
if ( $date->getTimestamp() <= time() ) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$result = $this->create(
|
||||||
|
$event->calendar_id,
|
||||||
|
$event->title,
|
||||||
|
$date->getTimestamp(),
|
||||||
|
$event->description,
|
||||||
|
$event->location,
|
||||||
|
$event->repeats,
|
||||||
|
$event->color,
|
||||||
|
$event->ID,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
84
app/plugins/calendar/plugin.php
Normal file
84
app/plugins/calendar/plugin.php
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* app/plugins/calendar/plugin.php
|
||||||
|
*
|
||||||
|
* This houses all of the main plugin info and functionality.
|
||||||
|
*
|
||||||
|
* @package TP Calendar
|
||||||
|
* @version 3.0
|
||||||
|
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||||
|
* @link https://TheTempusProject.com
|
||||||
|
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||||
|
*/
|
||||||
|
namespace TheTempusProject\Plugins;
|
||||||
|
|
||||||
|
use TheTempusProject\Classes\Plugin;
|
||||||
|
use TheTempusProject\Models\Events;
|
||||||
|
use TheTempusProject\Models\Calendars;
|
||||||
|
use TheTempusProject\Houdini\Classes\Components;
|
||||||
|
use TheTempusProject\Houdini\Classes\Template;
|
||||||
|
|
||||||
|
class Calendar extends Plugin {
|
||||||
|
public $pluginName = 'TP Calendar';
|
||||||
|
public $configName = 'calendar';
|
||||||
|
public $pluginAuthor = 'JoeyK';
|
||||||
|
public $pluginWebsite = 'https://TheTempusProject.com';
|
||||||
|
public $modelVersion = '1.0';
|
||||||
|
public $pluginVersion = '3.0';
|
||||||
|
public $pluginDescription = 'A simple plugin which adds a site wide calendar system.';
|
||||||
|
public $permissionMatrix = [
|
||||||
|
'useCalendar' => [
|
||||||
|
'pretty' => 'Can use the calendar feature',
|
||||||
|
'default' => false,
|
||||||
|
],
|
||||||
|
'createEvents' => [
|
||||||
|
'pretty' => 'Can add events to calendars',
|
||||||
|
'default' => false,
|
||||||
|
],
|
||||||
|
];
|
||||||
|
public $main_links = [
|
||||||
|
[
|
||||||
|
'text' => 'Calendar',
|
||||||
|
'url' => '{ROOT_URL}calendar/index',
|
||||||
|
'filter' => 'loggedin',
|
||||||
|
],
|
||||||
|
];
|
||||||
|
public $configMatrix = [
|
||||||
|
'enabled' => [
|
||||||
|
'type' => 'radio',
|
||||||
|
'pretty' => 'Enable Calendar.',
|
||||||
|
'default' => true,
|
||||||
|
],
|
||||||
|
];
|
||||||
|
public $preferenceMatrix = [
|
||||||
|
'calendarPreference' => [
|
||||||
|
'pretty' => 'Default Calendar View',
|
||||||
|
'type' => 'select',
|
||||||
|
'default' => 'byMonth',
|
||||||
|
'options' => [
|
||||||
|
'Daily' => 'byDay',
|
||||||
|
'Weekly' => 'byWeek',
|
||||||
|
'Monthly' => 'byMonth',
|
||||||
|
'Yearly' => 'byYear',
|
||||||
|
'All Events' => 'events',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
'weekStart' => [
|
||||||
|
'pretty' => 'First day of the week for the Calendar',
|
||||||
|
'type' => 'select',
|
||||||
|
'default' => 'sunday',
|
||||||
|
'options' => [
|
||||||
|
'Sunday' => '6',
|
||||||
|
'Monday' => '7',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
||||||
|
public $events;
|
||||||
|
public $calendars;
|
||||||
|
|
||||||
|
public function __construct( $load = false ) {
|
||||||
|
$this->events = new Events;
|
||||||
|
$this->calendars = new Calendars;
|
||||||
|
parent::__construct( $load );
|
||||||
|
}
|
||||||
|
}
|
41
app/plugins/calendar/templates/calendar.inc.php
Normal file
41
app/plugins/calendar/templates/calendar.inc.php
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* app/plugins/blog/templates/blog.inc.php
|
||||||
|
*
|
||||||
|
* This is the loader for the blog template.
|
||||||
|
*
|
||||||
|
* @package TP Blog
|
||||||
|
* @version 3.0
|
||||||
|
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||||
|
* @link https://TheTempusProject.com
|
||||||
|
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||||
|
*/
|
||||||
|
namespace TheTempusProject\Templates;
|
||||||
|
|
||||||
|
use TheTempusProject\Plugins\Calendar;
|
||||||
|
|
||||||
|
use TheTempusProject\Houdini\Classes\Components;
|
||||||
|
use TheTempusProject\Houdini\Classes\Navigation;
|
||||||
|
use TheTempusProject\Houdini\Classes\Views;
|
||||||
|
use TheTempusProject\Houdini\Classes\Template;
|
||||||
|
use TheTempusProject\Bedrock\Functions\Input;
|
||||||
|
use TheTempusProject\Models\Events;
|
||||||
|
use TheTempusProject\Models\Calendars;
|
||||||
|
|
||||||
|
class CalendarLoader extends DefaultLoader {
|
||||||
|
/**
|
||||||
|
* This is the function used to generate any components that may be
|
||||||
|
* needed by this template.
|
||||||
|
*/
|
||||||
|
public function __construct() {
|
||||||
|
$events = new Events;
|
||||||
|
$calendars = new Calendars;
|
||||||
|
Navigation::setCrumbComponent( 'CALENDAR_BREADCRUMBS', Input::get( 'url' ) );
|
||||||
|
Components::set( 'todaysDate', date( 'F d, Y', time()) );
|
||||||
|
Components::set( 'currentDay', date( 'F d, Y', time()) );
|
||||||
|
Components::set( 'weekOf', 'Week of ' . date( 'F d, Y', strtotime( 'this week' ) ) );
|
||||||
|
Components::set( 'year', date( 'Y', time() ));
|
||||||
|
Components::set( 'month', date( 'F', time() ));
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
}
|
96
app/plugins/calendar/templates/calendar.tpl
Normal file
96
app/plugins/calendar/templates/calendar.tpl
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<!--
|
||||||
|
* app/plugins/calendar/templates/calendar.tpl
|
||||||
|
*
|
||||||
|
* @package TP Calendar
|
||||||
|
* @version 3.0
|
||||||
|
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||||
|
* @link https://TheTempusProject.com
|
||||||
|
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||||
|
-->
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta property="og:url" content="{CURRENT_URL}">
|
||||||
|
<meta name='twitter:card' content='summary' />
|
||||||
|
<title>{TITLE}</title>
|
||||||
|
<meta itemprop="name" content="{TITLE}">
|
||||||
|
<meta name="twitter:title" content="{TITLE}">
|
||||||
|
<meta property="og:title" content="{TITLE}">
|
||||||
|
<meta name="description" content="{PAGE_DESCRIPTION}">
|
||||||
|
<meta itemprop="description" content="{PAGE_DESCRIPTION}">
|
||||||
|
<meta name="twitter:description" content="{PAGE_DESCRIPTION}">
|
||||||
|
<meta property="og:description" content="{PAGE_DESCRIPTION}">
|
||||||
|
<meta itemprop="image" content="{META_IMAGE}">
|
||||||
|
<meta name="twitter:image" content="{META_IMAGE}">
|
||||||
|
<meta property="og:image" content="{META_IMAGE}">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<meta name="author" content="The Tempus Project">
|
||||||
|
{ROBOT}
|
||||||
|
<link rel="alternate" hreflang="en-us" href="alternateURL">
|
||||||
|
<link rel="icon" href="{ROOT_URL}images/favicon.ico">
|
||||||
|
<!-- Required CSS -->
|
||||||
|
<link rel="stylesheet" href="{FONT_AWESOME_URL}font-awesome.min.css" crossorigin="anonymous">
|
||||||
|
<link rel="stylesheet" href="{BOOTSTRAP_CDN}css/bootstrap-theme.min.css" crossorigin="anonymous">
|
||||||
|
<link rel="stylesheet" href="{BOOTSTRAP_CDN}css/bootstrap.min.css" crossorigin="anonymous">
|
||||||
|
<!-- RSS -->
|
||||||
|
<link rel="alternate" href="{ROOT_URL}blog/rss" title="{TITLE} Feed" type="application/rss+xml" />
|
||||||
|
<!-- Custom styles for this template -->
|
||||||
|
{TEMPLATE_CSS_INCLUDES}
|
||||||
|
<link rel="stylesheet" href="{ROOT_URL}app/plugins/calendar/css/calendar.css" />
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">
|
||||||
|
<!--Brand and toggle should get grouped for better mobile display -->
|
||||||
|
<div class="navbar-header">
|
||||||
|
<a href="{ROOT_URL}" class="navbar-brand">{SITENAME}</a>
|
||||||
|
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-ex1-collapse" style="">
|
||||||
|
<span class="sr-only">Toggle navigation</span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
<span class="icon-bar"></span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="collapse navbar-collapse navbar-ex1-collapse">
|
||||||
|
{topNavLeft}
|
||||||
|
<div class="navbar-right">
|
||||||
|
<ul class="nav navbar-nav">
|
||||||
|
{topNavRight}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="foot-pad">
|
||||||
|
{ISSUES}
|
||||||
|
<div class="row">
|
||||||
|
<div class="container">
|
||||||
|
{ERROR}
|
||||||
|
{NOTICE}
|
||||||
|
{SUCCESS}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/ISSUES}
|
||||||
|
<div class="row">
|
||||||
|
<div class="container-fluid calendar-container">
|
||||||
|
<div class="row">
|
||||||
|
{CalendarNav}
|
||||||
|
{CONTENT}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<footer>
|
||||||
|
{COPY}
|
||||||
|
</footer>
|
||||||
|
<!-- Bootstrap core JavaScript and jquery -->
|
||||||
|
<script src="{JQUERY_CDN}jquery.min.js" crossorigin="anonymous"></script>
|
||||||
|
<script src="{BOOTSTRAP_CDN}js/bootstrap.min.js" crossorigin="anonymous"></script>
|
||||||
|
<!-- Custom javascript for this template -->
|
||||||
|
{TEMPLATE_JS_INCLUDES}
|
||||||
|
</body>
|
||||||
|
</html>
|
25
app/plugins/calendar/views/byDay.html
Normal file
25
app/plugins/calendar/views/byDay.html
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<h2 class="pull-left">
|
||||||
|
<a href="{ROOT_URL}calendar/byDay/{calendarID}?day={lastDay}&month={lastDayMonth}" role="button" class="btn btn-primary">
|
||||||
|
<i class="glyphicon glyphicon-chevron-left"></i>
|
||||||
|
</a>
|
||||||
|
<span class="dateDayContainer">{activeDate}</span>
|
||||||
|
<a href="{ROOT_URL}calendar/byDay/{calendarID}?day={nextDay}&month={nextDayMonth}" role="button" class="btn btn-primary">
|
||||||
|
<i class="glyphicon glyphicon-chevron-right"></i>
|
||||||
|
</a>
|
||||||
|
</h2>
|
||||||
|
{dateDropdown}
|
||||||
|
<div class="container-fluid">
|
||||||
|
{LOOP}
|
||||||
|
<div class="hour-row{hourSelected}">
|
||||||
|
<h2 class="hour-header">{hour}:00</h2>
|
||||||
|
{EventCells}
|
||||||
|
<span class="hour-footer">
|
||||||
|
<a href="{ROOT_URL}calendar/createEvent?calendar_id={calendarID}&hour={hour}&day={day}" class="btn btn-sm btn-success" role="button"><i class="glyphicon glyphicon-plus"></i></a>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
{/LOOP}
|
||||||
|
{ALT}
|
||||||
|
<div class="hour-row{hourSelected}">
|
||||||
|
</div>
|
||||||
|
{/ALT}
|
||||||
|
</div>
|
34
app/plugins/calendar/views/byMonth.html
Normal file
34
app/plugins/calendar/views/byMonth.html
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<h2 class="pull-left">
|
||||||
|
<a href="{ROOT_URL}calendar/byMonth/{calendarID}?month={lastMonth}&year={lastMonthYear}" role="button" class="btn btn-primary">
|
||||||
|
<i class="glyphicon glyphicon-chevron-left"></i>
|
||||||
|
</a>
|
||||||
|
<span class="dateMonthContainer">{dateMonth}</span>
|
||||||
|
<a href="{ROOT_URL}calendar/byMonth/{calendarID}?month={nextMonth}&year={nextMonthYear}" role="button" class="btn btn-primary">
|
||||||
|
<i class="glyphicon glyphicon-chevron-right"></i>
|
||||||
|
</a>
|
||||||
|
</h2>
|
||||||
|
{dateDropdown}
|
||||||
|
<div class="container-fluid">
|
||||||
|
<!-- Header -->
|
||||||
|
<div class="row calendar-row">
|
||||||
|
<div class="col-xs-1 calendar-cell"><h4>Sunday</h4></div>
|
||||||
|
<div class="col-xs-1 calendar-cell"><h4>Monday</h4></div>
|
||||||
|
<div class="col-xs-1 calendar-cell"><h4>Tuesday</h4></div>
|
||||||
|
<div class="col-xs-1 calendar-cell"><h4>Wednesday</h4></div>
|
||||||
|
<div class="col-xs-1 calendar-cell"><h4>Thursday</h4></div>
|
||||||
|
<div class="col-xs-1 calendar-cell"><h4>Friday</h4></div>
|
||||||
|
<div class="col-xs-1 calendar-cell"><h4>Saturday</h4></div>
|
||||||
|
</div>
|
||||||
|
<!-- Week 1 -->
|
||||||
|
{week1Element}
|
||||||
|
<!-- Week 2 -->
|
||||||
|
{week2Element}
|
||||||
|
<!-- Week 3 -->
|
||||||
|
{week3Element}
|
||||||
|
<!-- Week 4 -->
|
||||||
|
{week4Element}
|
||||||
|
<!-- Week 5 -->
|
||||||
|
{week5Element}
|
||||||
|
<!-- Week 6 -->
|
||||||
|
{week6Element}
|
||||||
|
</div>
|
25
app/plugins/calendar/views/byWeek.html
Normal file
25
app/plugins/calendar/views/byWeek.html
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
|
||||||
|
<h2 class="pull-left">
|
||||||
|
<a href="{ROOT_URL}calendar/byWeek/{calendarID}?month={lastWeekMonth}&day={lastWeek}&year={lastYear}" role="button" class="btn btn-primary">
|
||||||
|
<i class="glyphicon glyphicon-chevron-left"></i>
|
||||||
|
</a>
|
||||||
|
<span class="dateWeekContainer">{dateWeek}</span>
|
||||||
|
<a href="{ROOT_URL}calendar/byWeek/{calendarID}?month={nextWeekMonth}&day={nextWeek}&year={nextYear}" role="button" class="btn btn-primary">
|
||||||
|
<i class="glyphicon glyphicon-chevron-right"></i>
|
||||||
|
</a>
|
||||||
|
</h2>
|
||||||
|
{dateDropdown}
|
||||||
|
<div class="container-fluid">
|
||||||
|
<!-- Header -->
|
||||||
|
<div class="row calendar-row">
|
||||||
|
<div class="col-xs-1 calendar-cell"><h4>Sunday</h4></div>
|
||||||
|
<div class="col-xs-1 calendar-cell"><h4>Monday</h4></div>
|
||||||
|
<div class="col-xs-1 calendar-cell"><h4>Tuesday</h4></div>
|
||||||
|
<div class="col-xs-1 calendar-cell"><h4>Wednesday</h4></div>
|
||||||
|
<div class="col-xs-1 calendar-cell"><h4>Thursday</h4></div>
|
||||||
|
<div class="col-xs-1 calendar-cell"><h4>Friday</h4></div>
|
||||||
|
<div class="col-xs-1 calendar-cell"><h4>Saturday</h4></div>
|
||||||
|
</div>
|
||||||
|
<!-- Week 1 -->
|
||||||
|
{week1Element}
|
||||||
|
</div>
|
42
app/plugins/calendar/views/byYear.html
Normal file
42
app/plugins/calendar/views/byYear.html
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
<h2 class="pull-left">
|
||||||
|
<a href="{ROOT_URL}calendar/byYear/{calendarID}?year={lastYear}" role="button" class="btn btn-primary">
|
||||||
|
<i class="glyphicon glyphicon-chevron-left"></i>
|
||||||
|
</a>
|
||||||
|
<span class="dateYearContainer">{dateYear}</span>
|
||||||
|
<a href="{ROOT_URL}calendar/byYear/{calendarID}?year={nextYear}" role="button" class="btn btn-primary">
|
||||||
|
<i class="glyphicon glyphicon-chevron-right"></i>
|
||||||
|
</a>
|
||||||
|
</h2>
|
||||||
|
{dateDropdown}
|
||||||
|
<table class="table table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th style="width: 10%">ID</th>
|
||||||
|
<th style="width: 20%">Time</th>
|
||||||
|
<th style="width: 40%">Title</th>
|
||||||
|
<th style="width: 10%"></th>
|
||||||
|
<th style="width: 10%"></th>
|
||||||
|
<th style="width: 10%"></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{LOOP}
|
||||||
|
<tr>
|
||||||
|
<td style="text-align: center;">{ID}</td>
|
||||||
|
<td style="text-align: center;">{DTC}{event_time}{/DTC}</td>
|
||||||
|
<td style="text-align: center;">{title}</td>
|
||||||
|
<td><a href="{ROOT_URL}calendar/event/{ID}" class="btn btn-sm btn-primary" role="button"><i class="glyphicon glyphicon-open"></i></a></td>
|
||||||
|
<td><a href="{ROOT_URL}calendar/editEvent/{ID}" class="btn btn-sm btn-warning" role="button"><i class="glyphicon glyphicon-edit"></i></a></td>
|
||||||
|
<td><a href="{ROOT_URL}calendar/deleteEvent/{ID}" class="btn btn-sm btn-danger" role="button"><i class="glyphicon glyphicon-trash"></i></a></td>
|
||||||
|
</tr>
|
||||||
|
{/LOOP}
|
||||||
|
{ALT}
|
||||||
|
<tr>
|
||||||
|
<td style="text-align: center;" colspan="6">
|
||||||
|
No results to show.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{/ALT}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<a href="{ROOT_URL}calendar/createEvent" class="btn btn-sm btn-primary" role="button">Create</a>
|
34
app/plugins/calendar/views/calendar/create.html
Normal file
34
app/plugins/calendar/views/calendar/create.html
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
<legend>Create Calendar</legend>
|
||||||
|
<form action="" method="post" class="form-horizontal">
|
||||||
|
<input type="hidden" name="token" value="{TOKEN}">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="title" class="col-lg-3 control-label">Title</label>
|
||||||
|
<div class="col-lg-3">
|
||||||
|
<input type="text" class="form-control" name="title" id="title">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="description" class="col-lg-3 control-label">Description</label>
|
||||||
|
<div class="col-lg-3">
|
||||||
|
<textarea class="form-control" name="description" maxlength="2000" rows="10" cols="50" id="description"></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="description" class="col-lg-3 control-label">Timezone</label>
|
||||||
|
<div class="col-lg-3">
|
||||||
|
{timezoneSelect}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="color" class="col-lg-3 control-label">Calendar Color</label>
|
||||||
|
<div class="col-lg-3 select-container" id="colorContainer">
|
||||||
|
{colorSelect}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="submit" class="col-lg-3 control-label"></label>
|
||||||
|
<div class="col-lg-3">
|
||||||
|
<button name="submit" value="submit" type="submit" class="btn btn-lg btn-primary center-block ">Submit</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
29
app/plugins/calendar/views/calendar/edit.html
Normal file
29
app/plugins/calendar/views/calendar/edit.html
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<legend>Edit Calendar</legend>
|
||||||
|
<form action="" method="post" class="form-horizontal">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="title" class="col-lg-3 control-label">Title</label>
|
||||||
|
<div class="col-lg-3">
|
||||||
|
<input type="text" class="form-check-input form-control" name="title" id="title" value="{title}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="description" class="col-lg-3 control-label">Description</label>
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<textarea class="form-control" name="description" maxlength="2000" rows="10" cols="50" id="description">{description}</textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="description" class="col-lg-3 control-label">Timezone</label>
|
||||||
|
<div class="col-lg-3">
|
||||||
|
{timezoneSelect}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="color" class="col-lg-3 control-label">Calendar Color</label>
|
||||||
|
<div class="col-lg-3 select-container" id="colorContainer">
|
||||||
|
{colorSelect}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<input type="hidden" name="token" value="{TOKEN}">
|
||||||
|
<button name="submit" value="submit" type="submit" class="btn btn-lg btn-primary center-block">Submit</button>
|
||||||
|
</form>
|
45
app/plugins/calendar/views/calendar/list.html
Normal file
45
app/plugins/calendar/views/calendar/list.html
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
<legend>Calendars</legend>
|
||||||
|
<form action="{ROOT_URL}calendar/deleteCalendar" method="post">
|
||||||
|
<table class="table table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th style="width: 5%">ID</th>
|
||||||
|
<th style="width: 20%">Title</th>
|
||||||
|
<th style="width: 50%">Description</th>
|
||||||
|
<th style="width: 5%"></th>
|
||||||
|
<th style="width: 5%"></th>
|
||||||
|
<th style="width: 5%"></th>
|
||||||
|
<th style="width: 5%"></th>
|
||||||
|
<th style="width: 5%">
|
||||||
|
<input type="checkbox" onchange="checkAll(this)" name="check.br" value="CAL_[]"/>
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{LOOP}
|
||||||
|
<tr>
|
||||||
|
<td align="center">{ID}</td>
|
||||||
|
<td align="center">{title}</td>
|
||||||
|
<td>{description}</td>
|
||||||
|
<td><a href="{ROOT_URL}calendar/byMonth/{ID}" class="btn btn-sm btn-primary" role="button"><i class="glyphicon glyphicon-share-alt"></i></a></td>
|
||||||
|
<td><a href="{ROOT_URL}calendar/calendar/{ID}" class="btn btn-sm btn-primary" role="button"><i class="glyphicon glyphicon-info-sign"></i></a></td>
|
||||||
|
<td><a href="{ROOT_URL}calendar/editCalendar/{ID}" class="btn btn-sm btn-warning" role="button"><i class="glyphicon glyphicon-edit"></i></a></td>
|
||||||
|
<td><a href="{ROOT_URL}calendar/deleteCalendar/{ID}" class="btn btn-sm btn-danger" role="button"><i class="glyphicon glyphicon-trash"></i></a></td>
|
||||||
|
<td>
|
||||||
|
<input type="checkbox" value="{ID}" name="CAL_[]">
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{/LOOP}
|
||||||
|
{ALT}
|
||||||
|
<tr>
|
||||||
|
<td align="center" colspan="7">
|
||||||
|
No results to show.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{/ALT}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<a href="{ROOT_URL}calendar/createCalendar" class="btn btn-sm btn-primary" role="button">Create</a>
|
||||||
|
<button name="submit" value="submit" type="submit" class="btn btn-sm btn-danger">Delete</button>
|
||||||
|
</form>
|
||||||
|
<br />
|
42
app/plugins/calendar/views/calendar/view.html
Normal file
42
app/plugins/calendar/views/calendar/view.html
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
<div class="container col-md-4 col-lg-4">
|
||||||
|
<div class="row">
|
||||||
|
<div class="panel panel-primary">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<h3 class="panel-title">Calendar</h3>
|
||||||
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<div class="row">
|
||||||
|
<div class="">
|
||||||
|
<table class="table table-user-primary">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td align="left" width="200"><b>Title</b></td>
|
||||||
|
<td align="right">{title}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><b>Created</b></td>
|
||||||
|
<td align="right">{DTC}{createdAt}{/DTC}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td align="center" colspan="2"><b>Description</b></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">{description}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><b>TimeZone</b></td>
|
||||||
|
<td align="right">{timezone}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="panel-footer">
|
||||||
|
<a href="{ROOT_URL}calendar/deleteCalendar/{ID}" class="btn btn-md btn-danger" role="button">Delete</a>
|
||||||
|
<a href="{ROOT_URL}calendar/editCalendar/{ID}" class="btn btn-md btn-warning" role="button">Edit</a>
|
||||||
|
<a href="{ROOT_URL}calendar/byMonth/{ID}" class="btn btn-md btn-primary" role="button">View Events</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
20
app/plugins/calendar/views/dateSelect.html
Normal file
20
app/plugins/calendar/views/dateSelect.html
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
<div class="form-group">
|
||||||
|
<label for="day" class="col-lg-3 control-label">All-Day Event</label>
|
||||||
|
<div class="col-lg-3">
|
||||||
|
<input class="" type="checkbox" name="allDay" id="allDay" value="true" {CHECKED:allDay=true}>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="month" class="col-lg-3 control-label">Event Start</label>
|
||||||
|
<div class="col-lg-3">
|
||||||
|
<input type="date" name="date" id="date" class="form-control" value="{date}" />
|
||||||
|
<input type="time" name="time" id="time" class="form-control" value="{time}" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="month" class="col-lg-3 control-label">Event End</label>
|
||||||
|
<div class="col-lg-3">
|
||||||
|
<input type="date" name="endDate" id="endDate" class="form-control" value="{endDate}" />
|
||||||
|
<input type="time" name="endTime" id="endTime" class="form-control" value="{endTime}" />
|
||||||
|
</div>
|
||||||
|
</div>
|
37
app/plugins/calendar/views/events/create.html
Normal file
37
app/plugins/calendar/views/events/create.html
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
<legend>Create Event</legend>
|
||||||
|
<form action="" method="post" class="form-horizontal">
|
||||||
|
<input type="hidden" name="token" value="{TOKEN}">
|
||||||
|
{calendarSelect}
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="title" class="col-lg-3 control-label">Title</label>
|
||||||
|
<div class="col-lg-3">
|
||||||
|
<input type="text" class="form-control" name="title" id="title">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="description" class="col-lg-3 control-label">Description</label>
|
||||||
|
<div class="col-lg-3">
|
||||||
|
<textarea class="form-control" name="description" maxlength="2000" rows="6" cols="30" id="description"></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="location" class="col-lg-3 control-label">Location</label>
|
||||||
|
<div class="col-lg-3">
|
||||||
|
<input type="text" class="form-control" name="location" id="location">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="color" class="col-lg-3 control-label">Event Color</label>
|
||||||
|
<div class="col-lg-3 select-container" id="colorContainer">
|
||||||
|
{colorSelect}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{dateSelect}
|
||||||
|
{repeatSelect}
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="submit" class="col-lg-3 control-label"></label>
|
||||||
|
<div class="col-lg-3">
|
||||||
|
<button name="submit" value="submit" type="submit" class="btn btn-lg btn-primary center-block">Submit</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
31
app/plugins/calendar/views/events/edit.html
Normal file
31
app/plugins/calendar/views/events/edit.html
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<legend>Edit Event</legend>
|
||||||
|
<form action="" method="post" class="form-horizontal">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="title" class="col-lg-3 control-label">Title</label>
|
||||||
|
<div class="col-lg-3">
|
||||||
|
<input type="text" class="form-control" name="title" id="title" value="{title}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="description" class="col-lg-3 control-label">Description</label>
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<textarea class="form-control" name="description" maxlength="2000" rows="10" cols="50" id="description">{description}</textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="location" class="col-lg-3 control-label">Location</label>
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<input type="text" class="form-control" name="location" id="location" value="{location}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="color" class="col-lg-3 control-label">Event Color</label>
|
||||||
|
<div class="col-lg-3 select-container" id="colorContainer">
|
||||||
|
{colorSelect}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{dateSelect}
|
||||||
|
{repeatSelect}
|
||||||
|
<input type="hidden" name="token" value="{TOKEN}">
|
||||||
|
<button name="submit" value="submit" type="submit" class="btn btn-lg btn-primary center-block">Submit</button>
|
||||||
|
</form>
|
34
app/plugins/calendar/views/events/list.html
Normal file
34
app/plugins/calendar/views/events/list.html
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
{PAGINATION}
|
||||||
|
<table class="table table-striped">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th style="width: 10%">ID</th>
|
||||||
|
<th style="width: 20%">Time</th>
|
||||||
|
<th style="width: 40%">Title</th>
|
||||||
|
<th style="width: 10%"></th>
|
||||||
|
<th style="width: 10%"></th>
|
||||||
|
<th style="width: 10%"></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{LOOP}
|
||||||
|
<tr>
|
||||||
|
<td style="text-align: center;">{ID}</td>
|
||||||
|
<td style="text-align: center;">{DTC}{event_time}{/DTC}</td>
|
||||||
|
<td style="text-align: center;">{title}</td>
|
||||||
|
<td><a href="{ROOT_URL}calendar/event/{ID}" class="btn btn-sm btn-primary" role="button"><i class="glyphicon glyphicon-open"></i></a></td>
|
||||||
|
<td><a href="{ROOT_URL}calendar/editEvent/{ID}" class="btn btn-sm btn-warning" role="button"><i class="glyphicon glyphicon-edit"></i></a></td>
|
||||||
|
<td><a href="{ROOT_URL}calendar/deleteEvent/{ID}" class="btn btn-sm btn-danger" role="button"><i class="glyphicon glyphicon-trash"></i></a></td>
|
||||||
|
</tr>
|
||||||
|
{/LOOP}
|
||||||
|
{ALT}
|
||||||
|
<tr>
|
||||||
|
<td style="text-align: center;" colspan="6">
|
||||||
|
No results to show.
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{/ALT}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{PAGINATION}
|
||||||
|
<a href="{ROOT_URL}calendar/createEvent" class="btn btn-sm btn-primary" role="button">Create</a>
|
52
app/plugins/calendar/views/events/view.html
Normal file
52
app/plugins/calendar/views/events/view.html
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
<div class="container col-md-4 col-lg-4">
|
||||||
|
<div class="row">
|
||||||
|
<div class="panel panel-primary">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<h3 class="panel-title">Event</h3>
|
||||||
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<div class="row">
|
||||||
|
<table class="table table-user-primary">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td style="text-align: left;" width="200"><b>Title</b></td>
|
||||||
|
<td style="text-align: right;">{title}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><b>Created</b></td>
|
||||||
|
<td style="text-align: right;">{DTC}{createdAt}{/DTC}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><b>Event Time</b></td>
|
||||||
|
<td style="text-align: right;">{DTC}{event_time}{/DTC}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td style="text-align: center;" colspan="2"><b>Description</b></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">{description}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><b>Location</b></td>
|
||||||
|
<td style="text-align: right;">{location}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><b>Frequency</b></td>
|
||||||
|
<td style="text-align: right;">{repeatsText}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><b>Calendar</b></td>
|
||||||
|
<td style="text-align: right;">{calendarName}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="panel-footer">
|
||||||
|
<a href="{ROOT_URL}calendar/deleteEvent/{ID}" class="btn btn-md btn-danger" role="button">Delete</a>
|
||||||
|
<a href="{ROOT_URL}calendar/editEvent/{ID}" class="btn btn-md btn-warning" role="button">Edit</a>
|
||||||
|
<a href="{ROOT_URL}calendar/byMonth/{calendar_id}" class="btn btn-md btn-primary" role="button">View Events</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
16
app/plugins/calendar/views/nav/calendarDropdown.html
Normal file
16
app/plugins/calendar/views/nav/calendarDropdown.html
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<li class="pull-right dropdown">
|
||||||
|
<button type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||||
|
Calendars <span class="caret"></span>
|
||||||
|
</button>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<li><a href="{ROOT_URL}calendar/{currentView}/">All</a></li>
|
||||||
|
<li role="separator" class="divider"></li>
|
||||||
|
{LOOP}
|
||||||
|
<li><a href="{ROOT_URL}calendar/{currentView}/{ID}">{title}</a></li>
|
||||||
|
{/LOOP}
|
||||||
|
<li role="separator" class="divider"></li>
|
||||||
|
<li><a href="{ROOT_URL}calendar/createCalendar">Create Calendar</a></li>
|
||||||
|
<li><a href="{ROOT_URL}calendar/editCalendar/{calendarID}">Edit Calendar</a></li>
|
||||||
|
<li><a href="{ROOT_URL}calendar/deleteCalendar/{calendarID}">Delete Calendar</a></li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
23
app/plugins/calendar/views/nav/cell.html
Normal file
23
app/plugins/calendar/views/nav/cell.html
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<ul class="list-group">
|
||||||
|
{LOOP}
|
||||||
|
<li class="list-group-item btn-{displayColor}">
|
||||||
|
<p style="text-align: center;">{title}</p>
|
||||||
|
<p style="text-align: center;">{DTC}{event_time}{/DTC}</p>
|
||||||
|
<p>
|
||||||
|
<a href="{ROOT_URL}calendar/event/{ID}" class="btn btn-sm btn-primary" role="button"><i class="glyphicon glyphicon-open"></i></a>
|
||||||
|
<a href="{ROOT_URL}calendar/editEvent/{ID}" class="btn btn-sm btn-warning" role="button"><i class="glyphicon glyphicon-edit"></i></a>
|
||||||
|
<a href="{ROOT_URL}calendar/deleteEvent/{ID}" class="btn btn-sm btn-danger" role="button"><i class="glyphicon glyphicon-trash"></i></a>
|
||||||
|
</p>
|
||||||
|
</li>
|
||||||
|
{/LOOP}
|
||||||
|
{ALT}
|
||||||
|
<li class="list-group-item">
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
</li>
|
||||||
|
{/ALT}
|
||||||
|
<a href="{ROOT_URL}calendar/createEvent?calendar_id={calendarID}&month={currentMonth}&day={currentDay}" class="list-group-item list-group-item-success"><i class="glyphicon glyphicon-plus"></i></a>
|
||||||
|
</ul>
|
18
app/plugins/calendar/views/nav/dateDropdown.html
Normal file
18
app/plugins/calendar/views/nav/dateDropdown.html
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<ul class="nav nav-pills">
|
||||||
|
<li class="dropdown pull-right">
|
||||||
|
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||||
|
Switch Date <span class="caret"></span>
|
||||||
|
</button>
|
||||||
|
<ul class="dropdown-menu">
|
||||||
|
<form action="" method="post" class="form-horizontal">
|
||||||
|
<li><input type="date" name="date" id="date" class="form-control" value="{date}" /></li>
|
||||||
|
<li role="separator" class="divider"></li>
|
||||||
|
<li>
|
||||||
|
<button name="submit" value="submit" type="submit" class="btn btn-primary center-block">
|
||||||
|
Select Date
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
</form>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
12
app/plugins/calendar/views/nav/row.html
Normal file
12
app/plugins/calendar/views/nav/row.html
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<span class="hour-body">
|
||||||
|
{LOOP}
|
||||||
|
<div class="hour-cell btn-{displayColor}">
|
||||||
|
<p class="event-title">{title}</p>
|
||||||
|
<a href="{ROOT_URL}calendar/event/{ID}" class="btn btn-sm btn-primary" role="button"><i class="glyphicon glyphicon-open"></i></a>
|
||||||
|
<a href="{ROOT_URL}calendar/editEvent/{ID}" class="btn btn-sm btn-warning" role="button"><i class="glyphicon glyphicon-edit"></i></a>
|
||||||
|
<a href="{ROOT_URL}calendar/deleteEvent/{ID}" class="btn btn-sm btn-danger" role="button"><i class="glyphicon glyphicon-trash"></i></a>
|
||||||
|
</div>
|
||||||
|
{/LOOP}
|
||||||
|
{ALT}
|
||||||
|
{/ALT}
|
||||||
|
</span>
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user