Initial commit
This commit is contained in:
34
app/classes/admin_controller.php
Normal file
34
app/classes/admin_controller.php
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
/**
|
||||
* app/classes/admin_controller.php
|
||||
*
|
||||
* This is the base admin controller. Every other admin controller should
|
||||
* extend this class.
|
||||
*
|
||||
* @version 3.0
|
||||
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||
* @link https://TheTempusProject.com
|
||||
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||
*/
|
||||
namespace TheTempusProject\Classes;
|
||||
|
||||
use TheTempusProject\Houdini\Classes\Template;
|
||||
use TheTempusProject\Houdini\Classes\Filters;
|
||||
use TheTempusProject\Houdini\Classes\Issues;
|
||||
use TheTempusProject\TheTempusProject as App;
|
||||
use TheTempusProject\Hermes\Functions\Redirect;
|
||||
use TheTempusProject\Bedrock\Functions\Session;
|
||||
|
||||
class AdminController extends Controller {
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
if ( !App::$isAdmin ) {
|
||||
Session::flash( 'error', 'You do not have permission to view this page.' );
|
||||
return Redirect::home();
|
||||
}
|
||||
Template::noFollow();
|
||||
Template::noIndex();
|
||||
Template::setTemplate( 'admin' );
|
||||
Filters::add( 'logMenu', '#<ul id="log-menu" class="collapse">#is', '<ul id="log-menu" class="">', true );
|
||||
}
|
||||
}
|
32
app/classes/api_controller.php
Normal file
32
app/classes/api_controller.php
Normal file
@ -0,0 +1,32 @@
|
||||
<?php
|
||||
/**
|
||||
* app/classes/admin_controller.php
|
||||
*
|
||||
* This is the base admin controller. Every other admin controller should
|
||||
* extend this class.
|
||||
*
|
||||
* @version 3.0
|
||||
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||
* @link https://TheTempusProject.com
|
||||
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||
*/
|
||||
namespace TheTempusProject\Classes;
|
||||
|
||||
use TheTempusProject\Houdini\Classes\Template;
|
||||
use TheTempusProject\TheTempusProject as App;
|
||||
use TheTempusProject\Hermes\Functions\Redirect;
|
||||
use TheTempusProject\Bedrock\Functions\Session;
|
||||
|
||||
class ApiController extends Controller {
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
if ( ! App::verifyApiRequest() ) {
|
||||
Session::flash( 'error', 'You do not have permission to view this page.' );
|
||||
return Redirect::home();
|
||||
}
|
||||
Template::noFollow();
|
||||
Template::noIndex();
|
||||
Template::addHeader( 'Content-Type: application/json; charset=utf-8' );
|
||||
Template::setTemplate( 'api' );
|
||||
}
|
||||
}
|
71
app/classes/config.php
Normal file
71
app/classes/config.php
Normal file
@ -0,0 +1,71 @@
|
||||
<?php
|
||||
/**
|
||||
* classes/config.php
|
||||
*
|
||||
* This class handles all the hard-coded configurations.
|
||||
*
|
||||
* @version 3.0
|
||||
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||
* @link https://TheTempusProject.com/Core
|
||||
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||
*/
|
||||
namespace TheTempusProject\Classes;
|
||||
|
||||
use TheTempusProject\Houdini\Classes\Forms;
|
||||
use TheTempusProject\Canary\Canary as Debug;
|
||||
use TheTempusProject\Bedrock\Functions\Check;
|
||||
use TheTempusProject\Bedrock\Functions\Input;
|
||||
use TheTempusProject\Bedrock\Classes\Config as BedrockConfig;
|
||||
|
||||
class Config extends BedrockConfig {
|
||||
public static function getFieldEditHtml( $name, $includeProtected = false ) {
|
||||
// @todo: includeProtected is unused here
|
||||
$node = self::get( $name );
|
||||
if ( empty( $node ) ) {
|
||||
return;
|
||||
}
|
||||
if ( true === $node['protected'] ) {
|
||||
return;
|
||||
}
|
||||
$fieldname = str_ireplace( '/', '-', $name );
|
||||
$html = Forms::getFormFieldHtml(
|
||||
$fieldname,
|
||||
$node['pretty'],
|
||||
$node['type'],
|
||||
$node['value'],
|
||||
);
|
||||
return $html;
|
||||
}
|
||||
|
||||
public static function getCategoryEditHtml( $category ) {
|
||||
$html = '';
|
||||
if ( self::$config === false ) {
|
||||
Debug::warn( 'Config not loaded.' );
|
||||
return;
|
||||
}
|
||||
if ( empty( self::$config[$category] ) ) {
|
||||
Debug::warn( "Config category not found: $category" );
|
||||
return;
|
||||
}
|
||||
$categoryHeader = '<div class="form-group"><label>' . ucfirst( $category ) . ':</label><hr></div>';
|
||||
foreach ( self::$config[$category] as $field => $node ) {
|
||||
$html .= self::getFieldEditHtml( $category . '/' . $field );
|
||||
}
|
||||
if ( !empty( $html ) ) {
|
||||
$html = $categoryHeader . $html;
|
||||
}
|
||||
return $html;
|
||||
}
|
||||
|
||||
public static function getEditHtml() {
|
||||
if ( self::$config === false ) {
|
||||
Debug::warn( 'Config not loaded.' );
|
||||
return;
|
||||
}
|
||||
$html = '';
|
||||
foreach ( self::$config as $category => $fields ) {
|
||||
$html .= self::getCategoryEditHtml( $category );
|
||||
}
|
||||
return $html;
|
||||
}
|
||||
}
|
41
app/classes/controller.php
Normal file
41
app/classes/controller.php
Normal file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
/**
|
||||
* app/classes/controller.php
|
||||
*
|
||||
* This is the main controller class.
|
||||
*
|
||||
* @version 3.0
|
||||
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||
* @link https://TheTempusProject.com
|
||||
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||
*/
|
||||
namespace TheTempusProject\Classes;
|
||||
|
||||
use TheTempusProject\Bedrock\Classes\Controller as BedrockController;
|
||||
use TheTempusProject\Houdini\Classes\Template;
|
||||
use TheTempusProject\Houdini\Classes\Pagination;
|
||||
use TheTempusProject\TheTempusProject as App;
|
||||
use TheTempusProject\Models\User;
|
||||
use TheTempusProject\Models\Sessions;
|
||||
|
||||
class Controller extends BedrockController {
|
||||
public static $user;
|
||||
public static $session;
|
||||
public static $pagination;
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
self::$session = new Sessions;
|
||||
self::$user = new User;
|
||||
self::$pagination = Pagination::generate();
|
||||
if ( ! empty( App::$activePrefs ) ) {
|
||||
self::$pagination::updatePrefs( App::$activePrefs['pageLimit'] );
|
||||
}
|
||||
new Template;
|
||||
Template::setTemplate( 'default' );
|
||||
}
|
||||
|
||||
public function __destruct() {
|
||||
parent::__destruct();
|
||||
}
|
||||
}
|
145
app/classes/database_model.php
Normal file
145
app/classes/database_model.php
Normal file
@ -0,0 +1,145 @@
|
||||
<?php
|
||||
/**
|
||||
* app/classes/database_model.php
|
||||
*
|
||||
* This is the main TempusProject database model.
|
||||
*
|
||||
* @version 3.0
|
||||
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||
* @link https://TheTempusProject.com
|
||||
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||
*/
|
||||
namespace TheTempusProject\Classes;
|
||||
|
||||
use TheTempusProject\Bedrock\Classes\DatabaseModel as BedrockDatabaseModel;
|
||||
use TheTempusProject\Bedrock\Functions\Check;
|
||||
use TheTempusProject\Canary\Canary as Debug;
|
||||
use TheTempusProject\Models\Log;
|
||||
|
||||
class DatabaseModel extends BedrockDatabaseModel {
|
||||
public $preferenceMatrix;
|
||||
public $permissionMatrix;
|
||||
public static $installFlags = MODEL_INSTALL_FLAGS;
|
||||
protected static $user;
|
||||
protected static $log;
|
||||
protected static $group;
|
||||
protected static $session;
|
||||
protected static $message;
|
||||
protected static $routes;
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function uninstall() {
|
||||
Debug::log( 'Uninstalling Model: ' . get_class($this) );
|
||||
|
||||
parent::uninstall();
|
||||
$this->uninstallPreferences();
|
||||
$this->uninstallPermissions();
|
||||
return true;
|
||||
}
|
||||
|
||||
public function installPreferences() {
|
||||
if ( empty( $this->preferenceMatrix ) ) {
|
||||
Debug::log( 'preferenceMatrix is empty' );
|
||||
return true;
|
||||
}
|
||||
$prefs = new Preferences();
|
||||
foreach ( $this->preferenceMatrix as $name => $details ) {
|
||||
$prefs->add( $name, $details );
|
||||
}
|
||||
return $prefs->save( true );
|
||||
}
|
||||
|
||||
public function uninstallPreferences() {
|
||||
if ( empty( $this->preferenceMatrix ) ) {
|
||||
Debug::log( 'preferenceMatrix is empty' );
|
||||
return true;
|
||||
}
|
||||
$prefs = new Preferences();
|
||||
foreach ( $this->preferenceMatrix as $name => $details ) {
|
||||
$prefs->remove( $name, true );
|
||||
}
|
||||
}
|
||||
|
||||
public function installPermissions() {
|
||||
if ( empty( $this->permissionMatrix ) ) {
|
||||
Debug::log( 'permissionMatrix is empty' );
|
||||
return true;
|
||||
}
|
||||
$perms = new Permissions();
|
||||
foreach ( $this->permissionMatrix as $name => $details ) {
|
||||
$perms->add( $name, $details );
|
||||
}
|
||||
return $perms->save( true );
|
||||
}
|
||||
|
||||
public function uninstallPermissions() {
|
||||
$perms = new Permissions();
|
||||
if ( empty( $this->permissionMatrix ) ) {
|
||||
Debug::log( 'permissionMatrix is empty' );
|
||||
return true;
|
||||
}
|
||||
foreach ( $this->permissionMatrix as $name => $details ) {
|
||||
$perms->remove( $name, true );
|
||||
}
|
||||
}
|
||||
|
||||
public function delete( $idArray ) {
|
||||
if ( empty( self::$log ) ) {
|
||||
self::$log = new Log;
|
||||
}
|
||||
if ( !is_array( $idArray ) ) {
|
||||
$idArray = [ $idArray ];
|
||||
}
|
||||
foreach ( $idArray as $id ) {
|
||||
if ( !Check::id( $id ) ) {
|
||||
Debug::info( "invalid ID: $id." );
|
||||
$error = true;
|
||||
continue;
|
||||
}
|
||||
$result = parent::delete( $id );
|
||||
if ( true !== $result ) {
|
||||
Debug::info( ucfirst( $this->tableName ) . " did not delete properly: $id" );
|
||||
$error = true;
|
||||
continue;
|
||||
}
|
||||
self::$log->admin( 'Deleted ' . ucfirst( $this->tableName ) . ": $id" );
|
||||
Debug::info( ucfirst( $this->tableName ) . " successfully deleted: $id" );
|
||||
}
|
||||
if ( !empty( $error ) ) {
|
||||
Debug::error( 'One or more rows were not deleted.' );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function install( $options ) {
|
||||
Debug::log( 'Installing Database Model');
|
||||
$module_data = [];
|
||||
$errors = [];
|
||||
foreach ( self::$installFlags as $flag_name ) {
|
||||
if ( empty( $options[$flag_name] ) ) {
|
||||
$module_data[ $flag_name ] = INSTALL_STATUS_SKIPPED;
|
||||
continue;
|
||||
}
|
||||
|
||||
$result = $this->$flag_name();
|
||||
|
||||
if ( empty( $result ) ) {
|
||||
$errors[] = ['errorInfo' => get_class($this) . " Failed to execute $flag_name properly."];
|
||||
$module_data[ $flag_name ] = INSTALL_STATUS_FAIL;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( 'installResources' === $flag_name ) {
|
||||
$module_data['installedResources'] = $result;
|
||||
}
|
||||
|
||||
$module_data[ $flag_name ] = INSTALL_STATUS_SUCCESS;
|
||||
continue;
|
||||
}
|
||||
return [ $module_data, $errors ];
|
||||
}
|
||||
}
|
212
app/classes/email.php
Normal file
212
app/classes/email.php
Normal file
@ -0,0 +1,212 @@
|
||||
<?php
|
||||
/**
|
||||
* app/classes/email.php
|
||||
*
|
||||
* This is our class for constructing and sending various kinds of emails.
|
||||
*
|
||||
* @version 3.0
|
||||
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||
* @link https://TheTempusProject.com
|
||||
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||
*/
|
||||
namespace TheTempusProject\Classes;
|
||||
|
||||
use TheTempusProject\Houdini\Classes\Template;
|
||||
use TheTempusProject\Houdini\Classes\Views;
|
||||
use TheTempusProject\Hermes\Functions\Route as Routes;
|
||||
use TheTempusProject\Canary\Canary as Debug;
|
||||
|
||||
class Email {
|
||||
private static $header = null;
|
||||
private static $subject = null;
|
||||
private static $title = null;
|
||||
private static $message = null;
|
||||
private static $unsub = false;
|
||||
private static $useTemplate = false;
|
||||
private static $footer = null;
|
||||
private static $debug = false;
|
||||
|
||||
/**
|
||||
* Sends pre-constructed email templates. Useful for modifying the
|
||||
* entire theme or layout of the system generated emails.
|
||||
*
|
||||
* @param string $email - The email you are sending to.
|
||||
* @param string $type - The template you wish to send.
|
||||
* @param string|array $params - Any special parameters that may be required from your individual email template.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function send( $email, $type, $params = null, $flags = null ) {
|
||||
if ( !empty( $flags ) ) {
|
||||
if ( is_array( $flags ) ) {
|
||||
foreach ( $flags as $key => $value ) {
|
||||
switch ( $key ) {
|
||||
case 'template':
|
||||
if ( $value == true ) {
|
||||
self::$useTemplate = true;
|
||||
}
|
||||
break;
|
||||
case 'unsubscribe':
|
||||
if ( $value == true ) {
|
||||
self::$unsub = true;
|
||||
}
|
||||
break;
|
||||
case 'debug':
|
||||
if ( $value == true ) {
|
||||
self::$debug = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
self::build();
|
||||
switch ( $type ) {
|
||||
case 'debug':
|
||||
self::$subject = 'Please Confirm your email at {SITENAME}';
|
||||
self::$title = 'Almost Done';
|
||||
self::$message = 'Please click or copy-paste this link to confirm your registration: <a href="{BASE}register/confirm/{PARAMS}">Confirm Your Email</a>';
|
||||
break;
|
||||
|
||||
case 'confirmation':
|
||||
self::$subject = 'Please Confirm your email at {SITENAME}';
|
||||
self::$title = 'Almost Done';
|
||||
self::$message = 'Please click or copy-paste this link to confirm your registration: <a href="{BASE}register/confirm/{PARAMS}">Confirm Your Email</a>';
|
||||
break;
|
||||
|
||||
case 'install':
|
||||
self::$subject = 'Notification from {SITENAME}';
|
||||
self::$title = 'Installation Success';
|
||||
self::$message = 'This is just a simple email to notify you that you have successfully installed The Tempus Project framework!';
|
||||
break;
|
||||
|
||||
case 'passwordChange':
|
||||
self::$subject = 'Security Notice from {SITENAME}';
|
||||
self::$title = 'Password Successfully Changed';
|
||||
self::$message = 'Recently your password on {SITENAME} was changed. If you are the one who changed the password, please ignore this email.';
|
||||
break;
|
||||
|
||||
case 'emailChangeNotice':
|
||||
self::$subject = 'Account Update from {SITENAME}';
|
||||
self::$title = 'Email Updated';
|
||||
self::$message = 'This is a simple notification to let you know your email has been changed at {SITENAME}.';
|
||||
break;
|
||||
|
||||
case 'emailChange':
|
||||
self::$subject = 'Account Update from {SITENAME}';
|
||||
self::$title = 'Confirm your E-mail';
|
||||
self::$message = 'Please click or copy-paste this link to confirm your new Email: <a href="{BASE}register/confirm/{PARAMS}">Confirm Your Email</a>';
|
||||
break;
|
||||
|
||||
case 'emailNotify':
|
||||
self::$subject = 'Account Update from {SITENAME}';
|
||||
self::$title = 'Email Updated';
|
||||
self::$message = 'You recently changed your email address on {SITENAME}.';
|
||||
break;
|
||||
|
||||
case 'forgotPassword':
|
||||
self::$subject = 'Reset Instructions for {SITENAME}';
|
||||
self::$title = 'Reset your Password';
|
||||
self::$message = 'You recently requested information to change your password at {SITENAME}.<br>Your password reset code is: {PARAMS}<br> Please click or copy-paste this link to reset your password: <a href="{BASE}register/reset/{PARAMS}">Password Reset</a>';
|
||||
break;
|
||||
|
||||
case 'forgotUsername':
|
||||
self::$subject = 'Account Update from {SITENAME}';
|
||||
self::$title = 'Account Details';
|
||||
self::$message = 'Your username for {SITENAME} is {PARAMS}.';
|
||||
break;
|
||||
|
||||
case 'subscribe':
|
||||
self::$subject = 'Thanks for Subscribing';
|
||||
self::$title = 'Thanks for Subscribing!';
|
||||
self::$message = 'Thank you for subscribing to updates from {SITENAME}. If you no longer wish to receive these emails, you can un-subscribe using the link below.';
|
||||
self::$unsub = true;
|
||||
break;
|
||||
|
||||
case 'unsubInstructions':
|
||||
self::$subject = 'Unsubscribe Instructions';
|
||||
self::$title = 'We are sad to see you go';
|
||||
self::$message = 'If you would like to be un-subscribed from future emails from {SITENAME} simply click the link below.<br><br><a href="{BASE}home/unsubscribe/{EMAIL}/{PARAMS}">Click here to unsubscribe</a>';
|
||||
self::$unsub = true;
|
||||
break;
|
||||
|
||||
case 'unsubscribe':
|
||||
self::$subject = 'Unsubscribed';
|
||||
self::$title = 'We are sad to see you go';
|
||||
self::$message = 'This is just a notification that you have successfully been unsubscribed from future emails from {SITENAME}.';
|
||||
break;
|
||||
|
||||
case 'contact':
|
||||
self::$subject = $params['subject'];
|
||||
self::$title = $params['title'];
|
||||
self::$message = $params['message'];
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
if ( self::$useTemplate ) {
|
||||
$data = new \stdClass();
|
||||
if ( self::$unsub ) {
|
||||
$data->UNSUB = Views::simpleView( 'email.unsubscribe' );
|
||||
} else {
|
||||
$data->UNSUB = '';
|
||||
}
|
||||
$data->LOGO = Config::getValue( 'main/logo' );
|
||||
$data->SITENAME = Config::getValue( 'main/name' );
|
||||
$data->EMAIL = $email;
|
||||
if ( !is_array( $params ) ) {
|
||||
$data->PARAMS = $params;
|
||||
} else {
|
||||
foreach ( $params as $key => $value ) {
|
||||
$data->$key = $value;
|
||||
}
|
||||
}
|
||||
$data->MAIL_FOOT = Views::simpleView( 'email.foot' );
|
||||
$data->MAIL_TITLE = self::$title;
|
||||
$data->MAIL_BODY = Template::parse( self::$message, $data );
|
||||
$subject = Template::parse( self::$subject, $data );
|
||||
$body = Views::simpleView( 'email.template', $data );
|
||||
} else {
|
||||
$subject = self::$subject;
|
||||
$body = '<h1>' . self::$title . '</h1>' . self::$message;
|
||||
}
|
||||
if ( is_object( $email ) ) {
|
||||
foreach ( $email as $data ) {
|
||||
if ( !@mail( $data->email, $subject, $body, self::$header ) ) {
|
||||
Debug::error( 'Failed to send email. Subject: ' . $subject . ' Email: ' . $data->email );
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ( !@mail( $email, $subject, $body, self::$header ) ) {
|
||||
Debug::error( 'Failed to send email. Subject: ' . $subject . ' Email: ' . $email );
|
||||
}
|
||||
}
|
||||
Debug::info( "Email sent: $type." );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor for the header.
|
||||
*/
|
||||
public static function build() {
|
||||
if ( !self::$header ) {
|
||||
self::$header = 'From: ' . Config::getValue( 'main/name' ) . ' <noreply@' . $_SERVER['HTTP_HOST'] . ">\r\n";
|
||||
self::$header .= "MIME-Version: 1.0\r\n";
|
||||
self::$header .= "Content-Type: text/html; charset=ISO-8859-1\r\n";
|
||||
$url = parse_url( Routes::getAddress(), PHP_URL_HOST );
|
||||
$parts = explode( '.', $url );
|
||||
$count = count( $parts );
|
||||
if ( $count > 2 ) {
|
||||
$host = $parts[ $count - 2 ] . '.' . $parts[ $count - 1 ];
|
||||
} else {
|
||||
$host = $url;
|
||||
}
|
||||
if ( self::$debug ) {
|
||||
self::$header .= "CC: webmaster@localhost.com\r\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
77
app/classes/forms.php
Normal file
77
app/classes/forms.php
Normal file
@ -0,0 +1,77 @@
|
||||
<?php
|
||||
/**
|
||||
* app/classes/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\Classes;
|
||||
|
||||
use TheTempusProject\Bedrock\Functions\Check;
|
||||
use TheTempusProject\Canary\Canary as Debug;
|
||||
|
||||
class Forms extends Check {
|
||||
private static $formHandlers = [];
|
||||
|
||||
public static function check( $formName ) {
|
||||
if ( empty( self::$formHandlers[ $formName ] ) ) {
|
||||
Debug::error( "Form not found: $formName" );
|
||||
return false;
|
||||
}
|
||||
$handler = self::$formHandlers[ $formName ];
|
||||
return call_user_func_array( [ $handler['class'], $handler['method'] ], $handler['params'] );
|
||||
}
|
||||
|
||||
public static function addHandler( $formName, $class, $method, $params = [] ) {
|
||||
if ( !empty( self::$formHandlers[ $formName ] ) ) {
|
||||
return false;
|
||||
}
|
||||
self::$formHandlers[$formName] = [
|
||||
'class' => $class,
|
||||
'method' => $method,
|
||||
'params' => $params,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks username formatting.
|
||||
*
|
||||
* Requirements:
|
||||
* - 4 - 16 characters long
|
||||
* - must only contain numbers and letters: [A - Z] , [a - z], [0 - 9]
|
||||
*
|
||||
* @param string $data - The string being tested.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public static function checkUsername( $data ) {
|
||||
if ( strlen( $data ) > 16 ) {
|
||||
self::addError( 'Username must be be 4 to 16 numbers or letters.', $data );
|
||||
return false;
|
||||
}
|
||||
if ( strlen( $data ) < 4 ) {
|
||||
self::addError( 'Username must be be 4 to 16 numbers or letters.', $data );
|
||||
return false;
|
||||
}
|
||||
if ( !ctype_alnum( $data ) ) {
|
||||
self::addError( 'Username must be be 4 to 16 numbers or letters.', $data );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static function date( $data ) {
|
||||
if ( strtotime( $data ) == false ) {
|
||||
self::addError( 'Username must be be 4 to 16 numbers or letters.', $data );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
640
app/classes/installer.php
Normal file
640
app/classes/installer.php
Normal file
@ -0,0 +1,640 @@
|
||||
<?php
|
||||
/**
|
||||
* app/classes/installer.php
|
||||
*
|
||||
* This class is used for the installation, regulation, tracking, and updating of
|
||||
* the application. It handles installing the application, installing and updating
|
||||
* models as well as the database, and generating and checking the htaccess file.
|
||||
*
|
||||
* @version 3.0
|
||||
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||
* @link https://TheTempusProject.com
|
||||
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||
*/
|
||||
namespace TheTempusProject\Classes;
|
||||
|
||||
use TheTempusProject\Bedrock\Functions\Check;
|
||||
use TheTempusProject\Bedrock\Functions\Code;
|
||||
use TheTempusProject\Bedrock\Functions\Cookie;
|
||||
use TheTempusProject\Canary\Canary as Debug;
|
||||
use TheTempusProject\Hermes\Functions\Redirect;
|
||||
use TheTempusProject\Hermes\Functions\Route as Routes;
|
||||
use TheTempusProject\Bedrock\Functions\Session;
|
||||
use TheTempusProject\Classes\DatabaseModel;
|
||||
use TheTempusProject\Classes\Plugin;
|
||||
|
||||
class Installer {
|
||||
const MATRIX_MAP = [
|
||||
'installPreferences' => 'preferenceMatrix',
|
||||
'installPermissions' => 'permissionMatrix',
|
||||
'installConfigs' => 'configMatrix',
|
||||
'installTable' => 'databaseMatrix',
|
||||
'installResources' => 'resourceMatrix',
|
||||
];
|
||||
|
||||
private $override = false;
|
||||
private $status = null;
|
||||
private static $installJson = null;
|
||||
private static $errors = [];
|
||||
|
||||
public function __construct() {
|
||||
Debug::log( 'Installer initialized.' );
|
||||
if ( self::$installJson === null ) {
|
||||
self::$installJson = self::getJson();
|
||||
}
|
||||
}
|
||||
|
||||
public function getComposerJson() {
|
||||
if ( !file_exists( COMPOSER_JSON_LOCATION ) ) {
|
||||
Debug::error( 'No install json found.' );
|
||||
return false;
|
||||
}
|
||||
return json_decode( file_get_contents( COMPOSER_JSON_LOCATION ), true );
|
||||
}
|
||||
|
||||
public function getComposerLock() {
|
||||
if ( !file_exists( COMPOSER_LOCK_LOCATION ) ) {
|
||||
Debug::error( 'No install json found.' );
|
||||
return false;
|
||||
}
|
||||
return json_decode( file_get_contents( COMPOSER_LOCK_LOCATION ), true );
|
||||
}
|
||||
|
||||
public static function emptyModule( $type, $folder, $filename = '' ) {
|
||||
switch ( $type ) {
|
||||
case 'model':
|
||||
if ( empty( $filename ) ) {
|
||||
$class = '';
|
||||
$class_name = '';
|
||||
break;
|
||||
}
|
||||
$class = convertFileNameToModelClass( $filename );
|
||||
$class_name = convertFileNameToClassName( $filename );
|
||||
break;
|
||||
case 'plugin':
|
||||
if ( empty( $folder ) ) {
|
||||
$class = '';
|
||||
$class_name = '';
|
||||
break;
|
||||
}
|
||||
$class = convertFileNameToPluginClass( $folder );
|
||||
$class_name = convertFolderToClassName( $folder );
|
||||
break;
|
||||
}
|
||||
if ( empty( $folder ) ) {
|
||||
$folder = '';
|
||||
}
|
||||
$object = (object) [
|
||||
'name' => $class_name,
|
||||
'class' => $class,
|
||||
'version' => '0.0',
|
||||
'installedVersion' => '',
|
||||
'folder' => $folder,
|
||||
'type' => $type,
|
||||
'installDate' => '',
|
||||
'lastUpdate' => '',
|
||||
'installStatus' => INSTALL_STATUS_NOT_INSTALLED,
|
||||
'enabled' => false,
|
||||
'enabled_txt' => 'no',
|
||||
];
|
||||
return $object;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function automatically attempts to install all models in the
|
||||
* specified directory.
|
||||
* NOTE: The 'Models/ folder is used by default.
|
||||
*
|
||||
* @param string $directory - The directory you wish to install all
|
||||
* models from.
|
||||
* @return boolean
|
||||
*/
|
||||
public function getErrors( $array = true ) {
|
||||
if ( $array ) {
|
||||
$out = [];
|
||||
foreach (self::$errors as $error) {
|
||||
if ( ! is_array($error) ) {
|
||||
exit(var_export($error,true));
|
||||
}
|
||||
$out[] = $error['errorInfo'];
|
||||
}
|
||||
} else {
|
||||
$out = self::$errors;
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
|
||||
private static function getJson() {
|
||||
if ( file_exists( INSTALL_JSON_LOCATION ) ) {
|
||||
$content = file_get_contents( INSTALL_JSON_LOCATION );
|
||||
$json = json_decode( $content, true );
|
||||
} else {
|
||||
touch( INSTALL_JSON_LOCATION );
|
||||
$json = [];
|
||||
}
|
||||
return $json;
|
||||
}
|
||||
|
||||
public static function saveJson() {
|
||||
$encodedJson = json_encode( self::$installJson );
|
||||
if ( !file_exists( INSTALL_JSON_LOCATION ) ) {
|
||||
$content = file_get_contents( $location );
|
||||
$json = json_decode( $content, true );
|
||||
$fh = fopen( INSTALL_JSON_LOCATION, 'w' );
|
||||
}
|
||||
$writeSuccess = file_put_contents( INSTALL_JSON_LOCATION, $encodedJson );
|
||||
if ( $writeSuccess ) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getModule( $name ) {
|
||||
$name = ucfirst( $name );
|
||||
if ( isset( self::$installJson['modules'][$name] ) ) {
|
||||
if ( isset( self::$installJson['modules'][$name]['enabled'] ) ) {
|
||||
if ( self::$installJson['modules'][$name]['enabled'] == true ) {
|
||||
self::$installJson['modules'][$name]['enabled_txt'] = '<span class="text-success">Yes</span>';
|
||||
} else {
|
||||
self::$installJson['modules'][$name]['enabled_txt'] = '<span class="text-danger">No</span>';
|
||||
}
|
||||
}
|
||||
return self::$installJson['modules'][$name];
|
||||
}
|
||||
Debug::info( "install module not found: $name" );
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getModules( $includeObjects ) {
|
||||
if ( isset( self::$installJson['modules'] ) ) {
|
||||
if ( empty( $includeObjects ) ) {
|
||||
return self::$installJson['modules'];
|
||||
} else {
|
||||
$data = self::$installJson['modules'];
|
||||
foreach ( $data as $name => $module) {
|
||||
$class_object = new $module['class'];
|
||||
$data[$name]['class_object'] = $class_object;
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
}
|
||||
Debug::error( "install modules not found" );
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getNode( $name) {
|
||||
if ( isset( self::$installJson[$name] ) ) {
|
||||
return self::$installJson[$name];
|
||||
}
|
||||
}
|
||||
|
||||
public function setNode( $name, $value, $save = false ) {
|
||||
self::$installJson[$name] = $value;
|
||||
if ( $save !== false ) {
|
||||
return self::saveJson();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function setModule( $name, $value, $save = false ) {
|
||||
if ( !isset( self::$installJson['modules'] ) ) {
|
||||
self::$installJson['modules'] = [];
|
||||
}
|
||||
self::$installJson['modules'][$name] = $value;
|
||||
if ( $save !== false ) {
|
||||
return self::saveJson();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private function removeModule( $name, $save = false ) {
|
||||
if ( !isset( self::$installJson['modules'] ) ) {
|
||||
Debug::error( 'No modules installed' );
|
||||
return false;
|
||||
}
|
||||
if ( !isset( self::$installJson['modules'][$name] ) ) {
|
||||
Debug::error( 'Module not installed' );
|
||||
return false;
|
||||
}
|
||||
self::$installJson['modules'][$name] = null;
|
||||
if ( $save !== false ) {
|
||||
return self::saveJson();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function findModelFlags( $classObject ) {
|
||||
$install_flags = [];
|
||||
foreach ( self::MATRIX_MAP as $install_flag => $matrix_name ) {
|
||||
if ( !empty( $classObject->$matrix_name ) ) {
|
||||
$install_flags[$install_flag] = true;
|
||||
} else {
|
||||
$install_flags[$install_flag] = false;
|
||||
}
|
||||
}
|
||||
return $install_flags;
|
||||
}
|
||||
|
||||
public function getPluginInfo( $folder) {
|
||||
$object = self::emptyModule( 'plugin', $folder );
|
||||
|
||||
$location = $folder . 'plugin.php';
|
||||
if ( file_exists( $location ) ) {
|
||||
include_once $location;
|
||||
} else {
|
||||
self::$errors[] = ['errorInfo' => "Could not find the requested plugin file: $location"];
|
||||
return $object;
|
||||
}
|
||||
|
||||
if ( ! class_exists( $object->class ) ) {
|
||||
Debug::warn( 'Cannot get plugin version from class: ' . $object->class . ', class does NOT exist.');
|
||||
return $object;
|
||||
}
|
||||
|
||||
$class_object = new $object->class;
|
||||
$object->version = $class_object->pluginVersion;
|
||||
|
||||
$module = $class_object->module;
|
||||
|
||||
if ( false !== $module ) {
|
||||
$objectArray = (array) $object;
|
||||
$object = (object) array_replace( $objectArray, $module );
|
||||
}
|
||||
$object->class_object = $class_object;
|
||||
|
||||
return $object;
|
||||
}
|
||||
|
||||
public function getModelInfo( $filename, $folder = '' ) {
|
||||
$object = self::emptyModule( 'model', $folder, $filename );
|
||||
|
||||
if ( ! class_exists( $object->class ) ) {
|
||||
Debug::warn( 'Cannot get model version from class: ' . $object->class . ', class does NOT exist.');
|
||||
return $object;
|
||||
}
|
||||
|
||||
$class_object = new $object->class;
|
||||
$object->version = $class_object->modelVersion;
|
||||
|
||||
$module = $this->getModule( $object->name );
|
||||
if ( false !== $module ) {
|
||||
$objectArray = (array) $object;
|
||||
$object = (object) array_replace( $objectArray, $module );
|
||||
}
|
||||
$object->class_object = $class_object;
|
||||
|
||||
return $object;
|
||||
}
|
||||
|
||||
public function getAvailablePlugins() {
|
||||
$plugins = Plugin::getPluginDirectories();
|
||||
$list = [];
|
||||
foreach ( $plugins as $pluginName => $locations ) {
|
||||
foreach ( $locations as $location ) {
|
||||
foreach ( $location as $currentFolder => $file ) {
|
||||
if ( 'plugin.php' == $file ) {
|
||||
$list[ $pluginName ] = $this->getPluginInfo( str_ireplace( 'plugin.php', '', $currentFolder ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return $list;
|
||||
}
|
||||
|
||||
public function getModelList( $folder ) {
|
||||
$files = scandir( $folder );
|
||||
$models = [];
|
||||
|
||||
array_shift( $files );
|
||||
array_shift( $files );
|
||||
|
||||
foreach ( $files as $index => $filename ) {
|
||||
if ( stripos( $filename, '.php' ) ) {
|
||||
$list[] = $this->getModelInfo( $filename, $folder );
|
||||
}
|
||||
}
|
||||
return $list;
|
||||
}
|
||||
|
||||
public function installPlugin( $module_data, $flags = [], $defaultFlagValue = true ) {
|
||||
Debug::log( 'Installing Plugin: ' . $module_data->name );
|
||||
$errors = [];
|
||||
|
||||
if ( INSTALL_STATUS_INSTALLED === $module_data->installStatus ) {
|
||||
Debug::warn( "$name has already been successfully installed" );
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( empty( $module_data->class_object ) ) {
|
||||
self::$errors[] = [ 'errorInfo' => 'Class not found: ' . $module_data->class ];
|
||||
return false;
|
||||
}
|
||||
|
||||
// normalize install flags
|
||||
foreach ( PLUGIN_INSTALL_FLAGS as $flag_type ) {
|
||||
// add any missing flags
|
||||
if ( ! isset( $flags[ $flag_type ] ) ) {
|
||||
$flags[ $flag_type ] = $defaultFlagValue;
|
||||
}
|
||||
|
||||
// exclude any flags that have already been successfully installed
|
||||
if ( !empty( $module_data->$flag_type ) && $module_data->$flag_type == INSTALL_STATUS_SUCCESS ) {
|
||||
Debug::warn( "$flag_type has already been successfully executed" );
|
||||
$flags[ $flag_type ] = false;
|
||||
}
|
||||
}
|
||||
|
||||
list( $install_data, $errors ) = $module_data->class_object->install( $flags );
|
||||
$objectArray = (array) $module_data;
|
||||
$module_data = array_replace( $objectArray, $install_data );
|
||||
$module_data['installedVersion'] = $module_data['version'];
|
||||
$module_data['lastUpdate'] = time();
|
||||
|
||||
if ( empty( $module_data['installDate'] ) ) {
|
||||
$module_data['installDate'] = time();
|
||||
}
|
||||
|
||||
unset($module_data['class_object']); // we don't want the class object though
|
||||
$this->setModule( $module_data['name'], $module_data, true );
|
||||
$this->updateInstallStatus( $module_data['name'] );
|
||||
|
||||
if ( !empty( $errors ) ) {
|
||||
self::$errors = array_merge( self::$errors, $errors );
|
||||
return false;
|
||||
}
|
||||
|
||||
$errors[] = [ 'errorInfo' => $module_data['name'] . " has been installed." ];
|
||||
self::$errors = array_merge( self::$errors, $errors );
|
||||
return true;
|
||||
}
|
||||
|
||||
public function uninstallPlugin( $module_data, $flags = [], $defaultFlagValue = true ) {
|
||||
Debug::log( 'Uninstalling Plugin: ' . $module_data->name );
|
||||
$errors = [];
|
||||
|
||||
if ( empty( $module_data->class_object ) ) {
|
||||
self::$errors[] = [ 'errorInfo' => 'Class not found: ' . $module_data->class ];
|
||||
return false;
|
||||
}
|
||||
|
||||
// normalize install flags
|
||||
foreach ( PLUGIN_INSTALL_FLAGS as $flag_type ) {
|
||||
// add any missing flags
|
||||
if ( ! isset( $flags[ $flag_type ] ) ) {
|
||||
$flags[ $flag_type ] = $defaultFlagValue;
|
||||
}
|
||||
}
|
||||
|
||||
$errors = $module_data->class_object->uninstall( $flags );
|
||||
|
||||
if ( !empty( $errors ) ) {
|
||||
self::$errors = array_merge( self::$errors, $errors );
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->removeModule( $module_data->name, true );
|
||||
$errors[] = [ 'errorInfo' => $module_data->name . " has been installed." ];
|
||||
self::$errors = array_merge( self::$errors, $errors );
|
||||
return true;
|
||||
}
|
||||
|
||||
public function installModel( $module_data, $flags = [], $defaultFlagValue = true, $updateModule = true ) {
|
||||
Debug::log( 'Installing Model: ' . $module_data->name );
|
||||
$errors = [];
|
||||
|
||||
if ( INSTALL_STATUS_INSTALLED === $module_data->installStatus ) {
|
||||
Debug::warn( "$module_data->name has already been successfully installed" );
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( empty( $module_data->class_object ) ) {
|
||||
self::$errors[] = [ 'errorInfo' => 'Class not found: ' . $module_data->class ];
|
||||
return false;
|
||||
}
|
||||
|
||||
// normalize install flags
|
||||
$model_flags = $this->findModelFlags( $module_data->class_object );
|
||||
foreach ( MODEL_INSTALL_FLAGS as $flag_type ) {
|
||||
// add any missing flags
|
||||
if ( ! isset( $flags[ $flag_type ] ) ) {
|
||||
$flags[ $flag_type ] = $defaultFlagValue;
|
||||
}
|
||||
|
||||
// exclude any flags that have already been successfully installed
|
||||
if ( !empty( $module_data->$flag_type ) && $module_data->$flag_type == INSTALL_STATUS_SUCCESS ) {
|
||||
Debug::warn( "$flag_type has already been successfully installed" );
|
||||
$flags[ $flag_type ] = false;
|
||||
}
|
||||
|
||||
if ( $flags[ $flag_type ] === true ) {
|
||||
// exclude any flags we can't do anything with
|
||||
if ( ! isset( $model_flags[ $flag_type ] ) ) {
|
||||
Debug::warn( "$flag_type cannot be installed due to installFlags on the model." );
|
||||
$flags[ $flag_type ] = false;
|
||||
}
|
||||
|
||||
// check to make sure we have the proper mapping
|
||||
$matrix = self::MATRIX_MAP[ $flag_type ];
|
||||
|
||||
// exclude any flags we don't have a matric map for
|
||||
if ( empty( $module_data->class_object->$matrix ) ) {
|
||||
Debug::warn( "$flag_type does not have a proper matrix map and cannot be installed." );
|
||||
$module_data->$flag_type = INSTALL_STATUS_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
list( $install_data, $errors ) = $module_data->class_object->install( $flags );
|
||||
$objectArray = (array) $module_data;
|
||||
$module_data = array_replace( $objectArray, $install_data );
|
||||
$module_data['installedVersion'] = $module_data['version'];
|
||||
$module_data['lastUpdate'] = time();
|
||||
|
||||
if ( empty( $module_data['installDate'] ) ) {
|
||||
$module_data['installDate'] = time();
|
||||
}
|
||||
|
||||
if ($updateModule) {
|
||||
unset($module_data['class_object']); // we don't want the class object though
|
||||
$this->setModule( $module_data['name'], $module_data, true );
|
||||
$this->updateInstallStatus( $module_data['name'] );
|
||||
}
|
||||
|
||||
if ( !empty( $errors ) ) {
|
||||
self::$errors = array_merge( self::$errors, $errors );
|
||||
return false;
|
||||
}
|
||||
|
||||
$errors[] = [ 'errorInfo' => $module_data['name'] . " has been installed." ];
|
||||
self::$errors = array_merge( self::$errors, $errors );
|
||||
return true;
|
||||
}
|
||||
|
||||
public function uninstallModel( $module_data, $flags = [], $defaultFlagValue = true, $updateModule = true ) {
|
||||
Debug::log( 'Uninstalling Model: ' . $module_data->name );
|
||||
$errors = [];
|
||||
|
||||
if ( empty( $module_data->class_object ) ) {
|
||||
self::$errors[] = [ 'errorInfo' => 'Class not found: ' . $module_data->class ];
|
||||
return false;
|
||||
}
|
||||
|
||||
// normalize install flags
|
||||
$model_flags = $this->findModelFlags( $module_data->class_object );
|
||||
foreach ( MODEL_INSTALL_FLAGS as $flag_type ) {
|
||||
// add any missing flags
|
||||
if ( ! isset( $flags[ $flag_type ] ) ) {
|
||||
$flags[ $flag_type ] = $defaultFlagValue;
|
||||
}
|
||||
|
||||
if ( $flags[ $flag_type ] === true ) {
|
||||
// exclude any flags we can't do anything with
|
||||
if ( ! isset( $model_flags[ $flag_type ] ) ) {
|
||||
Debug::warn( "$flag_type cannot be installed due to installFlags on the model." );
|
||||
$flags[ $flag_type ] = false;
|
||||
}
|
||||
|
||||
// check to make sure we have the proper mapping
|
||||
$matrix = self::MATRIX_MAP[ $flag_type ];
|
||||
|
||||
// exclude any flags we don't have a matric map for
|
||||
if ( empty( $module_data->class_object->$matrix ) ) {
|
||||
Debug::warn( "$flag_type does not have a proper matrix map and cannot be installed." );
|
||||
$module_data->$flag_type = INSTALL_STATUS_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
list( $install_data, $errors ) = $module_data->class_object->uninstall( $flags );
|
||||
|
||||
if ( !empty( $errors ) ) {
|
||||
self::$errors = array_merge( self::$errors, $errors );
|
||||
return false;
|
||||
}
|
||||
|
||||
$errors[] = [ 'errorInfo' => $module_data->name . " has been uninstalled." ];
|
||||
self::$errors = array_merge( self::$errors, $errors );
|
||||
return true;
|
||||
}
|
||||
|
||||
private function updateInstallStatus( $name ) {
|
||||
$modelInfo = $this->getModule( $name );
|
||||
if ( $modelInfo === false ) {
|
||||
return;
|
||||
}
|
||||
if ( $modelInfo['type'] == 'plugin' ) {
|
||||
$flags = PLUGIN_INSTALL_FLAGS;
|
||||
} else {
|
||||
$flags = MODEL_INSTALL_FLAGS;
|
||||
}
|
||||
|
||||
foreach ( $flags as $flag_type ) {
|
||||
if ( ! in_array( $modelInfo[ $flag_type ], [ INSTALL_STATUS_SUCCESS, INSTALL_STATUS_NOT_REQUIRED ] ) ) {
|
||||
$modelInfo['installStatus'] = INSTALL_STATUS_PARTIALLY_INSTALLED;
|
||||
break;
|
||||
}
|
||||
$modelInfo['installStatus'] = INSTALL_STATUS_INSTALLED;
|
||||
}
|
||||
$this->setModule( $name, $modelInfo, true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the root directory for a .htaccess file and compares it with
|
||||
* the .htaccess file the application generates by default.
|
||||
*
|
||||
* NOTE: The $override flag will cause this function to automatically generate a
|
||||
* new htaccess file if the .htaccess found in the root directory does not match
|
||||
* the default generated version.
|
||||
*
|
||||
* @param boolean $create - Optional flag to generate and save a new htaccess
|
||||
* if none is found.
|
||||
*
|
||||
* @return boolean - Returns true if the htaccess file was found or
|
||||
* created, false otherwise.
|
||||
*/
|
||||
public function saveHtaccess( $text = false ) {
|
||||
if ( false === $text ) {
|
||||
$text = $this->generateHtaccess();
|
||||
}
|
||||
if ( file_exists( HTACCESS_LOCATION ) ) {
|
||||
Debug::error( "Can't overwrite existing htaccess file" );
|
||||
return false;
|
||||
}
|
||||
return file_put_contents( HTACCESS_LOCATION, $text );
|
||||
}
|
||||
|
||||
public function checkHtaccess( $create = false ) {
|
||||
$check = 0;
|
||||
$findRewrite1 = "RewriteEngine On\n";
|
||||
$findRewrite2 = 'RewriteBase ' . Routes::getRoot() . "\n\n";
|
||||
if ( file_exists( HTACCESS_LOCATION ) ) {
|
||||
$htaccess = file_get_contents( HTACCESS_LOCATION );
|
||||
if ( $htaccess === $this->generateHtaccess() ) {
|
||||
return true;
|
||||
}
|
||||
if ( stripos( $htaccess, $findRewrite1 ) ) {
|
||||
$check++;
|
||||
}
|
||||
if ( stripos( $htaccess, $findRewrite2 ) ) {
|
||||
$check++;
|
||||
}
|
||||
if ( $check === 2 ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function baseHtaccess() {
|
||||
$out = "# Intercepts for images not found
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteRule ^images/(.*)$ index.php?error=image404&url=$1 [L,NC,QSA]
|
||||
|
||||
# Intercepts for uploads not found
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteRule ^uploads/(.*)$ index.php?error=upload404&url=$1 [L,NC,QSA]
|
||||
|
||||
# Intercepts other errors
|
||||
RewriteRule ^errors/(.*)$ index.php?error=$1 [L,NC,QSA]
|
||||
|
||||
# Intercept all traffic not originating locally and not going to images or uploads
|
||||
RewriteCond %{REMOTE_ADDR} !^127\.0\.0\.1
|
||||
RewriteCond %{REMOTE_ADDR} !^\:\:1
|
||||
RewriteCond %{REQUEST_URI} !^(.*)/images/(.*)$ [NC]
|
||||
RewriteCond %{REQUEST_URI} !^(.*)/uploads/(.*)$ [NC]
|
||||
RewriteCond %{REQUEST_URI} !^(.*).js$ [NC]
|
||||
RewriteCond %{REQUEST_URI} !^(.*).css$ [NC]
|
||||
RewriteCond %{REQUEST_URI} !^(.*).ico$ [NC]
|
||||
RewriteRule ^(.+)$ index.php?url=$1 [QSA,L]
|
||||
|
||||
# Catchall for any non existent files or folders
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteRule ^(.+)$ index.php?url=$1 [QSA,L]";
|
||||
return str_ireplace( ' ', '', $out );
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the default htaccess file for the application. This will funnel
|
||||
* all traffic that comes into the application directory to index.php where we
|
||||
* use that data to construct the desired page using the controller.
|
||||
*
|
||||
* @param string $docroot - A custom document root to use instead of the default.
|
||||
*
|
||||
* @return string - The generated contents of the htaccess file.
|
||||
*/
|
||||
protected function generateHtaccess( $docroot = null, $rewrite = true ) {
|
||||
$out = '';
|
||||
if ( empty( $docroot ) ) {
|
||||
$docroot = Routes::getRoot();
|
||||
}
|
||||
if ( $rewrite === true ) {
|
||||
$out .= "RewriteEngine On\n\n";
|
||||
}
|
||||
$out .= "RewriteBase $docroot\n\n";
|
||||
$out .= $this->baseHtaccess();
|
||||
return $out;
|
||||
}
|
||||
}
|
244
app/classes/permissions.php
Normal file
244
app/classes/permissions.php
Normal file
@ -0,0 +1,244 @@
|
||||
<?php
|
||||
/**
|
||||
* app/classes/permissions.php
|
||||
*
|
||||
* This class handles all the hard-coded permissions.
|
||||
*
|
||||
* @version 3.0
|
||||
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||
* @link https://TheTempusProject.com
|
||||
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||
*/
|
||||
namespace TheTempusProject\Classes;
|
||||
|
||||
use TheTempusProject\Canary\Canary as Debug;
|
||||
use TheTempusProject\Bedrock\Functions\Check;
|
||||
use TheTempusProject\Houdini\Classes\Forms;
|
||||
use TheTempusProject\Bedrock\Functions\Input;
|
||||
|
||||
class Permissions {
|
||||
public static $permissions = false;
|
||||
private static $location = false;
|
||||
private static $initialized = false;
|
||||
|
||||
/**
|
||||
* Default constructor which will attempt to load the permissions from the location specified.
|
||||
*
|
||||
* @param {string} [$location]
|
||||
* @return {null|object}
|
||||
*/
|
||||
public function __construct( $location = '' ) {
|
||||
if ( self::$initialized !== false ) {
|
||||
Debug::log( 'Permissions already initialized.' );
|
||||
return $this;
|
||||
}
|
||||
if ( empty( $location ) ) {
|
||||
$location = PERMISSIONS_JSON;
|
||||
}
|
||||
self::$initialized = $this->load( $location );
|
||||
if ( self::$initialized !== false ) {
|
||||
Debug::log( 'Permissions initialization succeeded.' );
|
||||
return $this;
|
||||
}
|
||||
Debug::warn( 'Permissions initialization failed.' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to retrieve then set the configuration from a file.
|
||||
* @note This function will reset the permissions every time it is used.
|
||||
*
|
||||
* @param {string} [$location]
|
||||
* @return {bool}
|
||||
*/
|
||||
public function load( $location ) {
|
||||
self::$permissions = $this->getPermsFile( $location );
|
||||
self::$location = $location;
|
||||
if ( self::$permissions === false || empty( self::$permissions ) ) {
|
||||
Debug::warn( 'Permissions load failed.' );
|
||||
return false;
|
||||
}
|
||||
Debug::log( 'Permissions load succeeded.' );
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens and decodes the permissions json from the location provided.
|
||||
*
|
||||
* @param {string} [$location]
|
||||
* @return {bool|array}
|
||||
*/
|
||||
public function getPermsFile( $location ) {
|
||||
if ( file_exists( $location ) ) {
|
||||
Debug::debug( "Permissions json found: $location" );
|
||||
return json_decode( file_get_contents( $location ), true );
|
||||
} else {
|
||||
Debug::warn( "Permissions json not found: $location" );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the permissions option for $name.
|
||||
*
|
||||
* @param {string} [$name]
|
||||
* @return {WILD}
|
||||
*/
|
||||
public function get( $name ) {
|
||||
if ( self::$permissions === false ) {
|
||||
Debug::warn( 'Permissions not loaded.' );
|
||||
return;
|
||||
}
|
||||
if ( isset( self::$permissions[$name] ) ) {
|
||||
return self::$permissions[$name];
|
||||
}
|
||||
Debug::warn( "Permission not found: $name" );
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the current permissions.
|
||||
*
|
||||
* @param {bool} [$default] - Whether or not to save a default copy.
|
||||
* @return {bool}
|
||||
*/
|
||||
public function save( $save_backup = true ) {
|
||||
if ( self::$permissions === false ) {
|
||||
Debug::warn( 'Permissions not loaded.' );
|
||||
return false;
|
||||
}
|
||||
if ( self::$location === false ) {
|
||||
Debug::warn( 'Permissions location not set.' );
|
||||
return false;
|
||||
}
|
||||
if ( $save_backup ) {
|
||||
$locationArray = explode( '.', self::$location );
|
||||
$locationArray[] = 'bak';
|
||||
$backupLoction = implode( '.', $locationArray );
|
||||
if ( !file_put_contents( $backupLoction, json_encode( self::$permissions ) ) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ( file_put_contents( self::$location, json_encode( self::$permissions ) ) ) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new permission to the $permissions array.
|
||||
*
|
||||
* @param {string} [$name]
|
||||
* @param {string} [$value]
|
||||
* @return {bool}
|
||||
*/
|
||||
public function add( $permName, $details ) {
|
||||
if ( !Check::simpleName( $permName ) ) {
|
||||
Debug::error( "Permission name invalid: $permName" );
|
||||
return false;
|
||||
}
|
||||
if ( isset( self::$permissions[$permName] ) ) {
|
||||
Debug::warn( "Permission already exists: $permName" );
|
||||
return false;
|
||||
}
|
||||
if ( self::$permissions === false ) {
|
||||
self::$permissions = [];
|
||||
}
|
||||
self::$permissions[$permName] = $details;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds many new permissions to the $permissions array.
|
||||
*
|
||||
* @param {array} [$data]
|
||||
* @return {bool}
|
||||
*/
|
||||
public function addMany( $data ) {
|
||||
if ( !is_array( $data ) ) {
|
||||
Debug::error( 'Permissions must be an array.' );
|
||||
return false;
|
||||
}
|
||||
foreach ( $data as $name => $value ) {
|
||||
$this->add( $name, $value );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an existing permission from the $permissions array.
|
||||
*
|
||||
* @param {string} [$name]
|
||||
* @param {string} [$save]
|
||||
* @return {bool}
|
||||
*/
|
||||
public function remove( $name, $save = false ) {
|
||||
if ( self::$permissions === false ) {
|
||||
Debug::warn( 'Permissions not loaded.' );
|
||||
return false;
|
||||
}
|
||||
if ( !isset( self::$permissions[$name] ) ) {
|
||||
Debug::error( "Permission does not exist: $name" );
|
||||
return false;
|
||||
}
|
||||
unset( self::$permissions[$name] );
|
||||
if ( $save === true ) {
|
||||
return $this->save();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getDefaultPermissionsArray() {
|
||||
if ( self::$permissions === false ) {
|
||||
Debug::warn( 'Permissions not loaded.' );
|
||||
return false;
|
||||
}
|
||||
$permsArray = [];
|
||||
foreach ( self::$permissions as $name => $details ) {
|
||||
$permsArray[$name] = $details['default'];
|
||||
}
|
||||
return $permsArray;
|
||||
}
|
||||
|
||||
public function convertFormToArray() {
|
||||
$permsArray = [];
|
||||
foreach ( self::$permissions as $name => $details ) {
|
||||
if ( Input::exists( $name ) ) {
|
||||
$permsArray[$name] = true;
|
||||
} else {
|
||||
$permsArray[$name] = false;
|
||||
}
|
||||
}
|
||||
return $permsArray;
|
||||
}
|
||||
|
||||
public function getDefault( $name ) {
|
||||
$perm = $this->get( $name );
|
||||
if ( empty( $perm ) || empty( $perm['default'] ) ) {
|
||||
Debug::warn( "Permission Default not found: $name" );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public function getPrettyName( $name ) {
|
||||
$pref = $this->get( $name );
|
||||
if ( empty( $pref ) || empty( $pref['pretty'] ) ) {
|
||||
Debug::warn( "Permission Pretty Name not found: $name" );
|
||||
return;
|
||||
}
|
||||
return $pref['pretty'];
|
||||
}
|
||||
|
||||
public function getFormHtml( $populated = [] ) {
|
||||
$form = '';
|
||||
foreach ( self::$permissions as $name => $details ) {
|
||||
if ( isset( $populated[$name] ) && $populated[$name] !== false ) {
|
||||
$checked = true;
|
||||
} else {
|
||||
$checked = false;
|
||||
}
|
||||
$form .= Forms::getFormFieldHtml( $name, $details['pretty'], 'checkbox', $checked );
|
||||
}
|
||||
return $form;
|
||||
}
|
||||
}
|
493
app/classes/plugin.php
Normal file
493
app/classes/plugin.php
Normal file
@ -0,0 +1,493 @@
|
||||
<?php
|
||||
/**
|
||||
* app/classes/plugin.php
|
||||
*
|
||||
* This class is used as a foundation for all plugins to build from.
|
||||
*
|
||||
* @version 3.0
|
||||
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||
* @link https://TheTempusProject.com
|
||||
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||
*/
|
||||
namespace TheTempusProject\Classes;
|
||||
|
||||
use TheTempusProject\Houdini\Classes\Navigation;
|
||||
use TheTempusProject\Houdini\Classes\Filters;
|
||||
use TheTempusProject\TheTempusProject as App;
|
||||
use TheTempusProject\Canary\Canary as Debug;
|
||||
use TheTempusProject\Bedrock\Classes\Database;
|
||||
|
||||
class Plugin {
|
||||
public $required_models = [];
|
||||
public $models = [];
|
||||
public $errors = [];
|
||||
|
||||
// Global Properties
|
||||
public $module;
|
||||
public $initialized = false;
|
||||
public static $installer;
|
||||
public static $db;
|
||||
public static $installFlags = PLUGIN_INSTALL_FLAGS;
|
||||
public static $pluginFolders = [];
|
||||
public static $pluginsAvailable = [];
|
||||
public static $pluginsActive = [];
|
||||
|
||||
// Basic Required Info
|
||||
public $pluginName = 'Default Plugin Name';
|
||||
public $pluginAuthor = 'TheTempusProject';
|
||||
public $pluginWebsite = 'https://TheTempusProject.com';
|
||||
public $pluginVersion = 0.0;
|
||||
public $pluginDescription = 'The Default Plugin Description';
|
||||
|
||||
// Front-end Properties
|
||||
public $admin_links = [];
|
||||
public $main_links = [];
|
||||
public $footer_links = [];
|
||||
public $filters = [];
|
||||
|
||||
// Install Related
|
||||
public $configName = '';
|
||||
public $configMatrix = [];
|
||||
public $resourceMatrix = [];
|
||||
public $preferenceMatrix = [];
|
||||
public $permissionMatrix = [];
|
||||
|
||||
const PLUGIN_FLAG_MAP = [
|
||||
'preferences_installed' => 'installPreferences',
|
||||
'permissions_installed' => 'installPermissions',
|
||||
'configs_installed' => 'installConfigs',
|
||||
'models_installed' => 'installModels',
|
||||
'resources_installed' => 'installResources',
|
||||
];
|
||||
|
||||
public function __construct( $load = false ) {
|
||||
if ( true === $this->initialized && false == $load ) {
|
||||
return;
|
||||
}
|
||||
self::$db = Database::getInstance();
|
||||
if ( ! isset( self::$installer ) ) {
|
||||
self::$installer = new Installer();
|
||||
}
|
||||
if ( ! isset( $this->module ) ) {
|
||||
$this->module = self::$installer->getModule( getClassName( $this ) );
|
||||
}
|
||||
if ( true == $load ) {
|
||||
if ( $this->checkEnabled() ) {
|
||||
$this->loadAdminNav();
|
||||
$this->loadMainNav();
|
||||
$this->loadFooterNav();
|
||||
$this->loadFilters();
|
||||
}
|
||||
$this->initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
public function install( $options ) {
|
||||
Debug::log( 'Installing Plugin: ' . $this->pluginName );
|
||||
$module_data = [];
|
||||
$errors = [];
|
||||
|
||||
foreach ( self::PLUGIN_FLAG_MAP as $flag_name => $function_name ) {
|
||||
if ( empty( $options[$flag_name] ) ) {
|
||||
$module_data[ $flag_name ] = INSTALL_STATUS_SKIPPED;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( 'installModels' != $function_name ) {
|
||||
$result = $this->$function_name( $options );
|
||||
} else {
|
||||
$model_options = $this->convertPluginOptionsToModelOptions( $options );
|
||||
$result = $this->$function_name( $model_options );
|
||||
}
|
||||
|
||||
if ( empty( $result ) ) {
|
||||
$errors[] = ['errorInfo' => get_class($this) . " Failed to execute $flag_name properly."];
|
||||
$module_data[ $flag_name ] = INSTALL_STATUS_FAIL;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( 'installResources' === $function_name ) {
|
||||
$module_data[ $flag_name ] = $result;
|
||||
continue;
|
||||
}
|
||||
|
||||
$module_data[ $flag_name ] = INSTALL_STATUS_SUCCESS;
|
||||
continue;
|
||||
}
|
||||
|
||||
return [ $module_data, $errors ];
|
||||
}
|
||||
|
||||
public function uninstall( $options ) {
|
||||
Debug::log( 'Uninstalling Plugin: ' . $this->pluginName );
|
||||
$module_data = [];
|
||||
$errors = [];
|
||||
|
||||
foreach ( self::PLUGIN_FLAG_MAP as $flag_name => $function_name ) {
|
||||
$function_name = 'un' . $function_name;
|
||||
if ( empty( $options[$flag_name] ) ) {
|
||||
$module_data[ $flag_name ] = INSTALL_STATUS_SKIPPED;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( 'installModels' != $function_name ) {
|
||||
$result = $this->$function_name( $options );
|
||||
} else {
|
||||
$model_options = $this->convertPluginOptionsToModelOptions( $options );
|
||||
$result = $this->$function_name( $model_options );
|
||||
}
|
||||
|
||||
if ( empty( $result ) ) {
|
||||
$errors[] = ['errorInfo' => get_class($this) . " Failed to execute $flag_name properly."];
|
||||
$module_data[ $flag_name ] = INSTALL_STATUS_FAIL;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( 'uninstallResources' === $function_name ) {
|
||||
$module_data[ $flag_name ] = $result;
|
||||
continue;
|
||||
}
|
||||
|
||||
$module_data[ $flag_name ] = INSTALL_STATUS_UNINSTALLED;
|
||||
continue;
|
||||
}
|
||||
|
||||
return $errors;
|
||||
}
|
||||
|
||||
public function installModels( $options ) {
|
||||
$class = get_class($this);
|
||||
$nameArray = explode( '\\', $class );
|
||||
$name = array_pop( $nameArray );
|
||||
$directory = PLUGIN_DIRECTORY . lcfirst($name) . DIRECTORY_SEPARATOR . 'models' . DIRECTORY_SEPARATOR;
|
||||
if ( ! file_exists( $directory ) ) {
|
||||
Debug::log( 'models directory is empty' );
|
||||
return true;
|
||||
}
|
||||
$models = self::$installer->getModelList( $directory );
|
||||
$error = false;
|
||||
foreach ( $models as $model ) {
|
||||
$result = self::$installer->installModel( $model, $options, true, false );
|
||||
|
||||
if ( $result === false ) {
|
||||
$error = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if ( $error ) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public function uninstallModels( $options ) {
|
||||
$class = get_class($this);
|
||||
$nameArray = explode( '\\', $class );
|
||||
$name = array_pop( $nameArray );
|
||||
$directory = PLUGIN_DIRECTORY . lcfirst($name) . DIRECTORY_SEPARATOR . 'models' . DIRECTORY_SEPARATOR;
|
||||
if ( ! file_exists( $directory ) ) {
|
||||
Debug::log( 'models directory is empty' );
|
||||
return true;
|
||||
}
|
||||
$models = self::$installer->getModelList( $directory );
|
||||
$error = false;
|
||||
foreach ( $models as $model ) {
|
||||
$result = self::$installer->uninstallModel( $model, $options, true, false );
|
||||
|
||||
if ( $result === false ) {
|
||||
$error = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if ( $error ) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public function installPermissions( $options = '' ) {
|
||||
if ( empty( $this->permissionMatrix ) ) {
|
||||
Debug::log( 'permissionMatrix is empty' );
|
||||
return true;
|
||||
}
|
||||
$perms = new Permissions();
|
||||
foreach ( $this->permissionMatrix as $name => $details ) {
|
||||
$perms->add( $name, $details );
|
||||
}
|
||||
return $perms->save( true );
|
||||
}
|
||||
|
||||
public function uninstallPermissions( $options = '' ) {
|
||||
if ( empty( $this->permissionMatrix ) ) {
|
||||
Debug::log( 'permissionMatrix is empty' );
|
||||
return true;
|
||||
}
|
||||
$perms = new Permissions();
|
||||
foreach ( $this->permissionMatrix as $name => $details ) {
|
||||
$perms->remove( $name, true );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public function installConfigs( $options = '' ) {
|
||||
if ( empty( $this->configMatrix ) || empty( $this->configName )) {
|
||||
Debug::log( 'configMatrix is empty' );
|
||||
return true;
|
||||
}
|
||||
$config = new Config( CONFIG_JSON );
|
||||
// should have some sort of DELTA functionality and safeguards
|
||||
$config->addCategory( $this->configName );
|
||||
foreach ( $this->configMatrix as $name => $details ) {
|
||||
$config->add( $this->configName, $name, $details );
|
||||
}
|
||||
return $config->save();
|
||||
}
|
||||
|
||||
public function uninstallConfigs( $options = '' ) {
|
||||
if ( empty( $this->configName ) ) {
|
||||
return true;
|
||||
}
|
||||
$config = new Config( CONFIG_JSON );
|
||||
return $config->removeCategory( $this->configName, true, true );
|
||||
}
|
||||
|
||||
public function installPreferences( $options = '' ) {
|
||||
$prefs = new Preferences();
|
||||
if ( empty( $this->preferenceMatrix ) ) {
|
||||
Debug::log( 'preferenceMatrix is empty' );
|
||||
return true;
|
||||
}
|
||||
foreach ( $this->preferenceMatrix as $name => $details ) {
|
||||
$prefs->add( $name, $details );
|
||||
}
|
||||
return $prefs->save( true );
|
||||
}
|
||||
|
||||
public function uninstallPreferences( $options = '' ) {
|
||||
if ( empty( $this->preferenceMatrix ) ) {
|
||||
Debug::log( 'preferenceMatrix is empty' );
|
||||
return true;
|
||||
}
|
||||
$prefs = new Preferences();
|
||||
foreach ( $this->preferenceMatrix as $name => $details ) {
|
||||
$prefs->remove( $name, true );
|
||||
}
|
||||
return $prefs->save( true );
|
||||
}
|
||||
|
||||
public function installResources( $options = '' ) {
|
||||
if ( empty( $this->resourceMatrix ) ) {
|
||||
Debug::log( 'resourceMatrix is empty' );
|
||||
return true;
|
||||
}
|
||||
$ids = [];
|
||||
foreach( $this->resourceMatrix as $tableName => $entries ) {
|
||||
foreach ( $entries as $entry ) {
|
||||
foreach ( $entry as $key => $value ) {
|
||||
if ( '{time}' == $value ) {
|
||||
$entry[$key] = time();
|
||||
}
|
||||
}
|
||||
self::$db->insert( $tableName, $entry );
|
||||
$id = self::$db->lastId();
|
||||
if ( $id ) {
|
||||
$ids[] = $id;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $ids;
|
||||
}
|
||||
|
||||
public function uninstallResources( $options = '' ) {
|
||||
if ( empty( $this->resourceMatrix ) ) {
|
||||
Debug::log( 'resourceMatrix is empty' );
|
||||
return true;
|
||||
}
|
||||
$ids = $this->module['resources_installed'];
|
||||
$data = [];
|
||||
foreach( $this->resourceMatrix as $tableName => $entries ) {
|
||||
foreach ($ids as $id) {
|
||||
$data[] = self::$db->delete( $tableName, $id );
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loaders
|
||||
*/
|
||||
public function loadAdminNav() {
|
||||
if ( !empty( $this->admin_links ) ) {
|
||||
foreach( $this->admin_links as $key => $link ) {
|
||||
Navigation::addLink( App::ADMIN_MENU_NAME, $link );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function loadMainNav() {
|
||||
if ( !empty( $this->main_links ) ) {
|
||||
foreach( $this->main_links as $key => $link ) {
|
||||
Navigation::addLink( App::MAIN_MENU_NAME, $link );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function loadFooterNav() {
|
||||
if ( !empty( $this->footer_links ) ) {
|
||||
foreach( $this->footer_links as $key => $link ) {
|
||||
Navigation::addLink( App::FOOTER_MENU_NAME, $link );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function loadFilters() {
|
||||
if ( ! empty( $this->filters ) ) {
|
||||
foreach( $this->filters as $filter ) {
|
||||
Filters::add( $filter['name'], $filter['find'], $filter['replace'], $filter['enabled'] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function convertPluginOptionsToModelOptions( $options ) {
|
||||
$data = [];
|
||||
foreach (self::PLUGIN_FLAG_MAP as $pluginValue => $modelValue) {
|
||||
if ( isset( $options[$pluginValue] ) ) {
|
||||
$data[$modelValue] = $options[$pluginValue];
|
||||
}
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
public static function getPluginDirectories( $forceRefresh = false ) {
|
||||
if ( !empty( self::$pluginFolders ) && true !== $forceRefresh ) {
|
||||
return self::$pluginFolders;
|
||||
}
|
||||
$pluginFolders = [];
|
||||
if ( ! PLUGINS_ENABLED && true !== $forceRefresh ) {
|
||||
Debug::warn('Plugins disabled');
|
||||
return $pluginFolders;
|
||||
}
|
||||
|
||||
if ( ! file_exists( PLUGIN_DIRECTORY ) ) {
|
||||
Debug::warn("Plugins folder is missing: $dir");
|
||||
return $pluginFolders;
|
||||
}
|
||||
|
||||
// get a list of all plugins in the plugin directory
|
||||
$pluginDirectories = scandir( PLUGIN_DIRECTORY );
|
||||
array_shift( $pluginDirectories ); // remove the .
|
||||
array_shift( $pluginDirectories ); // remove the ..
|
||||
|
||||
foreach ( $pluginDirectories as $key => $pluginName ) {
|
||||
$pluginDirectory = PLUGIN_DIRECTORY . $pluginName;
|
||||
if ( is_file( $pluginDirectory ) ) {
|
||||
continue; // skip any files in the main plugin directory if they exist
|
||||
}
|
||||
|
||||
// get a list of all directories in this plugin directory
|
||||
$pluginFolders[ $pluginName ] = [];
|
||||
$pluginDirectory .= DIRECTORY_SEPARATOR;
|
||||
$pluginDirectoryArray = scandir( $pluginDirectory );
|
||||
array_shift( $pluginDirectoryArray ); // remove the .
|
||||
array_shift( $pluginDirectoryArray ); // remove the ..
|
||||
|
||||
// loop over each sub-directory insider plugin directory
|
||||
foreach ( $pluginDirectoryArray as $key => $file ) {
|
||||
$currentFolder = $pluginDirectory . $file . DIRECTORY_SEPARATOR;
|
||||
switch ( $file ) {
|
||||
case 'controllers':
|
||||
case 'config':
|
||||
case 'models':
|
||||
case 'views':
|
||||
case 'templates':
|
||||
break;
|
||||
case 'forms.php':
|
||||
$currentFolder = rtrim( $currentFolder, DIRECTORY_SEPARATOR );
|
||||
break;
|
||||
case 'plugin.php':
|
||||
$currentFolder = rtrim( $currentFolder, DIRECTORY_SEPARATOR );
|
||||
break;
|
||||
default:
|
||||
continue 2; // break if we aren't looking for whatever we found
|
||||
}
|
||||
$pluginFolders[ $pluginName ][] = [ $currentFolder => $file ];
|
||||
}
|
||||
}
|
||||
|
||||
self::$pluginFolders = $pluginFolders;
|
||||
return self::$pluginFolders;
|
||||
}
|
||||
|
||||
public static function getActivePlugins( $forceRefresh = false ) {
|
||||
if ( ! empty( self::$pluginsActive ) && true !== $forceRefresh ) {
|
||||
return self::$pluginsActive;
|
||||
}
|
||||
if ( ! isset( self::$installer ) ) {
|
||||
self::$installer = new Installer();
|
||||
}
|
||||
$out = [];
|
||||
$plugins = self::$installer->getAvailablePlugins( $forceRefresh );
|
||||
|
||||
if ( ! empty( $plugins ) ) {
|
||||
foreach ( $plugins as $plugin ) {
|
||||
if ( !isset( $plugin->class_object )) {
|
||||
continue;
|
||||
}
|
||||
$installedPlugin = $plugin->class_object->module;
|
||||
if ( !isset( $installedPlugin['enabled'] ) || !$installedPlugin['enabled'] ) {
|
||||
continue;
|
||||
}
|
||||
$out[] = [
|
||||
$plugin->name => $installedPlugin['class'],
|
||||
];
|
||||
}
|
||||
}
|
||||
self::$pluginsActive = $out;
|
||||
return self::$pluginsActive;
|
||||
}
|
||||
|
||||
public static function enable( $name, $save = true ) {
|
||||
if ( ! isset( self::$installer ) ) {
|
||||
self::$installer = new Installer();
|
||||
}
|
||||
$module = self::$installer->getModule( $name );
|
||||
if ( empty( $module ) ) {
|
||||
Debug::warn( "plugin not found: $name" );
|
||||
return false;
|
||||
}
|
||||
if ( ! isset( $module['enabled'] ) ) {
|
||||
Debug::error( "plugin enabled not set: $name" );
|
||||
return false;
|
||||
}
|
||||
$module['enabled'] = true;
|
||||
return self::$installer->setModule( $name, $module, $save );
|
||||
}
|
||||
|
||||
public static function disable( $name, $save = true ) {
|
||||
if ( ! isset( self::$installer ) ) {
|
||||
self::$installer = new Installer();
|
||||
}
|
||||
$module = self::$installer->getModule( $name );
|
||||
if ( empty($module) ) {
|
||||
Debug::warn( "plugin not found: $name" );
|
||||
return false;
|
||||
}
|
||||
if ( ! isset( $module['enabled'] ) ) {
|
||||
Debug::error( "plugin not enabled: $name" );
|
||||
return false;
|
||||
}
|
||||
$module['enabled'] = false;
|
||||
return self::$installer->setModule( $name, $module, $save );
|
||||
}
|
||||
|
||||
public function checkEnabled() {
|
||||
$name = ucfirst( strtolower( $this->pluginName ) );
|
||||
if ( isset( $this->module['enabled'] ) ) {
|
||||
return $this->module['enabled'];
|
||||
}
|
||||
Debug::warn( "install not found: {$this->pluginName}" );
|
||||
return false;
|
||||
}
|
||||
}
|
297
app/classes/preferences.php
Normal file
297
app/classes/preferences.php
Normal file
@ -0,0 +1,297 @@
|
||||
<?php
|
||||
/**
|
||||
* app/classes/preferences.php
|
||||
*
|
||||
* This class handles all the hard-coded preferences.
|
||||
*
|
||||
* @version 3.0
|
||||
* @author Joey Kimsey <Joey@thetempusproject.com>
|
||||
* @link https://TheTempusProject.com
|
||||
* @license https://opensource.org/licenses/MIT [MIT LICENSE]
|
||||
*/
|
||||
namespace TheTempusProject\Classes;
|
||||
|
||||
use TheTempusProject\Houdini\Classes\Issues;
|
||||
use TheTempusProject\Houdini\Classes\Forms;
|
||||
use TheTempusProject\Canary\Canary as Debug;
|
||||
use TheTempusProject\Bedrock\Functions\Check;
|
||||
use TheTempusProject\Bedrock\Functions\Upload;
|
||||
use TheTempusProject\Bedrock\Functions\Input;
|
||||
use TheTempusProject\TheTempusProject as App;
|
||||
|
||||
class Preferences {
|
||||
public static $preferences = false;
|
||||
private static $location = false;
|
||||
private static $initialized = false;
|
||||
|
||||
/**
|
||||
* Default constructor which will attempt to load the preferences from the location specified.
|
||||
*
|
||||
* @param {string} [$location]
|
||||
* @return {null|object}
|
||||
*/
|
||||
public function __construct( $location = '' ) {
|
||||
if ( self::$initialized !== false ) {
|
||||
Debug::log( 'Preferences already initialized.' );
|
||||
return $this;
|
||||
}
|
||||
if ( empty( $location ) ) {
|
||||
$location = PREFERENCES_JSON;
|
||||
}
|
||||
self::$initialized = $this->load( $location );
|
||||
if ( self::$initialized !== false ) {
|
||||
Debug::log( 'Preferences initialization succeeded.' );
|
||||
return $this;
|
||||
}
|
||||
Debug::warn( 'Preferences initialization failed.' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to retrieve then set the preferences from a file.
|
||||
* @note This function will reset the preferences every time it is used.
|
||||
*
|
||||
* @param {string} [$location]
|
||||
* @return {bool}
|
||||
*/
|
||||
public function load( $location ) {
|
||||
self::$preferences = $this->getPrefsFile( $location );
|
||||
self::$location = $location;
|
||||
if ( self::$preferences === false || empty( self::$preferences ) ) {
|
||||
Debug::warn( 'Preferences load failed.' );
|
||||
return false;
|
||||
}
|
||||
Debug::log( 'Preferences load succeeded.' );
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens and decodes the preferences json from the location provided.
|
||||
*
|
||||
* @param {string} [$location]
|
||||
* @return {bool|array}
|
||||
*/
|
||||
public function getPrefsFile( $location ) {
|
||||
if ( file_exists( $location ) ) {
|
||||
Debug::debug( "Preferences json found: $location" );
|
||||
return json_decode( file_get_contents( $location ), true );
|
||||
} else {
|
||||
Debug::warn( "Preferences json not found: $location" );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the preference option for $name.
|
||||
*
|
||||
* @param {string} [$name]
|
||||
* @return {WILD}
|
||||
*/
|
||||
public static function get( $name ) {
|
||||
if ( self::$preferences === false ) {
|
||||
return Debug::warn( 'Preferences not loaded.' );
|
||||
}
|
||||
if ( isset( self::$preferences[$name] ) ) {
|
||||
return self::$preferences[$name];
|
||||
}
|
||||
return Debug::warn( "Preference not found: $name" );
|
||||
}
|
||||
|
||||
public function getType( $name ) {
|
||||
$pref = $this->get( $name );
|
||||
if ( empty( $pref ) || empty( $pref['type'] ) ) {
|
||||
return Debug::warn( "Preference Type not found: $name" );
|
||||
}
|
||||
return $pref['type'];
|
||||
}
|
||||
|
||||
public function getDefault( $name ) {
|
||||
$pref = $this->get( $name );
|
||||
if ( empty( $pref ) || empty( $pref['default'] ) ) {
|
||||
return Debug::warn( "Preference Default not found: $name" );
|
||||
}
|
||||
return $pref['default'];
|
||||
}
|
||||
|
||||
public function getOptions( $name ) {
|
||||
$pref = $this->get( $name );
|
||||
if ( empty( $pref ) || empty( $pref['options'] ) ) {
|
||||
return Debug::warn( "Preference Options not found: $name" );
|
||||
}
|
||||
return $pref['options'];
|
||||
}
|
||||
|
||||
public function getPrettyName( $name ) {
|
||||
$pref = $this->get( $name );
|
||||
if ( empty( $pref ) || empty( $pref['pretty'] ) ) {
|
||||
return Debug::warn( "Preference Pretty Name not found: $name" );
|
||||
}
|
||||
return $pref['pretty'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the current preferences.
|
||||
*
|
||||
* @param {bool} [$default] - Whether or not to save a default copy.
|
||||
* @return {bool}
|
||||
*/
|
||||
public function save( $backup = true ) {
|
||||
if ( self::$preferences === false ) {
|
||||
Debug::warn( 'Preferences not loaded.' );
|
||||
return false;
|
||||
}
|
||||
if ( self::$location === false ) {
|
||||
Debug::warn( 'Preferences location not set.' );
|
||||
return false;
|
||||
}
|
||||
if ( $backup ) {
|
||||
$locationArray = explode( '.', self::$location );
|
||||
$locationArray[] = 'bak';
|
||||
$backupLoction = implode( '.', $locationArray );
|
||||
if ( !file_put_contents( $backupLoction, json_encode( self::$preferences ) ) ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if ( file_put_contents( self::$location, json_encode( self::$preferences ) ) ) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new preference to the $preferences array.
|
||||
*
|
||||
* @param {string} [$name]
|
||||
* @param {string} [$value]
|
||||
* @return {bool}
|
||||
*/
|
||||
public function add( $name, $details ) {
|
||||
if ( !Check::simpleName( $name ) ) {
|
||||
Debug::error( "Preference name invalid: $name" );
|
||||
return false;
|
||||
}
|
||||
if ( isset( self::$preferences[$name] ) ) {
|
||||
Debug::warn( "Preference already exists: $name" );
|
||||
return false;
|
||||
}
|
||||
if ( self::$preferences === false ) {
|
||||
self::$preferences = [];
|
||||
}
|
||||
$prefsArray = $this->normalizePreferenceArray( $name, $details );
|
||||
if ( false === $prefsArray ) {
|
||||
Debug::warn( 'Preference array failed to load properly.' );
|
||||
return false;
|
||||
}
|
||||
self::$preferences[$name] = $prefsArray;
|
||||
return true;
|
||||
}
|
||||
|
||||
public function getFormHtml( $populated = [] ) {
|
||||
$form = '';
|
||||
foreach ( self::$preferences as $name => $details ) {
|
||||
$tempPrefsArray = $this->normalizePreferenceArray( $name, $details );
|
||||
if ( isset( $populated[ $name ] ) ) {
|
||||
$tempPrefsArray['default'] = $populated[$name];
|
||||
}
|
||||
$form .= Forms::getFormFieldHtml( $name, $tempPrefsArray['pretty'], $tempPrefsArray['type'], $tempPrefsArray['default'], $tempPrefsArray['options'] );
|
||||
}
|
||||
return $form;
|
||||
}
|
||||
|
||||
public function convertFormToArray( $fillMissing = true, $defaultsOnly = true ) {
|
||||
$prefsArray = [];
|
||||
foreach ( self::$preferences as $name => $details ) {
|
||||
if ( true === $fillMissing ) {
|
||||
if ( true !== $defaultsOnly && !empty( App::$activePrefs[$name] ) ) {
|
||||
$prefsArray[$name] = App::$activePrefs[$name];
|
||||
} else {
|
||||
$prefsArray[$name] = $details['default'];
|
||||
}
|
||||
}
|
||||
if ( Input::exists( $name ) ) {
|
||||
$prefsArray[$name] = Input::post( $name );
|
||||
}
|
||||
if ( 'file' == $details['type'] ) {
|
||||
if ( Input::exists( $name ) ) {
|
||||
$folder = IMAGE_UPLOAD_DIRECTORY . App::$activeUser->username . DIRECTORY_SEPARATOR;
|
||||
if ( !Upload::image( $name, $folder ) ) {
|
||||
Issues::add( 'error', [ 'There was an error with your upload.' => Check::systemErrors() ] );
|
||||
} else {
|
||||
$route = str_replace( APP_ROOT_DIRECTORY, '', $folder );
|
||||
$prefsArray[$name] = $route . Upload::last();
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( 'checkbox' == $details['type'] ) {
|
||||
if ( Input::exists( $name ) ) {
|
||||
$prefsArray[$name] = true;
|
||||
} else {
|
||||
$prefsArray[$name] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $prefsArray;
|
||||
}
|
||||
|
||||
public function getDefaultPreferencesArray() {
|
||||
if ( self::$preferences === false ) {
|
||||
Debug::warn( 'Preferences not loaded.' );
|
||||
return false;
|
||||
}
|
||||
$prefsArray = [];
|
||||
foreach ( self::$preferences as $name => $details ) {
|
||||
$tempPrefsArray = $this->normalizePreferenceArray( $name, $details );
|
||||
$prefsArray[$name] = $tempPrefsArray['default'];
|
||||
}
|
||||
return $prefsArray;
|
||||
}
|
||||
|
||||
public function normalizePreferenceArray( $name, $prefsArray ) {
|
||||
if ( !is_array( $prefsArray ) ) {
|
||||
Debug::warn( 'Preference array was not an array.' );
|
||||
return false;
|
||||
}
|
||||
if ( !isset( $prefsArray['type'] ) ) {
|
||||
if ( isset( $prefsArray['options'] ) ) {
|
||||
$prefsArray['type'] = 'select';
|
||||
} else {
|
||||
$prefsArray['type'] = 'text';
|
||||
}
|
||||
}
|
||||
if ( !isset( $prefsArray['pretty'] ) ) {
|
||||
$prefsArray['pretty'] = ucfirst( $name );
|
||||
}
|
||||
if ( !isset( $prefsArray['default'] ) ) {
|
||||
$prefsArray['default'] = '';
|
||||
}
|
||||
if ( ( empty( $prefsArray['avatar'] ) ) || ( $prefsArray['avatar'] == 'defaultAvatar.png' ) ) {
|
||||
$prefsArray['avatar'] = IMAGE_DIRECTORY . 'defaultAvatar.png';
|
||||
}
|
||||
if ( !isset( $prefsArray['options'] ) ) {
|
||||
$prefsArray['options'] = null;
|
||||
}
|
||||
return $prefsArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an existing preference from the $preferences array.
|
||||
*
|
||||
* @param {string} [$name]
|
||||
* @param {bool} [$save]
|
||||
* @return {bool}
|
||||
*/
|
||||
public function remove( $name, $save = false ) {
|
||||
if ( self::$preferences === false ) {
|
||||
Debug::warn( 'Preferences not loaded.' );
|
||||
return false;
|
||||
}
|
||||
if ( !isset( self::$preferences[$name] ) ) {
|
||||
Debug::error( "Preference does not exist: $name" );
|
||||
return false;
|
||||
}
|
||||
unset( self::$preferences[$name] );
|
||||
if ( $save === true ) {
|
||||
return $this->save( true );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user