From 62ed07a6c4d6bf0febb9bb406ba929c08f1bc370 Mon Sep 17 00:00:00 2001 From: Justin Beaty Date: Tue, 3 Dec 2024 07:27:14 -0800 Subject: [PATCH 01/15] Better autoloading --- app/Mage.php | 60 +----- app/bootstrap.php | 40 +++- app/code/core/Mage/Api/Model/Wsdl/Config.php | 8 +- app/code/core/Mage/Core/Block/Template.php | 4 +- .../Controller/Varien/Router/Standard.php | 2 +- app/code/core/Mage/Core/Model/Config.php | 38 ++-- .../core/Mage/Core/Model/Config/System.php | 4 +- .../core/Mage/Core/Model/Design/Config.php | 13 +- .../core/Mage/Core/Model/Design/Package.php | 6 +- .../core/Mage/Core/Model/Resource/Setup.php | 63 +++---- .../Core/Model/Session/Abstract/Varien.php | 2 +- app/code/core/Mage/Core/Model/Translate.php | 4 +- app/code/core/Mage/Core/functions.php | 77 +------- app/code/core/Mage/Install/Block/Begin.php | 2 +- .../Mage/Install/Model/Installer/Config.php | 2 +- .../Mage/Widget/Model/Widget/Instance.php | 2 +- composer.json | 5 +- composer.lock | 44 +++-- lib/Maho.php | 173 ++++++++++++++++++ lib/Varien/Simplexml/Config.php | 4 +- public/api.php | 8 +- public/index.php | 12 +- 22 files changed, 297 insertions(+), 276 deletions(-) create mode 100644 lib/Maho.php diff --git a/app/Mage.php b/app/Mage.php index 80006dd17..e6d64a928 100644 --- a/app/Mage.php +++ b/app/Mage.php @@ -10,55 +10,6 @@ * @license https://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -define('DS', DIRECTORY_SEPARATOR); -define('PS', PATH_SEPARATOR); -define('BP', MAHO_ROOT_DIR); - -/* - * Require Composer autoloader and set include paths - * @var \Composer\Autoload\ClassLoader $composerClassLoader - */ -$composerClassLoader = require BP . '/vendor/autoload.php'; -set_include_path(implode(PS, \Maho\MahoAutoload::generatePaths(BP)) . PS . get_include_path()); - -if (!empty($_SERVER['MAGE_IS_DEVELOPER_MODE']) || !empty($_ENV['MAGE_IS_DEVELOPER_MODE'])) { - Mage::setIsDeveloperMode(true); - ini_set('display_errors', '1'); - ini_set('error_prepend_string', '
');
-    ini_set('error_append_string', '
'); - - // Fix for overriding zf1-future during development - ini_set('opcache.revalidate_path', 1); - - // Check if we used `composer dump --optimize-autoloader` in development - $classMap = $composerClassLoader->getClassMap(); - if (isset($classMap['Mage_Core_Model_App'])) { - Mage::addBootupWarning('Optimized autoloader detected in developer mode.'); - } - - // Reload PSR-0 namespaces and controller classmap during development in case new files are added - $prefixes = $composerClassLoader->getPrefixes(); - foreach (\Maho\MahoAutoload::generatePsr0(BP) as $prefix => $paths) { - $prefixes[$prefix] ??= []; - if (count($prefixes[$prefix])) { - $prefixes[$prefix] = array_diff($prefixes[$prefix], $paths); - } - array_push($prefixes[$prefix], ...$paths); - $composerClassLoader->set($prefix, $paths); - } - $composerClassLoader->addClassMap(\Maho\MahoAutoload::generateControllerClassMap(BP)); -} - -require_once __DIR__ . '/code/core/Mage/Core/functions.php'; - -/** - * Support additional includes, originally used for OpenMage composer support - * See: https://github.com/OpenMage/magento-lts/pull/559 - */ -foreach (glob(BP . '/app/etc/includes/*.php') as $path) { - include_once $path; -} - /** * Main Mage hub class */ @@ -588,9 +539,8 @@ public static function throwException($message, $messageStorage = null) public static function addBootupWarning(string $message) { - $messages = Mage::registry('bootup_warnings') ?? []; - $messages[] = $message; - Mage::register('bootup_warnings', $message); + self::$_registry['bootup_warnings'] ??= []; + self::$_registry['bootup_warnings'][] = $message; } /** @@ -642,7 +592,7 @@ public static function init($code = '', $type = 'store', $options = [], $modules header('Location: ' . self::getBaseUrl()); die; } catch (Mage_Core_Model_Store_Exception $e) { - mahoErrorReport([], 404); + Maho::errorReport([], 404); die; } catch (Exception $e) { self::printException($e); @@ -685,7 +635,7 @@ public static function run($code = '', $type = 'store', $options = []) header('Location: ' . self::getBaseUrl()); die(); } catch (Mage_Core_Model_Store_Exception $e) { - mahoErrorReport([], 404); + Maho::errorReport([], 404); die(); } catch (Exception $e) { if (self::isInstalled()) { @@ -926,7 +876,7 @@ public static function printException(Throwable $e, $extra = '') $reportData['script_name'] = $_SERVER['SCRIPT_NAME']; } - mahoErrorReport($reportData); + Maho::errorReport($reportData); } die(); diff --git a/app/bootstrap.php b/app/bootstrap.php index cde8e1812..e0a86e3b9 100644 --- a/app/bootstrap.php +++ b/app/bootstrap.php @@ -6,14 +6,40 @@ * @package Mage * @copyright Copyright (c) 2006-2020 Magento, Inc. (https://magento.com) * @copyright Copyright (c) 2020-2022 The OpenMage Contributors (https://openmage.org) + * @copyright Copyright (c) 2024 Maho (https://mahocommerce.com) * @license https://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -/** - * Apply workaround for the libxml PHP bugs: - * @link https://bugs.php.net/bug.php?id=62577 - * @link https://bugs.php.net/bug.php?id=64938 - */ -if ((LIBXML_VERSION < 20900) && function_exists('libxml_disable_entity_loader')) { - libxml_disable_entity_loader(false); +if (file_exists(__DIR__ . '/../vendor/autoload.php')) { + require __DIR__ . '/../vendor/autoload.php'; +} elseif (file_exists(__DIR__ . '/../../../autoload.php')) { + require __DIR__ . '/../../../vendor/autoload.php'; +} else { + throw new Exception('Autoloader not found. Please run \'composer install\'.'); +} + +defined('DS') || define('DS', DIRECTORY_SEPARATOR); +defined('PS') || define('PS', PATH_SEPARATOR); +defined('BP') || define('BP', Maho::getBasePath()); + +/** @deprecated */ +defined('MAGENTO_ROOT') || define('MAGENTO_ROOT', BP); + +if (!empty($_SERVER['MAGE_IS_DEVELOPER_MODE']) || !empty($_ENV['MAGE_IS_DEVELOPER_MODE'])) { + Mage::setIsDeveloperMode(true); + + ini_set('display_errors', '1'); + ini_set('error_prepend_string', '
');
+    ini_set('error_append_string', '
'); + + // Fix for overriding zf1-future during development + ini_set('opcache.revalidate_path', 1); + + // Update Composer's autoloader during development in case new files are added + Maho::updateComposerAutoloader(); + + // Check if we used `composer dump --optimize-autoloader` in development + if (Maho::isComposerAutoloaderOptimized()) { + Mage::addBootupWarning('Optimized autoloader detected in developer mode.'); + } } diff --git a/app/code/core/Mage/Api/Model/Wsdl/Config.php b/app/code/core/Mage/Api/Model/Wsdl/Config.php index 0719ab704..77cda61c1 100644 --- a/app/code/core/Mage/Api/Model/Wsdl/Config.php +++ b/app/code/core/Mage/Api/Model/Wsdl/Config.php @@ -120,10 +120,10 @@ public function init() * Exclude Mage_Api wsdl xml file because it used for previous version * of API wsdl declaration */ - $mergeWsdl->addLoadedFile(mahoFindFileInIncludePath("$moduleDir/wsi.xml")); + $mergeWsdl->addLoadedFile(Maho::findFile("$moduleDir/wsi.xml")); // Base wsi file - $this->loadFile(mahoFindFileInIncludePath("$moduleDir/wsi.xml")); + $this->loadFile(Maho::findFile("$moduleDir/wsi.xml")); Mage::getConfig()->loadModulesConfiguration('wsi.xml', $this, $mergeWsdl); } else { @@ -131,10 +131,10 @@ public function init() * Exclude Mage_Api wsdl xml file because it used for previous version * of API wsdl declaration */ - $mergeWsdl->addLoadedFile(mahoFindFileInIncludePath("$moduleDir/wsdl.xml")); + $mergeWsdl->addLoadedFile(Maho::findFile("$moduleDir/wsdl.xml")); // Base wsdl file - $this->loadFile(mahoFindFileInIncludePath("$moduleDir/wsdl2.xml")); + $this->loadFile(Maho::findFile("$moduleDir/wsdl2.xml")); Mage::getConfig()->loadModulesConfiguration('wsdl.xml', $this, $mergeWsdl); } diff --git a/app/code/core/Mage/Core/Block/Template.php b/app/code/core/Mage/Core/Block/Template.php index f5bc7470a..f5cfffaca 100644 --- a/app/code/core/Mage/Core/Block/Template.php +++ b/app/code/core/Mage/Core/Block/Template.php @@ -267,9 +267,9 @@ public function fetchView($fileName) && ($this->_viewDir == Mage::getBaseDir('design') || str_starts_with(realpath($this->_viewDir), realpath(Mage::getBaseDir('design')))) ) { - $fileToInclude = mahoFindFileInIncludePath($fileName); + $fileToInclude = Maho::findFile($fileName); if (!$fileToInclude) { - $fileToInclude = mahoFindFileInIncludePath($this->_viewDir . DS . $fileName); + $fileToInclude = Maho::findFile($this->_viewDir . DS . $fileName); } include $fileToInclude; } else { diff --git a/app/code/core/Mage/Core/Controller/Varien/Router/Standard.php b/app/code/core/Mage/Core/Controller/Varien/Router/Standard.php index 461addf07..48b93faa6 100644 --- a/app/code/core/Mage/Core/Controller/Varien/Router/Standard.php +++ b/app/code/core/Mage/Core/Controller/Varien/Router/Standard.php @@ -417,7 +417,7 @@ public function getControllerFileName($realModule, $controller) $file .= DS . implode(DS, $parts); } $file .= DS . uc_words($controller, DS) . 'Controller.php'; - $file = mahoFindFileInIncludePath($file); + $file = Maho::findFile($file); return $file; } diff --git a/app/code/core/Mage/Core/Model/Config.php b/app/code/core/Mage/Core/Model/Config.php index 5b2eeaf2e..e294c5717 100644 --- a/app/code/core/Mage/Core/Model/Config.php +++ b/app/code/core/Mage/Core/Model/Config.php @@ -325,22 +325,16 @@ public function loadBase() { $files = []; - // Include Maho core and 3rd party module files - $modules = \Maho\MahoAutoload::getInstalledModules(BP); - foreach ($modules as $module => $info) { + foreach (Maho::getInstalledPackages() as $package => $info) { foreach (glob($info['path'] . '/app/etc/*.xml') as $file) { - $files[basename($file)] = $file; + $basename = basename($file); + if ($basename === 'local.xml' && $package !== 'root') { + continue; + } + $files[$basename] = $file; } } - // Prevent any module from defining a local.xml - unset($files['local.xml']); - - // Include local files, overriding core and 3rd party module files - foreach (glob($this->getOptions()->getEtcDir() . '/*.xml') as $file) { - $files[basename($file)] = $file; - } - // Merge all config files $this->loadFile(current($files)); while ($file = next($files)) { @@ -503,7 +497,7 @@ public function getCacheSaveLock($waitTime = null, $ignoreFailure = false) throw new Exception('Could not get lock on cache save operation.'); } else { Mage::log(sprintf('Failed to get cache save lock in %d seconds.', $waitTime), Zend_Log::NOTICE); - mahoErrorReport(); + Maho::errorReport(); die(); } } @@ -780,20 +774,13 @@ protected function _getDeclaredModuleFiles() { $moduleFiles = []; - // Include Maho core and 3rd party module files - $modules = \Maho\MahoAutoload::getInstalledModules(BP); - foreach ($modules as $module => $info) { + foreach (Maho::getInstalledPackages() as $package => $info) { foreach (glob($info['path'] . '/app/etc/modules/*.xml') as $file) { $moduleFiles[basename($file)] = $file; } } - // Include local files, overriding core and 3rd party module files - foreach (glob($this->getOptions()->getEtcDir() . '/modules/*.xml') as $file) { - $moduleFiles[basename($file)] = $file; - } - - if (!$moduleFiles) { + if (empty($moduleFiles)) { return false; } @@ -803,9 +790,7 @@ protected function _getDeclaredModuleFiles() ]; foreach ($moduleFiles as $v) { - $name = explode(DIRECTORY_SEPARATOR, $v); - $name = substr($name[count($name) - 1], 0, -4); - + $name = pathinfo($v, PATHINFO_FILENAME); if (array_key_exists($name, self::MAGE_MODULES)) { $collectModuleFiles['mage'][self::MAGE_MODULES[$name]] = $v; } else { @@ -1037,6 +1022,7 @@ public function loadModulesConfiguration($fileName, $mergeToObject = null, $merg if ($mergeModel === null) { $mergeModel = clone $this->_prototype; } + $modules = $this->getNode('modules')->children(); foreach ($modules as $modName => $module) { if ($module->is('active')) { @@ -1046,7 +1032,7 @@ public function loadModulesConfiguration($fileName, $mergeToObject = null, $merg foreach ($fileName as $configFile) { $moduleDir = $this->getModuleDir('etc', $modName); - $configFile = mahoFindFileInIncludePath("$moduleDir/$configFile"); + $configFile = Maho::findFile("$moduleDir/$configFile"); if ($mergeModel->loadFile($configFile)) { $this->_makeEventsLowerCase(Mage_Core_Model_App_Area::AREA_GLOBAL, $mergeModel); diff --git a/app/code/core/Mage/Core/Model/Config/System.php b/app/code/core/Mage/Core/Model/Config/System.php index aea388b48..ad029527d 100644 --- a/app/code/core/Mage/Core/Model/Config/System.php +++ b/app/code/core/Mage/Core/Model/Config/System.php @@ -23,9 +23,7 @@ class Mage_Core_Model_Config_System extends Mage_Core_Model_Config_Base */ public function load($module) { - $file = Mage::getConfig()->getModuleDir('etc', $module) . DS . 'system.xml'; - $file = mahoFindFileInIncludePath($file); - $this->loadFile($file); + $this->loadFile(Maho::findFile(Mage::getConfig()->getModuleDir('etc', $module) . '/system.xml')); return $this; } } diff --git a/app/code/core/Mage/Core/Model/Design/Config.php b/app/code/core/Mage/Core/Model/Design/Config.php index 86f394729..7fd5dfbad 100644 --- a/app/code/core/Mage/Core/Model/Design/Config.php +++ b/app/code/core/Mage/Core/Model/Design/Config.php @@ -42,21 +42,12 @@ public function __construct(array $params = []) $files = []; - // Include Maho core and 3rd party module files - $modules = \Maho\MahoAutoload::getInstalledModules(BP); - foreach ($modules as $module => $info) { + foreach (Maho::getInstalledPackages() as $info) { foreach (glob($info['path'] . '/app/design/*/*/*/etc/theme.xml') as $file) { - $normalizedFile = str_replace($info['path'] . '/app/design', '', $file); - $files[$normalizedFile] = $file; + $files[Maho::toRelativePath($file)] = $file; } } - // Include local files, overriding core and 3rd party module files - foreach (glob($this->_designRoot . '/*/*/*/etc/theme.xml') as $file) { - $normalizedFile = str_replace($this->_designRoot, '', $file); - $files[$normalizedFile] = $file; - } - foreach ($files as $file) { $config = new Varien_Simplexml_Config(); $config->loadFile($file); diff --git a/app/code/core/Mage/Core/Model/Design/Package.php b/app/code/core/Mage/Core/Model/Design/Package.php index b6e625c22..492f359c4 100644 --- a/app/code/core/Mage/Core/Model/Design/Package.php +++ b/app/code/core/Mage/Core/Model/Design/Package.php @@ -373,7 +373,7 @@ public function validateFile($file, array $params) { $fileName = $this->_renderFilename($file, $params); $fileName = (empty($params['_relative']) ? '' : Mage::getBaseDir('design') . DS) . $fileName; - $fileName = mahoFindFileInIncludePath($fileName); + $fileName = Maho::findFile($fileName); return $fileName; } @@ -538,7 +538,7 @@ public function getSkinUrl($file = null, array $params = []) public function getPackageList() { $directory = Mage::getBaseDir('design') . DS . 'frontend'; - return mahoListDirectories($directory); + return Maho::listDirectories($directory); } /** @@ -556,7 +556,7 @@ public function getThemeList($package = null) } } else { $directory = Mage::getBaseDir('design') . DS . 'frontend' . DS . $package; - $result = mahoListDirectories($directory); + $result = Maho::listDirectories($directory); } return $result; diff --git a/app/code/core/Mage/Core/Model/Resource/Setup.php b/app/code/core/Mage/Core/Model/Resource/Setup.php index b5ab22490..c65314dd2 100644 --- a/app/code/core/Mage/Core/Model/Resource/Setup.php +++ b/app/code/core/Mage/Core/Model/Resource/Setup.php @@ -512,26 +512,20 @@ protected function _getAvailableDbFiles($actionType, $fromVersion, $toVersion) $resModel = (string)$this->_connectionConfig->model; $modName = (string)$this->_moduleConfig[0]->getName(); - $filesDir = Mage::getModuleDir('sql', $modName) . DS . $this->_resourceName; - $filesDir = mahoFindFileInIncludePath($filesDir); - if (!is_dir($filesDir) || !is_readable($filesDir)) { - return []; - } - $dbFiles = []; $typeFiles = []; $regExpDb = sprintf('#^%s-(.*)\.(php|sql)$#i', $actionType); $regExpType = sprintf('#^%s-%s-(.*)\.(php|sql)$#i', $resModel, $actionType); - $handlerDir = dir($filesDir); - while (($file = $handlerDir->read()) !== false) { + + $filesDir = Mage::getModuleDir('sql', $modName) . DS . $this->_resourceName; + foreach (Maho::globPackages("$filesDir/*") as $file) { $matches = []; if (preg_match($regExpDb, $file, $matches)) { - $dbFiles[$matches[1]] = $filesDir . DS . $file; + $dbFiles[$matches[1]] = "$filesDir/$file"; } elseif (preg_match($regExpType, $file, $matches)) { - $typeFiles[$matches[1]] = $filesDir . DS . $file; + $typeFiles[$matches[1]] = "$filesDir/$file"; } } - $handlerDir->close(); if (empty($typeFiles) && empty($dbFiles)) { return []; @@ -557,33 +551,24 @@ protected function _getAvailableDataFiles($actionType, $fromVersion, $toVersion) $modName = (string)$this->_moduleConfig[0]->getName(); $files = []; + $regExp = sprintf('#^%s-(.*)\.php$#i', $actionType); + $regExpOld = sprintf('#^%s-%s-(.*)\.php$#i', $this->_connectionConfig->model, $actionType); + $filesDir = Mage::getModuleDir('data', $modName) . DS . $this->_resourceName; - $filesDir = mahoFindFileInIncludePath($filesDir); - if (is_dir($filesDir) && is_readable($filesDir)) { - $regExp = sprintf('#^%s-(.*)\.php$#i', $actionType); - $handlerDir = dir($filesDir); - while (($file = $handlerDir->read()) !== false) { - $matches = []; - if (preg_match($regExp, $file, $matches)) { - $files[$matches[1]] = $filesDir . DS . $file; - } + foreach (Maho::globPackages("$filesDir/*") as $file) { + $matches = []; + if (preg_match($regExp, $file, $matches)) { + $files[$matches[1]] = "$filesDir/$file"; } - $handlerDir->close(); } // search data files in old location $filesDir = Mage::getModuleDir('sql', $modName) . DS . $this->_resourceName; - if (is_dir($filesDir) && is_readable($filesDir)) { - $regExp = sprintf('#^%s-%s-(.*)\.php$#i', $this->_connectionConfig->model, $actionType); - $handlerDir = dir($filesDir); - - while (($file = $handlerDir->read()) !== false) { - $matches = []; - if (preg_match($regExp, $file, $matches)) { - $files[$matches[1]] = $filesDir . DS . $file; - } + foreach (Maho::globPackages("$filesDir/*") as $file) { + $matches = []; + if (preg_match($regExpOld, $file, $matches)) { + $files[$matches[1]] = "$filesDir/$file"; } - $handlerDir->close(); } if (empty($files)) { @@ -601,18 +586,14 @@ protected function _getAvailableMahoFiles(string $actionType, string $fromVersio $modName = (string)$this->_moduleConfig[0]->getName(); $files = []; + $regExp = sprintf('#^%s-(.*)\.php$#i', $actionType); + $filesDir = Mage::getModuleDir('sql', $modName) . DS . 'maho_setup'; - $filesDir = mahoFindFileInIncludePath($filesDir); - if (is_dir($filesDir) && is_readable($filesDir)) { - $regExp = sprintf('#^%s-(.*)\.php$#i', $actionType); - $handlerDir = dir($filesDir); - while (($file = $handlerDir->read()) !== false) { - $matches = []; - if (preg_match($regExp, $file, $matches)) { - $files[$matches[1]] = $filesDir . DS . $file; - } + foreach (Maho::globPackages("$filesDir/*") as $file) { + $matches = []; + if (preg_match($regExp, $file, $matches)) { + $files[$matches[1]] = "$filesDir/$file"; } - $handlerDir->close(); } if (empty($files)) { diff --git a/app/code/core/Mage/Core/Model/Session/Abstract/Varien.php b/app/code/core/Mage/Core/Model/Session/Abstract/Varien.php index f0ee5b447..49594fc27 100644 --- a/app/code/core/Mage/Core/Model/Session/Abstract/Varien.php +++ b/app/code/core/Mage/Core/Model/Session/Abstract/Varien.php @@ -146,7 +146,7 @@ public function start($sessionName = null) } catch (Throwable $e) { session_abort(); if (Mage::registry(self::REGISTRY_CONCURRENCY_ERROR)) { - mahoErrorReport(); + Maho::errorReport(); die(); } else { Mage::printException($e); diff --git a/app/code/core/Mage/Core/Model/Translate.php b/app/code/core/Mage/Core/Model/Translate.php index d693ee669..f277c8f38 100644 --- a/app/code/core/Mage/Core/Model/Translate.php +++ b/app/code/core/Mage/Core/Model/Translate.php @@ -292,9 +292,7 @@ protected function _loadDbTranslation($forceReload = false) */ protected function _getModuleFilePath($module, $fileName) { - $file = "app/locale/{$this->getLocale()}/{$fileName}"; - $file = mahoFindFileInIncludePath($file); - return $file; + return Maho::findFile("app/locale/{$this->getLocale()}/{$fileName}"); } /** diff --git a/app/code/core/Mage/Core/functions.php b/app/code/core/Mage/Core/functions.php index 953873fc2..db23714df 100644 --- a/app/code/core/Mage/Core/functions.php +++ b/app/code/core/Mage/Core/functions.php @@ -71,9 +71,7 @@ function is_empty_date($date) */ function mageFindClassFile($class) { - /** @var \Composer\Autoload\ClassLoader $composerClassLoader */ - $composerClassLoader = require BP . '/vendor/autoload.php'; - return $composerClassLoader->findFile($class); + return Maho::findClassFile($class); } /** @@ -295,76 +293,3 @@ function is_dir_writeable($dir) { return isDirWriteable($dir); } - -function mahoFindFileInIncludePath(string $path): string|false -{ - $paths = []; - $paths[] = BP; - - $modules = \Maho\MahoAutoload::getInstalledModules(BP); - foreach ($modules as $module => $info) { - if ($module === 'mahocommerce/maho') { - continue; - } - $paths[] = $info['path']; - } - if ($modules['mahocommerce/maho']['isChildProject']) { - $paths[] = $modules['mahocommerce/maho']['path']; - } - - $relativePath = str_replace(array_reverse($paths), '', $path); - $relativePath = ltrim($relativePath, '/'); - - // Temporarily set include paths, then revert - $oldPaths = get_include_path(); - set_include_path(implode(PS, $paths)); - $file = stream_resolve_include_path($relativePath); - set_include_path($oldPaths); - - return $file; -} - -function mahoListDirectories(string $path): array -{ - $results = []; - $relativePath = str_replace(BP . '/', '', $path); - - foreach (glob("$path/*", GLOB_ONLYDIR) as $folder) { - $results[] = basename($folder); - } - - $modules = \Maho\MahoAutoload::getInstalledModules(BP); - foreach ($modules as $module => $info) { - foreach (glob($info['path'] . "/$relativePath/*", GLOB_ONLYDIR) as $folder) { - $results[] = basename($folder); - } - } - - return array_unique($results); -} - -function mahoErrorReport(array $reportData = [], int $httpResponseCode = 503): void -{ - $reportIdMessage = ''; - if ($reportData) { - $reportId = abs((int)(microtime(true) * random_int(100, 1000))); - $reportIdMessage = "

Error log record number: {$reportId}

"; - $reportDir = Mage::getBaseDir('var') . '/report'; - if (!file_exists($reportDir)) { - @mkdir($reportDir, 0750, true); - } - - $reportFile = "{$reportDir}/$reportId"; - $reportData = array_map('strip_tags', $reportData); - @file_put_contents($reportFile, serialize($reportData)); - @chmod($reportFile, 0640); - } - - $description = match ($httpResponseCode) { - 404 => 'Not Found', - 503 => 'Service Unavailable', - default => '', - }; - header("HTTP/1.1 {$httpResponseCode} {$description}", true, $httpResponseCode); - echo "

There has been an error processing your request

{$reportIdMessage}"; -} diff --git a/app/code/core/Mage/Install/Block/Begin.php b/app/code/core/Mage/Install/Block/Begin.php index bdebd1b1f..e4786a91e 100644 --- a/app/code/core/Mage/Install/Block/Begin.php +++ b/app/code/core/Mage/Install/Block/Begin.php @@ -52,6 +52,6 @@ public function getPostUrl() */ public function getLicenseHtml() { - return nl2br(file_get_contents(mahoFindFileInIncludePath((string)Mage::getConfig()->getNode('install/eula_file')))); + return nl2br(file_get_contents(Maho::findFile((string)Mage::getConfig()->getNode('install/eula_file')))); } } diff --git a/app/code/core/Mage/Install/Model/Installer/Config.php b/app/code/core/Mage/Install/Model/Installer/Config.php index 6f1220fd9..54d7242b5 100644 --- a/app/code/core/Mage/Install/Model/Installer/Config.php +++ b/app/code/core/Mage/Install/Model/Installer/Config.php @@ -78,7 +78,7 @@ public function install() $this->_getInstaller()->getDataModel()->setConfigData($data); - $template = file_get_contents(mahoFindFileInIncludePath(Mage::getBaseDir('etc') . DS . 'local.xml.template')); + $template = file_get_contents(Maho::findFile(Mage::getBaseDir('etc') . DS . 'local.xml.template')); foreach ($data as $index => $value) { $template = str_replace('{{' . $index . '}}', '', $template); } diff --git a/app/code/core/Mage/Widget/Model/Widget/Instance.php b/app/code/core/Mage/Widget/Model/Widget/Instance.php index 1e21a73c6..e728eaf0c 100644 --- a/app/code/core/Mage/Widget/Model/Widget/Instance.php +++ b/app/code/core/Mage/Widget/Model/Widget/Instance.php @@ -381,7 +381,7 @@ public function getWidgetConfig() '_theme' => $this->getTheme(), '_type' => 'etc' ]) . DS . 'widget.xml'; - $configFile = mahoFindFileInIncludePath($configFile); + $configFile = Maho::findFile($configFile); if (is_readable($configFile)) { $themeWidgetsConfig = new Varien_Simplexml_Config(); $themeWidgetsConfig->loadFile($configFile); diff --git a/composer.json b/composer.json index 94c9daa79..d46d16d08 100644 --- a/composer.json +++ b/composer.json @@ -6,6 +6,9 @@ "OSL-3.0", "AFL-3.0" ], + "repositories": [ + { "type": "git", "url": "https://github.com/justinbeaty/maho-composer-plugin.git" } + ], "type": "maho-source", "require": { "php": ">=8.2", @@ -33,7 +36,7 @@ "composer-runtime-api": "^2", "cweagans/composer-patches": "^1.7", "ezyang/htmlpurifier": "^4.17", - "mahocommerce/maho-composer-plugin": "^2", + "mahocommerce/maho-composer-plugin": "dev-topic-v3", "pelago/emogrifier": "^7.0", "phpseclib/mcrypt_compat": "^2.0.3", "phpseclib/phpseclib": "^3.0.14", diff --git a/composer.lock b/composer.lock index 7f4e1e75d..e453dc541 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "c55c597d2e92396f3255ab3fd01d284b", + "content-hash": "4506ffa474bba19a96a5f333495e73bb", "packages": [ { "name": "cweagans/composer-patches", @@ -117,36 +117,38 @@ }, { "name": "mahocommerce/maho-composer-plugin", - "version": "v2.1.0", + "version": "dev-topic-v3", "source": { "type": "git", - "url": "https://github.com/MahoCommerce/maho-composer-plugin.git", - "reference": "f27036354a10aa699718c9e3828fb2b2720eb94e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/MahoCommerce/maho-composer-plugin/zipball/f27036354a10aa699718c9e3828fb2b2720eb94e", - "reference": "f27036354a10aa699718c9e3828fb2b2720eb94e", - "shasum": "" + "url": "https://github.com/justinbeaty/maho-composer-plugin.git", + "reference": "5d79023ffea6c0dda505c87cb02c039f9468ad03" }, "require": { - "composer-plugin-api": "^2.0" + "composer-plugin-api": "^2.1" + }, + "require-dev": { + "composer/composer": "^2.8", + "phpstan/phpstan": "^2.0", + "phpstan/phpstan-deprecation-rules": "^2.0", + "phpstan/phpstan-strict-rules": "^2.0" }, "type": "composer-plugin", "extra": { - "class": "Maho\\MahoComposerPlugin" + "class": [ + "Maho\\ComposerPlugin\\FileCopyPlugin", + "Maho\\ComposerPlugin\\AutoloadPlugin" + ] }, "autoload": { "psr-4": { - "Maho\\": "src/" + "Maho\\ComposerPlugin\\": "src/" } }, - "notification-url": "https://packagist.org/downloads/", - "support": { - "issues": "https://github.com/MahoCommerce/maho-composer-plugin/issues", - "source": "https://github.com/MahoCommerce/maho-composer-plugin/tree/v2.1.0" - }, - "time": "2024-11-15T10:31:25+00:00" + "license": [ + "MIT" + ], + "description": "Extension for Composer to copy assets and enable autoloading for Maho projects.", + "time": "2024-12-03T14:44:11+00:00" }, { "name": "paragonie/constant_time_encoding", @@ -3030,7 +3032,9 @@ ], "aliases": [], "minimum-stability": "dev", - "stability-flags": {}, + "stability-flags": { + "mahocommerce/maho-composer-plugin": 20 + }, "prefer-stable": true, "prefer-lowest": false, "platform": { diff --git a/lib/Maho.php b/lib/Maho.php new file mode 100644 index 000000000..240ca5671 --- /dev/null +++ b/lib/Maho.php @@ -0,0 +1,173 @@ +addClassMap(AutoloadRuntime::generateClassMap()); + + foreach (AutoloadRuntime::generatePsr0() as $prefix => $paths) { + $composerClassLoader->add($prefix, $paths, true); + } + + $requireFile = \Closure::bind(static function ($file) { + require_once $file; + }, null, null); + + foreach (AutoloadRuntime::generateIncludeFiles() as $file) { + $requireFile($file); + } + } + + /** + * Check if Composer was run with the `--optimize` flag + */ + public static function isComposerAutoloaderOptimized(): bool + { + return isset(self::getComposerAutoloader()->getClassMap()['Mage_Core_Model_App']); + } + + /** + * Return the absolute path to a class file + */ + public static function findClassFile($class): string|false + { + return realpath(self::getComposerAutoloader()->findFile($class)); + } + + /** + * Generate an error report and output HTML + */ + public static function errorReport(array $reportData = [], int $httpResponseCode = 503): void + { + $reportIdMessage = ''; + if ($reportData) { + $reportId = abs((int)(microtime(true) * random_int(100, 1000))); + $reportIdMessage = "

Error log record number: {$reportId}

"; + $reportDir = Mage::getBaseDir('var') . '/report'; + if (!file_exists($reportDir)) { + @mkdir($reportDir, 0750, true); + } + + $reportFile = "{$reportDir}/$reportId"; + $reportData = array_map('strip_tags', $reportData); + @file_put_contents($reportFile, serialize($reportData)); + @chmod($reportFile, 0640); + } + + $description = match ($httpResponseCode) { + 404 => 'Not Found', + 503 => 'Service Unavailable', + default => '', + }; + header("HTTP/1.1 {$httpResponseCode} {$description}", true, $httpResponseCode); + echo "

There has been an error processing your request

{$reportIdMessage}"; + } +} diff --git a/lib/Varien/Simplexml/Config.php b/lib/Varien/Simplexml/Config.php index c94673251..24a886d86 100644 --- a/lib/Varien/Simplexml/Config.php +++ b/lib/Varien/Simplexml/Config.php @@ -422,10 +422,10 @@ public function loadFile($filePath) /** * All calls from core will be an absolute path, but for compatibility with - * 3rd party modules we will alternatively use mahoFindFileInIncludePath() + * 3rd party modules we will alternatively use Maho::findFile() */ if (!is_readable($filePath)) { - $filePath = mahoFindFileInIncludePath($filePath); + $filePath = Maho::findFile($filePath); if (!is_readable($filePath)) { //throw new Exception('Can not read xml file '.$filePath); return false; diff --git a/public/api.php b/public/api.php index 72f8c88be..381ad7135 100644 --- a/public/api.php +++ b/public/api.php @@ -15,13 +15,7 @@ define('MAHO_ROOT_DIR', dirname(__DIR__)); define('MAHO_PUBLIC_DIR', __DIR__); -if (file_exists(MAHO_ROOT_DIR . '/app/bootstrap.php')) { - require MAHO_ROOT_DIR . '/app/bootstrap.php'; - require MAHO_ROOT_DIR . '/app/Mage.php'; -} else { - require MAHO_ROOT_DIR . '/vendor/mahocommerce/maho/app/bootstrap.php'; - require MAHO_ROOT_DIR . '/vendor/mahocommerce/maho/app/Mage.php'; -} +require '../vendor/autoload.php'; if (!Mage::isInstalled()) { echo 'Application is not installed yet.'; diff --git a/public/index.php b/public/index.php index 5a4d727d0..9f04234ab 100644 --- a/public/index.php +++ b/public/index.php @@ -10,18 +10,10 @@ * @license https://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -/** @deprecated Use MAHO_ROOT_DIR instead. */ -define('MAGENTO_ROOT', dirname(__DIR__)); define('MAHO_ROOT_DIR', dirname(__DIR__)); define('MAHO_PUBLIC_DIR', __DIR__); -if (file_exists(MAHO_ROOT_DIR . '/app/bootstrap.php')) { - require MAHO_ROOT_DIR . '/app/bootstrap.php'; - require MAHO_ROOT_DIR . '/app/Mage.php'; -} else { - require MAHO_ROOT_DIR . '/vendor/mahocommerce/maho/app/bootstrap.php'; - require MAHO_ROOT_DIR . '/vendor/mahocommerce/maho/app/Mage.php'; -} +require '../vendor/autoload.php'; #Varien_Profiler::enable(); @@ -47,7 +39,7 @@ } } if (!$maintenanceBypass) { - mahoErrorReport(); + Maho::errorReport(); exit; } From aad38926e892610dbc079f650f0ad32c7fb9a4d5 Mon Sep 17 00:00:00 2001 From: Justin Beaty Date: Tue, 3 Dec 2024 08:28:30 -0800 Subject: [PATCH 02/15] fix child project --- app/bootstrap.php | 15 +++++++++------ lib/Maho.php | 16 ++++++++++------ public/api.php | 4 +--- public/index.php | 2 +- 4 files changed, 21 insertions(+), 16 deletions(-) diff --git a/app/bootstrap.php b/app/bootstrap.php index e0a86e3b9..46d2161a5 100644 --- a/app/bootstrap.php +++ b/app/bootstrap.php @@ -10,12 +10,15 @@ * @license https://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -if (file_exists(__DIR__ . '/../vendor/autoload.php')) { - require __DIR__ . '/../vendor/autoload.php'; -} elseif (file_exists(__DIR__ . '/../../../autoload.php')) { - require __DIR__ . '/../../../vendor/autoload.php'; -} else { - throw new Exception('Autoloader not found. Please run \'composer install\'.'); +// Require the autoloader if not already loaded +if (!class_exists('Maho')) { + if (file_exists(__DIR__ . '/../vendor/autoload.php')) { + require __DIR__ . '/../vendor/autoload.php'; + } elseif (file_exists(__DIR__ . '/../../../autoload.php')) { + require __DIR__ . '/../../../autoload.php'; + } else { + throw new Exception('Autoloader not found. Please run \'composer install\'.'); + } } defined('DS') || define('DS', DIRECTORY_SEPARATOR); diff --git a/lib/Maho.php b/lib/Maho.php index 240ca5671..01855f095 100644 --- a/lib/Maho.php +++ b/lib/Maho.php @@ -18,8 +18,9 @@ */ final class Maho { - /** @var ?ClassLoader */ - private static $composerClassLoader = null; + private static ?ClassLoader $composerClassLoader = null; + + private static ?string $bp = null; /** * Return an array of Maho packages installed by Composer @@ -36,7 +37,10 @@ public static function getInstalledPackages(): array */ public static function getBasePath(): string { - return self::getInstalledPackages()['root']['path']; + if (self::$bp === null) { + self::$bp = realpath(self::getInstalledPackages()['root']['path']); + } + return self::$bp; } /** @@ -44,9 +48,9 @@ public static function getBasePath(): string */ public static function toRelativePath(string $path): string { - $relativePath = str_replace(self::getBasePath(), '', $path); - $relativePath = preg_replace("/^\/?(vendor\/\w+\/\w+\/)?/", '', $relativePath); - return $relativePath; + $paths = array_column(self::getInstalledPackages(), 'path'); + usort($paths, fn ($a, $b) => strlen($b) <=> strlen($a)); + return ltrim(str_replace($paths, '', $path), '/'); } /** diff --git a/public/api.php b/public/api.php index 381ad7135..e602d80a9 100644 --- a/public/api.php +++ b/public/api.php @@ -10,12 +10,10 @@ * @license https://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0) */ -/** @deprecated Use MAHO_ROOT_DIR instead. */ -define('MAGENTO_ROOT', dirname(__DIR__)); define('MAHO_ROOT_DIR', dirname(__DIR__)); define('MAHO_PUBLIC_DIR', __DIR__); -require '../vendor/autoload.php'; +require MAHO_ROOT_DIR . '/vendor/autoload.php'; if (!Mage::isInstalled()) { echo 'Application is not installed yet.'; diff --git a/public/index.php b/public/index.php index 9f04234ab..3f39ef163 100644 --- a/public/index.php +++ b/public/index.php @@ -13,7 +13,7 @@ define('MAHO_ROOT_DIR', dirname(__DIR__)); define('MAHO_PUBLIC_DIR', __DIR__); -require '../vendor/autoload.php'; +require MAHO_ROOT_DIR . '/vendor/autoload.php'; #Varien_Profiler::enable(); From 31a528fdc82c4b04f83c989b2645d7d8c5008dc4 Mon Sep 17 00:00:00 2001 From: Justin Beaty Date: Tue, 3 Dec 2024 13:47:10 -0800 Subject: [PATCH 03/15] Change class_exists check --- app/bootstrap.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/bootstrap.php b/app/bootstrap.php index 46d2161a5..8a67f1c2f 100644 --- a/app/bootstrap.php +++ b/app/bootstrap.php @@ -11,7 +11,7 @@ */ // Require the autoloader if not already loaded -if (!class_exists('Maho')) { +if (!class_exists('Mage')) { if (file_exists(__DIR__ . '/../vendor/autoload.php')) { require __DIR__ . '/../vendor/autoload.php'; } elseif (file_exists(__DIR__ . '/../../../autoload.php')) { From ecf8988a6231ecae58fa1264c0207bfe4971d85e Mon Sep 17 00:00:00 2001 From: Justin Beaty Date: Tue, 3 Dec 2024 14:47:10 -0800 Subject: [PATCH 04/15] update plugin --- composer.json | 1 + composer.lock | 10 ++++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/composer.json b/composer.json index d46d16d08..2f5881a01 100644 --- a/composer.json +++ b/composer.json @@ -89,6 +89,7 @@ "allow-plugins": { "dealerdirect/phpcodesniffer-composer-installer": true, "cweagans/composer-patches": true, + "magento-hackathon/magento-composer-installer": false, "mahocommerce/maho-composer-plugin": true }, "platform": { diff --git a/composer.lock b/composer.lock index e453dc541..b7dff77a1 100644 --- a/composer.lock +++ b/composer.lock @@ -121,10 +121,11 @@ "source": { "type": "git", "url": "https://github.com/justinbeaty/maho-composer-plugin.git", - "reference": "5d79023ffea6c0dda505c87cb02c039f9468ad03" + "reference": "890cc0e84df30b5becd90c4d1c5ec1c348e91ee4" }, "require": { - "composer-plugin-api": "^2.1" + "composer-plugin-api": "^2.1", + "composer-runtime-api": "^2" }, "require-dev": { "composer/composer": "^2.8", @@ -135,8 +136,9 @@ "type": "composer-plugin", "extra": { "class": [ + "Maho\\ComposerPlugin\\AutoloadPlugin", "Maho\\ComposerPlugin\\FileCopyPlugin", - "Maho\\ComposerPlugin\\AutoloadPlugin" + "Maho\\ComposerPlugin\\ModmanPlugin" ] }, "autoload": { @@ -148,7 +150,7 @@ "MIT" ], "description": "Extension for Composer to copy assets and enable autoloading for Maho projects.", - "time": "2024-12-03T14:44:11+00:00" + "time": "2024-12-05T21:44:08+00:00" }, { "name": "paragonie/constant_time_encoding", From 5251122c8f1067fe1163f61e145fe1fb8b120909 Mon Sep 17 00:00:00 2001 From: Justin Beaty Date: Thu, 5 Dec 2024 14:15:38 -0800 Subject: [PATCH 05/15] phpcs --- .phpcs.xml | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/.phpcs.xml b/.phpcs.xml index 0537b2a2a..b888b5317 100644 --- a/.phpcs.xml +++ b/.phpcs.xml @@ -2,18 +2,14 @@ maho - app/bootstrap.php - app/Mage.php - app/code/core/Mage/ - lib/Mage/ - lib/MahoCLI/ - lib/Varien/ + app + lib public/api.php public/index.php public/api.php public/index.php - app/Mage.php + app/bootstrap.php From 74e0ee53688c247d185d72ed8d0b7f40d46d09c9 Mon Sep 17 00:00:00 2001 From: Justin Beaty Date: Thu, 5 Dec 2024 15:12:31 -0800 Subject: [PATCH 06/15] globPackages fixes --- app/code/core/Mage/Core/Model/Config.php | 6 ++---- .../core/Mage/Core/Model/Design/Config.php | 6 ++---- .../core/Mage/Core/Model/Resource/Setup.php | 20 +++++++++---------- lib/Maho.php | 6 ++---- 4 files changed, 16 insertions(+), 22 deletions(-) diff --git a/app/code/core/Mage/Core/Model/Config.php b/app/code/core/Mage/Core/Model/Config.php index e294c5717..8c6d19140 100644 --- a/app/code/core/Mage/Core/Model/Config.php +++ b/app/code/core/Mage/Core/Model/Config.php @@ -774,10 +774,8 @@ protected function _getDeclaredModuleFiles() { $moduleFiles = []; - foreach (Maho::getInstalledPackages() as $package => $info) { - foreach (glob($info['path'] . '/app/etc/modules/*.xml') as $file) { - $moduleFiles[basename($file)] = $file; - } + foreach (Maho::globPackages('/app/etc/modules/*.xml') as $file) { + $moduleFiles[basename($file)] = $file; } if (empty($moduleFiles)) { diff --git a/app/code/core/Mage/Core/Model/Design/Config.php b/app/code/core/Mage/Core/Model/Design/Config.php index 7fd5dfbad..3b1d2b75c 100644 --- a/app/code/core/Mage/Core/Model/Design/Config.php +++ b/app/code/core/Mage/Core/Model/Design/Config.php @@ -42,10 +42,8 @@ public function __construct(array $params = []) $files = []; - foreach (Maho::getInstalledPackages() as $info) { - foreach (glob($info['path'] . '/app/design/*/*/*/etc/theme.xml') as $file) { - $files[Maho::toRelativePath($file)] = $file; - } + foreach (Maho::globPackages('/app/design/*/*/*/etc/theme.xml') as $file) { + $files[Maho::toRelativePath($file)] = $file; } foreach ($files as $file) { diff --git a/app/code/core/Mage/Core/Model/Resource/Setup.php b/app/code/core/Mage/Core/Model/Resource/Setup.php index c65314dd2..80302c8e9 100644 --- a/app/code/core/Mage/Core/Model/Resource/Setup.php +++ b/app/code/core/Mage/Core/Model/Resource/Setup.php @@ -520,10 +520,10 @@ protected function _getAvailableDbFiles($actionType, $fromVersion, $toVersion) $filesDir = Mage::getModuleDir('sql', $modName) . DS . $this->_resourceName; foreach (Maho::globPackages("$filesDir/*") as $file) { $matches = []; - if (preg_match($regExpDb, $file, $matches)) { - $dbFiles[$matches[1]] = "$filesDir/$file"; - } elseif (preg_match($regExpType, $file, $matches)) { - $typeFiles[$matches[1]] = "$filesDir/$file"; + if (preg_match($regExpDb, basename($file), $matches) === 1) { + $dbFiles[$matches[1]] = $file; + } elseif (preg_match($regExpType, basename($file), $matches) === 1) { + $typeFiles[$matches[1]] = $file; } } @@ -557,8 +557,8 @@ protected function _getAvailableDataFiles($actionType, $fromVersion, $toVersion) $filesDir = Mage::getModuleDir('data', $modName) . DS . $this->_resourceName; foreach (Maho::globPackages("$filesDir/*") as $file) { $matches = []; - if (preg_match($regExp, $file, $matches)) { - $files[$matches[1]] = "$filesDir/$file"; + if (preg_match($regExp, basename($file), $matches) === 1) { + $files[$matches[1]] = $file; } } @@ -566,8 +566,8 @@ protected function _getAvailableDataFiles($actionType, $fromVersion, $toVersion) $filesDir = Mage::getModuleDir('sql', $modName) . DS . $this->_resourceName; foreach (Maho::globPackages("$filesDir/*") as $file) { $matches = []; - if (preg_match($regExpOld, $file, $matches)) { - $files[$matches[1]] = "$filesDir/$file"; + if (preg_match($regExpOld, basename($file), $matches) === 1) { + $files[$matches[1]] = $file; } } @@ -591,8 +591,8 @@ protected function _getAvailableMahoFiles(string $actionType, string $fromVersio $filesDir = Mage::getModuleDir('sql', $modName) . DS . 'maho_setup'; foreach (Maho::globPackages("$filesDir/*") as $file) { $matches = []; - if (preg_match($regExp, $file, $matches)) { - $files[$matches[1]] = "$filesDir/$file"; + if (preg_match($regExp, basename($file), $matches) === 1) { + $files[$matches[1]] = $file; } } diff --git a/lib/Maho.php b/lib/Maho.php index 01855f095..2421ed8d0 100644 --- a/lib/Maho.php +++ b/lib/Maho.php @@ -58,6 +58,7 @@ public static function toRelativePath(string $path): string */ public static function globPackages(string $pattern, int $flags = 0): array { + $pattern = self::toRelativePath($pattern); return AutoloadRuntime::globPackages($pattern, $flags); } @@ -83,13 +84,10 @@ public static function findFile(string $path): string|false */ public static function listDirectories(string $path): array { - $relativePath = self::toRelativePath($path); $results = []; - - foreach (AutoloadRuntime::globPackages("$relativePath/*", GLOB_ONLYDIR) as $dir) { + foreach (self::globPackages("$path/*", GLOB_ONLYDIR) as $dir) { $results[] = basename($dir); } - return array_unique($results); } From d54ed41eeaa8075ef3f18dc49318e5c0d1b60528 Mon Sep 17 00:00:00 2001 From: Justin Beaty Date: Fri, 6 Dec 2024 07:14:30 -0800 Subject: [PATCH 07/15] fix possibility of different _designRoot --- app/code/core/Mage/Core/Model/Design/Config.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/code/core/Mage/Core/Model/Design/Config.php b/app/code/core/Mage/Core/Model/Design/Config.php index 3b1d2b75c..3ceba712e 100644 --- a/app/code/core/Mage/Core/Model/Design/Config.php +++ b/app/code/core/Mage/Core/Model/Design/Config.php @@ -42,8 +42,11 @@ public function __construct(array $params = []) $files = []; - foreach (Maho::globPackages('/app/design/*/*/*/etc/theme.xml') as $file) { - $files[Maho::toRelativePath($file)] = $file; + foreach (Maho::getInstalledPackages() as $package => $info) { + $path = $package === 'root' ? $this->_designRoot : $info['path']; + foreach (glob("$path/app/design/*/*/*/etc/theme.xml") as $file) { + $files[Maho::toRelativePath($file)] = $file; + } } foreach ($files as $file) { From 6c40ba662e3738c66dac27e1c287f44dbb1b5a17 Mon Sep 17 00:00:00 2001 From: Justin Beaty Date: Fri, 6 Dec 2024 07:20:03 -0800 Subject: [PATCH 08/15] actual fix for possibility of different _designRoot --- app/code/core/Mage/Core/Model/Design/Config.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/app/code/core/Mage/Core/Model/Design/Config.php b/app/code/core/Mage/Core/Model/Design/Config.php index 3ceba712e..d7c24d16e 100644 --- a/app/code/core/Mage/Core/Model/Design/Config.php +++ b/app/code/core/Mage/Core/Model/Design/Config.php @@ -43,8 +43,12 @@ public function __construct(array $params = []) $files = []; foreach (Maho::getInstalledPackages() as $package => $info) { - $path = $package === 'root' ? $this->_designRoot : $info['path']; - foreach (glob("$path/app/design/*/*/*/etc/theme.xml") as $file) { + if ($package === 'root') { + $designRoot = $this->_designRoot; + } else { + $designRoot = $info['path'] . '/app/design'; + } + foreach (glob("$designRoot/*/*/*/etc/theme.xml") as $file) { $files[Maho::toRelativePath($file)] = $file; } } From 170c73ae58a953678e6e7f1107ff94722b7f81aa Mon Sep 17 00:00:00 2001 From: Justin Beaty Date: Fri, 6 Dec 2024 07:28:26 -0800 Subject: [PATCH 09/15] one more fix for _designRoot --- app/code/core/Mage/Core/Model/Design/Config.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/code/core/Mage/Core/Model/Design/Config.php b/app/code/core/Mage/Core/Model/Design/Config.php index d7c24d16e..52837d33d 100644 --- a/app/code/core/Mage/Core/Model/Design/Config.php +++ b/app/code/core/Mage/Core/Model/Design/Config.php @@ -49,7 +49,8 @@ public function __construct(array $params = []) $designRoot = $info['path'] . '/app/design'; } foreach (glob("$designRoot/*/*/*/etc/theme.xml") as $file) { - $files[Maho::toRelativePath($file)] = $file; + $relativePath = str_replace($designRoot, '', $file); + $files[$relativePath] = $file; } } From 9339f891ad30344daadc8124bdb93d1268505997 Mon Sep 17 00:00:00 2001 From: Justin Beaty Date: Fri, 6 Dec 2024 13:33:47 -0800 Subject: [PATCH 10/15] Prevent local.xml from being loaded from installed packages --- app/code/core/Mage/Core/Model/Config.php | 30 ++++++++++++++---------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/app/code/core/Mage/Core/Model/Config.php b/app/code/core/Mage/Core/Model/Config.php index 8c6d19140..5795d7e59 100644 --- a/app/code/core/Mage/Core/Model/Config.php +++ b/app/code/core/Mage/Core/Model/Config.php @@ -206,6 +206,11 @@ class Mage_Core_Model_Config extends Mage_Core_Model_Config_Base */ protected $_prototype; + /** + * Reference to the Varien_Simplexml_Config object where local.xml was loaded in to + */ + protected Mage_Core_Model_Config_Base $_refLocalConfigObject; + /** * Flag which identify what local configuration is loaded * @@ -323,6 +328,11 @@ public function init($options = []) */ public function loadBase() { + // Prevent double loading of base config + if ($this->getNode() !== false) { + return; + } + $files = []; foreach (Maho::getInstalledPackages() as $package => $info) { @@ -336,17 +346,17 @@ public function loadBase() } // Merge all config files - $this->loadFile(current($files)); - while ($file = next($files)) { + $this->loadString(''); + foreach ($files as $basename => $file) { $merge = clone $this->_prototype; $merge->loadFile($file); + if ($basename === 'local.xml') { + $this->_isLocalConfigLoaded = true; + $this->_refLocalConfigObject = $merge; + } $this->extend($merge); } - if (isset($files['local.xml'])) { - $this->_isLocalConfigLoaded = true; - } - return $this; } @@ -382,13 +392,9 @@ public function loadModules() $resourceConfig = sprintf('config.%s.xml', $this->_getResourceConnectionModel('core')); $this->loadModulesConfiguration(['config.xml', $resourceConfig], $this); - /** - * Prevent local.xml directives overwriting - */ - $mergeConfig = clone $this->_prototype; - $this->_isLocalConfigLoaded = $mergeConfig->loadFile($this->getOptions()->getEtcDir() . DS . 'local.xml'); + // Prevent local.xml directives overwriting if ($this->_isLocalConfigLoaded) { - $this->extend($mergeConfig); + $this->extend($this->_refLocalConfigObject); } $this->applyExtends(); From ccefa3e33e843d0e86d112cb14cee00921d09339 Mon Sep 17 00:00:00 2001 From: Justin Beaty Date: Fri, 6 Dec 2024 13:35:00 -0800 Subject: [PATCH 11/15] phpstan fix --- app/code/core/Mage/Core/Model/Config.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/core/Mage/Core/Model/Config.php b/app/code/core/Mage/Core/Model/Config.php index 5795d7e59..76ac4a701 100644 --- a/app/code/core/Mage/Core/Model/Config.php +++ b/app/code/core/Mage/Core/Model/Config.php @@ -330,7 +330,7 @@ public function loadBase() { // Prevent double loading of base config if ($this->getNode() !== false) { - return; + return $this; } $files = []; From 6f603e9de55855bf1c00eb060a05bd4eb35763b1 Mon Sep 17 00:00:00 2001 From: Justin Beaty Date: Fri, 6 Dec 2024 13:42:21 -0800 Subject: [PATCH 12/15] Fix Maho CLI --- lib/MahoCLI/Commands/BaseMahoCommand.php | 9 --------- 1 file changed, 9 deletions(-) diff --git a/lib/MahoCLI/Commands/BaseMahoCommand.php b/lib/MahoCLI/Commands/BaseMahoCommand.php index 805ad074f..e2bc7cb7c 100644 --- a/lib/MahoCLI/Commands/BaseMahoCommand.php +++ b/lib/MahoCLI/Commands/BaseMahoCommand.php @@ -17,15 +17,6 @@ abstract class BaseMahoCommand extends Command { protected function initMaho(): void { - $cwd = getcwd(); - if (file_exists("$cwd/app/bootstrap.php")) { - require "$cwd/app/bootstrap.php"; - require "$cwd/app/Mage.php"; - } else { - require "$cwd/vendor/mahocommerce/maho/app/bootstrap.php"; - require "$cwd/vendor/mahocommerce/maho/app/Mage.php"; - } - Mage::register('isSecureArea', true); Mage::app(); } From bba5132f85f926ba35fe4879dc8bdcabec96337b Mon Sep 17 00:00:00 2001 From: Justin Beaty Date: Fri, 6 Dec 2024 13:49:57 -0800 Subject: [PATCH 13/15] update composer plugin --- composer.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.lock b/composer.lock index d7756ec50..17d0ea878 100644 --- a/composer.lock +++ b/composer.lock @@ -121,7 +121,7 @@ "source": { "type": "git", "url": "https://github.com/justinbeaty/maho-composer-plugin.git", - "reference": "890cc0e84df30b5becd90c4d1c5ec1c348e91ee4" + "reference": "236c5653eab9c0d50aad29875a2fed8582205f5e" }, "require": { "composer-plugin-api": "^2.1", @@ -150,7 +150,7 @@ "MIT" ], "description": "Extension for Composer to copy assets and enable autoloading for Maho projects.", - "time": "2024-12-05T21:44:08+00:00" + "time": "2024-12-06T14:11:51+00:00" }, { "name": "paragonie/constant_time_encoding", From 5e57faa8ae7fdc4bdc1a457e418d4c710241be7a Mon Sep 17 00:00:00 2001 From: Justin Beaty Date: Fri, 6 Dec 2024 14:27:55 -0800 Subject: [PATCH 14/15] fix --- app/code/core/Mage/Core/Model/Config.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/code/core/Mage/Core/Model/Config.php b/app/code/core/Mage/Core/Model/Config.php index 76ac4a701..770e42c77 100644 --- a/app/code/core/Mage/Core/Model/Config.php +++ b/app/code/core/Mage/Core/Model/Config.php @@ -451,6 +451,8 @@ public function loadEnv(): Mage_Core_Model_Config */ public function reinit($options = []) { + $this->_xml = null; + $this->_isLocalConfigLoaded = false; $this->_allowCacheForInit = false; $this->_useCache = false; return $this->init($options); From 2290cd156ed5804f0522d8f70c0dc8d5d7eee787 Mon Sep 17 00:00:00 2001 From: Justin Beaty Date: Fri, 6 Dec 2024 15:02:16 -0800 Subject: [PATCH 15/15] phpstan fix --- app/code/core/Mage/Core/Model/Config.php | 2 +- lib/Varien/Simplexml/Config.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/core/Mage/Core/Model/Config.php b/app/code/core/Mage/Core/Model/Config.php index 770e42c77..61fce420a 100644 --- a/app/code/core/Mage/Core/Model/Config.php +++ b/app/code/core/Mage/Core/Model/Config.php @@ -85,7 +85,7 @@ class Mage_Core_Model_Config extends Mage_Core_Model_Config_Base /** * Configuration xml * - * @var Mage_Core_Model_Config_Element + * @var Mage_Core_Model_Config_Element|null */ protected $_xml = null; diff --git a/lib/Varien/Simplexml/Config.php b/lib/Varien/Simplexml/Config.php index 24a886d86..5a012d497 100644 --- a/lib/Varien/Simplexml/Config.php +++ b/lib/Varien/Simplexml/Config.php @@ -21,7 +21,7 @@ class Varien_Simplexml_Config /** * Configuration xml * - * @var Varien_Simplexml_Element|SimpleXMLElement + * @var Varien_Simplexml_Element|SimpleXMLElement|null */ protected $_xml = null;