diff --git a/.gitignore b/.gitignore index e257bbd..b8f74ff 100644 --- a/.gitignore +++ b/.gitignore @@ -63,4 +63,4 @@ vendor/canary/logs/* components/* mailhog.log uploads/* -images/qr-codes/ +images/qr-codes/* diff --git a/app/images/ttp-gitlab.png b/app/images/ttp-gitlab.png deleted file mode 100644 index 1bce8fa..0000000 Binary files a/app/images/ttp-gitlab.png and /dev/null differ diff --git a/app/images/ttp-install.png b/app/images/ttp-install.png deleted file mode 100644 index aace68d..0000000 Binary files a/app/images/ttp-install.png and /dev/null differ diff --git a/app/images/ttp.png b/app/images/ttp.png deleted file mode 100644 index 31bec2e..0000000 Binary files a/app/images/ttp.png and /dev/null differ diff --git a/app/plugins/messages/controllers/messages.php b/app/plugins/messages/controllers/messages.php deleted file mode 100644 index f5239a3..0000000 --- a/app/plugins/messages/controllers/messages.php +++ /dev/null @@ -1,121 +0,0 @@ - - * @link https://TheTempusProject.com - * @license https://opensource.org/licenses/MIT [MIT LICENSE] - */ -namespace TheTempusProject\Controllers; - -use TheTempusProject\Classes\Controller; -use TheTempusProject\Classes\Forms as FormChecker; -use TheTempusProject\Models\Message; -use TheTempusProject\Houdini\Classes\Components; -use TheTempusProject\Houdini\Classes\Views; -use TheTempusProject\Houdini\Classes\Issues; -use TheTempusProject\Bedrock\Functions\Check; -use TheTempusProject\Bedrock\Functions\Input; -use TheTempusProject\TheTempusProject as App; -use TheTempusProject\Hermes\Functions\Redirect; -use TheTempusProject\Bedrock\Functions\Session; - -class Messages extends Controller { - private static $message; - - public function __construct() { - parent::__construct(); - self::$title = 'Messages'; - self::$message = new Message; - if ( ! App::$isLoggedIn ) { - Session::flash( 'error', 'You do not have permission to access this page.' ); - return Redirect::home(); - } - } - - public function create() { - self::$title .= ' - New Message'; - if ( Input::get( 'prepopuser' ) ) { - $data = Input::get( 'prepopuser' ); - } - if ( !empty( $data ) && self::$user->checkUsername( $data ) ) { - Components::set( 'prepopuser', $data ); - } else { - Components::set( 'prepopuser', '' ); - } - if ( !Input::exists( 'submit' ) ) { - return Views::view( 'messages.create' ); - } - if ( !FormChecker::check( 'newMessage' ) ) { - Issues::add( 'error', [ 'There was an problem sending your messages.' => Check::userErrors() ] ); - return Views::view( 'messages.create' ); - } - if ( self::$message->newThread( Input::post( 'toUser' ), Input::post( 'subject' ), Input::post( 'message' ) ) ) { - Issues::add( 'success', 'Message Sent.' ); - } else { - Issues::add( 'notice', 'There was an problem sending your messages.' ); - } - return $this->index(); - } - - public function delete( $id = '' ) { - if ( Input::exists( 'T_' ) ) { - self::$message->delete( Input::post( 'T_' ) ); - } - if ( Input::exists( 'F_' ) ) { - self::$message->delete( Input::post( 'F_' ) ); - } - if ( Input::exists( 'ID' ) ) { - self::$message->delete( Input::get( 'ID' ) ); - } - if ( !empty( $id ) ) { - self::$message->delete( $id ); - } - return $this->index(); - } - - public function index() { - Components::set( 'message_inbox', Views::simpleView( 'messages.inbox', self::$message->getInbox() ) ); - Components::set( 'message_outbox', Views::simpleView( 'messages.outbox', self::$message->getOutbox() ) ); - Views::view( 'messages.index' ); - } - - public function read( $id = '' ) { - self::$message->markRead( $id ); - return $this->index(); - } - - public function reply() { - if ( Input::exists( 'messageID' ) ) { - $data = Input::post( 'messageID' ); - } - if ( !Check::id( $data ) ) { - Issues::add( 'error', 'There was an error with your request.' ); - return $this->index(); - } - self::$title .= ' - Reply to: ' . self::$message->messageTitle( $data ); - if ( !Input::exists( 'message' ) ) { - Components::set( 'messageID', $data ); - return Views::view( 'messages.reply' ); - } - if ( !FormChecker::check( 'replyMessage' ) ) { - Issues::add( 'error', [ 'There was an problem sending your messages.' => Check::userErrors() ] ); - Components::set( 'messageID', $data ); - return Views::view( 'messages.reply' ); - } - if ( !self::$message->newMessageReply( $data, Input::post( 'message' ) ) ) { - Issues::add( 'error', 'There was an error with your request.' ); - return $this->index(); - } - Issues::add( 'success', 'Reply Sent.' ); - return $this->index(); - } - - public function view( $id = '' ) { - self::$title = self::$message->messageTitle( $id ); - return Views::view( 'messages.message', self::$message->getThread( $id, true ) ); - } -} diff --git a/app/plugins/messages/models/message.php b/app/plugins/messages/models/message.php deleted file mode 100644 index 16a7920..0000000 --- a/app/plugins/messages/models/message.php +++ /dev/null @@ -1,454 +0,0 @@ - - * @link https://TheTempusProject.com - * @license https://opensource.org/licenses/MIT [MIT LICENSE] - */ -namespace TheTempusProject\Models; - -use TheTempusProject\Classes\DatabaseModel; -use TheTempusProject\Houdini\Classes\Components; -use TheTempusProject\Houdini\Classes\Views; -use TheTempusProject\Canary\Bin\Canary as Debug; -use TheTempusProject\Bedrock\Functions\Check; -use TheTempusProject\Bedrock\Functions\Sanitize; -use TheTempusProject\TheTempusProject as App; -use TheTempusProject\Canary\Classes\CustomException; - -class Message extends DatabaseModel { - public $tableName = 'messages'; - public $databaseMatrix = [ - [ 'userTo', 'int', '11' ], - [ 'userFrom', 'int', '11' ], - [ 'parent', 'int', '11' ], - [ 'sent', 'int', '10' ], - [ 'lastReply', 'int', '10' ], - [ 'senderDeleted', 'int', '1' ], - [ 'recieverDeleted', 'int', '1' ], - [ 'isRead', 'int', '1' ], - [ 'message', 'text', '' ], - [ 'subject', 'text', '' ], - ]; - private $messages; - private $usernames; - - /** - * The model constructor. - */ - public function __construct() { - parent::__construct(); - self::$message = $this; - } - - /** - * Retrieves the most recent relative message in a thread - * - * @param int $parent - the id of the parent message - * @param string $user - the id of the relative user - * @return object - */ - public function getLatestMessage( $parent, $user, $type = null ) { - if ( !Check::id( $parent ) ) { - Debug::info( 'Invalid message ID' ); - return false; - } - if ( !Check::id( $user ) ) { - Debug::info( 'Invalid user ID' ); - return false; - } - $messageData = self::$db->get( $this->tableName, [ 'ID', '=', $parent ] ); - if ( $messageData->count() == 0 ) { - Debug::info( 'Message not found.' ); - return false; - } - $message = $messageData->first(); - $params = [ 'parent', '=', $parent ]; - if ( $type !== null ) { - $params = array_merge( $params, [ 'AND', $type, '=', $user ] ); - } - $messageData = self::$db->get( $this->tableName, $params, 'ID', 'DESC', [ 0, 1 ] ); - if ( $messageData->count() != 0 ) { - if ( $messageData->first()->recieverDeleted == 0 ) { - $message = $messageData->first(); - } else { - $message->recieverDeleted = 1; - } - } - return $message; - } - - /** - * This calls a view of the requested message. - * - * @param int $ID - The message ID you are looking for. - * @return null - */ - public function getThread( $id, $markRead = false ) { - if ( !Check::id( $id ) ) { - Debug::info( 'Invalid ID' ); - return false; - } - $messageData = self::$db->get( $this->tableName, [ 'ID', '=', $id ] ); - if ( $messageData->count() == 0 ) { - Debug::info( 'Message not found.' ); - return false; - } - $message = $messageData->first(); - if ( $message->userTo == App::$activeUser->ID ) { - $permissionCheck = 1; - if ( $message->recieverDeleted == 1 ) { - Debug::info( 'User has already deleted this message.' ); - return false; - } - } - if ( $message->userFrom == App::$activeUser->ID ) { - $permissionCheck = 1; - if ( $message->senderDeleted == 1 ) { - Debug::info( 'User has already deleted this message.' ); - return false; - } - } - if ( empty( $permissionCheck ) ) { - Debug::info( 'You do not have permission to view this message.' ); - return false; - } - if ( $message->parent != 0 ) { - $find = $message->parent; - } else { - $find = $message->ID; - } - $messageData = self::$db->get( $this->tableName, [ 'ID', '=', $find, 'OR', 'Parent', '=', $find ], 'ID', 'ASC' )->results(); - Components::set( 'PID', $find ); - - if ( $markRead == true ) { - foreach ( $messageData as $instance ) { - $this->markRead( $instance->ID ); - } - } - return $this->filter( $messageData ); - } - - public function getInbox( $limit = null ) { - if ( empty( $limit ) ) { - $limit = 10; - } - $limit = [ 0, $limit ]; - $messageData = self::$db->get( - $this->tableName, - [ - 'parent', '=', 0, - 'AND', - 'userFrom', '=', App::$activeUser->ID, - 'OR', - 'parent', '=', 0, - 'AND', - 'userTo', '=', App::$activeUser->ID, - ], - 'ID', - 'DESC', - $limit - ); - if ( $messageData->count() == 0 ) { - Debug::info( 'getInbox: No messages found' ); - return false; - } - $filters = [ - 'importantUser' => App::$activeUser->ID, - 'deleted' => false, - 'type' => 'userTo', - ]; - return $this->filter( $messageData->results(), $filters ); - } - - /** - * This function calls the view for the message outbox. - * - * @return null - */ - public function getOutbox( $limit = null ) { - if ( empty( $limit ) ) { - $limit = 10; - } - $limit = [ 0, $limit ]; - $messageData = self::$db->get( - $this->tableName, - [ - 'parent', '=', 0, - 'AND', - 'userFrom', '=', App::$activeUser->ID, - ], - 'ID', - 'DESC', - $limit - ); - if ( $messageData->count() == 0 ) { - Debug::info( 'getOutbox: No messages found' ); - return false; - } - $filters = [ - 'importantUser' => App::$activeUser->ID, - 'deleted' => false, - 'type' => 'userFrom', - ]; - return $this->filter( $messageData->results(), $filters ); - } - - /** - * This function is to prep our messages for display. An array of raw messages - * sent through this function will automatically have all the user ID's filter - * into actual usernames. - * - * @param $messageArray - This is an array of messages that need to be processed. - * @return array - It will return the same message array after being processed. - * @todo add filtering for BB-code. - */ - public function filter( $messageArray, $filters = [] ) { - $out = []; - foreach ( $messageArray as $message ) { - if ( !is_object( $message ) ) { - $message = $messageArray; - $end = true; - } - if ( isset( $filters['type'] ) && isset( $filters['importantUser'] ) ) { - $type = $filters['type']; - } else { - $type = null; - } - if ( isset( $filters['importantUser'] ) ) { - $user = $filters['importantUser']; - } else { - $user = App::$activeUser->ID; - } - if ( $message->parent == 0 ) { - $last = $this->getLatestMessage( $message->ID, $user, $type ); - } else { - $last = $message; - } - if ( $type != null && $message->$type != $user && $last->$type != $user ) { - continue; - } - if ( isset( $filters['deleted'] ) && $filters['deleted'] == false ) { - if ( $type == 'userFrom' ) { - if ( $last->senderDeleted == 1 ) { - continue; - } - } - if ( $type == 'userTo' ) { - if ( $last->recieverDeleted == 1 ) { - continue; - } - } - } - $messageOut = (array) $message; - $short = explode( ' ', Sanitize::contentShort( $message->message ) ); - $summary = implode( ' ', array_splice( $short, 0, 25 ) ); - if ( count( $short, 1 ) >= 25 ) { - $messageOut['summary'] = $summary . '...'; - } else { - $messageOut['summary'] = $summary; - } - if ( $last->isRead == 0 ) { - $messageOut['unreadBadge'] = Views::simpleView( 'messages.unreadBadge' ); - } else { - $messageOut['unreadBadge'] = ''; - } - $messageOut['fromAvatar'] = self::$user->getAvatar( $message->userFrom ); - $messageOut['userTo'] = self::$user->getUsername( $message->userTo ); - $messageOut['userToPretty'] = \ucfirst( $messageOut['userTo'] ); - $messageOut['userFrom'] = self::$user->getUsername( $message->userFrom ); - $messageOut['userFromPretty'] = \ucfirst( $messageOut['userFrom'] ); - $out[] = (object) $messageOut; - if ( !empty( $end ) ) { - $out = $out[0]; - break; - } - } - return $out; - } - - /** - * Function to check input and save messages to the DB. - * - * @param string $data - Username of the person receiving the sent message. - * @return function - */ - public function newThread( $to, $subject, $message ) { - if ( !self::$user->usernameExists( $to ) ) { - Debug::info( 'Message->sendMessage: User not found.' ); - return false; - } - $fields = [ - 'userTo' => self::$user->getID( $to ), - 'userFrom' => App::$activeUser->ID, - 'parent' => 0, - 'sent' => time(), - 'lastReply' => time(), - 'senderDeleted' => 0, - 'recieverDeleted' => 0, - 'isRead' => 0, - 'subject' => $subject, - 'message' => $message, - ]; - if ( !self::$db->insert( $this->tableName, $fields ) ) { - new CustomException( 'messageSend' ); - return false; - } - return true; - } - - public function getUnreadCount( $userId ) { - $result = self::$db->get( - $this->tableName, - [ - 'userTo', '=', $userId, - 'AND', - 'isRead', '=', 0, - 'AND', - 'parent', '=', 0, - 'AND', - 'recieverDeleted', '=', 0, - ] - ); - return $result->count(); - } - - public function unreadCount() { - if ( empty( App::$activeUser->ID ) ) { - return 0; - } - return $this->getUnreadCount( App::$activeUser->ID ); - } - - public function hasPermission( $id ) { - if ( !Check::id( $id ) ) { - Debug::info( 'Invalid ID' ); - return false; - } - $messageData = self::$db->get( 'messages', [ 'ID', '=', $id ] ); - if ( $messageData->count() == 0 ) { - Debug::info( 'Message not found.' ); - return false; - } - $message = $messageData->first(); - if ( $message->userTo != App::$activeUser->ID && $message->userFrom != App::$activeUser->ID ) { - return false; - } - return true; - } - - /** - * Marks a message as read. This is setup to only work - * if the message was sent to the active user. - * - * @param int - The message ID you are marking as read. - * @return bool - */ - public function markRead( $id ) { - if ( !Check::id( $id ) ) { - Debug::info( 'Invalid ID' ); - return false; - } - $result = self::$db->get( $this->tableName, [ 'ID', '=', $id, 'AND', 'userTo', '=', App::$activeUser->ID, 'AND', 'isRead', '=', '0' ] ); - if ( $result->count() == 0 ) { - Debug::info( 'Failed to mark message as read.' ); - return false; - } - if ( !self::$db->update( $this->tableName, $id, [ 'isRead' => 1 ] ) ) { - Debug::error( 'Failed to mark message as read.' ); - return false; - } - return true; - } - - public function newMessageReply( $id, $message ) { - if ( !$this->hasPermission( $id ) ) { - Debug::info( 'Permission Denied.' ); - return false; - } - $messageData = self::$db->get( $this->tableName, [ 'ID', '=', $id ] )->first(); - if ( $messageData->userTo == App::$activeUser->ID ) { - $recipient = $messageData->userFrom; - } else { - $recipient = $messageData->userTo; - } - if ( $recipient === App::$activeUser->ID ) { - Debug::info( 'Cannot send messages to yourself' ); - return false; - } - if ( !self::$db->update( $this->tableName, $messageData->ID, [ 'lastReply' => time() ] ) ) { - new CustomException( 'messagesReplyUpdate' ); - return false; - } - $fields = [ - 'senderDeleted' => 0, - 'recieverDeleted' => 0, - 'isRead' => 0, - 'userTo' => $recipient, - 'userFrom' => App::$activeUser->ID, - 'message' => $message, - 'subject' => 're: ' . $messageData->subject, - 'sent' => time(), - 'parent' => $messageData->ID, - 'lastReply' => time(), - ]; - if ( !self::$db->insert( $this->tableName, $fields ) ) { - new CustomException( 'messagesReplySend' ); - return false; - } - return true; - } - - public function messageTitle( $id ) { - if ( !$this->hasPermission( $id ) ) { - Debug::info( 'Permission Denied.' ); - return false; - } - $message = self::$db->get( $this->tableName, [ 'ID', '=', $id ] )->first(); - return $message->subject; - } - - /** - * Function to delete messages from the DB. - * - * @param int $data - The ID of the message you are trying to delete. - * @todo - done at 5 am after no sleep. This can be simplified a lot, i just wanted a working solution ASAP - * @return bool - */ - public function delete( $data ) { - if ( !is_array( $data ) ) { - $data = [ $data ]; - } - foreach ( $data as $instance ) { - if ( !Check::id( $instance ) ) { - $error = true; - } - if ( !$this->hasPermission( $instance ) ) { - Debug::info( 'Permission Denied.' ); - return false; - } - $message = self::$db->get( $this->tableName, [ 'ID', '=', $instance ] )->first(); - if ( $message->userTo == App::$activeUser->ID ) { - $fields = [ 'recieverDeleted' => '1' ]; - } else { - $fields = [ 'senderDeleted' => '1' ]; - } - if ( !self::$db->update( $this->tableName, $instance, $fields ) ) { - $error = true; - } - Debug::info( "message Deleted: $instance" ); - if ( !empty( $end ) ) { - break; - } - } - if ( !empty( $error ) ) { - Debug::info( 'There was an error deleting one or more messages.' ); - return false; - } - return true; - } -} diff --git a/app/plugins/messages/plugin.php b/app/plugins/messages/plugin.php deleted file mode 100644 index 2f70323..0000000 --- a/app/plugins/messages/plugin.php +++ /dev/null @@ -1,57 +0,0 @@ - - * @link https://TheTempusProject.com - * @license https://opensource.org/licenses/MIT [MIT LICENSE] - */ -namespace TheTempusProject\Plugins; - -use TheTempusProject\TheTempusProject as App; -use TheTempusProject\Classes\Plugin; -use TheTempusProject\Models\Message; -use TheTempusProject\Houdini\Classes\Components; -use TheTempusProject\Houdini\Classes\Views; - -class Messages extends Plugin { - public $pluginName = 'TP Messages'; - 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 messaging system.'; - public $permissionMatrix = [ - 'sendMessages' => [ - 'pretty' => 'Can send Messages', - 'default' => false, - ], - ]; - private static $loaded = false; - - public function __construct() { - if ( ! self::$loaded ) { - $messages = new Message; - Components::set( 'MESSAGE_COUNT', $messages->unreadCount() ); - if ( $messages->unreadCount() > 0 ) { - $messageBadge = Views::simpleView( 'messages.badge' ); - } else { - $messageBadge = ''; - } - Components::set( 'MBADGE', $messageBadge ); - if ( App::$isLoggedIn ) { - Components::set( 'RECENT_MESSAGES', Views::simpleView( 'messages.nav.recentMessagesDropdown', $messages->getInbox( 5 ) ) ); - } else { - Components::set( 'RECENT_MESSAGES', '' ); - } - App::$topNavRight .= '{RECENT_MESSAGES}'; - App::$topNavRightDropdown .= '
{subject}
-- You can now log in and manage your site or jump straight into building your new features! -
- -- Some plugins may need additional configuration and there are already some pre-made resources to get you started. (Both in the files and the Admin Panel) -
- -All models are required for proper installation of The Tempus Project. In this step, we will add the database tables required for these models. In the next step, you'll be able to select which plugins you would like installed.
- -- The Tempus Project was built to utilize all of the plugins provided with the installer. You can choose not to enable any one of them, but it may negatively impact the operation of your site. -
- -- Some models such as groups will need additional database resources and configurations to function properly. In this step, we will install those features. -
- -The Tempus Project uses rewrites in htaccess files (Apache), or location directives (Nginx), to automatically route all incoming traffic through the app. In this step, we will help set-up and then test that the required configurations have been made.
-In this step, we will attempt to generate the appropriate files for Apache servers.
-If you are using Nginx, you will need to update your server's configuration manually. Please see the documentation, for convenience, an example configuration has been provided with TheTempusProject and can be found in the app/resources directory.
- -- This installer will guide you through the process of installing and configuring The Tempus Project. Do not forget to delete this file once you have completed installation. -
- -- {SITENAME} has been open source for many years now. The hopes and intentions for it were always to give others a leg-up to get started building web-apps like i wish i had as a kid. - There were so many tutorials and ideas, expansions and plans for the project. - Unfortunately no person is given unlimited time to accomplish their dreams and over the years the idea for a huge repository for learning and education has taken a back seat. -
-- At this time, the best recommendation available is to contact us for more information. - The site here is actively maintained so feel free to utilize any of our available resources for contact. - In addition to the site here, you can contact the lead developer (me) directly through JoeyKimsey.com. -
-- Right now, this entire system was built and managed by myself. As stated, I have used my own version of this for years, but translating it to a publicly available product is not a 1-to-1 job. There may be bugs or issues encountered while you use the product. I can't guarantee a fix for every need in every case immediately, but I do actively keep track of bugs and work hard to ensure everyone has a great experience using the app. -
-- If you encounter any bugs, feel free to report them here. Likewise, there are forms for feedback, reviews, suggestions, and a general contact form. Thanks for taking the time to check out the product! -
-