494 lines
16 KiB
PHP
494 lines
16 KiB
PHP
<?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\Bin\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;
|
|
}
|
|
}
|