⚝
One Hat Cyber Team
⚝
Your IP:
216.73.216.1
Server IP:
185.238.29.86
Server:
Linux server2 6.8.12-6-pve #1 SMP PREEMPT_DYNAMIC PMX 6.8.12-6 (2024-12-19T19:05Z) x86_64
Server Software:
nginx/1.18.0
PHP Version:
8.1.31
Buat File
|
Buat Folder
Eksekusi
Dir :
~
/
var
/
www
/
olasjoys
/
src
/
Core
/
Addon
/
Module
/
View File Name :
ModuleRepository.php
<?php /** * Copyright since 2007 PrestaShop SA and Contributors * PrestaShop is an International Registered Trademark & Property of PrestaShop SA * * NOTICE OF LICENSE * * This source file is subject to the Open Software License (OSL 3.0) * that is bundled with this package in the file LICENSE.md. * It is also available through the world-wide-web at this URL: * https://opensource.org/licenses/OSL-3.0 * If you did not receive a copy of the license and are unable to * obtain it through the world-wide-web, please send an email * to license@prestashop.com so we can send you a copy immediately. * * DISCLAIMER * * Do not edit or add to this file if you wish to upgrade PrestaShop to newer * versions in the future. If you wish to customize PrestaShop for your * needs please refer to https://devdocs.prestashop.com/ for more information. * * @author PrestaShop SA and Contributors <contact@prestashop.com> * @copyright Since 2007 PrestaShop SA and Contributors * @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) */ namespace PrestaShop\PrestaShop\Core\Addon\Module; use Doctrine\Common\Cache\ArrayCache; use Doctrine\Common\Cache\CacheProvider; use Exception; use Module as LegacyModule; use PrestaShop\PrestaShop\Adapter\Module\AdminModuleDataProvider; use PrestaShop\PrestaShop\Adapter\Module\Module; use PrestaShop\PrestaShop\Adapter\Module\ModuleDataProvider; use PrestaShop\PrestaShop\Adapter\Module\ModuleDataUpdater; use PrestaShop\PrestaShop\Adapter\Module\PrestaTrust\PrestaTrustChecker; use PrestaShop\PrestaShop\Core\Addon\AddonInterface; use PrestaShop\PrestaShop\Core\Addon\AddonListFilter; use PrestaShop\PrestaShop\Core\Addon\AddonListFilterOrigin; use PrestaShop\PrestaShop\Core\Addon\AddonListFilterStatus; use PrestaShop\PrestaShop\Core\Addon\AddonListFilterType; use PrestaShop\PrestaShop\Core\Addon\AddonsCollection; use Psr\Log\LoggerInterface; use Symfony\Component\Finder\Finder; use Symfony\Component\Translation\TranslatorInterface; class ModuleRepository implements ModuleRepositoryInterface { public const NATIVE_AUTHOR = 'PrestaShop'; public const PARTNER_AUTHOR = 'PrestaShop Partners'; /** * @var AdminModuleDataProvider */ private $adminModuleProvider; /** * @var Finder */ private $finder; /** * @var LoggerInterface */ private $logger; /** * @var ModuleDataProvider */ private $moduleProvider; /** * @var ModuleDataUpdater */ private $moduleUpdater; /** * @var TranslatorInterface */ private $translator; /** * Path to the module directory, coming from Confiuration class. * * @var string */ private $modulePath; /** * @var PrestaTrustChecker|null */ private $prestaTrustChecker = null; /** * Key of the cache content. * * @var string */ private $cacheFilePath; /** * Contains data from cache file about modules on disk. * * @var array */ private $cache = []; /** * Optionnal Doctrine cache provider. * * @var CacheProvider|null */ private $cacheProvider; /** * Keep loaded modules in cache. * * @var ArrayCache */ private $loadedModules; public function __construct( AdminModuleDataProvider $adminModulesProvider, ModuleDataProvider $modulesProvider, ModuleDataUpdater $modulesUpdater, LoggerInterface $logger, TranslatorInterface $translator, $modulePath, CacheProvider $cacheProvider = null ) { $this->adminModuleProvider = $adminModulesProvider; $this->logger = $logger; $this->moduleProvider = $modulesProvider; $this->moduleUpdater = $modulesUpdater; $this->translator = $translator; $this->finder = new Finder(); $this->modulePath = $modulePath; list($isoLang) = explode('-', $translator->getLocale()); // Cache related variables $this->cacheFilePath = $isoLang . '_local_modules'; $this->cacheProvider = $cacheProvider; $this->loadedModules = new ArrayCache(); if ($this->cacheProvider && $this->cacheProvider->contains($this->cacheFilePath)) { $this->cache = $this->cacheProvider->fetch($this->cacheFilePath); } } /** * Setter for the optional PrestaTrust checker. * * @param PrestaTrustChecker $checker * * @return $this */ public function setPrestaTrustChecker(PrestaTrustChecker $checker) { $this->prestaTrustChecker = $checker; return $this; } public function __destruct() { if ($this->cacheProvider) { $this->cacheProvider->save($this->cacheFilePath, $this->cache); } } public function clearCache() { if ($this->cacheProvider) { $this->cacheProvider->delete($this->cacheFilePath); } $this->cache = []; } /** * Get the **Legacy** Module object from its name. * * @param string $name The technical module name to instanciate * * @return \Module|null Instance of legacy Module, if valid */ public function getInstanceByName($name) { // Return legacy instance ! return $this->getModule($name)->getInstance(); } /** * @param AddonListFilter $filter * @param bool $skip_main_class_attributes * * @return AddonInterface[] retrieve a list of addons, regarding the $filter used */ public function getFilteredList(AddonListFilter $filter, $skip_main_class_attributes = false) { if ($filter->status >= AddonListFilterStatus::ON_DISK && $filter->status != AddonListFilterStatus::ALL) { /** @var Module[] $modules */ $modules = $this->getModulesOnDisk($skip_main_class_attributes); } else { /** @var Module[] $modules */ $modules = $this->getList(); } foreach ($modules as $key => &$module) { // Part One : Removing addons not related to the selected product type if ($filter->type != AddonListFilterType::ALL) { if ($module->attributes->get('productType') == 'module') { $productType = AddonListFilterType::MODULE; } if ($module->attributes->get('productType') == 'service') { $productType = AddonListFilterType::SERVICE; } if (!isset($productType) || $productType & ~$filter->type) { unset($modules[$key]); continue; } } // Part Two : Remove module not installed if specified if ($filter->status != AddonListFilterStatus::ALL) { if ($module->database->get('installed') == 1 && ($filter->hasStatus(AddonListFilterStatus::UNINSTALLED) || !$filter->hasStatus(AddonListFilterStatus::INSTALLED))) { unset($modules[$key]); continue; } if ($module->database->get('installed') == 0 && (!$filter->hasStatus(AddonListFilterStatus::UNINSTALLED) || $filter->hasStatus(AddonListFilterStatus::INSTALLED))) { unset($modules[$key]); continue; } if ($module->database->get('installed') == 1 && $module->database->get('active') == 1 && !$filter->hasStatus(AddonListFilterStatus::DISABLED) && $filter->hasStatus(AddonListFilterStatus::ENABLED)) { unset($modules[$key]); continue; } if ($module->database->get('installed') == 1 && $module->database->get('active') == 0 && !$filter->hasStatus(AddonListFilterStatus::ENABLED) && $filter->hasStatus(AddonListFilterStatus::DISABLED)) { unset($modules[$key]); continue; } } // Part Three : Remove addons not related to the proper source (ex Addons) if ($filter->origin != AddonListFilterOrigin::ALL) { if (!$module->attributes->has('origin_filter_value') && !$filter->hasOrigin(AddonListFilterOrigin::DISK) ) { unset($modules[$key]); continue; } if ($module->attributes->has('origin_filter_value') && !$filter->hasOrigin($module->attributes->get('origin_filter_value')) ) { unset($modules[$key]); continue; } } } return $modules; } /** * @return AddonInterface[] retrieve the universe of Modules */ public function getList() { return array_merge( $this->getAddonsCatalogModules(), $this->getModulesOnDisk() ); } /** * @return AddonInterface[] retrieve the list of native modules */ public function getNativeModules() { static $nativeModules = null; if (null === $nativeModules) { $filter = new AddonListFilter(); $filter->setOrigin(AddonListFilterOrigin::ADDONS_NATIVE); /** @var Module[] $nativeModules */ $nativeModules = $this->getFilteredList($filter); foreach ($nativeModules as $key => $module) { $moduleAuthor = $module->attributes->get('author'); if (self::NATIVE_AUTHOR !== $moduleAuthor) { unset($nativeModules[$key]); } } } return $nativeModules; } /** * @return AddonInterface[] retrieve the list of partners modules */ public function getPartnersModules() { $filter = new AddonListFilter(); $filter->setOrigin(AddonListFilterOrigin::ADDONS_NATIVE); /** @var Module[] $partnersModules */ $partnersModules = $this->getFilteredList($filter); foreach ($partnersModules as $key => $module) { $moduleAuthor = $module->attributes->get('author'); if (self::PARTNER_AUTHOR !== $moduleAuthor) { unset($partnersModules[$key]); } } return $partnersModules; } /** * @return AddonInterface[] get the list of installed partners modules */ public function getInstalledPartnersModules() { /** @var Module[] $partnersModules */ $partnersModules = $this->getPartnersModules(); foreach ($partnersModules as $key => $module) { if (1 !== $module->database->get('installed')) { unset($partnersModules[$key]); } } return $partnersModules; } /** * @return AddonInterface[] get the list of not installed partners modules */ public function getNotInstalledPartnersModules() { /** @var Module[] $partnersModules */ $partnersModules = $this->getPartnersModules(); foreach ($partnersModules as $key => $module) { if (0 !== $module->database->get('installed')) { unset($partnersModules[$key]); } } return $partnersModules; } private function getAddonsCatalogModules() { $modules = []; foreach ($this->adminModuleProvider->getCatalogModulesNames() as $name) { try { $module = $this->getModule($name); if ($module instanceof Module) { $modules[$name] = $module; } } catch (\ParseError $e) { $this->logger->critical( $this->translator->trans( 'Parse error on module %module%. %error_details%', [ '%module%' => $name, '%error_details%' => $e->getMessage(), ], 'Admin.Modules.Notification' ) ); } catch (Exception $e) { $this->logger->critical( $this->translator->trans( 'Unexpected exception on module %module%. %error_details%', [ '%module%' => $name, '%error_details%' => $e->getMessage(), ], 'Admin.Modules.Notification' ) ); } } return $modules; } /** * Get the new module presenter class of the specified name provided. * It contains data from its instance, the disk, the database and from the marketplace if exists. * * @param string $name The technical name of the module * @param bool $skip_main_class_attributes * * @return Module */ public function getModule($name, $skip_main_class_attributes = false) { if ($this->loadedModules->contains($name)) { return $this->loadedModules->fetch($name); } $path = $this->modulePath . $name; $php_file_path = $path . '/' . $name . '.php'; /* Data which design the module class */ $attributes = ['name' => $name]; // Get filemtime of module main class (We do this directly with an error suppressor to go faster) $current_filemtime = (int) @filemtime($php_file_path); // We check that we have data from the marketplace try { $module_catalog_data = $this->adminModuleProvider->getCatalogModules(['name' => $name]); $attributes = array_merge( $attributes, (array) array_shift($module_catalog_data) ); } catch (Exception $e) { $this->logger->alert( $this->translator->trans( 'Loading data from Addons failed. %error_details%', ['%error_details%' => $e->getMessage()], 'Admin.Modules.Notification' ) ); } // Now, we check that cache is up to date if (isset($this->cache[$name]['disk']['filemtime']) && $this->cache[$name]['disk']['filemtime'] === $current_filemtime ) { // OK, cache can be loaded and used directly $attributes = array_merge($attributes, $this->cache[$name]['attributes']); $disk = $this->cache[$name]['disk']; } else { // NOPE, we have to fulfil the cache with the module data $disk = [ 'filemtime' => $current_filemtime, 'is_present' => (int) $this->moduleProvider->isOnDisk($name), 'is_valid' => 0, 'version' => null, 'path' => $path, ]; $main_class_attributes = []; if (!$skip_main_class_attributes && $this->moduleProvider->isModuleMainClassValid($name)) { // We load the main class of the module, and get its properties $tmp_module = LegacyModule::getInstanceByName($name); foreach (['warning', 'name', 'tab', 'displayName', 'description', 'author', 'author_address', 'limited_countries', 'need_instance', 'confirmUninstall', ] as $data_to_get) { if (isset($tmp_module->{$data_to_get})) { $main_class_attributes[$data_to_get] = $tmp_module->{$data_to_get}; } } $main_class_attributes['parent_class'] = get_parent_class($name); $main_class_attributes['is_paymentModule'] = is_subclass_of($name, 'PaymentModule'); $main_class_attributes['is_configurable'] = (int) method_exists($tmp_module, 'getContent'); $disk['is_valid'] = 1; $disk['version'] = $tmp_module->version; $attributes = array_merge($attributes, $main_class_attributes); } elseif (!$skip_main_class_attributes) { $main_class_attributes['warning'] = 'Invalid module class'; } else { $disk['is_valid'] = 1; } $this->cache[$name]['attributes'] = $main_class_attributes; $this->cache[$name]['disk'] = $disk; } // Get data from database $database = $this->moduleProvider->findByName($name); $module = new Module($attributes, $disk, $database); $this->loadedModules->save($name, $module); if ($this->prestaTrustChecker) { $this->prestaTrustChecker->loadDetailsIntoModule($module); } return $module; } public function getModuleAttributes($name) { $module = $this->getModule($name); return $module->attributes; } /** * Send request to get module details on the marketplace, then merge the data received in Module instance. * * @param int $moduleId * * @return Module */ public function getModuleById($moduleId) { $moduleAttributes = $this->adminModuleProvider->getModuleAttributesById($moduleId); $module = $this->getModule($moduleAttributes['name']); foreach ($moduleAttributes as $name => $value) { if (!$module->attributes->has($name)) { $module->attributes->set($name, $value); } } return $module; } /** * Instanciate every module present in the modules folder. * * @param bool $skip_main_class_attributes * * @return \PrestaShop\PrestaShop\Adapter\Module\Module[] */ private function getModulesOnDisk($skip_main_class_attributes = false) { $modules = []; $modulesDirsList = $this->finder->directories() ->in($this->modulePath) ->depth('== 0') ->exclude(['__MACOSX']) ->ignoreVCS(true); foreach ($modulesDirsList as $moduleDir) { $moduleName = $moduleDir->getFilename(); if (!file_exists($this->modulePath . $moduleName . '/' . $moduleName . '.php')) { continue; } try { $module = $this->getModule($moduleName, $skip_main_class_attributes); if ($module instanceof Module) { $modules[$moduleName] = $module; } } catch (\ParseError $e) { $this->logger->critical( $this->translator->trans( 'Parse error detected in module %module%. %error_details%.', [ '%module%' => $moduleName, '%error_details%' => $e->getMessage(), ], 'Admin.Modules.Notification' ) ); } catch (Exception $e) { $this->logger->critical( $this->translator->trans( 'Exception detected while loading module %module%. %error_details%.', [ '%module%' => $moduleName, '%error_details%' => $e->getMessage(), ], 'Admin.Modules.Notification' ) ); } } return $modules; } /** * Function loading all installed modules on the shop. Can be used as example for AddonListFilter use. * * @return array */ public function getInstalledModules() { $filters = new AddonListFilter(); $filters->setType(AddonListFilterType::MODULE | AddonListFilterType::SERVICE) ->setStatus(AddonListFilterStatus::INSTALLED); return $this->getFilteredList($filters); } /** * Gets all installed modules as a collection. * * @return AddonsCollection */ public function getInstalledModulesCollection() { $installedModules = $this->getInstalledModules(); return AddonsCollection::createFrom($installedModules); } /** * Returns installed module filepaths. * * @return array */ public function getInstalledModulesPaths() { $paths = []; $modulesFiles = Finder::create()->directories()->in(__DIR__ . '/../../../../modules')->depth(0); $installedModules = array_keys($this->getInstalledModules()); foreach ($modulesFiles as $moduleFile) { if (in_array($moduleFile->getFilename(), $installedModules)) { $paths[] = $moduleFile->getPathname(); } } return $paths; } }