[ Mini Kiebo ]
Server: Windows NT DESKTOP-5B8S0D4 6.2 build 9200 (Windows 8 Professional Edition) i586
Path:
D:
/
Backup
/
05122024
/
htdocs
/
jurnal-kesmas
/
baru
/
lib
/
pkp
/
classes
/
plugins
/
[
Home
]
File: Plugin.php
<?php /** * @defgroup plugins Plugins * Implements a plugin structure that can be used to flexibly extend PKP * software via the use of a set of plugin categories. */ /** * @file classes/plugins/Plugin.php * * Copyright (c) 2014-2021 Simon Fraser University * Copyright (c) 2000-2021 John Willinsky * Distributed under the GNU GPL v3. For full terms see the file docs/COPYING. * * @class Plugin * * @ingroup plugins * * @see PluginRegistry, PluginSettingsDAO * * @brief Abstract class for plugins * * For best performance, a plug-in should not be instantiated if it is * disabled or the current page/operation does not require the plug-in's * functionality. * * Newer plug-ins support enable/disable and request filter settings that * enable the PKP library plug-in framework to lazy-load plug-ins only * when their functionality is actually being required for a request. * * For backwards compatibility we need to assume that older plug-ins * do not support lazy-load because their register() method and hooks * may have side-effects required on all requests. We have no way of * knowing on which pages these side effects are important so we need * to load legacy plug-ins on all pages. * * In these cases the register() function will be called on every request * when the category the plug-in belongs to is being loaded. This was the * default behavior before plug-in lazy load was introduced. * * Plug-ins that want to enable lazy-load have to include a 'lazy-load' * setting in their version.xml: * * <lazy-load>1</lazy-load> */ namespace PKP\plugins; use APP\core\Application; use APP\template\TemplateManager; use Exception; use Illuminate\Database\Migrations\Migration; use PKP\config\Config; use PKP\core\JSONMessage; use PKP\core\PKPApplication; use PKP\core\PKPRequest; use PKP\core\Registry; use PKP\db\DAORegistry; use PKP\facades\Locale; use PKP\facades\Repo; use PKP\install\Installer; use PKP\observers\events\PluginSettingChanged; use PKP\site\Version; use PKP\site\VersionDAO; use PKP\template\PKPTemplateResource; // Define the well-known file name for filter configuration data. define('PLUGIN_FILTER_DATAFILE', 'filterConfig.xml'); define('PLUGIN_TEMPLATE_RESOURCE_PREFIX', 'plugins'); abstract class Plugin { /** @var string Path name to files for this plugin */ public $pluginPath; /** @var string Category name this plugin is registered to*/ public $pluginCategory; /** @var PKPRequest the current request object */ public $request; /** * Constructor */ public function __construct() { } /* * Public Plugin API (Registration and Initialization) */ /** * Load and initialize the plug-in and register plugin hooks. * * For backwards compatibility this method will be called whenever * the plug-in's category is being loaded. If, however, registerOn() * returns an array then this method will only be called when * the plug-in is enabled and an entry in the result set of * registerOn() matches the current request operation. An empty array * matches all request operations. * * @param string $category Name of category plugin was registered to * @param string $path The path the plugin was found in * @param int $mainContextId To identify if the plugin is enabled * we need a context. This context is usually taken from the * request but sometimes there is no context in the request * (e.g. when executing CLI commands). Then the main context * can be given as an explicit ID. * * @return bool True iff plugin registered successfully; if false, * the plugin will not be executed. */ public function register($category, $path, $mainContextId = null) { $this->pluginPath = $path; $this->pluginCategory = $category; if ($this->getInstallMigration()) { Hook::add('Installer::postInstall', [$this, 'updateSchema']); } if ($this->getInstallSitePluginSettingsFile()) { Hook::add('Installer::postInstall', [$this, 'installSiteSettings']); } if ($this->getInstallEmailTemplatesFile()) { Hook::add('Installer::postInstall', [$this, 'installEmailTemplates']); Hook::add('Locale::installLocale', [$this, 'installLocale']); } if ($this->getInstallEmailTemplateDataFile()) { Hook::add('Installer::postInstall', [$this, 'installEmailTemplateData']); } if ($this->getContextSpecificPluginSettingsFile()) { Hook::add('Context::add', [$this, 'installContextSpecificSettings']); } Hook::add('Installer::postInstall', [$this, 'installFilters']); $this->_registerTemplateResource(); return true; } /** * Protected methods (may be overridden by custom plugins) */ // // Plugin Display // /** * Get the name of this plugin. The name must be unique within * its category, and should be suitable for part of a filename * (ie short, no spaces, and no dependencies on cases being unique). * * @return string name of plugin */ abstract public function getName(); /** * Get the display name for this plugin. * * @return string */ abstract public function getDisplayName(); /** * Get a description of this plugin. * * @return string */ abstract public function getDescription(); // // Plugin Behavior and Management // /** * Return a number indicating the sequence in which this plugin * should be registered compared to others of its category. * Higher = later. * * @return int */ public function getSeq() { return 0; } /** * Site-wide plugins should override this function to return true. * * @return bool */ public function isSitePlugin() { return false; } /** * Perform a management function. * * @param array $args * @param PKPRequest $request * * @return JSONMessage A JSON-encoded response */ public function manage($args, $request) { throw new Exception('Unhandled management action!'); } /** * Determine whether or not this plugin should be hidden from the * management interface. Useful in the case of derivative plugins, * i.e. when a generic plugin registers a feed plugin. * * @return bool */ public function getHideManagement() { return false; } // // Plugin Installation // /** * @deprecated See https://github.com/pkp/pkp-lib/issues/2493 */ final public function getInstallSchemaFile() { } /** * Get the installation migration for this plugin. * * @return ?Migration */ public function getInstallMigration() { return null; } /** * Get the filename of the settings data for this plugin to install * when the system is installed (i.e. site-level plugin settings). * Subclasses using default settings should override this. * * @return string */ public function getInstallSitePluginSettingsFile() { return null; } /** * Get the filename of the settings data for this plugin to install * when a new application context (e.g. journal, conference or press) * is installed. * * Subclasses using default settings should override this. * * @return string */ public function getContextSpecificPluginSettingsFile() { return null; } /** * Get the filename of the email templates for this plugin. * Subclasses using email templates should override this. * * @return string */ public function getInstallEmailTemplatesFile() { return null; } /** * Get the filename of the email template data for this plugin. * Subclasses using email templates should override this. * * @deprecated Starting with OJS/OMP 3.2, localized content should be specified via getInstallEmailTemplatesFile(). (pkp/pkp-lib#5461) * @return string */ public function getInstallEmailTemplateDataFile() { return null; } /** * Get the filename(s) of the filter configuration data for * this plugin. Subclasses using filters can override this. * * The default implementation establishes "well known" locations * for the filter configuration. If you keep your files in these * locations then there's no need to override this method. * * @return string|array one or more file locations. */ public function getInstallFilterConfigFiles() { // Construct the well-known filter configuration file names. $filterConfigFile = $this->getPluginPath() . '/filter/' . PLUGIN_FILTER_DATAFILE; $filterConfigFiles = [ './lib/pkp/' . $filterConfigFile, './' . $filterConfigFile ]; return $filterConfigFiles; } /* * Protected helper methods (can be used by custom plugins but * should not be overridden by custom plugins) */ /** * Get the name of the category this plugin is registered to. * * @return string category */ public function getCategory() { return $this->pluginCategory; } /** * Get the path this plugin's files are located in. * * @return string pathname */ public function getPluginPath() { return $this->pluginPath; } /** * Get the directory name of the plugin * * @return string directory name */ public function getDirName() { return basename($this->pluginPath); } /** * Return the Resource Name for templates in this plugin, or if specified, the full resource locator * for a specific template. * * @param string $template path/filename, if desired * @param bool $inCore True if a "core" template should be used. * * @return string */ public function getTemplateResource($template = null, $inCore = false) { $pluginPath = $this->getPluginPath(); if ($inCore) { $pluginPath = PKP_LIB_PATH . "/{$pluginPath}"; } $plugin = basename($pluginPath); $category = basename(dirname($pluginPath)); $contextId = PKPApplication::CONTEXT_SITE; if (Application::isInstalled()) { $context = Application::get()->getRequest()->getContext(); if ($context instanceof \PKP\context\Context) { $contextId = $context->getId(); } } // Slash characters (/) are not allowed in resource names, so use dashes (-) instead. $resourceName = strtr(join('/', [PLUGIN_TEMPLATE_RESOURCE_PREFIX, $contextId, $pluginPath, $category, $plugin]), '/', '-'); return $resourceName . ($template !== null ? ":{$template}" : ''); } /** * Return the canonical template path of this plug-in * * @param bool $inCore Return the core template path if true. * * @return string|null */ public function getTemplatePath($inCore = false) { $templatePath = ($inCore ? PKP_LIB_PATH . '/' : '') . "{$this->getPluginPath()}/templates"; if (is_dir($templatePath)) { return $templatePath; } return null; } /** * Register this plugin's templates as a template resource * * @param bool $inCore True iff this is a core resource. */ protected function _registerTemplateResource($inCore = false) { if ($templatePath = $this->getTemplatePath($inCore)) { $templateMgr = TemplateManager::getManager(Application::get()->getRequest()); $pluginTemplateResource = new PKPTemplateResource($templatePath); $templateMgr->registerResource($this->getTemplateResource(null, $inCore), $pluginTemplateResource); } } /** * Call this method when an enabled plugin is registered in order to override * template files. Any plugin which calls this method can * override template files by adding their own templates to: * <overridingPlugin>/templates/plugins/<category>/<originalPlugin>/templates/<path>.tpl * * @param string $hookName TemplateResource::getFilename * @param array $args [ * * @option string File path to preferred template. Leave as-is to not * override template. * @option string Template file requested * ] * * @return bool */ public function _overridePluginTemplates($hookName, $args) { $filePath = & $args[0]; $template = $args[1]; $checkFilePath = $filePath; // If there's a templates/ prefix on the template, clean up the test path. if (strpos($filePath, 'plugins/') === 0) { $checkFilePath = 'templates/' . $checkFilePath; } // If there's a lib/pkp/ prefix on the template, test without it. $libPkpPrefix = 'lib/pkp/'; if (strpos($checkFilePath, $libPkpPrefix) === 0) { $checkFilePath = substr($filePath, strlen($libPkpPrefix)); } // Check if an overriding plugin exists in the plugin path. if ($overriddenFilePath = $this->_findOverriddenTemplate($checkFilePath)) { $filePath = $overriddenFilePath; } return false; } /** * Recursive check for existing templates * * @param string $path * * @return string|null */ private function _findOverriddenTemplate($path) { $fullPath = sprintf('%s/%s', $this->getPluginPath(), $path); if (file_exists($fullPath)) { return $fullPath; } // Backward compatibility for OJS prior to 3.1.2; changed path to templates for plugins. if (($fullPath = preg_replace("/templates\/(?!.*templates\/)/", '', $fullPath)) && file_exists($fullPath)) { if (Config::getVar('debug', 'deprecation_warnings')) { trigger_error('Deprecated: The template at ' . $fullPath . ' has moved and will not be found in the future.'); } return $fullPath; } // Recursive check for templates in ancestors of a current theme plugin if ($this instanceof ThemePlugin && $this->parent && $fullPath = $this->parent->_findOverriddenTemplate($path)) { return $fullPath; } return null; } /** * Load locale data for this plugin. */ public function addLocaleData(): void { $basePath = $this->getPluginPath() . '/locale'; foreach ([$basePath, "lib/pkp/{$basePath}"] as $path) { if (is_dir($path)) { Locale::registerPath($path); } } } /** * Retrieve a plugin setting within the given context * * @param int $contextId Context ID * @param string $name Setting name */ public function getSetting($contextId, $name) { if (!Application::isUpgrading() && !Application::isInstalled()) { return null; } $pluginSettingsDao = DAORegistry::getDAO('PluginSettingsDAO'); /** @var PluginSettingsDAO $pluginSettingsDao */ return $pluginSettingsDao->getSetting($contextId, $this->getName(), $name); } /** * Update a plugin setting within the given context. * * @param int $contextId Context ID * @param string $name The name of the setting * @param mixed $value Setting value * @param string $type optional */ public function updateSetting($contextId, $name, $value, $type = null) { $pluginSettingsDao = DAORegistry::getDAO('PluginSettingsDAO'); /** @var PluginSettingsDAO $pluginSettingsDao */ $pluginSettingsDao->updateSetting($contextId, $this->getName(), $name, $value, $type); event(new PluginSettingChanged($this, $name, $value, $contextId)); } /** * Load a PHP file from this plugin's installation directory. * * @deprecated 3.4.0 pkp/pkp-lib#8186 * * @param string $class */ public function import($class) { require_once $this->getPluginPath() . '/' . str_replace('.', '/', $class) . '.inc.php'; } /* * Helper methods (for internal use only, should not * be used by custom plug-ins) * * NB: These methods may change without notice in the future! */ /** * Callback used to install settings on system install. * * @param string $hookName * @param array $args * * @return bool */ public function installSiteSettings($hookName, $args) { $pluginSettingsDao = DAORegistry::getDAO('PluginSettingsDAO'); /** @var PluginSettingsDAO $pluginSettingsDao */ $pluginSettingsDao->installSettings(PKPApplication::CONTEXT_SITE, $this->getName(), $this->getInstallSitePluginSettingsFile()); return false; } /** * Callback used to install settings on new context * (e.g. journal, conference or press) creation. * * @param string $hookName * @param array $args * * @return bool */ public function installContextSpecificSettings($hookName, $args) { $context = $args[0]; $pluginSettingsDao = DAORegistry::getDAO('PluginSettingsDAO'); /** @var PluginSettingsDAO $pluginSettingsDao */ $pluginSettingsDao->installSettings($context->getId(), $this->getName(), $this->getContextSpecificPluginSettingsFile()); return false; } /** * Callback used to install email templates. * * @param string $hookName * @param array $args * * @return bool */ public function installEmailTemplates($hookName, $args) { $installer = & $args[0]; /** @var Installer $installer */ $result = & $args[1]; // Load email template data as required from the locale files. $locales = []; foreach ($installer->installedLocales as $locale) { if (file_exists($this->getPluginPath() . "/locale/{$locale}/emails.po")) { $locales[] = $locale; } } // Localized data is needed by the email installation $this->addLocaleData(); $status = Repo::emailTemplate()->dao->installEmailTemplates($this->getInstallEmailTemplatesFile(), $locales, null, true); if ($status === false) { // The template file seems to be invalid. $installer->setError(Installer::INSTALLER_ERROR_DB, str_replace('{$file}', $this->getInstallEmailTemplatesFile(), __('installer.installParseEmailTemplatesFileError'))); $result = false; } return false; } /** * Callback used to install email template data. * * @deprecated Email template data should be installed via installEmailTemplates (pkp/pkp-lib#5461) * * @param string $hookName * @param array $args * * @return bool */ public function installEmailTemplateData($hookName, $args) { $installer = & $args[0]; $result = & $args[1]; foreach ($installer->installedLocales as $locale) { $filename = str_replace('{$installedLocale}', $locale, $this->getInstallEmailTemplateDataFile()); if (!file_exists($filename)) { continue; } $sql = Repo::emailTemplate()->dao->installEmailTemplateData($filename, $locale, true); if ($sql) { $result = $installer->executeSQL($sql); } else { $installer->setError(Installer::INSTALLER_ERROR_DB, str_replace('{$file}', $filename, __('installer.installParseEmailTemplatesFileError'))); $result = false; } } return false; } /** * Callback used to install email template data on locale install. * * @param string $hookName * @param array $args * * @return bool */ public function installLocale($hookName, $args) { $locale = & $args[0]; $filename = str_replace('{$installedLocale}', $locale, $this->getInstallEmailTemplateDataFile()); // Since pkp/pkp-lib#5461, there are two ways to specify localized email data in plugins. // Install locale data specified in the old form. (Deprecated!) if ($this->getInstallEmailTemplateDataFile()) { Repo::emailTemplate()->dao->installEmailTemplateData($filename, $locale); } // Install locale data specified in the new form. if (file_exists($this->getPluginPath() . "/locale/{$locale}/emails.po")) { $this->addLocaleData(); Repo::emailTemplate()->dao->installEmailTemplateLocaleData($this->getInstallEmailTemplatesFile(), [$locale]); } return false; } /** * Callback used to install filters. * * @param string $hookName * @param array $args */ public function installFilters($hookName, $args) { $installer = & $args[0]; /** @var Installer $installer */ $result = & $args[1]; /** @var bool $result */ // Get the filter configuration file name(s). $filterConfigFiles = $this->getInstallFilterConfigFiles(); if (is_scalar($filterConfigFiles)) { $filterConfigFiles = [$filterConfigFiles]; } // Run through the config file positions and see // whether one of these exists and needs to be installed. foreach ($filterConfigFiles as $filterConfigFile) { // Is there a filter configuration? if (!file_exists($filterConfigFile)) { continue; } // Install the filter configuration. $result = $installer->installFilterConfig($filterConfigFile); if (!$result) { // The filter configuration file seems to be invalid. $installer->setError(Installer::INSTALLER_ERROR_DB, str_replace('{$file}', $filterConfigFile, __('installer.installParseFilterConfigFileError'))); } } // Do not stop installation. return false; } /** * Called during the install process to install the plugin schema, * if applicable. * * @param string $hookName * @param array $args * * @return bool */ public function updateSchema($hookName, $args) { $installer = & $args[0]; $result = & $args[1]; if ($migration = $this->getInstallMigration()) { try { $migration->up(); } catch (Exception $e) { $installer->setError(Installer::INSTALLER_ERROR_DB, __('installer.installMigrationError', ['class' => get_class($migration), 'message' => $e->getMessage()])); $result = false; } } return false; } /** * Extend the {url ...} smarty to support plugins. * * @param array $params * @param \Smarty $smarty * * @return string */ public function smartyPluginUrl($params, $smarty) { $path = [$this->getCategory(), $this->getName()]; if (is_array($params['path'])) { $params['path'] = array_merge($path, $params['path']); } elseif (!empty($params['path'])) { $params['path'] = array_merge($path, [$params['path']]); } else { $params['path'] = $path; } return $smarty->smartyUrl($params, $smarty); } /** * Get the current version of this plugin * * @return ?Version */ public function getCurrentVersion() { $versionDao = DAORegistry::getDAO('VersionDAO'); /** @var VersionDAO $versionDao */ $pluginPath = $this->getPluginPath(); $product = basename($pluginPath); $category = basename(dirname($pluginPath)); $installedPlugin = $versionDao->getCurrentVersion('plugins.' . $category, $product); if ($installedPlugin) { return $installedPlugin; } else { return false; } } /** * Get the current request object * * @return PKPRequest */ public function &getRequest() { if (!$this->request) { $this->request = & Registry::get('request'); } return $this->request; } /* * Private helper methods */ /** * Get a list of link actions for plugin management. * * @param PKPRequest $request * @param array $actionArgs The list of action args to be included in request URLs. * * @return array List of LinkActions */ public function getActions($request, $actionArgs) { return []; } /** * Determine whether the plugin can be enabled. * * @return bool */ public function getCanEnable() { return false; } /** * Determine whether the plugin can be disabled. * * @return bool */ public function getCanDisable() { return false; } /** * Determine whether the plugin is enabled. * * @return bool */ public function getEnabled() { return true; } } if (!PKP_STRICT_MODE) { class_alias('\PKP\plugins\Plugin', '\Plugin'); }