Initial commit

This commit is contained in:
Joey Kimsey
2024-08-04 21:15:59 -04:00
parent c9d1fb983f
commit 0d469501ee
695 changed files with 70184 additions and 71 deletions

View File

@ -0,0 +1,82 @@
<?php
/**
* app/plugins/notifications/controllers/admin/notifications.php
*
* This is the notifications admin controller.
*
* @package TP Notifications
* @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\Notification as NotificationsModel;
use TheTempusProject\Models\Group;
use TheTempusProject\Models\User;
use TheTempusProject\Houdini\Classes\Forms;
use TheTempusProject\Classes\Forms as FormChecker;
class Notifications extends AdminController {
protected static $notifications;
public static $user;
public static $group;
public function __construct() {
parent::__construct();
self::$title = 'Admin - Notifications';
self::$notifications = new NotificationsModel;
self::$user = new User;
self::$group = new Group;
$view = Navigation::activePageSelect( 'nav.admin', '/admin/Notifications' );
Components::set( 'ADMINNAV', $view );
}
public function index( $data = null ) {
// this is just a simple form to allow admins to send notifications
return $this->create();
}
public function create() {
$select = Forms::getFormFieldHtml( 'groupSelect', 'User Group', 'select', 'All', self::$group->listGroupsSimple( true ) );
Components::set( 'groupSelect', $select );
if ( ! Input::exists( 'submit' ) ) {
return Views::view( 'notifications.admin.send' );
}
if ( ! FormChecker::check( 'createNotification' ) ) {
Issues::add( 'error', [ 'There was an error with your request.' => Check::userErrors() ] );
return Views::view( 'notifications.admin.send' );
}
if ( Input::exists( 'expires' ) ) {
$expiresAt = time() + intval( Input::post( 'expires' ) );
} else {
$expiresAt = 0;
}
if ( Input::exists( 'groupSelect' ) && Input::post( 'groupSelect' ) != 0 && Input::post( 'groupSelect' ) != 'all' ) {
$list = self::$group->listMembers( Input::post( 'groupSelect' ) );
} else {
$list = self::$user->userList();
}
$results = [];
foreach ( $list as $recipient ) {
$results[] = self::$notifications->create( Input::post( 'notification' ), 'Admin Issued', $recipient->ID, $expiresAt );
}
// $result = self::$notifications->create( Input::post( 'notification' ), 'Admin Issued', XXXXXXX_user_idsXXXXXX, $expiresAt );
if ( ! empty( $results ) ) {
Issues::add( 'success', 'Your notification has been sent.' );
} else {
Issues::add( 'error', [ 'There was an unknown error submitting your data.' => Check::userErrors() ] );
}
Views::view( 'notifications.admin.send' );
}
}

View File

@ -0,0 +1,73 @@
<?php
/**
* app/plugins/notifications/controllers/notifications.php
*
* This is the home controller for the notifications plugin.
*
* @package TP Notifications
* @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\Houdini\Classes\Views;
use TheTempusProject\Houdini\Classes\Issues;
use TheTempusProject\Classes\Controller;
use TheTempusProject\Models\Notification as NotificationsModel;
use TheTempusProject\TheTempusProject as App;
class Notifications extends Controller {
protected static $notifications;
public function __construct() {
parent::__construct();
self::$notifications = new NotificationsModel;
self::$title = 'Notifications - {SITENAME}';
self::$pageDescription = 'Your recent notifications';
}
public function index() {
$notifications = self::$notifications->getByUser( 10 );
Views::view( 'notifications.list', $notifications );
}
public function markRead( $id = null ) {
$notification = self::$notifications->findById( $id );
if ( $notification == false ) {
Issues::add( 'error', 'Notification not found.' );
return $this->index();
}
if ( $notification->userID != App::$activeUser->ID ) {
Issues::add( 'error', 'You do not have permission to modify this notification.' );
return $this->index();
}
$result = self::$notifications->markSeen( $id );
if ( $result == true ) {
Issues::add( 'success', 'Notification marked as read.' );
} else {
Issues::add( 'notice', 'There was an problem updating your notification.' );
}
return $this->index();
}
public function delete( $id = null ) {
$notification = self::$notifications->findById( $id );
if ( $notification == false ) {
Issues::add( 'error', 'Notification not found.' );
return $this->index();
}
if ( $notification->userID != App::$activeUser->ID ) {
Issues::add( 'error', 'You do not have permission to modify this notification.' );
return $this->index();
}
$result = self::$notifications->delete( $id );
if ( $result == true ) {
Issues::add( 'success', 'Notification deleted.' );
} else {
Issues::add( 'notice', 'There was an problem deleting your notification.' );
}
return $this->index();
}
}

View File

@ -0,0 +1,41 @@
<?php
/**
* app/plugins/notifications/forms.php
*
* This houses all of the form checking functions for this plugin.
*
* @package TP Notifications
* @version 3.0
* @author Joey Kimsey <Joey@thetempusproject.com>
* @link https://TheTempusProject.com
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
*/
namespace TheTempusProject\Plugins\Feedback;
use TheTempusProject\Bedrock\Functions\Input;
use TheTempusProject\Bedrock\Functions\Check;
use TheTempusProject\Classes\Forms;
class NotificationForms extends Forms {
/**
* Adds these functions to the form list.
*/
public function __construct() {
self::addHandler( 'createNotification', __CLASS__, 'createNotification' );
}
/**
* Validates the createNotification form.
*
* @return {bool}
*/
public static function createNotification() {
if ( ! Input::exists( 'notification' ) ) {
Check::addUserError( 'You must provide a notification.' );
return false;
}
return true;
}
}
new NotificationForms;

