![]() Server : Apache System : Linux server2.corals.io 4.18.0-348.2.1.el8_5.x86_64 #1 SMP Mon Nov 15 09:17:08 EST 2021 x86_64 User : corals ( 1002) PHP Version : 7.4.33 Disable Function : exec,passthru,shell_exec,system Directory : /home/corals/old/vendor/magento/framework/App/Cache/Frontend/ |
<?php /** * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ /** * Factory that creates cache frontend instances based on options */ namespace Magento\Framework\App\Cache\Frontend; use Cm_Cache_Backend_File; use Exception; use LogicException; use Magento\Framework\App\Filesystem\DirectoryList; use Magento\Framework\App\ResourceConnection; use Magento\Framework\Cache\Backend\Database; use Magento\Framework\Cache\Backend\Eaccelerator; use Magento\Framework\Cache\Backend\RemoteSynchronizedCache; use Magento\Framework\Cache\Core; use Magento\Framework\Cache\Frontend\Adapter\Zend; use Magento\Framework\Cache\FrontendInterface; use Magento\Framework\Filesystem; use Magento\Framework\ObjectManagerInterface; use Magento\Framework\Profiler; use UnexpectedValueException; use Zend_Cache; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class Factory { /** * Default cache entry lifetime */ const DEFAULT_LIFETIME = 7200; /** * Caching params, that applied for all cache frontends regardless of type */ const PARAM_CACHE_FORCED_OPTIONS = 'cache_options'; /** * @var ObjectManagerInterface */ private $_objectManager; /** * @var Filesystem */ private $_filesystem; /** * Cache options to be enforced for all instances being created * * @var array */ private $_enforcedOptions = []; /** * Configuration of decorators that are to be applied to every cache frontend being instantiated, format: * array( * array('class' => '<decorator_class>', 'arguments' => array()), * ... * ) * * @var array */ private $_decorators = []; /** * Default cache backend type * * @var string */ protected $_defaultBackend = 'Cm_Cache_Backend_File'; /** * Options for default backend * * @var array */ protected $_backendOptions = [ 'hashed_directory_level' => 1, 'file_name_prefix' => 'mage', ]; /** * Resource * * @var ResourceConnection */ protected $_resource; /** * @param ObjectManagerInterface $objectManager * @param Filesystem $filesystem * @param ResourceConnection $resource * @param array $enforcedOptions * @param array $decorators */ public function __construct( ObjectManagerInterface $objectManager, Filesystem $filesystem, ResourceConnection $resource, array $enforcedOptions = [], array $decorators = [] ) { $this->_objectManager = $objectManager; $this->_filesystem = $filesystem; $this->_resource = $resource; $this->_enforcedOptions = $enforcedOptions; $this->_decorators = $decorators; } /** * Return newly created cache frontend instance * * @param array $options * @return FrontendInterface */ public function create(array $options) { $options = $this->_getExpandedOptions($options); foreach (['backend_options', 'slow_backend_options'] as $section) { if (!empty($options[$section]['cache_dir'])) { $directory = $this->_filesystem->getDirectoryWrite(DirectoryList::VAR_DIR); $directory->create($options[$section]['cache_dir']); $options[$section]['cache_dir'] = $directory->getAbsolutePath($options[$section]['cache_dir']); } } $idPrefix = isset($options['id_prefix']) ? $options['id_prefix'] : ''; if (!$idPrefix && isset($options['prefix'])) { $idPrefix = $options['prefix']; } if (empty($idPrefix)) { $configDirPath = $this->_filesystem->getDirectoryRead(DirectoryList::CONFIG)->getAbsolutePath(); $idPrefix = // md5() here is not for cryptographic use. // phpcs:ignore Magento2.Security.InsecureFunction substr(md5($configDirPath), 0, 3) . '_'; } $options['frontend_options']['cache_id_prefix'] = $idPrefix; $backend = $this->_getBackendOptions($options); $frontend = $this->_getFrontendOptions($options); // Start profiling $profilerTags = [ 'group' => 'cache', 'operation' => 'cache:create', 'frontend_type' => $frontend['type'], 'backend_type' => $backend['type'], ]; Profiler::start('cache_frontend_create', $profilerTags); try { $result = $this->_objectManager->create( Zend::class, [ 'frontendFactory' => function () use ($frontend, $backend) { return Zend_Cache::factory( $frontend['type'], $backend['type'], $frontend, $backend['options'], true, true, true ); }, ] ); } catch (\Exception $e) { $result = $this->createCacheWithDefaultOptions($options); } $result = $this->_applyDecorators($result); // stop profiling Profiler::stop('cache_frontend_create'); return $result; } /** * Return options expanded with enforced values * * @param array $options * @return array */ private function _getExpandedOptions(array $options) { return array_replace_recursive($options, $this->_enforcedOptions); } /** * Apply decorators to a cache frontend instance and return the topmost one * * @param FrontendInterface $frontend * @return FrontendInterface * @throws LogicException * @throws UnexpectedValueException */ private function _applyDecorators(FrontendInterface $frontend) { foreach ($this->_decorators as $decoratorConfig) { if (!isset($decoratorConfig['class'])) { throw new LogicException('Class has to be specified for a cache frontend decorator.'); } $decoratorClass = $decoratorConfig['class']; $decoratorParams = isset($decoratorConfig['parameters']) ? $decoratorConfig['parameters'] : []; $decoratorParams['frontend'] = $frontend; // conventionally, 'frontend' argument is a decoration subject $frontend = $this->_objectManager->create($decoratorClass, $decoratorParams); if (!$frontend instanceof FrontendInterface) { throw new UnexpectedValueException('Decorator has to implement the cache frontend interface.'); } } return $frontend; } /** * Get cache backend options. Result array contain backend type ('type' key) and backend options ('options') * * @param array $cacheOptions * @return array * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) */ protected function _getBackendOptions(array $cacheOptions) { $enableTwoLevels = false; $type = isset($cacheOptions['backend']) ? $cacheOptions['backend'] : $this->_defaultBackend; if (isset($cacheOptions['backend_options']) && is_array($cacheOptions['backend_options'])) { $options = $cacheOptions['backend_options']; } else { $options = []; } $backendType = false; switch (strtolower($type)) { case 'sqlite': if (extension_loaded('sqlite') && isset($options['cache_db_complete_path'])) { $backendType = 'Sqlite'; } break; case 'memcached': if (extension_loaded('memcached')) { if (isset($cacheOptions['memcached'])) { $options = $cacheOptions['memcached']; } $enableTwoLevels = true; $backendType = 'Libmemcached'; } elseif (extension_loaded('memcache')) { if (isset($cacheOptions['memcached'])) { $options = $cacheOptions['memcached']; } $enableTwoLevels = true; $backendType = 'Memcached'; } break; case 'apc': if (extension_loaded('apc') && ini_get('apc.enabled')) { $enableTwoLevels = true; $backendType = 'Apc'; } break; case 'xcache': if (extension_loaded('xcache')) { $enableTwoLevels = true; $backendType = 'Xcache'; } break; case 'eaccelerator': case 'varien_cache_backend_eaccelerator': if (extension_loaded('eaccelerator') && ini_get('eaccelerator.enable')) { $enableTwoLevels = true; $backendType = Eaccelerator::class; } break; case 'database': $backendType = Database::class; $options = $this->_getDbAdapterOptions(); break; case 'remote_synchronized_cache': $backendType = RemoteSynchronizedCache::class; $options['remote_backend'] = Database::class; $options['remote_backend_options'] = $this->_getDbAdapterOptions(); $options['local_backend'] = Cm_Cache_Backend_File::class; $cacheDir = $this->_filesystem->getDirectoryWrite(DirectoryList::CACHE); $options['local_backend_options']['cache_dir'] = $cacheDir->getAbsolutePath(); $cacheDir->create(); break; default: if ($type != $this->_defaultBackend) { try { if (class_exists($type, true)) { $implements = class_implements($type, true); if (in_array('Zend_Cache_Backend_Interface', $implements)) { $backendType = $type; } } } catch (Exception $e) { } } } if (!$backendType) { $backendType = $this->_defaultBackend; $cacheDir = $this->_filesystem->getDirectoryWrite(DirectoryList::CACHE); $this->_backendOptions['cache_dir'] = $cacheDir->getAbsolutePath(); $cacheDir->create(); } foreach ($this->_backendOptions as $option => $value) { if (!array_key_exists($option, $options)) { $options[$option] = $value; } } $backendOptions = ['type' => $backendType, 'options' => $options]; if ($enableTwoLevels) { $backendOptions = $this->_getTwoLevelsBackendOptions($backendOptions, $cacheOptions); } return $backendOptions; } /** * Get options for database backend type * * @return array */ protected function _getDbAdapterOptions() { $options['adapter_callback'] = function () { return $this->_resource->getConnection(); }; $options['data_table_callback'] = function () { return $this->_resource->getTableName('cache'); }; $options['tags_table_callback'] = function () { return $this->_resource->getTableName('cache_tag'); }; return $options; } /** * Initialize two levels backend model options * * @param array $fastOptions fast level backend type and options * @param array $cacheOptions all cache options * @return array */ protected function _getTwoLevelsBackendOptions($fastOptions, $cacheOptions) { $options = []; $options['fast_backend'] = $fastOptions['type']; $options['fast_backend_options'] = $fastOptions['options']; $options['fast_backend_custom_naming'] = true; $options['fast_backend_autoload'] = true; $options['slow_backend_custom_naming'] = true; $options['slow_backend_autoload'] = true; if (isset($cacheOptions['auto_refresh_fast_cache'])) { $options['auto_refresh_fast_cache'] = (bool)$cacheOptions['auto_refresh_fast_cache']; } else { $options['auto_refresh_fast_cache'] = false; } if (isset($cacheOptions['slow_backend'])) { $options['slow_backend'] = $cacheOptions['slow_backend']; } else { $options['slow_backend'] = $this->_defaultBackend; } if (isset($cacheOptions['slow_backend_options'])) { $options['slow_backend_options'] = $cacheOptions['slow_backend_options']; } else { $options['slow_backend_options'] = $this->_backendOptions; } if ($options['slow_backend'] == 'database') { $options['slow_backend'] = Database::class; $options['slow_backend_options'] = $this->_getDbAdapterOptions(); if (isset($cacheOptions['slow_backend_store_data'])) { $options['slow_backend_options']['store_data'] = (bool)$cacheOptions['slow_backend_store_data']; } else { $options['slow_backend_options']['store_data'] = false; } } $backend = ['type' => 'TwoLevels', 'options' => $options]; return $backend; } /** * Get options of cache frontend (options of \Zend_Cache_Core) * * @param array $cacheOptions * @return array * @SuppressWarnings(PHPMD.NPathComplexity) */ protected function _getFrontendOptions(array $cacheOptions) { $options = isset($cacheOptions['frontend_options']) ? $cacheOptions['frontend_options'] : []; if (!array_key_exists('caching', $options)) { $options['caching'] = true; } if (!array_key_exists('lifetime', $options)) { $options['lifetime'] = isset( $cacheOptions['lifetime'] ) ? $cacheOptions['lifetime'] : self::DEFAULT_LIFETIME; } if (!array_key_exists('automatic_cleaning_factor', $options)) { $options['automatic_cleaning_factor'] = 0; } $options['type'] = isset($cacheOptions['frontend']) ? $cacheOptions['frontend'] : Core::class; return $options; } /** * Create frontend cache with default options. * * @param array $options * @return Zend */ private function createCacheWithDefaultOptions(array $options): Zend { unset($options['backend']); unset($options['frontend']); $backend = $this->_getBackendOptions($options); $frontend = $this->_getFrontendOptions($options); return $this->_objectManager->create( Zend::class, [ 'frontendFactory' => function () use ($frontend, $backend) { return Zend_Cache::factory( $frontend['type'], $backend['type'], $frontend, $backend['options'], true, true, true ); }, ] ); } }