From 9264a5389d45499bde9cc1ea7c2aea718e0d53b6 Mon Sep 17 00:00:00 2001 From: Ryan Cramer Date: Thu, 7 Aug 2014 07:02:35 -0400 Subject: [PATCH] Add support for module substitutes, enabling you to sub one module with another via config settings or API. This corrects the issue of some 3rd party modules assuming InputfieldTinyMCE is available. It substitutes InputfieldCKEditor. --- wire/config.php | 11 +++++++ wire/core/Modules.php | 69 ++++++++++++++++++++++++++++++++++++++- wire/core/ProcessWire.php | 1 + 3 files changed, 80 insertions(+), 1 deletion(-) diff --git a/wire/config.php b/wire/config.php index 30dddd7c..39052376 100644 --- a/wire/config.php +++ b/wire/config.php @@ -253,6 +253,17 @@ */ $config->ignoreTemplateFileRegex = '/^_/'; +/** + * Substitute module names for when requested module doesn't exist + * + * Array of module name => substitute module name + * + */ +$config->substituteModules = array( + // TinyMCE replaced with CKEditor as default RTE in 2.4.9+ + 'InputfieldTinyMCE' => 'InputfieldCKEditor' + ); + /** * Settings specific to InputfieldWrapper class * diff --git a/wire/core/Modules.php b/wire/core/Modules.php index 13dd5624..b60f6ac9 100644 --- a/wire/core/Modules.php +++ b/wire/core/Modules.php @@ -132,6 +132,17 @@ class Modules extends WireArray { */ protected $modulesTableCache = array(); + /** + * Array of moduleName => substituteModuleName to be used when moduleName doesn't exist + * + * Primarily for providing backwards compatiblity with modules assumed installed that + * may no longer be in core. + * + * see setSubstitutes() method + * + */ + protected $substitutes = array(); + /** * Construct the Modules * @@ -720,6 +731,28 @@ public function get($key) { return $this->getModule($key); } + /** + * Attempt to find a substitute for moduleName and return module if found or null if not + * + * @param $moduleName + * @param array $options See getModule() options + * @return Module|null + * + */ + protected function getSubstituteModule($moduleName, array $options = array()) { + + $module = null; + $options['noSubstitute'] = true; // prevent recursion + + while(isset($this->substitutes[$moduleName]) && !$module) { + $substituteName = $this->substitutes[$moduleName]; + $module = $this->getModule($substituteName, $options); + if(!$module) $moduleName = $substituteName; + } + + return $module; + } + /** * Get the requested Module or NULL if it doesn't exist + specify one or more options * @@ -728,6 +761,7 @@ public function get($key) { * - noPermissionCheck: Specify true to disable module permission checks (and resulting exception). * - noInstall: Specify true to prevent a non-installed module from installing from this request. * - noInit: Specify true to prevent the module from being initialized. + * - noSubstitute: Specify true to prevent inclusion of a substitute module. * @return Module|null * @throws WirePermissionException If module requires a particular permission the user does not have * @@ -742,7 +776,13 @@ public function getModule($key, array $options = array()) { if(!$key = array_search($key, $this->moduleIDs)) return null; } - if($module = parent::get($key)) { + $module = parent::get($key); + if(!$module && empty($options['noSubstitute'])) { + $module = $this->getSubstituteModule($key, $options); + if($module) return $module; // returned module is ready to use + } + + if($module) { // check if it's a placeholder, and if it is then include/instantiate/init the real module // OR check if it's non-singular, so that a new instance is created @@ -2138,6 +2178,33 @@ public function getDebugLog() { return $this->debugLog; } + /** + * Substitute one module for another, to be used only when $moduleName doesn't exist. + * + * @param string $moduleName Module class name that may need a substitute + * @param string $substituteName Module class name you want to substitute when $moduleName isn't found. + * Specify null to remove substitute. + * + */ + public function setSubstitute($moduleName, $substituteName = null) { + if(is_null($substituteName)) { + unset($this->substitues[$moduleName]); + } else { + $this->substitutes[$moduleName] = $substituteName; + } + } + + /** + * Substitute modules for other modules, to be used only when $moduleName doesn't exist. + * + * This appends existing entries rather than replacing them. + * + * @param array $substitutes Array of module name => substitute module name + * + */ + public function setSubstitutes(array $substitutes) { + $this->substitutes = array_merge($this->substitutes, $substitutes); + } } diff --git a/wire/core/ProcessWire.php b/wire/core/ProcessWire.php index 7e846bd2..a71a6fc1 100644 --- a/wire/core/ProcessWire.php +++ b/wire/core/ProcessWire.php @@ -167,6 +167,7 @@ public function load(Config $config) { $modules = new Modules($config->paths->modules); $modules->addPath($config->paths->siteModules); $this->wire('modules', $modules, true); + $modules->setSubstitutes($config->substituteModules); $modules->init(); if($this->debug) Debug::saveTimer('boot.load.modules'); } catch(Exception $e) {