View File

@ -0,0 +1,157 @@
<?php
/**
* app/plugins/feedback/models/feedback.php
*
* This class is used for the manipulation of the feedback database table.
*
* @todo make this send a confirmation email
*
* @package TP Feedback
* @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\Plugins\Feedback as Plugin;
use TheTempusProject\TheTempusProject as App;
use TheTempusProject\Houdini\Classes\Views;
use TheTempusProject\Bedrock\Classes\CustomException;
class Notification extends DatabaseModel {
public $tableName = 'notifications';
public $databaseMatrix = [
[ 'notification', 'text', '' ],
[ 'origin', 'varchar', '128' ],
[ 'userID', 'int', '11' ],
[ 'createdAt', 'int', '11' ],
[ 'expiresAt', 'int', '11' ],
[ 'deletedAt', 'int', '11' ],
[ 'seenAt', 'int', '11' ],
];
public $plugin;
/**
* The model constructor.
*/
public function __construct() {
parent::__construct();
$this->plugin = new Plugin;
}
public function getUnreadCount( $userID ) {
$result = self::$db->get(
$this->tableName,
[
'userID', '=', $userID,
'AND',
'deletedAt', '=', '0',
'AND',
'seenAt', '=', '0',
'AND',
'expiresAt', '<', time(),
]
);
return $result->count();
}
public function create( $notification, $origin, $userID, $expiresAt = '0', $deletedAt = '0', $seenAt = '0' ) {
$fields = [
'notification' => $notification,
'origin' => $origin,
'userID' => $userID,
'createdAt' => time(),
'expiresAt' => $expiresAt,
'deletedAt' => $deletedAt,
'seenAt' => $seenAt,
];
if ( !self::$db->insert( $this->tableName, $fields ) ) {
Debug::info( 'Events::create - failed to insert to db' );
return false;
}
return self::$db->lastId();
}
public function getByUser( $limit = 0 ) {
$whereClause = [
'userID', '=', App::$activeUser->ID,
'AND',
'deletedAt', '=', '0',
'AND',
'expiresAt', '<', time(),
];
if ( empty( $limit ) ) {
$notifications = self::$db->get( $this->tableName, $whereClause );
} else {
$notifications = self::$db->get( $this->tableName, $whereClause, 'ID', 'DESC', [0, $limit] );
}
if ( !$notifications->count() ) {
Debug::info( 'No Notifications found.' );
return false;
}
return $this->filter( $notifications->results() );
}
public function markSeen( $id ) {
if ( !Check::id( $id ) ) {
Debug::info( 'Notifications: illegal ID.' );
return false;
}
$fields = [
'seenAt' => time(),
];
$notification = self::findById( $id );
if ( ! $notification ) {
Debug::error( "Notifications: $id not updated" );
return false;
}
if ( !self::$db->update( $this->tableName, $id, $fields ) ) {
new CustomException( 'notificationUpdate' );
Debug::error( "Notifications: $id not updated" );
return false;
}
return true;
}
public function delete( $id ) {
if ( !Check::id( $id ) ) {
Debug::info( 'Notifications: illegal ID.' );
return false;
}
$fields = [
'deletedAt' => time(),
];
if ( !self::$db->update( $this->tableName, $id, $fields ) ) {
new CustomException( 'notificationDelete' );
Debug::error( "Bookmarks: $id not updated" );
return false;
}
return true;
}
public function filter( $messageArray, $filters = [] ) {
$out = [];
foreach ( $messageArray as $message ) {
if ( !is_object( $message ) ) {
$message = $messageArray;
$end = true;
}
if ( $message->seenAt == 0 ) {
$message->unseenBadge = Views::simpleView( 'notifications.unseenBadge' );
} else {
$message->unseenBadge = '';
}
$out[] = (object) $message;
if ( !empty( $end ) ) {
$out = $out[0];
break;
}
}
return $out;
}
}

View File

