Compare commits
61 Commits
Author | SHA1 | Date | |
---|---|---|---|
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 | |||
0aa1b52a6d | |||
d48e77e78d | |||
21ba74ab0a | |||
840563e25c |
5
.gitignore
vendored
5
.gitignore
vendored
@ -54,14 +54,11 @@ Temporary Items
|
|||||||
|
|
||||||
# TheTempusProject Specific
|
# TheTempusProject Specific
|
||||||
.htaccess
|
.htaccess
|
||||||
composer.lock
|
|
||||||
app/config/*
|
app/config/*
|
||||||
!app/config/constants.php
|
!app/config/constants.php
|
||||||
app/install.json
|
|
||||||
app/config.default.json
|
|
||||||
uploads/images/*
|
uploads/images/*
|
||||||
.env
|
|
||||||
logs/*
|
logs/*
|
||||||
.vscode/
|
.vscode/
|
||||||
mail.log
|
mail.log
|
||||||
vendor/canary/logs/*
|
vendor/canary/logs/*
|
||||||
|
.env
|
||||||
|
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
|
||||||
|
439
README.md
439
README.md
@ -1,374 +1,131 @@
|
|||||||
# The Tempus Project
|
# The Tempus Project
|
||||||
|
|
||||||
|
_Rapid Prototyping Framework built on PHP utilizing the MVC pattern with a Bootstrap front-end_
|
||||||
|
|
||||||
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
|
__Developer(s):__
|
||||||
|
|
||||||
need to track points once a week
|
- __Joey Kimsey__ - _Lead Developer_
|
||||||
|
|
||||||
a huge table tracks points day to day then we add and erase the old data, or move it to historical...
|
|
||||||
|
|
||||||
## Rapid Prototyping Framework
|
|
||||||
|
|
||||||
### 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
|
## Table of contents
|
||||||
|
|
||||||
|
[[_TOC_]]
|
||||||
|
|
||||||
|
## Find Us
|
||||||
|
|
||||||
|
* [DockerHub](https://hub.docker.com/repositories/thetempusproject)
|
||||||
|
* [Packagist](https://packagist.org/users/joeyk4816/packages/)
|
||||||
|
* [GitLab](https://git.thetempusproject.com/the-tempus-project/thetempusproject)
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
The Tempus Project is a PHP application utilizing the MVC pattern to serve up simple pages and APIs with minimal effort. It requires a MySQL database to function and is designed to run equally well with nginx or apache powering the webserver. Most of the core functionality is developed in house and provided through dependencies. At this time, the frontend is driven on bootstrap 3 and FontAwesome for simplicity.
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
A User management system with groups, permissions, preferences, registration, and recovery. (All Controlled dynamically via our plugin interface)
|
- A Plugin system that allows plug-and-play functionality
|
||||||
A Plugin system that allows plug-and-play functionality for a huge number of features.
|
- A User management system
|
||||||
Compatibility with both Apache and NGINX.
|
- groups
|
||||||
Built with Bootstrap with a focus on mobile compatibility.
|
- permissions
|
||||||
Incredibly easy to set-up, deploy, and develop with.
|
- preferences
|
||||||
|
- 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.
|
The preferred method for installation is [Composer](#composer) but special attention has been given to installation and usage [without Composer](#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:
|
||||||
|
|
||||||
|
#### via create-project
|
||||||
|
|
||||||
|
```
|
||||||
|
composer create-project thetempusproject/thetempusproject test-app
|
||||||
|
```
|
||||||
|
|
||||||
|
#### via clone & install
|
||||||
|
|
||||||
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.
|
`git clone https://git.thetempusproject.com/the-tempus-project/thetempusproject.git <test-app>`
|
||||||
3. Install using composer:
|
1. Open your terminal to the directory you previously cloned the repository.
|
||||||
|
`cd <test-app>`
|
||||||
|
1. Install using composer:
|
||||||
`php composer.phar install`
|
`php composer.phar install`
|
||||||
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.
|
|
||||||
|
|
||||||
#### Apache
|
### Manually
|
||||||
|
|
||||||
#### NGINX
|
1. Clone the directory to wherever you want to install the framework.
|
||||||
|
`git clone https://git.thetempusproject.com/the-tempus-project/thetempusproject.git <test-app>`
|
||||||
|
1. Open your terminal to the directory you previously cloned the repository.
|
||||||
|
`cd <test-app>/`
|
||||||
|
1. Clone the dependency directories to the vendor/ folder.
|
||||||
|
```
|
||||||
|
cd vendor/
|
||||||
|
git clone https://git.thetempusproject.com/the-tempus-project/bedrock.git bedrock
|
||||||
|
git clone https://git.thetempusproject.com/the-tempus-project/canary.git canary
|
||||||
|
git clone https://git.thetempusproject.com/the-tempus-project/hermes.git hermes
|
||||||
|
git clone https://git.thetempusproject.com/the-tempus-project/houdini.git houdini
|
||||||
|
```
|
||||||
|
|
||||||
#### Docker-Compose
|
__Note:__ The autoloader should automatically detect and use the dependencies, but they need to be sorted into the folders ans shown above.
|
||||||
|
|
||||||
If you have any trouble with the installation, you can check out our FAQ page on the wiki for answers to common issues.
|
|
||||||
|
|
||||||
If you would like a full copy of the project with all of its included dependencies you can find it at https://github.com/TheTempusProject/TempusProjectFull
|
## Docker
|
||||||
Please note this repository is only up to the latest _stable_ release. Please continue to use composer update to get the latest development releases.
|
|
||||||
|
|
||||||
**Do not forget to remove install.php once you have finished installation!**
|
To enable quick deployment and collaboration The Tempus Project is distributed with the files to build your own docker images or stack with apache or nginx The included `docker-compose.yml` will load up an entire stack including apache and nginx, as well as a MySQL server with phpmyadmin.
|
||||||
|
|
||||||
#### Currently being developed
|
You will need docker installed on your system then you can either download the latest images from DockerHud:
|
||||||
|
|
||||||
|
```
|
||||||
|
docker pull thetempusproject/ttp-apache
|
||||||
|
docker pull thetempusproject/ttp-nginx
|
||||||
|
```
|
||||||
|
|
||||||
|
Or you can build your own images from this repository. More information can be found in the included README files:
|
||||||
|
|
||||||
|
* [Apache Image](docker/ttp-apache/README.md)
|
||||||
|
* [Nginx Image](docker/ttp-nginx/README.md)
|
||||||
|
|
||||||
|
### Docker-Compose
|
||||||
|
|
||||||
|
The Docker stack included here will build new versions of the nginx and apache webserver and launch them in individual containers. It will also create 2 more containers; one for php, and one for phpmyadmin.
|
||||||
|
|
||||||
|
```
|
||||||
|
docker-compose -f docker-compose.yml up --build -d --no-cache
|
||||||
|
```
|
||||||
|
|
||||||
|
__Note:__ If you cloned the repository from git, you will need to copy the `docker/.env.example` to `.env` in the root directory and update the contents before proceeding with docker-compose.
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
TheTempusProject is an open source project and welcomes community contributions. Please refer to the [Contributing file](CONTRIBUTING.md) for more details.
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
See the [LICENSE](LICENSE) file for licensing information as it pertains to files in this repository.
|
||||||
|
|
||||||
|
## Known Issues
|
||||||
|
|
||||||
|
- [ ] The blog plugin should add a welcome post during the installResources step of the installer. It doesn't work right now.
|
||||||
|
|
||||||
|
## Currently being developed
|
||||||
|
|
||||||
- [ ] Adding documentation
|
- [ ] Adding documentation
|
||||||
- [ ] Unit tests
|
- [ ] Unit testing
|
||||||
|
|
||||||
#### Future updates
|
## Future updates
|
||||||
|
|
||||||
- [ ] Expansion of PDO to allow different database types
|
- [ ] Expansion of PDO to allow different database types
|
||||||
- [ ] Update installer to account for updates.
|
- [ ] Update installer to account for database deltas, allowing easy updating.
|
||||||
- [ ] Implement uniformity in terms of error reporting, exceptions, logging.
|
- [ ] Implement uniformity in terms of error reporting, exceptions, logging.
|
||||||
- [ ] The templating system has gotten too large and needs to be split into its own repo
|
- [ ] I want to make an api that allows you to download and install new plugins from a centralized repository
|
||||||
|
- [ ] i want plugin instalation to be compatible with composer for easier management of added plugins.
|
||||||
TTP ToDo:
|
|
||||||
|
|
||||||
need to integrate new plugins for some moved features
|
|
||||||
canary
|
|
||||||
comments
|
|
||||||
members
|
|
||||||
messages
|
|
||||||
Split inbox and outbox apart
|
|
||||||
split messages from usercp
|
|
||||||
redirects
|
|
||||||
|
|
||||||
need to make sure all 'use ' statements are updated to new repo names
|
|
||||||
|
|
||||||
namespace TempusDebugger; => namespace TheTempusProject\Canary;
|
|
||||||
namespace TheTempusProject\Houdini; => namespace TheTempusProject\houdini;
|
|
||||||
namespace TheTempusProject/TempusTool; => namespace TheTempusProject\Overwatch;
|
|
||||||
need a mechanism for handeling config/constants.php in each plugin
|
|
||||||
migrate all 'secondary' constants (constants not used in the default execution of the application) to plugin folders
|
|
||||||
|
|
||||||
Perform final F & R for:
|
|
||||||
"tpc"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
need better handeling around blog filters like month and day
|
|
||||||
|
|
||||||
split profile from usercp
|
|
||||||
|
|
||||||
|
|
||||||
need a way to secure the api
|
|
||||||
need a standard way to do apis
|
|
||||||
need a way to show parts conditionally like {@if}
|
|
||||||
need
|
|
||||||
if
|
|
||||||
else
|
|
||||||
elseif
|
|
||||||
need a way to show something conditionally if a plugin is enabled
|
|
||||||
like {@enabled:comments}
|
|
||||||
{comments}
|
|
||||||
{@enabled}
|
|
||||||
|
|
||||||
https://css-tricks.com/drag-and-drop-file-uploading/
|
|
||||||
|
|
||||||
https://www.smashingmagazine.com/2018/01/drag-drop-file-uploader-vanilla-js/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
need to merge both autoloaders into the same one under bin
|
|
||||||
need to be able to install multiple database tables for the same plugin
|
|
||||||
|
|
||||||
|
|
||||||
rename default.js and .css to main.js/css
|
|
||||||
fix where i moved those to the app/css and app/js folders
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
make a new template repo/dependency
|
|
||||||
make a new Debug repo/dependency
|
|
||||||
Fix the plugin
|
|
||||||
fix the console logger
|
|
||||||
|
|
||||||
add the ability to include js files
|
|
||||||
add the ability to include css files as needed
|
|
||||||
|
|
||||||
chat should include a config for the refresh timer
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
and better error handeling for models and plugins
|
|
||||||
need to make a singular list function to remove or combine these:
|
|
||||||
listGroupsSimple
|
|
||||||
listPosts
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
i need to move everything moderator relateed to comments
|
|
||||||
i also need to make sure that moderators can actually moderate
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
the get form html thing should work perfectly with the database array to create hella simple to generate forms for anything
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
we are not doing anything with requiredPlugins
|
|
||||||
|
|
||||||
|
|
||||||
comments and blog are being manually added in the admin dashboard, this could be a problem when they are disabled
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
removed from blog filter
|
|
||||||
commentCount
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
need to address the error handler just failing to work
|
|
||||||
|
|
||||||
and the exception handler picking up random errors
|
|
||||||
|
|
||||||
|
|
||||||
need to revisit all of the form checking and make sure it is apparent to the user when and how they mess something up.
|
|
||||||
|
|
||||||
|
|
||||||
many pages are missing descriptions, need to add them
|
|
||||||
|
|
||||||
|
|
||||||
https://jsonapi.org/format/
|
|
||||||
|
|
||||||
|
|
||||||
need a way for the template system to:
|
|
||||||
switch between the meta-header content types for the sharing info
|
|
||||||
xlarge
|
|
||||||
large
|
|
||||||
etc
|
|
||||||
need better checking around title, meta-image, and descriptions
|
|
||||||
prevent accidently feeding bad images or text to these fields
|
|
||||||
need to manages js and css includes better, and incorperate it into templating system
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
the get timezone getdate gettime format functions all need to be migrated to app, stored as static vars and refactored
|
|
||||||
in core, am i using htaccess.html or nginx.html anywhere, if not, change them to .example
|
|
||||||
Routes -> getHost is using a terrible conditional for docker hosts, need to improve
|
|
||||||
Need to test all the filters for the editor stuff
|
|
||||||
need the ability for the autoloader to accept specific file name associations
|
|
||||||
needs a require_all
|
|
||||||
need to re-namespace all classes and functions
|
|
||||||
some classes need to be converted to non-static
|
|
||||||
some functions need to be converted to more static
|
|
||||||
run from the command line
|
|
||||||
|
|
||||||
initiated // is in so many controllers, i def want this removed initialized
|
|
||||||
tempus_project.php
|
|
||||||
test running commands from cli
|
|
||||||
if we move install.php to the bin, it will be unaccessible to the web server??
|
|
||||||
if its unaccessible except theough the index.php router, we don't need to delete it because its unaccessible again
|
|
||||||
can i use submodules?
|
|
||||||
errors should be able to be customized
|
|
||||||
if its in the app
|
|
||||||
should add more logging, esp for admin actions
|
|
||||||
need to add self::$pageDescription to many pages
|
|
||||||
man, messages is hot garbage, def needs a rework
|
|
||||||
need a mechanism to add listeners and events
|
|
||||||
ability to restore backups of perms prefs and configs
|
|
||||||
if your controller has no index method, you're just SOL
|
|
||||||
a blank page is called and no method is loaded
|
|
||||||
Warns should be for failed checks
|
|
||||||
add a check for having write access to the config folder and the uploads folder
|
|
||||||
and whatever is going to be needed to the plugin downloading
|
|
||||||
|
|
||||||
some configs have been removed and need to be accounted for
|
|
||||||
Unused:
|
|
||||||
---------------------------
|
|
||||||
Config::getValue('bugReports/sendEmail')
|
|
||||||
Config::getValue('bugReports/emailTemplate')
|
|
||||||
Config::getValue('feedback/sendEmail')
|
|
||||||
Config::getValue('feedback/emailTemplate')
|
|
||||||
Config::getValue('uploads/files')
|
|
||||||
Config::getValue('uploads/images')
|
|
||||||
Config::getValue('uploads/maxFileSize')
|
|
||||||
|
|
||||||
|
|
||||||
after all changes are pushed up and available, docker needs to be tested and updated
|
|
||||||
when using composer, the composer page is populated and correct
|
|
||||||
|
|
||||||
the config step of install should be checking the db creds
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// need to make notes of other standards as i go to update the contributing document
|
|
||||||
// need to cross refrence the configs from core and ttp
|
|
||||||
// ensure the resources folder is current
|
|
||||||
// document, fix, and remove @TODO's where possible
|
|
||||||
Search for cuss words, they make you look stupid
|
|
||||||
fuck
|
|
||||||
shit
|
|
||||||
dam
|
|
||||||
damm
|
|
||||||
damn
|
|
||||||
god
|
|
||||||
ass
|
|
||||||
cunt
|
|
||||||
bitch
|
|
||||||
ffs
|
|
||||||
wtf
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
had to remove the tracking pixel that was to be used with the contacts form, this will need to be re- added in a future update
|
|
||||||
had to remove the rest controller, its currently just unused
|
|
||||||
|
|
||||||
// this can be used for the tempus project
|
|
||||||
composer create-project laravel/laravel example-app
|
|
||||||
|
|
||||||
# Release Checklist
|
|
||||||
|
|
||||||
=====================
|
|
||||||
- [] Spell check every file.
|
|
||||||
- [] All documentation must be reviewed for accuracy.
|
|
||||||
- [] If a new year has passed, ensure the year has been updated where applicable.
|
|
||||||
- [] If default permissions, preferences, configs, base classes or models have been updated, update resources accordingly.
|
|
||||||
- []
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
namespace TempusDebugger; => namespace TheTempusProject\Canary;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
need to make sure a template loader can be called and still use the default template file, IE always add these CSS or JS resources.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
discord bot that shares updates on your party from the site
|
|
||||||
maybe a summary after each session
|
|
||||||
warning that time is coming up
|
|
||||||
changes made to anything
|
|
||||||
D&D news
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
is it possible to store a campaigns state on the blockchain?
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
keeping this as a repository for podcasts would get more people to check it out
|
|
||||||
same for youtube
|
|
||||||
|
|
||||||
people love sharing their resources, so make it EASY to find podcasts, and youtube channels, and etsy stores, and give people a place to share it with their groups
|
|
||||||
|
|
||||||
try and earn commisions from this and do featured XYZ every x days or weeks or whatever
|
|
||||||
|
|
||||||
have different "kinds" of dice to portray on the dice roll page
|
|
||||||
|
|
||||||
maybe spinners instead of conventional die
|
|
||||||
|
|
||||||
maybe weird health potions for D4's
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
namespace TheTempusProject\Classes;
|
namespace TheTempusProject\Classes;
|
||||||
|
|
||||||
use TheTempusProject\Houdini\Classes\Forms;
|
use TheTempusProject\Houdini\Classes\Forms;
|
||||||
use TheTempusProject\Canary\Canary as Debug;
|
use TheTempusProject\Canary\Bin\Canary as Debug;
|
||||||
use TheTempusProject\Bedrock\Functions\Check;
|
use TheTempusProject\Bedrock\Functions\Check;
|
||||||
use TheTempusProject\Bedrock\Functions\Input;
|
use TheTempusProject\Bedrock\Functions\Input;
|
||||||
use TheTempusProject\Bedrock\Classes\Config as BedrockConfig;
|
use TheTempusProject\Bedrock\Classes\Config as BedrockConfig;
|
||||||
|
@ -13,10 +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\Houdini\Classes\Components;
|
||||||
|
|
||||||
class Controller extends BedrockController {
|
class Controller extends BedrockController {
|
||||||
public static $user;
|
public static $user;
|
||||||
@ -33,6 +35,7 @@ class Controller extends BedrockController {
|
|||||||
}
|
}
|
||||||
new Template;
|
new Template;
|
||||||
Template::setTemplate( 'default' );
|
Template::setTemplate( 'default' );
|
||||||
|
Components::set( 'TOKEN', Token::generate() );
|
||||||
}
|
}
|
||||||
|
|
||||||
public function __destruct() {
|
public function __destruct() {
|
||||||
|
@ -13,7 +13,7 @@ namespace TheTempusProject\Classes;
|
|||||||
|
|
||||||
use TheTempusProject\Bedrock\Classes\DatabaseModel as BedrockDatabaseModel;
|
use TheTempusProject\Bedrock\Classes\DatabaseModel as BedrockDatabaseModel;
|
||||||
use TheTempusProject\Bedrock\Functions\Check;
|
use TheTempusProject\Bedrock\Functions\Check;
|
||||||
use TheTempusProject\Canary\Canary as Debug;
|
use TheTempusProject\Canary\Bin\Canary as Debug;
|
||||||
use TheTempusProject\Models\Log;
|
use TheTempusProject\Models\Log;
|
||||||
|
|
||||||
class DatabaseModel extends BedrockDatabaseModel {
|
class DatabaseModel extends BedrockDatabaseModel {
|
||||||
|
@ -14,7 +14,7 @@ namespace TheTempusProject\Classes;
|
|||||||
use TheTempusProject\Houdini\Classes\Template;
|
use TheTempusProject\Houdini\Classes\Template;
|
||||||
use TheTempusProject\Houdini\Classes\Views;
|
use TheTempusProject\Houdini\Classes\Views;
|
||||||
use TheTempusProject\Hermes\Functions\Route as Routes;
|
use TheTempusProject\Hermes\Functions\Route as Routes;
|
||||||
use TheTempusProject\Canary\Canary as Debug;
|
use TheTempusProject\Canary\Bin\Canary as Debug;
|
||||||
|
|
||||||
class Email {
|
class Email {
|
||||||
private static $header = null;
|
private static $header = null;
|
||||||
|
@ -15,12 +15,20 @@
|
|||||||
namespace TheTempusProject\Classes;
|
namespace TheTempusProject\Classes;
|
||||||
|
|
||||||
use TheTempusProject\Bedrock\Functions\Check;
|
use TheTempusProject\Bedrock\Functions\Check;
|
||||||
use TheTempusProject\Canary\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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ namespace TheTempusProject\Classes;
|
|||||||
use TheTempusProject\Bedrock\Functions\Check;
|
use TheTempusProject\Bedrock\Functions\Check;
|
||||||
use TheTempusProject\Bedrock\Functions\Code;
|
use TheTempusProject\Bedrock\Functions\Code;
|
||||||
use TheTempusProject\Bedrock\Functions\Cookie;
|
use TheTempusProject\Bedrock\Functions\Cookie;
|
||||||
use TheTempusProject\Canary\Canary as Debug;
|
use TheTempusProject\Canary\Bin\Canary as Debug;
|
||||||
use TheTempusProject\Hermes\Functions\Redirect;
|
use TheTempusProject\Hermes\Functions\Redirect;
|
||||||
use TheTempusProject\Hermes\Functions\Route as Routes;
|
use TheTempusProject\Hermes\Functions\Route as Routes;
|
||||||
use TheTempusProject\Bedrock\Functions\Session;
|
use TheTempusProject\Bedrock\Functions\Session;
|
||||||
@ -266,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;
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
*/
|
*/
|
||||||
namespace TheTempusProject\Classes;
|
namespace TheTempusProject\Classes;
|
||||||
|
|
||||||
use TheTempusProject\Canary\Canary as Debug;
|
use TheTempusProject\Canary\Bin\Canary as Debug;
|
||||||
use TheTempusProject\Bedrock\Functions\Check;
|
use TheTempusProject\Bedrock\Functions\Check;
|
||||||
use TheTempusProject\Houdini\Classes\Forms;
|
use TheTempusProject\Houdini\Classes\Forms;
|
||||||
use TheTempusProject\Bedrock\Functions\Input;
|
use TheTempusProject\Bedrock\Functions\Input;
|
||||||
|
@ -14,7 +14,7 @@ namespace TheTempusProject\Classes;
|
|||||||
use TheTempusProject\Houdini\Classes\Navigation;
|
use TheTempusProject\Houdini\Classes\Navigation;
|
||||||
use TheTempusProject\Houdini\Classes\Filters;
|
use TheTempusProject\Houdini\Classes\Filters;
|
||||||
use TheTempusProject\TheTempusProject as App;
|
use TheTempusProject\TheTempusProject as App;
|
||||||
use TheTempusProject\Canary\Canary as Debug;
|
use TheTempusProject\Canary\Bin\Canary as Debug;
|
||||||
use TheTempusProject\Bedrock\Classes\Database;
|
use TheTempusProject\Bedrock\Classes\Database;
|
||||||
|
|
||||||
class Plugin {
|
class Plugin {
|
||||||
|
@ -13,7 +13,7 @@ namespace TheTempusProject\Classes;
|
|||||||
|
|
||||||
use TheTempusProject\Houdini\Classes\Issues;
|
use TheTempusProject\Houdini\Classes\Issues;
|
||||||
use TheTempusProject\Houdini\Classes\Forms;
|
use TheTempusProject\Houdini\Classes\Forms;
|
||||||
use TheTempusProject\Canary\Canary as Debug;
|
use TheTempusProject\Canary\Bin\Canary as Debug;
|
||||||
use TheTempusProject\Bedrock\Functions\Check;
|
use TheTempusProject\Bedrock\Functions\Check;
|
||||||
use TheTempusProject\Bedrock\Functions\Upload;
|
use TheTempusProject\Bedrock\Functions\Upload;
|
||||||
use TheTempusProject\Bedrock\Functions\Input;
|
use TheTempusProject\Bedrock\Functions\Input;
|
||||||
|
@ -1,135 +1,137 @@
|
|||||||
<?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( 'APP_DIRECTORY', APP_ROOT_DIRECTORY . 'app' . DIRECTORY_SEPARATOR );
|
||||||
define( 'CONFIG_DIRECTORY', APP_ROOT_DIRECTORY . 'app' . DIRECTORY_SEPARATOR . 'config' . DIRECTORY_SEPARATOR );
|
|
||||||
}
|
|
||||||
// Directories
|
// Directories
|
||||||
define( 'APP_DIRECTORY', APP_ROOT_DIRECTORY . 'app' . DIRECTORY_SEPARATOR );
|
define( 'CSS_DIRECTORY', APP_ROOT_DIRECTORY . 'css' . DIRECTORY_SEPARATOR );
|
||||||
define( 'CSS_DIRECTORY', APP_ROOT_DIRECTORY . 'css' . DIRECTORY_SEPARATOR );
|
define( 'IMAGE_DIRECTORY', APP_ROOT_DIRECTORY . 'images' . DIRECTORY_SEPARATOR );
|
||||||
define( 'IMAGE_DIRECTORY', APP_ROOT_DIRECTORY . 'images' . DIRECTORY_SEPARATOR );
|
define( 'JAVASCRIPT_DIRECTORY', APP_ROOT_DIRECTORY . 'js' . DIRECTORY_SEPARATOR );
|
||||||
define( 'JAVASCRIPT_DIRECTORY', APP_ROOT_DIRECTORY . 'js' . DIRECTORY_SEPARATOR );
|
define( 'HTACCESS_LOCATION', APP_ROOT_DIRECTORY . '.htaccess' );
|
||||||
define( 'HTACCESS_LOCATION', APP_ROOT_DIRECTORY . '.htaccess' );
|
if ( ! defined( 'CONFIG_DIRECTORY' ) ) {
|
||||||
define( 'PLUGIN_DIRECTORY', APP_DIRECTORY . 'plugins' . DIRECTORY_SEPARATOR );
|
define( 'CONFIG_DIRECTORY', APP_DIRECTORY . 'config' . DIRECTORY_SEPARATOR );
|
||||||
define( 'MODEL_DIRECTORY', APP_DIRECTORY . 'models' . DIRECTORY_SEPARATOR );
|
}
|
||||||
define( 'CONTROLLER_DIRECTORY', APP_DIRECTORY . 'controllers' . DIRECTORY_SEPARATOR );
|
define( 'PLUGIN_DIRECTORY', APP_DIRECTORY . 'plugins' . DIRECTORY_SEPARATOR );
|
||||||
define( 'ADMIN_CONTROLLER_DIRECTORY', CONTROLLER_DIRECTORY. 'admin' . DIRECTORY_SEPARATOR );
|
define( 'MODEL_DIRECTORY', APP_DIRECTORY . 'models' . DIRECTORY_SEPARATOR );
|
||||||
define( 'API_CONTROLLER_DIRECTORY', CONTROLLER_DIRECTORY. 'api' . DIRECTORY_SEPARATOR );
|
define( 'CONTROLLER_DIRECTORY', APP_DIRECTORY . 'controllers' . DIRECTORY_SEPARATOR );
|
||||||
|
define( 'ADMIN_CONTROLLER_DIRECTORY', CONTROLLER_DIRECTORY. 'admin' . DIRECTORY_SEPARATOR );
|
||||||
|
define( 'API_CONTROLLER_DIRECTORY', CONTROLLER_DIRECTORY. 'api' . DIRECTORY_SEPARATOR );
|
||||||
// Files
|
// Files
|
||||||
define( 'PERMISSIONS_JSON', CONFIG_DIRECTORY . 'permissions.json' );
|
define( 'PERMISSIONS_JSON', CONFIG_DIRECTORY . 'permissions.json' );
|
||||||
define( 'PREFERENCES_JSON', CONFIG_DIRECTORY . 'preferences.json' );
|
define( 'PREFERENCES_JSON', CONFIG_DIRECTORY . 'preferences.json' );
|
||||||
define( 'INSTALL_JSON_LOCATION', CONFIG_DIRECTORY . 'install.json' );
|
define( 'INSTALL_JSON_LOCATION', CONFIG_DIRECTORY . 'install.json' );
|
||||||
define( 'INSTALLER_LOCATION', APP_ROOT_DIRECTORY . 'install.php' );
|
define( 'INSTALLER_LOCATION', APP_ROOT_DIRECTORY . 'install.php' );
|
||||||
// Other
|
// Other
|
||||||
define( 'PLUGINS_ENABLED', true );
|
define( 'PLUGINS_ENABLED', true );
|
||||||
define( 'INSTALL_STATUS_NOT_REQUIRED', 'Not Required' );
|
define( 'INSTALL_STATUS_NOT_REQUIRED', 'Not Required' );
|
||||||
define( 'INSTALL_STATUS_NOT_FOUND', 'Not Found' );
|
define( 'INSTALL_STATUS_NOT_FOUND', 'Not Found' );
|
||||||
define( 'INSTALL_STATUS_PARTIALLY_INSTALLED', 'Partially Installed' );
|
define( 'INSTALL_STATUS_PARTIALLY_INSTALLED', 'Partially Installed' );
|
||||||
define( 'INSTALL_STATUS_NOT_INSTALLED', 'Not Installed' );
|
define( 'INSTALL_STATUS_NOT_INSTALLED', 'Not Installed' );
|
||||||
define( 'INSTALL_STATUS_INSTALLED', 'Installed' );
|
define( 'INSTALL_STATUS_INSTALLED', 'Installed' );
|
||||||
define( 'INSTALL_STATUS_UNINSTALLED', 'Uninstalled' );
|
define( 'INSTALL_STATUS_UNINSTALLED', 'Uninstalled' );
|
||||||
define( 'INSTALL_STATUS_SUCCESS', 'Success' );
|
define( 'INSTALL_STATUS_SUCCESS', 'Success' );
|
||||||
define( 'INSTALL_STATUS_SKIPPED', 'Skipped' );
|
define( 'INSTALL_STATUS_SKIPPED', 'Skipped' );
|
||||||
define( 'INSTALL_STATUS_FAIL', 'Failed' );
|
define( 'INSTALL_STATUS_FAIL', 'Failed' );
|
||||||
define( 'MODEL_INSTALL_FLAGS', [ 'installTable', 'installPermissions', 'installConfigs', 'installResources', 'installPreferences' ] );
|
define( 'MODEL_INSTALL_FLAGS', [ 'installTable', 'installPermissions', 'installConfigs', 'installResources', 'installPreferences' ] );
|
||||||
define( 'PLUGIN_INSTALL_FLAGS', [ 'models_installed', 'permissions_installed', 'configs_installed', 'resources_installed', 'preferences_installed' ] );
|
define( 'PLUGIN_INSTALL_FLAGS', [ 'models_installed', 'permissions_installed', 'configs_installed', 'resources_installed', 'preferences_installed' ] );
|
||||||
# Tempus Debugger
|
# Tempus Debugger
|
||||||
define( 'CANARY_SECURE_HASH', 'd73ed7591a30f0ca7d686a0e780f0d05' );
|
define( 'CANARY_SECURE_HASH', 'd73ed7591a30f0ca7d686a0e780f0d05' );
|
||||||
# Tempus Project Core
|
# Tempus Project Core
|
||||||
// Check
|
// Check
|
||||||
define( 'MINIMUM_PHP_VERSION', 8.1);
|
define( 'MINIMUM_PHP_VERSION', 8.1);
|
||||||
// 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' );
|
||||||
define( 'CANARY_DEBUG_LEVEL_LOG', 'log' );
|
define( 'CANARY_DEBUG_LEVEL_LOG', 'log' );
|
||||||
define( 'CANARY_DEBUG_LEVEL_DEBUG', 'debug' );
|
define( 'CANARY_DEBUG_LEVEL_DEBUG', 'debug' );
|
||||||
define( 'CANARY_DEBUG_TO_FILE_LEVEL', CANARY_DEBUG_LEVEL_INFO );
|
define( 'CANARY_DEBUG_TO_FILE_LEVEL', CANARY_DEBUG_LEVEL_INFO );
|
||||||
define( 'CANARY_ENABLED', true );
|
define( 'CANARY_ENABLED', true );
|
||||||
define( 'DEBUG_EMAIL', 'webmaster@' . $_SERVER['HTTP_HOST'] );
|
define( 'DEBUG_EMAIL', 'webmaster@' . $_SERVER['HTTP_HOST'] );
|
||||||
define( 'HERMES_REDIRECTS_ENABLED', true );
|
define( 'HERMES_REDIRECTS_ENABLED', true );
|
||||||
define( 'RENDERING_ENABLED', true );
|
define( 'RENDERING_ENABLED', true );
|
||||||
define( 'CANARY_TRACE_ENABLED', false );
|
define( 'CANARY_TRACE_ENABLED', false );
|
||||||
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
|
||||||
define( 'VENDOR_DIRECTORY', APP_ROOT_DIRECTORY . 'vendor' . DIRECTORY_SEPARATOR );
|
if ( ! defined( 'VENDOR_DIRECTORY' ) ) {
|
||||||
if ( is_dir( VENDOR_DIRECTORY . 'thetempusproject' )) {
|
define( 'VENDOR_DIRECTORY', APP_ROOT_DIRECTORY . 'vendor' . DIRECTORY_SEPARATOR );
|
||||||
define( 'TP_VENDOR_DIRECTORY', VENDOR_DIRECTORY . 'thetempusproject' . DIRECTORY_SEPARATOR );
|
}
|
||||||
} elseif ( 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 );
|
||||||
} else {
|
} elseif ( is_dir( VENDOR_DIRECTORY . 'TheTempusProject' )) {
|
||||||
define( 'TP_VENDOR_DIRECTORY', VENDOR_DIRECTORY);
|
define( 'TP_VENDOR_DIRECTORY', VENDOR_DIRECTORY . 'TheTempusProject' . DIRECTORY_SEPARATOR );
|
||||||
}
|
} else {
|
||||||
# Bedrock
|
define( 'TP_VENDOR_DIRECTORY', VENDOR_DIRECTORY);
|
||||||
if ( is_dir( TP_VENDOR_DIRECTORY . 'tempusprojectcore' )) {
|
}
|
||||||
define( 'BEDROCK_ROOT_DIRECTORY', TP_VENDOR_DIRECTORY . 'tempusprojectcore' . DIRECTORY_SEPARATOR );
|
# Bedrock
|
||||||
} elseif ( is_dir( TP_VENDOR_DIRECTORY . 'TempusProjectCore' )) {
|
if ( is_dir( TP_VENDOR_DIRECTORY . 'tempusprojectcore' )) {
|
||||||
define( 'BEDROCK_ROOT_DIRECTORY', TP_VENDOR_DIRECTORY . 'TempusProjectCore' . DIRECTORY_SEPARATOR );
|
define( 'BEDROCK_ROOT_DIRECTORY', TP_VENDOR_DIRECTORY . 'tempusprojectcore' . DIRECTORY_SEPARATOR );
|
||||||
} elseif ( is_dir( TP_VENDOR_DIRECTORY . 'bedrock' )) {
|
} elseif ( is_dir( TP_VENDOR_DIRECTORY . 'TempusProjectCore' )) {
|
||||||
define( 'BEDROCK_ROOT_DIRECTORY', TP_VENDOR_DIRECTORY . 'bedrock' . DIRECTORY_SEPARATOR );
|
define( 'BEDROCK_ROOT_DIRECTORY', TP_VENDOR_DIRECTORY . 'TempusProjectCore' . DIRECTORY_SEPARATOR );
|
||||||
} elseif ( is_dir( TP_VENDOR_DIRECTORY . 'Bedrock' )) {
|
} elseif ( is_dir( TP_VENDOR_DIRECTORY . 'bedrock' )) {
|
||||||
define( 'BEDROCK_ROOT_DIRECTORY', TP_VENDOR_DIRECTORY . 'Bedrock' . DIRECTORY_SEPARATOR );
|
define( 'BEDROCK_ROOT_DIRECTORY', TP_VENDOR_DIRECTORY . 'bedrock' . DIRECTORY_SEPARATOR );
|
||||||
}
|
} elseif ( is_dir( TP_VENDOR_DIRECTORY . 'Bedrock' )) {
|
||||||
if ( is_dir( BEDROCK_ROOT_DIRECTORY . 'config' )) {
|
define( 'BEDROCK_ROOT_DIRECTORY', TP_VENDOR_DIRECTORY . 'Bedrock' . DIRECTORY_SEPARATOR );
|
||||||
define( 'BEDROCK_CONFIG_DIRECTORY', BEDROCK_ROOT_DIRECTORY . 'config' . DIRECTORY_SEPARATOR );
|
}
|
||||||
}
|
if ( is_dir( BEDROCK_ROOT_DIRECTORY . 'config' )) {
|
||||||
# Canary
|
define( 'BEDROCK_CONFIG_DIRECTORY', BEDROCK_ROOT_DIRECTORY . 'config' . DIRECTORY_SEPARATOR );
|
||||||
if ( is_dir( TP_VENDOR_DIRECTORY . 'tempusdebugger' )) {
|
}
|
||||||
define( 'CANARY_ROOT_DIRECTORY', TP_VENDOR_DIRECTORY . 'tempusdebugger' . DIRECTORY_SEPARATOR );
|
# Canary
|
||||||
} elseif ( is_dir( TP_VENDOR_DIRECTORY . 'TempusDebugger' )) {
|
if ( is_dir( TP_VENDOR_DIRECTORY . 'tempusdebugger' )) {
|
||||||
define( 'CANARY_ROOT_DIRECTORY', TP_VENDOR_DIRECTORY . 'TempusDebugger' . DIRECTORY_SEPARATOR );
|
define( 'CANARY_ROOT_DIRECTORY', TP_VENDOR_DIRECTORY . 'tempusdebugger' . DIRECTORY_SEPARATOR );
|
||||||
} elseif ( is_dir( TP_VENDOR_DIRECTORY . 'canary' )) {
|
} elseif ( is_dir( TP_VENDOR_DIRECTORY . 'TempusDebugger' )) {
|
||||||
define( 'CANARY_ROOT_DIRECTORY', TP_VENDOR_DIRECTORY . 'canary' . DIRECTORY_SEPARATOR );
|
define( 'CANARY_ROOT_DIRECTORY', TP_VENDOR_DIRECTORY . 'TempusDebugger' . DIRECTORY_SEPARATOR );
|
||||||
} elseif ( is_dir( TP_VENDOR_DIRECTORY . 'Canary' )) {
|
} elseif ( is_dir( TP_VENDOR_DIRECTORY . 'canary' )) {
|
||||||
define( 'CANARY_ROOT_DIRECTORY', TP_VENDOR_DIRECTORY . 'Canary' . DIRECTORY_SEPARATOR );
|
define( 'CANARY_ROOT_DIRECTORY', TP_VENDOR_DIRECTORY . 'canary' . DIRECTORY_SEPARATOR );
|
||||||
}
|
} elseif ( is_dir( TP_VENDOR_DIRECTORY . 'Canary' )) {
|
||||||
if ( is_dir( CANARY_ROOT_DIRECTORY . 'config' )) {
|
define( 'CANARY_ROOT_DIRECTORY', TP_VENDOR_DIRECTORY . 'Canary' . DIRECTORY_SEPARATOR );
|
||||||
define( 'CANARY_CONFIG_DIRECTORY', CANARY_ROOT_DIRECTORY . 'config' . DIRECTORY_SEPARATOR );
|
}
|
||||||
}
|
if ( is_dir( CANARY_ROOT_DIRECTORY . 'config' )) {
|
||||||
# Hermes
|
define( 'CANARY_CONFIG_DIRECTORY', CANARY_ROOT_DIRECTORY . 'config' . DIRECTORY_SEPARATOR );
|
||||||
if ( is_dir( TP_VENDOR_DIRECTORY . 'hermes' )) {
|
}
|
||||||
define( 'HERMES_ROOT_DIRECTORY', TP_VENDOR_DIRECTORY . 'hermes' . DIRECTORY_SEPARATOR );
|
# Hermes
|
||||||
} elseif ( is_dir( TP_VENDOR_DIRECTORY . 'Hermes' )) {
|
if ( is_dir( TP_VENDOR_DIRECTORY . 'hermes' )) {
|
||||||
define( 'HERMES_ROOT_DIRECTORY', TP_VENDOR_DIRECTORY . 'Hermes' . DIRECTORY_SEPARATOR );
|
define( 'HERMES_ROOT_DIRECTORY', TP_VENDOR_DIRECTORY . 'hermes' . DIRECTORY_SEPARATOR );
|
||||||
}
|
} elseif ( is_dir( TP_VENDOR_DIRECTORY . 'Hermes' )) {
|
||||||
if ( is_dir( HERMES_ROOT_DIRECTORY . 'config' )) {
|
define( 'HERMES_ROOT_DIRECTORY', TP_VENDOR_DIRECTORY . 'Hermes' . DIRECTORY_SEPARATOR );
|
||||||
define( 'HERMES_CONFIG_DIRECTORY', HERMES_ROOT_DIRECTORY . 'config' . DIRECTORY_SEPARATOR );
|
}
|
||||||
}
|
if ( is_dir( HERMES_ROOT_DIRECTORY . 'config' )) {
|
||||||
# Houdini
|
define( 'HERMES_CONFIG_DIRECTORY', HERMES_ROOT_DIRECTORY . 'config' . DIRECTORY_SEPARATOR );
|
||||||
if ( is_dir( TP_VENDOR_DIRECTORY . 'houdini' )) {
|
}
|
||||||
define( 'HOUDINI_ROOT_DIRECTORY', TP_VENDOR_DIRECTORY . 'houdini' . DIRECTORY_SEPARATOR );
|
# Houdini
|
||||||
} elseif ( is_dir( TP_VENDOR_DIRECTORY . 'Houdini' )) {
|
if ( is_dir( TP_VENDOR_DIRECTORY . 'houdini' )) {
|
||||||
define( 'HOUDINI_ROOT_DIRECTORY', TP_VENDOR_DIRECTORY . 'Houdini' . DIRECTORY_SEPARATOR );
|
define( 'HOUDINI_ROOT_DIRECTORY', TP_VENDOR_DIRECTORY . 'houdini' . DIRECTORY_SEPARATOR );
|
||||||
}
|
} elseif ( is_dir( TP_VENDOR_DIRECTORY . 'Houdini' )) {
|
||||||
if ( is_dir( HOUDINI_ROOT_DIRECTORY . 'config' )) {
|
define( 'HOUDINI_ROOT_DIRECTORY', TP_VENDOR_DIRECTORY . 'Houdini' . DIRECTORY_SEPARATOR );
|
||||||
define( 'HOUDINI_CONFIG_DIRECTORY', HOUDINI_ROOT_DIRECTORY . 'config' . DIRECTORY_SEPARATOR );
|
}
|
||||||
}
|
if ( is_dir( HOUDINI_ROOT_DIRECTORY . 'config' )) {
|
||||||
// Shared Directories
|
define( 'HOUDINI_CONFIG_DIRECTORY', HOUDINI_ROOT_DIRECTORY . 'config' . DIRECTORY_SEPARATOR );
|
||||||
define( 'BIN_DIRECTORY', APP_ROOT_DIRECTORY . 'bin' . DIRECTORY_SEPARATOR );
|
}
|
||||||
define( 'VIEW_DIRECTORY', APP_DIRECTORY . 'views' . DIRECTORY_SEPARATOR );
|
// Shared Directories
|
||||||
define( 'ERRORS_DIRECTORY', VIEW_DIRECTORY . 'errors' . DIRECTORY_SEPARATOR );
|
define( 'BIN_DIRECTORY', APP_ROOT_DIRECTORY . 'bin' . DIRECTORY_SEPARATOR );
|
||||||
define( 'CLASSES_DIRECTORY', APP_DIRECTORY . 'classes' . DIRECTORY_SEPARATOR );
|
define( 'VIEW_DIRECTORY', APP_DIRECTORY . 'views' . DIRECTORY_SEPARATOR );
|
||||||
define( 'FUNCTIONS_DIRECTORY', APP_DIRECTORY . 'functions' . DIRECTORY_SEPARATOR );
|
define( 'ERRORS_DIRECTORY', VIEW_DIRECTORY . 'errors' . DIRECTORY_SEPARATOR );
|
||||||
define( 'RESOURCES_DIRECTORY', APP_DIRECTORY . 'resources' . DIRECTORY_SEPARATOR );
|
define( 'CLASSES_DIRECTORY', APP_DIRECTORY . 'classes' . DIRECTORY_SEPARATOR );
|
||||||
define( 'TEMPLATE_DIRECTORY', APP_DIRECTORY . 'templates' . DIRECTORY_SEPARATOR );
|
define( 'FUNCTIONS_DIRECTORY', APP_DIRECTORY . 'functions' . DIRECTORY_SEPARATOR );
|
||||||
define( 'UPLOAD_DIRECTORY', APP_ROOT_DIRECTORY . 'uploads' . DIRECTORY_SEPARATOR );
|
define( 'RESOURCES_DIRECTORY', APP_DIRECTORY . 'resources' . DIRECTORY_SEPARATOR );
|
||||||
define( 'IMAGE_UPLOAD_DIRECTORY', UPLOAD_DIRECTORY . 'images' . DIRECTORY_SEPARATOR );
|
define( 'TEMPLATE_DIRECTORY', APP_DIRECTORY . 'templates' . DIRECTORY_SEPARATOR );
|
||||||
// Files
|
define( 'UPLOAD_DIRECTORY', APP_ROOT_DIRECTORY . 'uploads' . DIRECTORY_SEPARATOR );
|
||||||
define( 'COMPOSER_JSON_LOCATION', APP_ROOT_DIRECTORY . 'composer.json' );
|
define( 'IMAGE_UPLOAD_DIRECTORY', UPLOAD_DIRECTORY . 'images' . DIRECTORY_SEPARATOR );
|
||||||
define( 'COMPOSER_LOCK_LOCATION', APP_ROOT_DIRECTORY . 'composer.lock' );
|
// Files
|
||||||
define( 'CONFIG_JSON', CONFIG_DIRECTORY . 'config.json' );
|
define( 'COMPOSER_JSON_LOCATION', APP_ROOT_DIRECTORY . 'composer.json' );
|
||||||
// Other
|
define( 'COMPOSER_LOCK_LOCATION', APP_ROOT_DIRECTORY . 'composer.lock' );
|
||||||
define( 'EMAIL_FROM_EMAIL', 'noreply@localohost.com' );
|
define( 'CONFIG_JSON', CONFIG_DIRECTORY . 'config.json' );
|
||||||
// Sessions
|
// Other
|
||||||
define( 'DEFAULT_SESSION_PREFIX', 'TP_' );
|
define( 'EMAIL_FROM_EMAIL', 'noreply@localohost.com' );
|
||||||
// Token
|
// Sessions
|
||||||
define( 'DEFAULT_TOKEN_NAME', 'TP_SESSION_TOKEN' );
|
define( 'DEFAULT_SESSION_PREFIX', 'TP_' );
|
||||||
|
// Token
|
||||||
|
define( 'DEFAULT_TOKEN_NAME', 'TP_SESSION_TOKEN' );
|
||||||
# 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 );
|
||||||
|
@ -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 ) {
|
||||||
|
@ -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;
|
|
@ -12,7 +12,7 @@
|
|||||||
namespace TheTempusProject\Models;
|
namespace TheTempusProject\Models;
|
||||||
|
|
||||||
use TheTempusProject\Bedrock\Functions\Check;
|
use TheTempusProject\Bedrock\Functions\Check;
|
||||||
use TheTempusProject\Canary\Canary as Debug;
|
use TheTempusProject\Canary\Bin\Canary as Debug;
|
||||||
use TheTempusProject\Classes\Permissions;
|
use TheTempusProject\Classes\Permissions;
|
||||||
use TheTempusProject\Bedrock\Classes\Config;
|
use TheTempusProject\Bedrock\Classes\Config;
|
||||||
use TheTempusProject\Bedrock\Functions\Input;
|
use TheTempusProject\Bedrock\Functions\Input;
|
||||||
@ -257,7 +257,7 @@ class Group extends DatabaseModel {
|
|||||||
if ( $group === false ) {
|
if ( $group === false ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$members = self::$db->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,10 +13,10 @@ namespace TheTempusProject\Models;
|
|||||||
|
|
||||||
use TheTempusProject\Bedrock\Functions\Check;
|
use TheTempusProject\Bedrock\Functions\Check;
|
||||||
use TheTempusProject\Bedrock\Classes\Config;
|
use TheTempusProject\Bedrock\Classes\Config;
|
||||||
use TheTempusProject\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\Canary as Debug;
|
use TheTempusProject\Canary\Bin\Canary as Debug;
|
||||||
|
|
||||||
class Log extends DatabaseModel {
|
class Log extends DatabaseModel {
|
||||||
public $tableName = 'logs';
|
public $tableName = 'logs';
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
namespace TheTempusProject\Models;
|
namespace TheTempusProject\Models;
|
||||||
|
|
||||||
use TheTempusProject\Bedrock\Functions\Check;
|
use TheTempusProject\Bedrock\Functions\Check;
|
||||||
use TheTempusProject\Canary\Canary as Debug;
|
use TheTempusProject\Canary\Bin\Canary as Debug;
|
||||||
use TheTempusProject\Classes\DatabaseModel;
|
use TheTempusProject\Classes\DatabaseModel;
|
||||||
|
|
||||||
class Routes extends DatabaseModel {
|
class Routes extends DatabaseModel {
|
||||||
|
@ -16,7 +16,7 @@ namespace TheTempusProject\Models;
|
|||||||
|
|
||||||
use TheTempusProject\Bedrock\Functions\Check;
|
use TheTempusProject\Bedrock\Functions\Check;
|
||||||
use TheTempusProject\Bedrock\Functions\Code;
|
use TheTempusProject\Bedrock\Functions\Code;
|
||||||
use TheTempusProject\Canary\Canary as Debug;
|
use TheTempusProject\Canary\Bin\Canary as Debug;
|
||||||
use TheTempusProject\Bedrock\Functions\Session;
|
use TheTempusProject\Bedrock\Functions\Session;
|
||||||
use TheTempusProject\Bedrock\Functions\Cookie;
|
use TheTempusProject\Bedrock\Functions\Cookie;
|
||||||
use TheTempusProject\Classes\DatabaseModel;
|
use TheTempusProject\Classes\DatabaseModel;
|
||||||
|
@ -16,12 +16,12 @@
|
|||||||
namespace TheTempusProject\Models;
|
namespace TheTempusProject\Models;
|
||||||
|
|
||||||
use TheTempusProject\Bedrock\Functions\Check;
|
use TheTempusProject\Bedrock\Functions\Check;
|
||||||
use TheTempusProject\Canary\Canary as Debug;
|
use TheTempusProject\Canary\Bin\Canary as Debug;
|
||||||
use TheTempusProject\Bedrock\Functions\Hash;
|
use TheTempusProject\Bedrock\Functions\Hash;
|
||||||
use TheTempusProject\Bedrock\Functions\Session;
|
use TheTempusProject\Bedrock\Functions\Session;
|
||||||
use TheTempusProject\Bedrock\Functions\Code;
|
use TheTempusProject\Bedrock\Functions\Code;
|
||||||
use TheTempusProject\Bedrock\Classes\Config;
|
use TheTempusProject\Bedrock\Classes\Config;
|
||||||
use TheTempusProject\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;
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
namespace TheTempusProject\Controllers;
|
namespace TheTempusProject\Controllers;
|
||||||
|
|
||||||
use TheTempusProject\Bedrock\Functions\Check;
|
use TheTempusProject\Bedrock\Functions\Check;
|
||||||
use TheTempusProject\Canary\Canary as Debug;
|
use TheTempusProject\Canary\Bin\Canary as Debug;
|
||||||
use TheTempusProject\Bedrock\Functions\Input;
|
use TheTempusProject\Bedrock\Functions\Input;
|
||||||
use TheTempusProject\Houdini\Classes\Components;
|
use TheTempusProject\Houdini\Classes\Components;
|
||||||
use TheTempusProject\Houdini\Classes\Issues;
|
use TheTempusProject\Houdini\Classes\Issues;
|
||||||
|
@ -12,16 +12,19 @@
|
|||||||
*/
|
*/
|
||||||
namespace TheTempusProject\Models;
|
namespace TheTempusProject\Models;
|
||||||
|
|
||||||
use TheTempusProject\Canary\Canary as Debug;
|
use TheTempusProject\Canary\Bin\Canary as Debug;
|
||||||
use TheTempusProject\Bedrock\Functions\Check;
|
use TheTempusProject\Bedrock\Functions\Check;
|
||||||
use TheTempusProject\Bedrock\Functions\Sanitize;
|
use TheTempusProject\Bedrock\Functions\Sanitize;
|
||||||
use TheTempusProject\Classes\DatabaseModel;
|
use TheTempusProject\Classes\DatabaseModel;
|
||||||
use TheTempusProject\TheTempusProject as App;
|
use TheTempusProject\TheTempusProject as App;
|
||||||
use TheTempusProject\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\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\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\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>
|
|
@ -14,8 +14,8 @@ namespace TheTempusProject\Models;
|
|||||||
|
|
||||||
use TheTempusProject\Bedrock\Functions\Check;
|
use TheTempusProject\Bedrock\Functions\Check;
|
||||||
use TheTempusProject\Bedrock\Classes\Config;
|
use TheTempusProject\Bedrock\Classes\Config;
|
||||||
use TheTempusProject\Canary\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\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\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\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\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);
|
|
||||||
// }
|
|
||||||
});
|
|
@ -1,145 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* app/plugins/chat/models/chat.php
|
|
||||||
*
|
|
||||||
* This class is used for the manipulation of the chat database table.
|
|
||||||
*
|
|
||||||
* @todo make this send a confirmation email
|
|
||||||
*
|
|
||||||
* @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\Models;
|
|
||||||
|
|
||||||
use TheTempusProject\Bedrock\Classes\Config;
|
|
||||||
use TheTempusProject\Bedrock\Functions\Check;
|
|
||||||
use TheTempusProject\Canary\Canary as Debug;
|
|
||||||
use TheTempusProject\Classes\DatabaseModel;
|
|
||||||
use TheTempusProject\TheTempusProject as App;
|
|
||||||
use TheTempusProject\Houdini\Classes\Filters;
|
|
||||||
|
|
||||||
class Chat extends DatabaseModel {
|
|
||||||
public $tableName = 'chat';
|
|
||||||
public $databaseMatrix = [
|
|
||||||
[ 'submittedAt', 'int', '10' ],
|
|
||||||
[ 'submittedBy', 'int', '11' ],
|
|
||||||
[ 'chatMessage', 'text', '' ],
|
|
||||||
];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The model constructor.
|
|
||||||
*/
|
|
||||||
public function __construct() {
|
|
||||||
parent::__construct();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Saves a chat form to the db.
|
|
||||||
*
|
|
||||||
* @param string $message -contents of the chat form.
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function create( $message ) {
|
|
||||||
$fields = [
|
|
||||||
'submittedBy' => App::$activeUser->ID,
|
|
||||||
'submittedAt' => time(),
|
|
||||||
'chatMessage' => $message,
|
|
||||||
];
|
|
||||||
if ( !self::$db->insert( $this->tableName, $fields ) ) {
|
|
||||||
Debug::info( 'Chat::create - failed to insert to db' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return self::$db->lastId();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function filter( $data, $params = [] ) {
|
|
||||||
foreach ( $data as $instance ) {
|
|
||||||
if ( !is_object( $instance ) ) {
|
|
||||||
$instance = $data;
|
|
||||||
$end = true;
|
|
||||||
}
|
|
||||||
$instance->chatMessage = Filters::applyOne( 'mentions.0', $instance->chatMessage, true );
|
|
||||||
$instance->chatMessage = Filters::applyOne( 'hashtags.0', $instance->chatMessage, true );
|
|
||||||
$user = self::$user->findById( $instance->submittedBy );
|
|
||||||
if ( ! empty( $user ) ) {
|
|
||||||
$instance->submittedByName = $user->username;
|
|
||||||
$instance->profileUrl = '/home/profile/' . $user->username;
|
|
||||||
} else {
|
|
||||||
$instance->submittedByName = 'Unknown';
|
|
||||||
$instance->profileUrl = '#';
|
|
||||||
}
|
|
||||||
$instance->avatar = self::$user->getAvatar( $instance->submittedBy );
|
|
||||||
$out[] = $instance;
|
|
||||||
if ( !empty( $end ) ) {
|
|
||||||
$out = $out[0];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $out;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function to clear chat from the DB.
|
|
||||||
*
|
|
||||||
* @todo is there a way i could check for success here I'm pretty sure this is just a bad idea?
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public function clear() {
|
|
||||||
if ( empty( self::$log ) ) {
|
|
||||||
self::$log = new Log;
|
|
||||||
}
|
|
||||||
self::$db->delete( $this->tableName, ['ID', '>=', '0'] );
|
|
||||||
self::$log->admin( 'Cleared Chat' );
|
|
||||||
Debug::info( 'Chat Cleared' );
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function recent( $limit = null ) {
|
|
||||||
if ( empty( $limit ) ) {
|
|
||||||
$postData = self::$db->get( $this->tableName, '*' );
|
|
||||||
} else {
|
|
||||||
$postData = self::$db->get( $this->tableName, '*', 'ID', 'ASC', [0, $limit] );
|
|
||||||
}
|
|
||||||
if ( !$postData->count() ) {
|
|
||||||
Debug::info( 'No messages found.' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return $this->filter( $postData->results() );
|
|
||||||
}
|
|
||||||
|
|
||||||
public function sinceMessage($id = 0) {
|
|
||||||
if (empty($id)) {
|
|
||||||
$postData = self::$db->get($this->tableName, '*', 'ID', 'DESC', [0, 20]);
|
|
||||||
} else {
|
|
||||||
$postData = self::$db->get($this->tableName, ['ID', '>', $id], 'ID', 'ASC', [0, 20]);
|
|
||||||
}
|
|
||||||
if ( ! $postData->count() ) {
|
|
||||||
Debug::debug( 'No messages found.' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (empty($id)) {
|
|
||||||
$results = array_reverse($postData->results()); // Reverse the order to get ascending IDs
|
|
||||||
} else {
|
|
||||||
$results = $postData->results();
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->filter($results);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function sinceMessageSingle( $id = 0 ) {
|
|
||||||
if ( empty( $id ) ) {
|
|
||||||
$postData = self::$db->get( $this->tableName, '*', 'ID', 'ASC', [0, 1] );
|
|
||||||
} else {
|
|
||||||
$postData = self::$db->get( $this->tableName, [ 'ID', '>', $id ], 'ID', 'ASC', [0, 1] );
|
|
||||||
}
|
|
||||||
if ( ! $postData->count() ) {
|
|
||||||
Debug::debug( 'No messages found.' );
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return $this->filter( $postData->results() );
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,55 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* app/plugins/chat/plugin.php
|
|
||||||
*
|
|
||||||
* This houses all of the main plugin info and functionality.
|
|
||||||
*
|
|
||||||
* @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;
|
|
||||||
|
|
||||||
use TheTempusProject\Classes\Plugin;
|
|
||||||
use TheTempusProject\TheTempusProject as App;
|
|
||||||
|
|
||||||
class Chat extends Plugin {
|
|
||||||
public $pluginName = 'TP Chat';
|
|
||||||
public $configName = 'chat';
|
|
||||||
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 chat system.';
|
|
||||||
public $permissionMatrix = [
|
|
||||||
'chat' => [
|
|
||||||
'pretty' => 'Can use chat',
|
|
||||||
'default' => false,
|
|
||||||
],
|
|
||||||
];
|
|
||||||
public $admin_links = [
|
|
||||||
[
|
|
||||||
'text' => '<i class="fa fa-fw fa-copy"></i> Chat',
|
|
||||||
'url' => '{ROOT_URL}admin/chat',
|
|
||||||
],
|
|
||||||
];
|
|
||||||
public $main_links = [
|
|
||||||
[
|
|
||||||
'text' => 'Chat',
|
|
||||||
'url' => '{ROOT_URL}chat/index',
|
|
||||||
'filter' => 'loggedin',
|
|
||||||
],
|
|
||||||
];
|
|
||||||
public $configMatrix = [
|
|
||||||
'enabled' => [
|
|
||||||
'type' => 'radio',
|
|
||||||
'pretty' => 'Enable Chat.',
|
|
||||||
'default' => true,
|
|
||||||
],
|
|
||||||
];
|
|
||||||
public function __construct( $load = false ) {
|
|
||||||
parent::__construct( $load );
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,32 +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;
|
|
||||||
|
|
||||||
class ChatLoader extends DefaultLoader {
|
|
||||||
/**
|
|
||||||
* This is the function used to generate any components that may be
|
|
||||||
* needed by this template.
|
|
||||||
*/
|
|
||||||
public function __construct() {
|
|
||||||
$this->addJs( '<script language="JavaScript" crossorigin="anonymous" type="text/javascript" src="{ROOT_URL}app/plugins/chat/js/chat.js"></script>' );
|
|
||||||
parent::__construct();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,88 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<!--
|
|
||||||
* app/templates/default/default.tpl
|
|
||||||
*
|
|
||||||
* @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_large_image' />
|
|
||||||
<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">
|
|
||||||
{AUTHOR}
|
|
||||||
{ROBOT}
|
|
||||||
<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">
|
|
||||||
<!-- Custom styles for this template -->
|
|
||||||
{TEMPLATE_CSS_INCLUDES}
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">
|
|
||||||
<!--Brand and toggle should get grouped for better mobile display but I had to account for additional menus-->
|
|
||||||
<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 top-pad foot-pad">
|
|
||||||
{ISSUES}
|
|
||||||
<div class="container">
|
|
||||||
<div class="row">
|
|
||||||
{ERROR}
|
|
||||||
{NOTICE}
|
|
||||||
{SUCCESS}
|
|
||||||
{INFO}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/ISSUES}
|
|
||||||
<div class="container">
|
|
||||||
<div class="row">
|
|
||||||
{CONTENT}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<footer>
|
|
||||||
{FOOT}
|
|
||||||
{COPY}
|
|
||||||
</footer>
|
|
||||||
<!-- Bootstrap core JavaScript and jquery -->
|
|
||||||
<script language="JavaScript" crossorigin="anonymous" type="text/javascript" src="{JQUERY_CDN}jquery.min.js"></script>
|
|
||||||
<script language="JavaScript" crossorigin="anonymous" type="text/javascript" src="{BOOTSTRAP_CDN}js/bootstrap.min.js"></script>
|
|
||||||
<!-- Custom javascript for this template -->
|
|
||||||
{TEMPLATE_JS_INCLUDES}
|
|
||||||
</body>
|
|
||||||
</html>
|
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user