[ 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: PluginGalleryDAO.php
<?php /** * @file classes/plugins/PluginGalleryDAO.php * * Copyright (c) 2014-2021 Simon Fraser University * Copyright (c) 2003-2021 John Willinsky * Distributed under the GNU GPL v3. For full terms see the file docs/COPYING. * * @class PluginGalleryDAO * * @ingroup plugins * * @see DAO * * @brief Operations for retrieving content from the PKP plugin gallery. */ namespace PKP\plugins; use APP\core\Application; use DOMDocument; use DOMElement; use PKP\cache\CacheManager; use PKP\cache\FileCache; use PKP\controllers\grid\plugins\PluginGalleryGridHandler; use PKP\core\PKPApplication; use PKP\core\PKPString; use PKP\db\DAORegistry; use PKP\site\VersionDAO; use Throwable; class PluginGalleryDAO extends \PKP\db\DAO { public const PLUGIN_GALLERY_XML_URL = 'https://pkp.sfu.ca/ojs/xml/plugins.xml'; /** * The default timeout (in seconds) to wait plugins.xml request * * @see https://docs.guzzlephp.org/en/6.5/request-options.html#timeout */ public const DEFAULT_TIMEOUT = 10; /** * TTL's Cache in seconds */ public const TTL_CACHE_SECONDS = 86400; /** * Get a set of GalleryPlugin objects describing the available * compatible plugins in their newest versions. * * @param PKPApplication $application * @param string $category Optional category name to use as filter * @param string $search Optional text to use as filter * * @return array GalleryPlugin objects */ public function getNewestCompatible($application, $category = null, $search = null) { $doc = $this->_getDocument(); $plugins = []; foreach ($doc->getElementsByTagName('plugin') as $index => $element) { $plugin = $this->_compatibleFromElement($element, $application); // May be null if no compatible version exists; also // apply search filters if any supplied. if ( $plugin && ($category == '' || $category == PluginGalleryGridHandler::PLUGIN_GALLERY_ALL_CATEGORY_SEARCH_VALUE || $plugin->getCategory() == $category) && ($search == '' || PKPString::strpos(PKPString::strtolower(serialize($plugin)), PKPString::strtolower($search)) !== false) ) { $plugins[$index] = $plugin; } } return $plugins; } /** * Get the external Plugin XML document * * @return ?string */ protected function getExternalDocument(): ?string { $application = Application::get(); $client = $application->getHttpClient(); /** @var VersionDAO */ $versionDao = DAORegistry::getDAO('VersionDAO'); $currentVersion = $versionDao->getCurrentVersion(); try { $response = $client->request( 'GET', static::PLUGIN_GALLERY_XML_URL, [ 'query' => [ 'application' => $application->getName(), 'version' => $currentVersion->getVersionString() ], 'timeout' => self::DEFAULT_TIMEOUT, ] ); return $response->getBody(); } catch (Throwable $e) { error_log($e->getMessage()); return null; } } /** * Get the cached Plugin XML document * * @return ?string */ protected function getCachedDocument(): ?string { $cacheManager = CacheManager::getManager(); /** @var FileCache */ $cache = $cacheManager->getCache( 'loadPluginsXML', Application::CONTEXT_SITE, function (FileCache $cache) { $cache->setEntireCache($this->getExternalDocument()); } ); $cacheTime = $cache->getCacheTime(); // Checking if the cache is older than 1 day, or its null if ($cacheTime === null || (time() - $cacheTime > self::TTL_CACHE_SECONDS)) { // This cache is out of date; so, lets request a new version. $response = $this->getExternalDocument(); // The plugins.xml request wasnt empty, so lets replace it if ($response !== null) { $cache->setEntireCache($response); } } return $cache->getContents(); } /** * Get the DOM document for the plugin gallery. * * @return DOMDocument */ private function _getDocument() { $doc = new DOMDocument('1.0', 'utf-8'); $doc->loadXML($this->getCachedDocument()); return $doc; } /** * Construct a new data object. * * @return GalleryPlugin */ public function newDataObject() { return new GalleryPlugin(); } /** * Build a GalleryPlugin from a DOM element, using the newest compatible * release with the supplied Application. * * @param DOMElement $element * @param Application $application * * @return GalleryPlugin|null, if no compatible plugin was available */ protected function _compatibleFromElement($element, $application) { $plugin = $this->newDataObject(); $plugin->setCategory($element->getAttribute('category')); $plugin->setProduct($element->getAttribute('product')); $doc = $element->ownerDocument; $foundRelease = false; for ($n = $element->firstChild; $n; $n = $n->nextSibling) { if (!($n instanceof DOMElement)) { continue; } switch ($n->tagName) { case 'name': $plugin->setName($n->nodeValue, $n->getAttribute('locale')); break; case 'homepage': $plugin->setHomepage($n->nodeValue); break; case 'description': $plugin->setDescription($n->nodeValue, $n->getAttribute('locale')); break; case 'installation': $plugin->setInstallationInstructions($n->nodeValue, $n->getAttribute('locale')); break; case 'summary': $plugin->setSummary($n->nodeValue, $n->getAttribute('locale')); break; case 'maintainer': $this->_handleMaintainer($n, $plugin); break; case 'release': // If a compatible release couldn't be // found, return null. if ($this->_handleRelease($n, $plugin, $application)) { $foundRelease = true; } break; default: // Not erroring out here so that future // additions won't break old releases. } } if (!$foundRelease) { // No compatible release was found. return null; } return $plugin; } /** * Handle a maintainer element * * @param GalleryPlugin $plugin */ public function _handleMaintainer($element, $plugin) { for ($n = $element->firstChild; $n; $n = $n->nextSibling) { if (!($n instanceof DOMElement)) { continue; } switch ($n->tagName) { case 'name': $plugin->setContactName($n->nodeValue); break; case 'institution': $plugin->setContactInstitutionName($n->nodeValue); break; case 'email': $plugin->setContactEmail($n->nodeValue); break; default: // Not erroring out here so that future // additions won't break old releases. } } } /** * Handle a release element * * @param GalleryPlugin $plugin * @param PKPApplication $application */ public function _handleRelease($element, $plugin, $application) { $release = [ 'date' => strtotime($element->getAttribute('date')), 'version' => $element->getAttribute('version'), 'md5' => $element->getAttribute('md5'), ]; $compatible = false; for ($n = $element->firstChild; $n; $n = $n->nextSibling) { if (!($n instanceof DOMElement)) { continue; } switch ($n->tagName) { case 'description': $release[$n->tagName][$n->getAttribute('locale')] = $n->nodeValue; break; case 'package': $release['package'] = $n->nodeValue; break; case 'compatibility': // If a compatible release couldn't be // found, return null. if ($this->_handleCompatibility($n, $plugin, $application)) { $compatible = true; } break; case 'certification': $release[$n->tagName][] = $n->getAttribute('type'); break; default: // Not erroring out here so that future // additions won't break old releases. } } if ($compatible && (!$plugin->getData('version') || version_compare($plugin->getData('version'), $release['version'], '<'))) { // This release is newer than the one found earlier, or // this is the first compatible release we've found. $plugin->setDate($release['date']); $plugin->setVersion($release['version']); $plugin->setReleaseMD5($release['md5']); $plugin->setReleaseDescription($release['description']); $plugin->setReleaseCertifications($release['certification'] ?? []); $plugin->setReleasePackage($release['package']); return true; } return false; } /** * Handle a compatibility element, fishing out the most recent statement * of compatibility. * * @param GalleryPlugin $plugin * @param PKPApplication $application * * @return bool True iff a compatibility statement matched this app */ public function _handleCompatibility($element, $plugin, $application) { // Check that the compatibility statement refers to this app if ($element->getAttribute('application') != $application->getName()) { return false; } for ($n = $element->firstChild; $n; $n = $n->nextSibling) { if (!($n instanceof DOMElement)) { continue; } switch ($n->tagName) { case 'version': $installedVersion = $application->getCurrentVersion(); if ($installedVersion->isCompatible($n->nodeValue)) { // Compatibility was determined. return true; } break; } } // No applicable compatibility statement found. return false; } } if (!PKP_STRICT_MODE) { class_alias('\PKP\plugins\PluginGalleryDAO', '\PluginGalleryDAO'); define('PLUGIN_GALLERY_XML_URL', PluginGalleryDAO::PLUGIN_GALLERY_XML_URL); }