@ -0,0 +1,65 @@
<?php
/**
* app/plugins/notifications/plugin.php
*
* This houses all of the main plugin info and functionality.
*
* @package TP Notifications
* @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\TheTempusProject as App;
use TheTempusProject\Classes\Plugin;
use TheTempusProject\Models\Notification;
use TheTempusProject\Houdini\Classes\Components;
use TheTempusProject\Houdini\Classes\Views;
class Notifications extends Plugin {
public $pluginName = 'TP Notifications';
public $configName = 'notifications';
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 notification system.';
public $permissionMatrix = [
'sendNotifications' => [
'pretty' => 'Can send notifications',
'default' => false,
],
];
public $admin_links = [
[
'text' => '<i class="glyphicon glyphicon-bell"></i> Notify',
'url' => '{ROOT_URL}admin/notifications',
],
];
private static $loaded = false;
public function __construct( $load = false ) {
parent::__construct( $load );
if ( $this->checkEnabled() && App::$isLoggedIn ) {
$notifications = new Notification;
Components::set( 'notificationCount', $notifications->getUnreadCount( App::$activeUser->ID ) );
if ( $notifications->getUnreadCount( App::$activeUser->ID ) > 0 ) {
$messageBadge = Views::simpleView( 'notifications.badge' );
} else {
$messageBadge = '';
}
Components::set( 'NBADGE', $messageBadge );
if ( App::$isLoggedIn ) {
Components::set( 'recentNotifications', Views::simpleView( 'notifications.nav.recentNotificationsDropdown', $notifications->getByUser( 10 ) ) );
} else {
Components::set( 'recentNotifications', '' );
}
if ( ! self::$loaded ) {
App::$topNavRight .= '{recentNotifications}';
App::$topNavRightDropdown .= '<li><a href="{ROOT_URL}notifications"><i class="glyphicon glyphicon-bell"></i> Notifications {NBADGE}</a></li>';
self::$loaded = true;
}
}
}
}

View File

@ -0,0 +1,44 @@
<form action="" method="post" class="form-horizontal" enctype="multipart/form-data">
<legend>Send Notification</legend>
<div class="form-group">
{groupSelect}
</div>
<div class="form-group">
<label for="expiration" class="col-lg-3 control-label">Expiration </label>
<div class="col-lg-3">
<select id="expiration" name="expiration" class="form-control custom-select">
<option value="0">forever</option>
<option value="1800">30 Minutes</option>
<option value="3600">60 Minutes</option>
<option value="14400">4 hours</option>
<option value="28800">8 hours</option>
<option value="43200">12 hours</option>
<option value="86400">24 hours</option>
<option value="172800">2 days</option>
<option value="259200">3 days</option>
<option value="432000">5 days</option>
<option value="604800">7 days</option>
<option value="1209600">2 weeks</option>
<option value="1814400">3 weeks</option>
<option value="2419200">4 weeks</option>
<option value="2592000">1 month</option>
<option value="5184000">2 months</option>
<option value="7776000">3 months</option>
<option value="15552000">6 months</option>
<option value="31536000">12 months</option>
</select>
</div>
</div>
<div class="form-group">
<label for="notification" class="col-lg-3 control-label">Notification</label>
<div class="col-lg-6">
<textarea class="form-control" name="notification" maxlength="2000" rows="10" cols="50" id="notification"></textarea>
</div>
</div>
<div class="form-group">
<div class="col-lg-6 col-lg-offset-3">
<button name="submit" value="publish" type="submit" class="btn btn-lg btn-primary">Send</button>
</div>
</div>
<input type="hidden" name="token" value="{TOKEN}">
</form>

View File

@ -0,0 +1 @@
<span class="label label-danger">{notificationCount}</span>

View File

@ -0,0 +1,31 @@
{PAGINATION}
<div class="row" style="margin-top: 30px; margin-bottom: 50px;">
<form action="" method="post">
<table class="table">
<thead>
<tr>
<th style="width: 90%">Notification</th>
<th style="width: 5%"></th>
<th style="width: 5%"></th>
</tr>
</thead>
<tbody>
{LOOP}
<tr {unseenBadge}>
<td>{notification}</td>
<td><a href="{ROOT_URL}notifications/markRead/{ID}" class="btn btn-sm btn-primary" role="button"><i class="glyphicon glyphicon-open"></i></a></td>
<td><a href="{ROOT_URL}notifications/delete/{ID}" class="btn btn-sm btn-danger" role="button"><i class="glyphicon glyphicon-trash"></i></a></td>
</tr>
{/LOOP}
{ALT}
<tr>
<td colspan="7">
No Notifications
</td>
</tr>
{/ALT}
</tbody>
</table>
</form>
</div>
{PAGINATION}

View File

@ -0,0 +1,29 @@
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown"><i class="glyphicon glyphicon-bell"></i>{NBADGE}</a>
<ul class="dropdown-menu message-dropdown">
{LOOP}
<li class="message-preview">
<a href="{ROOT_URL}notifications">
<div class="media">
<div class="media-body">
<p class="small text-muted"><i class="fa fa-clock-o"></i> {DTC}{createdAt}{/DTC}</p>
{notification}
</div>
</div>
</a>
</li>
{/LOOP}
{ALT}
<li class="message-preview">
<div class="media">
<div class="media-body text-center" style="padding-bottom: 10px; padding-top: 10px">
<h5 class="media-heading"><strong>No Notifications</strong></h5>
</div>
</div>
</li>
{/ALT}
<li class="message-footer text-center">
<a href="{ROOT_URL}notifications">See All Notifications</a>
</li>
</ul>
</li>

View File

@ -0,0 +1 @@
class="bg-info"