Compare commits
63 Commits
3.0.3
...
d7d8fc4b5e
Author | SHA1 | Date | |
---|---|---|---|
d7d8fc4b5e | |||
b1b0da0c08 | |||
3eec88c228 | |||
113499254b | |||
3b6d7f3a2c | |||
09f96c369a | |||
afb9624971 | |||
8d3dee2ac2 | |||
355e509e68 | |||
c3f46cf6c3 | |||
4a521afa88 | |||
0fa83b0ae6 | |||
5c7a320c2a | |||
551f6654f6 | |||
80048ad1dd | |||
80b8226218 | |||
cc9e57888f | |||
ec317e6426 | |||
910c9646b8 | |||
44dcb29060 | |||
431b1214fa | |||
9972f6a654 | |||
b658614ce8 | |||
55a725cd9e | |||
a8b972acf5 | |||
fd8d37d67a | |||
c8eed20814 | |||
b6767ae846 | |||
156f19ee97 | |||
0a9a5a433f | |||
b8c75a128a | |||
e4e72905fc | |||
74e9af4539 | |||
46c0376dfc | |||
90ba704a69 | |||
fb92682eed | |||
54e1a6a817 | |||
9eacdcdc37 | |||
4388a4baa8 | |||
ed43b2f2df | |||
e88c8486a1 | |||
16dbc6c4e2 | |||
14f8f134bc | |||
ea30628ef8 | |||
e1d7c7fcc7 | |||
ee5bcd23fa | |||
b6add64d14 | |||
19e34583d1 | |||
7e296b2468 | |||
e9988d4a14 | |||
4ccbd17607 | |||
7eb1ad9f7d | |||
14bc0c1e64 | |||
4d1e8d6753 | |||
468d48cc00 | |||
778a9882b8 | |||
60985c8c09 | |||
e2d32ab0a0 | |||
136e85dd14 | |||
2fc3338d0f | |||
aba39575fa | |||
508c25c111 | |||
6cf4594622 |
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/*
|
||||||
docker/.env
|
.env
|
||||||
|
components/*
|
||||||
|
74
.gitlab-ci.yml
Normal file
74
.gitlab-ci.yml
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
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,6 +1,10 @@
|
|||||||
MIT License
|
Copyright (c) 2024-present Joey Kimsey
|
||||||
|
|
||||||
Copyright (c) 2024 Joey Kimsey
|
Portions of this software are licensed as follows:
|
||||||
|
|
||||||
|
* 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
|
||||||
|
50
README.md
50
README.md
@ -1,39 +1,41 @@
|
|||||||
# The Tempus Project
|
# The Tempus Project
|
||||||
|
|
||||||
|
|
||||||
|
need to make a vs battle for dnd. someone makes a truly broken character, we take the base character and hand it to two people and give them some time to figure out how they would break it
|
||||||
|
|
||||||
|
need to track points once a week
|
||||||
|
|
||||||
|
a huge table tracks points day to day then we add and erase the old data, or move it to historical...
|
||||||
|
|
||||||
## Rapid Prototyping Framework
|
## Rapid Prototyping Framework
|
||||||
|
|
||||||
## Developer(s): Joey Kimsey
|
### Developer(s): Joey Kimsey
|
||||||
|
|
||||||
The aim of this project is to provide a simple and stable platform from which to easily add functionality. The goal being the ability to quickly build and test new projects with a lightweight ecosystem to help.
|
The aim of this project is to provide a simple and stable platform from which to easily add functionality. The goal being the ability to quickly build and test new projects with a lightweight ecosystem to help.
|
||||||
|
|
||||||
**Notice: This code is in _still_ not production ready. This framework is provided as is, use at your own risk.**
|
**Notice: This code is in _still_ not production ready. This framework is provided as is, use at your own risk.**
|
||||||
I am working very hard to ensure the system is safe and reliable enough for me to endorse its widespread use. Unfortunately, it still needs a lot of QA and improvements.
|
I am working very hard to ensure the system is safe and reliable enough for me to endorse its widespread use. Unfortunately, it still needs a lot of QA and improvements.
|
||||||
|
|
||||||
|
Currently I am in the process of testing all the systems in preparation for the first production ready release. The beta is still on-going. If you would like to participate or stay up to date with the latest, you can find more information at: https://TheTempusProject.com/beta
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
- A Plugin system that allows plug-and-play functionality
|
A User management system with groups, permissions, preferences, registration, and recovery. (All Controlled dynamically via our plugin interface)
|
||||||
- A User management system
|
A Plugin system that allows plug-and-play functionality for a huge number of features.
|
||||||
- groups
|
Compatibility with both Apache and NGINX.
|
||||||
- permissions
|
Built with Bootstrap with a focus on mobile compatibility.
|
||||||
- preferences
|
Incredibly easy to set-up, deploy, and develop with.
|
||||||
- registration and recovery
|
|
||||||
(All Controlled dynamically via our plugin interface)
|
|
||||||
- Compatibility with both Apache and NGINX
|
|
||||||
- Built with Bootstrap with a focus on mobile compatibility
|
|
||||||
- Incredibly easy to set-up, deploy, and develop
|
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
Preferred method for installation is using composer. Special attention has been given to use without composer and more information is included below.
|
Preferred method for installation is using composer.
|
||||||
|
|
||||||
|
### Manually
|
||||||
|
|
||||||
|
### Docker
|
||||||
|
|
||||||
### Composer
|
### Composer
|
||||||
|
|
||||||
The simplest method to start a new project is to use composer to create a new project and automatically clone all the necessary files:
|
|
||||||
|
|
||||||
```
|
|
||||||
composer create-project thetempusproject/thetempusproject test-app
|
|
||||||
```
|
|
||||||
|
|
||||||
1. Clone the directory to wherever you want to install the framework.
|
1. Clone the directory to wherever you want to install the framework.
|
||||||
2. Open your terminal to the directory you previously cloned the repository.
|
2. Open your terminal to the directory you previously cloned the repository.
|
||||||
3. Install using composer:
|
3. Install using composer:
|
||||||
@ -41,12 +43,6 @@ composer create-project thetempusproject/thetempusproject test-app
|
|||||||
4. Open your browser and navigate to install.php (it will be in the root directory of your installation)
|
4. Open your browser and navigate to install.php (it will be in the root directory of your installation)
|
||||||
5. When prompted, complete the forms and complete the process.
|
5. When prompted, complete the forms and complete the process.
|
||||||
|
|
||||||
|
|
||||||
### Manually
|
|
||||||
|
|
||||||
### Docker
|
|
||||||
|
|
||||||
|
|
||||||
#### Apache
|
#### Apache
|
||||||
|
|
||||||
#### NGINX
|
#### NGINX
|
||||||
@ -376,3 +372,9 @@ 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/admin_controller.php
|
* app/classes/api_controller.php
|
||||||
*
|
*
|
||||||
* This is the base admin controller. Every other admin controller should
|
* This is the base api controller. Every other api controller should
|
||||||
* extend this class.
|
* extend this class.
|
||||||
*
|
*
|
||||||
* @version 3.0
|
* @version 3.0
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* classes/config.php
|
* app/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/Core
|
* @link https://TheTempusProject.com
|
||||||
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||||
*/
|
*/
|
||||||
namespace TheTempusProject\Classes;
|
namespace TheTempusProject\Classes;
|
||||||
|
@ -13,11 +13,12 @@ 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\Houdini\Classes\Pagination;
|
use TheTempusProject\Bedrock\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;
|
||||||
|
@ -16,11 +16,19 @@ namespace TheTempusProject\Classes;
|
|||||||
|
|
||||||
use TheTempusProject\Bedrock\Functions\Check;
|
use TheTempusProject\Bedrock\Functions\Check;
|
||||||
use TheTempusProject\Canary\Bin\Canary as Debug;
|
use TheTempusProject\Canary\Bin\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;
|
||||||
@ -74,4 +82,530 @@ 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -266,6 +266,7 @@ 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 ) ) {
|
||||||
@ -326,7 +327,7 @@ class Installer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ( empty( $module_data->class_object ) ) {
|
if ( empty( $module_data->class_object ) ) {
|
||||||
self::$errors[] = [ 'errorInfo' => 'Class not found: ' . $module_data->class ];
|
self::$errors[] = [ 'errorInfo' => 'installPlugin: class_object not found: ' . $module_data->class ];
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -363,7 +364,7 @@ class Installer {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$errors[] = [ 'errorInfo' => $module_data['name'] . " has been installed." ];
|
$errors[] = [ 'errorInfo' => $module_data['name'] . " Plugin has been installed." ];
|
||||||
self::$errors = array_merge( self::$errors, $errors );
|
self::$errors = array_merge( self::$errors, $errors );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -373,7 +374,7 @@ class Installer {
|
|||||||
$errors = [];
|
$errors = [];
|
||||||
|
|
||||||
if ( empty( $module_data->class_object ) ) {
|
if ( empty( $module_data->class_object ) ) {
|
||||||
self::$errors[] = [ 'errorInfo' => 'Class not found: ' . $module_data->class ];
|
self::$errors[] = [ 'errorInfo' => 'uninstallPlugin: class_object not found: ' . $module_data->class ];
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -393,7 +394,7 @@ class Installer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$this->removeModule( $module_data->name, true );
|
$this->removeModule( $module_data->name, true );
|
||||||
$errors[] = [ 'errorInfo' => $module_data->name . " has been installed." ];
|
$errors[] = [ 'errorInfo' => $module_data->name . " Plugin has been uninstalled." ];
|
||||||
self::$errors = array_merge( self::$errors, $errors );
|
self::$errors = array_merge( self::$errors, $errors );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -408,7 +409,7 @@ class Installer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ( empty( $module_data->class_object ) ) {
|
if ( empty( $module_data->class_object ) ) {
|
||||||
self::$errors[] = [ 'errorInfo' => 'Class not found: ' . $module_data->class ];
|
self::$errors[] = [ 'errorInfo' => 'installModel class_object not found: ' . $module_data->class ];
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -465,7 +466,7 @@ class Installer {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$errors[] = [ 'errorInfo' => $module_data['name'] . " has been installed." ];
|
$errors[] = [ 'errorInfo' => $module_data['name'] . " model has been installed." ];
|
||||||
self::$errors = array_merge( self::$errors, $errors );
|
self::$errors = array_merge( self::$errors, $errors );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -475,7 +476,7 @@ class Installer {
|
|||||||
$errors = [];
|
$errors = [];
|
||||||
|
|
||||||
if ( empty( $module_data->class_object ) ) {
|
if ( empty( $module_data->class_object ) ) {
|
||||||
self::$errors[] = [ 'errorInfo' => 'Class not found: ' . $module_data->class ];
|
self::$errors[] = [ 'errorInfo' => 'uninstallModel: class_object not found: ' . $module_data->class ];
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -499,7 +500,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 installed." );
|
Debug::warn( "$flag_type does not have a proper matrix map and cannot be uninstalled." );
|
||||||
$module_data->$flag_type = INSTALL_STATUS_NOT_FOUND;
|
$module_data->$flag_type = INSTALL_STATUS_NOT_FOUND;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -512,7 +513,7 @@ class Installer {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$errors[] = [ 'errorInfo' => $module_data->name . " has been uninstalled." ];
|
$errors[] = [ 'errorInfo' => $module_data->name . " model has been uninstalled." ];
|
||||||
self::$errors = array_merge( self::$errors, $errors );
|
self::$errors = array_merge( self::$errors, $errors );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
312
app/config/config.json
Normal file
312
app/config/config.json
Normal file
@ -0,0 +1,312 @@
|
|||||||
|
{
|
||||||
|
"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
app/config/config.json.bak
Normal file
1
app/config/config.json.bak
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"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,19 +1,17 @@
|
|||||||
<?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
|
||||||
}
|
}
|
||||||
if ( ! defined( 'CONFIG_DIRECTORY' ) ) {
|
|
||||||
define( 'CONFIG_DIRECTORY', APP_ROOT_DIRECTORY . 'app' . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR );
|
|
||||||
}
|
|
||||||
// Directories
|
|
||||||
define( 'APP_DIRECTORY', APP_ROOT_DIRECTORY . 'app' . DIRECTORY_SEPARATOR );
|
define( 'APP_DIRECTORY', APP_ROOT_DIRECTORY . 'app' . DIRECTORY_SEPARATOR );
|
||||||
|
// Directories
|
||||||
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 );
|
||||||
@ -45,6 +43,8 @@ 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,7 +59,9 @@ 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' )) {
|
||||||
@ -131,5 +133,14 @@ 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 );
|
||||||
|
1
app/config/install.json
Normal file
1
app/config/install.json
Normal file
File diff suppressed because one or more lines are too long
1
app/config/permissions.json
Normal file
1
app/config/permissions.json
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"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
app/config/permissions.json.bak
Normal file
1
app/config/permissions.json.bak
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"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
app/config/preferences.json
Normal file
1
app/config/preferences.json
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"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
app/config/preferences.json.bak
Normal file
1
app/config/preferences.json.bak
Normal file
@ -0,0 +1 @@
|
|||||||
|
{"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->list( 'admin' ) );
|
return Views::view( 'admin.logs.admin_list', self::$log->listPaginated( '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.dependencies', $out );
|
Views::view( 'admin.modules.composer.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->list( 'error' ) );
|
return Views::view( 'admin.logs.error_list', self::$log->listPaginated( '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->list() );
|
Views::view( 'admin.groups.list', self::$group->listPaginated() );
|
||||||
}
|
}
|
||||||
|
|
||||||
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->list( 'login' ) );
|
return Views::view( 'admin.logs.login_list', self::$log->listPaginated( '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->list( 'error' ) );
|
Views::view( 'admin.logs.error_list', self::$log->listPaginated( 'error' ) );
|
||||||
Views::view( 'admin.logs.admin_list', self::$log->list( 'admin' ) );
|
Views::view( 'admin.logs.admin_list', self::$log->listPaginated( 'admin' ) );
|
||||||
Views::view( 'admin.logs.login_list', self::$log->list( 'login' ) );
|
Views::view( 'admin.logs.login_list', self::$log->listPaginated( '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\TTPForms;
|
use TheTempusProject\Classes\Forms as 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->list() );
|
return Views::view( 'admin.routes.list', self::$routes->listPaginated() );
|
||||||
}
|
}
|
||||||
|
|
||||||
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->userList() );
|
Views::view( 'admin.users.list', self::$user->listPaginated() );
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
$response = $user->ID;
|
||||||
}
|
}
|
||||||
Views::view( 'api.response', ['response' => json_encode( [ $responseType => $response ], true )]);
|
Views::view( 'api.response', ['response' => json_encode( [ $responseType => $response ], true )]);
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,11 @@ 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-example-generic {
|
#carousel-home {
|
||||||
margin-bottom: 30px;
|
margin-bottom: 30px;
|
||||||
}
|
}
|
||||||
.col-centered {
|
.col-centered {
|
||||||
|
@ -1,542 +0,0 @@
|
|||||||
<?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,101 +11,8 @@
|
|||||||
/**
|
/**
|
||||||
* 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 );
|
|
||||||
}
|
|
||||||
|
|
||||||
function insertTag( box, tag ) {
|
import BugsnagPerformance from '//d2wy8f7a9ursnm.cloudfront.net/v1/bugsnag-performance.min.js'
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
function cursorPos( el ) {
|
BugsnagPerformance.start({ apiKey: '88045bdc058de51139ac1a47dcd5694b' });
|
||||||
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);
|
|
||||||
};
|
|
||||||
|
@ -257,7 +257,7 @@ class Group extends DatabaseModel {
|
|||||||
if ( $group === false ) {
|
if ( $group === false ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$members = self::$db->get( 'users', [ 'userGroup', '=', $id ] );
|
$members = self::$db->getPaginated( '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,7 +13,7 @@ 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\Bedrock\Classes\CustomException;
|
use TheTempusProject\Canary\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\Bin\Canary as Debug;
|
||||||
|
@ -21,7 +21,7 @@ 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\Bedrock\Classes\CustomException;
|
use TheTempusProject\Canary\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;
|
||||||
|
@ -17,11 +17,14 @@ 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\Bedrock\Classes\CustomException;
|
use TheTempusProject\Canary\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' ],
|
||||||
@ -32,19 +35,14 @@ 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 ) {
|
||||||
@ -161,6 +159,9 @@ 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,6 +38,18 @@ 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 ) {
|
||||||
|
@ -1,402 +0,0 @@
|
|||||||
<?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 );
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,122 +0,0 @@
|
|||||||
<?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;
|
|
@ -1,149 +0,0 @@
|
|||||||
<?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\Bin\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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,705 +0,0 @@
|
|||||||
<?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\Bin\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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,157 +0,0 @@
|
|||||||
<?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\Bin\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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,62 +0,0 @@
|
|||||||
<?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 );
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,45 +0,0 @@
|
|||||||
<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>
|
|
@ -1,45 +0,0 @@
|
|||||||
<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>
|
|
@ -1,37 +0,0 @@
|
|||||||
{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>
|
|
@ -1,84 +0,0 @@
|
|||||||
{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>
|
|
@ -1,21 +0,0 @@
|
|||||||
<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>
|
|
@ -1,18 +0,0 @@
|
|||||||
|
|
||||||
{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}
|
|
@ -1,10 +0,0 @@
|
|||||||
{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}
|
|
@ -1,16 +0,0 @@
|
|||||||
|
|
||||||
{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>
|
|
@ -1,39 +0,0 @@
|
|||||||
<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>
|
|
@ -1,39 +0,0 @@
|
|||||||
<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>
|
|
@ -1,33 +0,0 @@
|
|||||||
{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>
|
|
@ -1,47 +0,0 @@
|
|||||||
{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>
|
|
@ -1,5 +0,0 @@
|
|||||||
<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}
|
|
@ -1,9 +0,0 @@
|
|||||||
<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>
|
|
@ -15,7 +15,7 @@ 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\Bin\Canary as Debug;
|
||||||
use TheTempusProject\Bedrock\Classes\CustomException;
|
use TheTempusProject\Canary\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;
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
<?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' );
|
|
@ -1,206 +0,0 @@
|
|||||||
<?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/' );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,92 +0,0 @@
|
|||||||
<?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;
|
|
@ -1,142 +0,0 @@
|
|||||||
<?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\Bin\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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,48 +0,0 @@
|
|||||||
<?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',
|
|
||||||
],
|
|
||||||
];
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
<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>
|
|
@ -1,30 +0,0 @@
|
|||||||
<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>
|
|
@ -1,6 +0,0 @@
|
|||||||
<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>
|
|
@ -1,45 +0,0 @@
|
|||||||
<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>
|
|
@ -1,74 +0,0 @@
|
|||||||
<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>
|
|
@ -1,593 +0,0 @@
|
|||||||
<?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,
|
|
||||||
];
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,153 +0,0 @@
|
|||||||
.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;
|
|
||||||
}
|
|
@ -1,136 +0,0 @@
|
|||||||
<?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;
|
|
@ -1,157 +0,0 @@
|
|||||||
<?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\Bin\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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,509 +0,0 @@
|
|||||||
<?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\Bin\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,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,84 +0,0 @@
|
|||||||
<?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 );
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,41 +0,0 @@
|
|||||||
<?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();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,96 +0,0 @@
|
|||||||
<!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>
|
|
@ -1,25 +0,0 @@
|
|||||||
<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>
|
|
@ -1,34 +0,0 @@
|
|||||||
<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>
|
|
@ -1,25 +0,0 @@
|
|||||||
|
|
||||||
<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>
|
|
@ -1,42 +0,0 @@
|
|||||||
<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>
|
|
@ -1,34 +0,0 @@
|
|||||||
<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>
|
|
@ -1,29 +0,0 @@
|
|||||||
<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>
|
|
@ -1,45 +0,0 @@
|
|||||||
<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 />
|
|
@ -1,42 +0,0 @@
|
|||||||
<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>
|
|
@ -1,20 +0,0 @@
|
|||||||
<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>
|
|
@ -1,37 +0,0 @@
|
|||||||
<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>
|
|
@ -1,31 +0,0 @@
|
|||||||
<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>
|
|
@ -1,34 +0,0 @@
|
|||||||
{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>
|
|
@ -1,52 +0,0 @@
|
|||||||
<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>
|
|
@ -1,16 +0,0 @@
|
|||||||
<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>
|
|
@ -1,23 +0,0 @@
|
|||||||
<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>
|
|
@ -1,18 +0,0 @@
|
|||||||
<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>
|
|
@ -1,12 +0,0 @@
|
|||||||
<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>
|
|
@ -1,8 +0,0 @@
|
|||||||
<ul class="nav nav-tabs">
|
|
||||||
<li><a href="{ROOT_URL}calendar/byDay/{calendarID}">Daily</a></li>
|
|
||||||
<li><a href="{ROOT_URL}calendar/byWeek/{calendarID}">Weekly</a></li>
|
|
||||||
<li><a href="{ROOT_URL}calendar/byMonth/{calendarID}">Monthly</a></li>
|
|
||||||
<li><a href="{ROOT_URL}calendar/byYear/{calendarID}">Yearly</a></li>
|
|
||||||
<li><a href="{ROOT_URL}calendar/events/{calendarID}">Events</a></li>
|
|
||||||
{calendarDropdown}
|
|
||||||
</ul>
|
|
@ -1,9 +0,0 @@
|
|||||||
<div class="row calendar-row">
|
|
||||||
{LOOP}
|
|
||||||
<div class="col-xs-1 calendar-cell">
|
|
||||||
<h4 class="{highlightedDate}">{day}</h4>{dayEventList}
|
|
||||||
</div>
|
|
||||||
{/LOOP}
|
|
||||||
{ALT}
|
|
||||||
{/ALT}
|
|
||||||
</div>
|
|
@ -1,37 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* app/plugins/chat/controllers/admin/chat.php
|
|
||||||
*
|
|
||||||
* This is the chat admin controller.
|
|
||||||
*
|
|
||||||
* @package TP Chat
|
|
||||||
* @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\Input;
|
|
||||||
use TheTempusProject\Houdini\Classes\Issues;
|
|
||||||
use TheTempusProject\Houdini\Classes\Views;
|
|
||||||
use TheTempusProject\Houdini\Classes\Navigation;
|
|
||||||
use TheTempusProject\Houdini\Classes\Components;
|
|
||||||
use TheTempusProject\Classes\AdminController;
|
|
||||||
use TheTempusProject\Models\Chat as ChatModel;
|
|
||||||
|
|
||||||
class Chat extends AdminController {
|
|
||||||
protected static $chat;
|
|
||||||
|
|
||||||
public function __construct() {
|
|
||||||
parent::__construct();
|
|
||||||
self::$title = 'Admin - Chat';
|
|
||||||
self::$chat = new ChatModel;
|
|
||||||
$view = Navigation::activePageSelect( 'nav.admin', '/admin/chat' );
|
|
||||||
Components::set( 'ADMINNAV', $view );
|
|
||||||
}
|
|
||||||
|
|
||||||
public function index() {
|
|
||||||
// Views::view( 'chat.admin.list', self::$chat->list() );
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,45 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* app/controllers/api/users.php
|
|
||||||
*
|
|
||||||
* This is the users' api controller.
|
|
||||||
*
|
|
||||||
* @version 3.0
|
|
||||||
* @author Joey Kimsey <Joey@thetempusproject.com>
|
|
||||||
* @link https://TheTempusProject.com
|
|
||||||
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
|
||||||
*/
|
|
||||||
namespace TheTempusProject\Controllers\Api;
|
|
||||||
|
|
||||||
use TheTempusProject\Models\User;
|
|
||||||
use TheTempusProject\Classes\ApiController;
|
|
||||||
use TheTempusProject\Houdini\Classes\Views;
|
|
||||||
use TheTempusProject\Bedrock\Functions\Input;
|
|
||||||
use TheTempusProject\Classes\Forms;
|
|
||||||
use TheTempusProject\Houdini\Classes\Template;
|
|
||||||
use TheTempusProject\Models\Chat;
|
|
||||||
|
|
||||||
class Messages extends ApiController {
|
|
||||||
public static $chat;
|
|
||||||
|
|
||||||
public function __construct() {
|
|
||||||
parent::__construct();
|
|
||||||
self::$chat = new Chat;
|
|
||||||
Template::setTemplate( 'api' );
|
|
||||||
}
|
|
||||||
|
|
||||||
public function sendMessage() {
|
|
||||||
$response = true;
|
|
||||||
if ( ! Forms::check( 'newChatMessage' ) ) {
|
|
||||||
$response = 'Invalid Form';
|
|
||||||
} else {
|
|
||||||
$response = self::$chat->create( Input::post( 'chatMessage' ) );
|
|
||||||
}
|
|
||||||
Views::view( 'api.response', ['response' => json_encode( [ 'data' => $response ], true )]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getMessages() {
|
|
||||||
$response = Views::simpleView( 'chat.chat', self::$chat->recent( 50 ) );
|
|
||||||
Views::view( 'api.response', ['response' => json_encode( [ 'data' => $response ], true )]);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,191 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* app/plugins/chat/controllers/chat.php
|
|
||||||
*
|
|
||||||
* This is the public chat controller.
|
|
||||||
*
|
|
||||||
* @package TP Chat
|
|
||||||
* @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\Upload;
|
|
||||||
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\Chat as ChatModel;
|
|
||||||
use TheTempusProject\Models\Upload as UploadModel;
|
|
||||||
use TheTempusProject\TheTempusProject as App;
|
|
||||||
use TheTempusProject\Houdini\Classes\Components;
|
|
||||||
use TheTempusProject\Houdini\Classes\Template;
|
|
||||||
use TheTempusProject\Canary\Bin\Canary as Debug;
|
|
||||||
|
|
||||||
class Chat extends Controller {
|
|
||||||
protected static $chat;
|
|
||||||
public function __construct() {
|
|
||||||
parent::__construct();
|
|
||||||
self::$chat = new ChatModel;
|
|
||||||
Template::setTemplate( 'chat' );
|
|
||||||
}
|
|
||||||
|
|
||||||
public function index() {
|
|
||||||
if ( !App::$isMember ) {
|
|
||||||
Session::flash( 'error', 'You do not have permission to view this page.' );
|
|
||||||
return Redirect::home();
|
|
||||||
}
|
|
||||||
self::$title = '{SITENAME} Chat';
|
|
||||||
self::$pageDescription = 'One of the privleges of membership is the ability to chat with your fellow members.';
|
|
||||||
|
|
||||||
if ( App::$isLoggedIn ) {
|
|
||||||
Components::set( 'CREATE_MESSAGE', Views::simpleView( 'chat.create' ) );
|
|
||||||
} else {
|
|
||||||
Components::set( 'CREATE_MESSAGE', '' );
|
|
||||||
}
|
|
||||||
|
|
||||||
$upload = '';
|
|
||||||
$sharePlugin = 'TheTempusProject\Plugins\Fileshare';
|
|
||||||
if ( class_exists( $sharePlugin ) ) {
|
|
||||||
$plugin = new $sharePlugin;
|
|
||||||
if ( $plugin->checkEnabled() ) {
|
|
||||||
$upload = Views::simpleView( 'chat.upload' );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Components::set( 'FILE_UPLOAD', $upload );
|
|
||||||
|
|
||||||
Components::set( 'CHAT', Views::simpleView( 'chat.chat' ) );
|
|
||||||
return Views::view( 'chat.index' );
|
|
||||||
}
|
|
||||||
|
|
||||||
public function sendMessage() {
|
|
||||||
Template::setTemplate( 'api' );
|
|
||||||
$out = [ 'response' => true ];
|
|
||||||
if ( !Forms::check( 'newChatMessage' ) ) {
|
|
||||||
$out = [ 'response' => false ];
|
|
||||||
echo json_encode($out);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
self::$chat->create(
|
|
||||||
Input::post( 'chatMessage' ),
|
|
||||||
);
|
|
||||||
echo json_encode($out);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function uploadFile() {
|
|
||||||
Template::setTemplate( 'api' );
|
|
||||||
$out = [ 'response' => true ];
|
|
||||||
if ( ! Forms::check( 'newFileUpload' ) ) {
|
|
||||||
$out = [ 'response' => false ];
|
|
||||||
echo json_encode($out);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$sharePlugin = 'TheTempusProject\Plugins\Fileshare';
|
|
||||||
if ( ! class_exists( $sharePlugin ) ) {
|
|
||||||
$out = [ 'error' => 'Fileshare must be installed and enabled for this feature to work1.' ];
|
|
||||||
echo json_encode($out);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$plugin = new $sharePlugin;
|
|
||||||
|
|
||||||
if ( ! $plugin->checkEnabled() ) {
|
|
||||||
$out = [ 'error' => 'Fileshare must be installed and enabled for this feature to work2.' ];
|
|
||||||
echo json_encode($out);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$folder = UPLOAD_DIRECTORY . App::$activeUser->username . DIRECTORY_SEPARATOR;
|
|
||||||
if ( ! Upload::image( 'file', $folder ) ) {
|
|
||||||
$out = [ 'error' => 'could not upload image' ];
|
|
||||||
echo json_encode($out);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
$route = str_replace( APP_ROOT_DIRECTORY, '', $folder );
|
|
||||||
$location = $route . Upload::last();
|
|
||||||
$uploads = new UploadModel;
|
|
||||||
$result = $uploads->create( 'Chat Upload', $location );
|
|
||||||
|
|
||||||
if ( ! $result ) {
|
|
||||||
$out = [ 'error' => 'could not add upload to fileshare.' ];
|
|
||||||
echo json_encode( $out );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
self::$chat->create(
|
|
||||||
'Shared a file with the chat: ' .
|
|
||||||
'<a href="/' . $location . '" target="_blank">Upload</a>'
|
|
||||||
);
|
|
||||||
echo json_encode($out);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getMessages() {
|
|
||||||
Template::setTemplate( 'api' );
|
|
||||||
echo Views::simpleView( 'chat.chat', self::$chat->recent( 50 ) );
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getMessageEvents() {
|
|
||||||
if ($_SERVER['HTTP_ACCEPT'] !== 'text/event-stream') {
|
|
||||||
Debug::info( 'connection refused, wrong HTTP_ACCEPT' );
|
|
||||||
exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
header("X-Accel-Buffering: no");
|
|
||||||
header('Content-Type: text/event-stream');
|
|
||||||
header('Cache-Control: no-cache');
|
|
||||||
header('Connection: keep-alive');
|
|
||||||
|
|
||||||
// Ensure unlimited script execution time
|
|
||||||
set_time_limit(0);
|
|
||||||
|
|
||||||
// Disable output buffering
|
|
||||||
ini_set('output_buffering', 'off');
|
|
||||||
ini_set('zlib.output_compression', false);
|
|
||||||
|
|
||||||
if (Input::exists('lastId')) {
|
|
||||||
$lastId = Input::get('lastId');
|
|
||||||
} else {
|
|
||||||
$lastId = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
while ( true ) {
|
|
||||||
echo "id: 0\n";
|
|
||||||
echo "event: ping\n";
|
|
||||||
echo 'data: {"time": "' . time() . '"}';
|
|
||||||
echo "\n\n";
|
|
||||||
if ( connection_aborted() ) {
|
|
||||||
Debug::info( 'getMessageEvents connection aborted' );
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
$newMessages = self::$chat->sinceMessage( $lastId );
|
|
||||||
if ( ! empty( $newMessages )) {
|
|
||||||
foreach ( $newMessages as $message ) {
|
|
||||||
$lastId = $message->ID;
|
|
||||||
echo "id: {$message->ID}\n";
|
|
||||||
echo "data: " . json_encode($message) . "\n\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If there were any messages added, flush the output buffer
|
|
||||||
if (ob_get_contents()) {
|
|
||||||
ob_end_flush();
|
|
||||||
}
|
|
||||||
flush();
|
|
||||||
// sessions will block the end-user from sending messages unless we close the session
|
|
||||||
session_write_close();
|
|
||||||
sleep(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,116 +0,0 @@
|
|||||||
* {
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
margin: 20px auto;
|
|
||||||
font-family: "Lato";
|
|
||||||
font-weight: 300;
|
|
||||||
}
|
|
||||||
|
|
||||||
form {
|
|
||||||
padding: 15px 25px;
|
|
||||||
display: flex;
|
|
||||||
gap: 10px;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
form label {
|
|
||||||
font-size: 1.5rem;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
input {
|
|
||||||
font-family: "Lato";
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
color: #0000ff;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
a:hover {
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
|
|
||||||
#chatMessages {
|
|
||||||
text-align: left;
|
|
||||||
margin: 0 auto;
|
|
||||||
padding: 10px;
|
|
||||||
height: 300px;
|
|
||||||
border: 1px solid #a7a7a7;
|
|
||||||
overflow: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
#usermsg {
|
|
||||||
flex: 1;
|
|
||||||
border-radius: 4px;
|
|
||||||
border: 1px solid #ff9800;
|
|
||||||
}
|
|
||||||
|
|
||||||
#name {
|
|
||||||
border-radius: 4px;
|
|
||||||
border: 1px solid #ff9800;
|
|
||||||
padding: 2px 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#submitmsg,
|
|
||||||
#enter{
|
|
||||||
background: #ff9800;
|
|
||||||
border: 2px solid #e65100;
|
|
||||||
color: white;
|
|
||||||
padding: 4px 10px;
|
|
||||||
font-weight: bold;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.error {
|
|
||||||
color: #ff0000;
|
|
||||||
}
|
|
||||||
|
|
||||||
#menu {
|
|
||||||
padding: 15px 25px;
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
#menu p.welcome {
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
a#exit {
|
|
||||||
color: white;
|
|
||||||
background: #c62828;
|
|
||||||
padding: 4px 8px;
|
|
||||||
border-radius: 4px;
|
|
||||||
font-weight: bold;
|
|
||||||
}
|
|
||||||
|
|
||||||
.msgln {
|
|
||||||
margin: 0 0 5px 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.span.left-info {
|
|
||||||
color: orangered;
|
|
||||||
}
|
|
||||||
|
|
||||||
span .chat-time {
|
|
||||||
color: #666;
|
|
||||||
font-size: 80%;
|
|
||||||
vertical-align: super;
|
|
||||||
width: 100px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.msgln b.user-name, .msgln b.user-name-left {
|
|
||||||
font-weight: bold;
|
|
||||||
background: #546e7a;
|
|
||||||
color: white;
|
|
||||||
padding: 2px 4px;
|
|
||||||
font-size: 90%;
|
|
||||||
border-radius: 4px;
|
|
||||||
margin: 0 5px 0 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.msgln b.user-name-left {
|
|
||||||
background: orangered;
|
|
||||||
}
|
|
@ -1,52 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* app/plugins/chat/forms.php
|
|
||||||
*
|
|
||||||
* This houses all of the form checking functions for this plugin.
|
|
||||||
*
|
|
||||||
* @package TP Chat
|
|
||||||
* @version 3.0
|
|
||||||
* @author Joey Kimsey <Joey@thetempusproject.com>
|
|
||||||
* @link https://TheTempusProject.com
|
|
||||||
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
|
||||||
*/
|
|
||||||
namespace TheTempusProject\Plugins\Chat;
|
|
||||||
|
|
||||||
use TheTempusProject\Bedrock\Functions\Input;
|
|
||||||
use TheTempusProject\Bedrock\Functions\Check;
|
|
||||||
use TheTempusProject\Classes\Forms;
|
|
||||||
|
|
||||||
class ChatForms extends Forms {
|
|
||||||
/**
|
|
||||||
* Adds these functions to the form list.
|
|
||||||
*/
|
|
||||||
public function __construct() {
|
|
||||||
self::addHandler( 'newChatMessage', __CLASS__, 'newChatMessage' );
|
|
||||||
self::addHandler( 'newFileUpload', __CLASS__, 'newFileUpload' );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Validates the new blog post form.
|
|
||||||
*
|
|
||||||
* @return {bool}
|
|
||||||
*/
|
|
||||||
public static function newChatMessage() {
|
|
||||||
if ( !Input::exists( 'chatMessage' ) ) {
|
|
||||||
self::addUserError( 'You must includes a message' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// if (!self::token()) {
|
|
||||||
// return false;
|
|
||||||
// }
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
public static function newFileUpload() {
|
|
||||||
if ( !Input::exists( 'file' ) ) {
|
|
||||||
self::addUserError( 'You must includes a file' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
new ChatForms;
|
|
@ -1,116 +0,0 @@
|
|||||||
$(document).ready(function() {
|
|
||||||
var chatform = $('#sendChatMessage');
|
|
||||||
var uploadForm = $('#uploadFile');
|
|
||||||
|
|
||||||
chatform.bind('submit', function(event) {
|
|
||||||
event.preventDefault(); // Prevent page reload
|
|
||||||
var msg = $("#chatMessage").val();
|
|
||||||
|
|
||||||
console.log("Submitting message:", msg);
|
|
||||||
|
|
||||||
var ajax_params = {
|
|
||||||
url: '/chat/sendMessage',
|
|
||||||
type: 'POST',
|
|
||||||
data: { chatMessage: msg },
|
|
||||||
success: function(response) {
|
|
||||||
console.log("Message sent successfully:", response);
|
|
||||||
$("#chatMessage").val("");
|
|
||||||
},
|
|
||||||
error: function(xhr, status, error) {
|
|
||||||
console.error("Error sending message:", error, status, xhr);
|
|
||||||
},
|
|
||||||
complete: function() {
|
|
||||||
console.log("AJAX request complete");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
$.ajax(ajax_params);
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
uploadForm.bind('submit', function(event) {
|
|
||||||
event.preventDefault(); // Prevent page reload
|
|
||||||
|
|
||||||
var formData = new FormData(this); // Create FormData object
|
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
url: '/chat/uploadFile',
|
|
||||||
type: 'POST',
|
|
||||||
data: formData,
|
|
||||||
processData: false, // Don't process the files
|
|
||||||
contentType: false, // Set content type to false as jQuery will tell the server its a query string request
|
|
||||||
success: function(response) {
|
|
||||||
console.log("File uploaded successfully:", response);
|
|
||||||
$("#file").val("");
|
|
||||||
},
|
|
||||||
error: function(xhr, status, error) {
|
|
||||||
console.error("Error uploading file:", error, status, xhr);
|
|
||||||
},
|
|
||||||
complete: function() {
|
|
||||||
console.log("AJAX request complete");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
|
|
||||||
const eventSource = new EventSource('/chat/getMessageEvents');
|
|
||||||
eventSource.onmessage = function( event ) {
|
|
||||||
const message = JSON.parse( event.data );
|
|
||||||
|
|
||||||
var userPopup = "<div class='media'>" +
|
|
||||||
"<span class='pull-left'>" +
|
|
||||||
"<img class='media-object avatar-round-40' src='/"+message.avatar+"' alt=''>" +
|
|
||||||
"</span>" +
|
|
||||||
"<div class='media-body'>" +
|
|
||||||
"<h5 class='media-heading'>" +
|
|
||||||
"<strong>"+message.submittedByName+"</strong>" +
|
|
||||||
"</h5>" +
|
|
||||||
"<a href='/home/profile/"+message.submittedByName+"' class='btn btn-sm btn-primary' role='button'><i class='glyphicon glyphicon-open'></i> View Profile</a>" +
|
|
||||||
"</div>" +
|
|
||||||
"</div>";
|
|
||||||
|
|
||||||
$("#chatMessages").append(
|
|
||||||
"<span class='chat-time'>" +
|
|
||||||
new Date(message.submittedAt * 1000).toLocaleString('en-US', { month: 'long', day: 'numeric', hour: 'numeric', minute: 'numeric', hour12: true }) +
|
|
||||||
// new Date(message.submittedAt * 1000).toLocaleString() +
|
|
||||||
"</span> " +
|
|
||||||
'<a tabindex="0" role="button" data-toggle="popover" data-html="true" data-trigger="focus" title="'+message.submittedByName+'" data-content="'+userPopup+'">' +
|
|
||||||
message.submittedByName +
|
|
||||||
'</a> ' +
|
|
||||||
message.chatMessage + "<br>"
|
|
||||||
);
|
|
||||||
$("[data-toggle=popover]").popover();
|
|
||||||
$("#chatMessages").scrollTop($("#chatMessages")[0].scrollHeight);
|
|
||||||
};
|
|
||||||
|
|
||||||
eventSource.onerror = function(event) {
|
|
||||||
console.error('EventSource failed:', event);
|
|
||||||
};
|
|
||||||
|
|
||||||
window.addEventListener('beforeunload', function() {
|
|
||||||
eventSource.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
window.addEventListener('unload', function() {
|
|
||||||
eventSource.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
// function getUserProfile( id ) {
|
|
||||||
// var ajax_params = {
|
|
||||||
// url: '/api/users/find/' + id,
|
|
||||||
// type: 'GET',
|
|
||||||
// success: function(response) {
|
|
||||||
// console.log("User retrieved:", response);
|
|
||||||
// $("#chatMessage").val("");
|
|
||||||
// },
|
|
||||||
// error: function(xhr, status, error) {
|
|
||||||
// console.error("Error retrieved user:", error, status, xhr);
|
|
||||||
// },
|
|
||||||
// complete: function() {
|
|
||||||
// console.log("AJAX request complete");
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
// $.ajax(ajax_params);
|
|
||||||
// }
|
|
||||||
});
|
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user