diff options
| author | Greg Roach <fisharebest@gmail.com> | 2015-03-02 08:02:00 +0000 |
|---|---|---|
| committer | Greg Roach <fisharebest@gmail.com> | 2015-03-02 15:55:40 +0000 |
| commit | 8c2e82270a639a3acf607b432e54721116dae723 (patch) | |
| tree | 6e9829818d82ad365229bbcad744b9b4999bb0fb /app/Module.php | |
| parent | 7126668f8fb92b0cac155adc02efde34bbd890ce (diff) | |
| download | webtrees-8c2e82270a639a3acf607b432e54721116dae723.tar.gz webtrees-8c2e82270a639a3acf607b432e54721116dae723.tar.bz2 webtrees-8c2e82270a639a3acf607b432e54721116dae723.zip | |
Module API
Diffstat (limited to 'app/Module.php')
| -rw-r--r-- | app/Module.php | 204 |
1 files changed, 78 insertions, 126 deletions
diff --git a/app/Module.php b/app/Module.php index 992360be66..a17135316a 100644 --- a/app/Module.php +++ b/app/Module.php @@ -22,29 +22,22 @@ namespace Fisharebest\Webtrees; */ abstract class Module { /** @var string A user-friendly, localized name for this module */ - private $_title; + private $title; + + /** @var string The directory where the module is installed */ + private $directory; /** @var string[] A cached copy of the module settings */ private $settings; /** - * Create a new module - */ - public function __construct() { - $this->_title = $this->getTitle(); - } - - /** - * Create a name for this module. - * - * Earlier modules did not have a constructor, and hence a number of custom - * modules fail to call parent::__construct(). If this happens, choose a - * default name, rather than erroring. + * Create a new module. * - * @return string + * @param string $directory Where is this module installed */ - public function __toString() { - return $this->_title ?: get_class(); + public function __construct($directory) { + $this->directory = $directory; + $this->title = $this->getTitle(); } /** @@ -74,12 +67,12 @@ abstract class Module { } /** - * Provide a localized name for this module + * Provide a unique internal name for this module * * @return string */ public function getName() { - return str_replace(array(__NAMESPACE__ . '\\', '_WT_Module'), '', get_class($this)); + return basename($this->directory); } /** @@ -184,41 +177,33 @@ abstract class Module { /** * Get a list of all active (enabled) modules. * - * @param boolean $sort Sort the module by the (localised) name - * * @return Module[] */ - public static function getActiveModules($sort = false) { - /** @var Module[] - We call this function several times, so cache the results. */ + private static function getActiveModules() { + /** @var Module[] - Only query the database once. */ static $modules; - /** @var boolean - Sorting is slow, so only do it when requested. */ - static $sorted = false; - if ($modules === null) { $module_names = Database::prepare( "SELECT SQL_CACHE module_name FROM `##module` WHERE status = 'enabled'" )->fetchOneColumn(); + $modules = array(); foreach ($module_names as $module_name) { - if (file_exists(WT_ROOT . WT_MODULES_DIR . $module_name . '/module.php')) { - require_once WT_ROOT . WT_MODULES_DIR . $module_name . '/module.php'; - $class = __NAMESPACE__ . '\\' . $module_name . '_WT_Module'; - $modules[$module_name] = new $class; - } else { - // Module has been deleted from disk? Disable it. - Log::addConfigurationLog("Module {$module_name} has been deleted from disk - disabling it"); + try { + $module = require WT_ROOT . WT_MODULES_DIR . $module_name . '/module.php'; + $modules[$module->getName()] = $module; + } catch (\Exception $ex) { + // Module has been deleted or is broken? Disable it. + Log::addConfigurationLog("Module {$module_name} is missing or broken - disabling it"); Database::prepare( - "UPDATE `##module` SET status = 'disabled' WHERE module_name = ?" - )->execute(array($module_name)); + "UPDATE `##module` SET status = 'disabled' WHERE module_name = :module_name" + )->execute(array( + 'module_name' => $module_name + )); } } } - if ($sort && !$sorted) { - $sorted = uasort($modules, function(Module $x, Module $y) { - return I18N::strcasecmp($x->getTitle(), $y->getTitle()); - }); - } return $modules; } @@ -229,42 +214,36 @@ abstract class Module { * We cannot currently use auto-loading for modules, as there may be user-defined * modules about which the auto-loader knows nothing. * + * @param Tree $tree * @param string $component The type of module, such as "tab", "report" or "menu" - * @param integer $tree_id * @param integer $access_level * * @return Module[] */ - private static function getActiveModulesByComponent($component, $tree_id, $access_level) { + private static function getActiveModulesByComponent(Tree $tree, $component, $access_level) { $module_names = Database::prepare( "SELECT SQL_CACHE module_name" . " FROM `##module`" . " JOIN `##module_privacy` USING (module_name)" . - " WHERE gedcom_id=? AND component=? AND status='enabled' AND access_level>=?" . + " WHERE gedcom_id = :tree_id AND component = :component AND status = 'enabled' AND access_level >= :access_level" . " ORDER BY CASE component WHEN 'menu' THEN menu_order WHEN 'sidebar' THEN sidebar_order WHEN 'tab' THEN tab_order ELSE 0 END, module_name" - )->execute(array($tree_id, $component, $access_level))->fetchOneColumn(); + )->execute(array( + 'tree_id' => $tree->getTreeId(), + 'component' => $component, + 'access_level' => $access_level, + ))->fetchOneColumn(); + + $active_modules = self::getActiveModules(); $array = array(); foreach ($module_names as $module_name) { - if (file_exists(WT_ROOT . WT_MODULES_DIR . $module_name . '/module.php')) { - require_once WT_ROOT . WT_MODULES_DIR . $module_name . '/module.php'; - $class = __NAMESPACE__ . '\\' . $module_name . '_WT_Module'; - $interface = __NAMESPACE__ . '\Module' . ucfirst($component) . 'Interface'; - $module = new $class; - // Check that this module is still implementing the desired interface. - if ($module instanceof $interface) { - $array[$module_name] = new $module; - } - } else { - // Module has been deleted from disk? Disable it. - Log::addConfigurationLog("Module {$module_name} has been deleted from disk - disabling it"); - Database::prepare( - "UPDATE `##module` SET status='disabled' WHERE module_name=?" - )->execute(array($module_name)); + $interface = __NAMESPACE__ . '\Module' . ucfirst($component) . 'Interface'; + if ($active_modules[$module_name] instanceof $interface) { + $array[$module_name] = $active_modules[$module_name]; } } - // The order of some modules is defined by the user. Others are sorted by name. + // The order of menus/sidebars/tabs is defined by the user. Others are sorted by name. if ($component !== 'menu' && $component !== 'sidebar' && $component !== 'tab') { uasort($array, function(Module $x, Module $y) { return I18N::strcasecmp($x->getTitle(), $y->getTitle()); @@ -277,127 +256,101 @@ abstract class Module { /** * Get a list of modules which (a) provide a block and (b) we have permission to see. * - * @param integer $tree_id + * @param Tree $tree * @param integer $access_level * * @return ModuleBlockInterface[] */ - public static function getActiveBlocks($tree_id = WT_GED_ID, $access_level = WT_USER_ACCESS_LEVEL) { - static $blocks; - - if ($blocks === null) { - $blocks = self::getActiveModulesByComponent('block', $tree_id, $access_level); - } - - return $blocks; + public static function getActiveBlocks(Tree $tree, $access_level = WT_USER_ACCESS_LEVEL) { + return self::getActiveModulesByComponent($tree, 'block', $access_level); } /** * Get a list of modules which (a) provide a chart and (b) we have permission to see. * - * @param integer $tree_id + * @param Tree $tree * @param integer $access_level * * @return ModuleChartInterface[] */ - public static function getActiveCharts($tree_id = WT_GED_ID, $access_level = WT_USER_ACCESS_LEVEL) { - static $charts; - - if ($charts === null) { - $charts = self::getActiveModulesByComponent('chart', $tree_id, $access_level); - } - - return $charts; + public static function getActiveCharts(Tree $tree, $access_level = WT_USER_ACCESS_LEVEL) { + return self::getActiveModulesByComponent($tree, 'chart', $access_level); } /** * Get a list of modules which (a) provide a menu and (b) we have permission to see. * - * @param integer $tree_id + * @param Tree $tree * @param integer $access_level * * @return ModuleMenuInterface[] */ - public static function getActiveMenus($tree_id = WT_GED_ID, $access_level = WT_USER_ACCESS_LEVEL) { - static $menus; - - if ($menus === null) { - $menus = self::getActiveModulesByComponent('menu', $tree_id, $access_level); - } - - return $menus; + public static function getActiveMenus(Tree $tree, $access_level = WT_USER_ACCESS_LEVEL) { + return self::getActiveModulesByComponent($tree, 'menu', $access_level); } /** * Get a list of modules which (a) provide a report and (b) we have permission to see. * - * @param integer $tree_id + * @param Tree $tree * @param integer $access_level * * @return ModuleReportInterface[] */ - public static function getActiveReports($tree_id = WT_GED_ID, $access_level = WT_USER_ACCESS_LEVEL) { - static $reports; - - if ($reports === null) { - $reports = self::getActiveModulesByComponent('report', $tree_id, $access_level); - } - - return $reports; + public static function getActiveReports(Tree $tree, $access_level = WT_USER_ACCESS_LEVEL) { + return self::getActiveModulesByComponent($tree, 'report', $access_level); } /** * Get a list of modules which (a) provide a sidebar and (b) we have permission to see. * - * @param integer $tree_id + * @param Tree $tree * @param integer $access_level * * @return ModuleSidebarInterface[] */ - public static function getActiveSidebars($tree_id = WT_GED_ID, $access_level = WT_USER_ACCESS_LEVEL) { - static $sidebars; - - if ($sidebars === null) { - $sidebars = self::getActiveModulesByComponent('sidebar', $tree_id, $access_level); - } - - return $sidebars; + public static function getActiveSidebars(Tree $tree, $access_level = WT_USER_ACCESS_LEVEL) { + return self::getActiveModulesByComponent($tree, 'sidebar', $access_level); } /** * Get a list of modules which (a) provide a tab and (b) we have permission to see. * - * @param integer $tree_id + * @param Tree $tree * @param integer $access_level * * @return ModuleTabInterface[] */ - public static function getActiveTabs($tree_id = WT_GED_ID, $access_level = WT_USER_ACCESS_LEVEL) { - static $tabs; - - if ($tabs === null) { - $tabs = self::getActiveModulesByComponent('tab', $tree_id, $access_level); - } - - return $tabs; + public static function getActiveTabs(Tree $tree, $access_level = WT_USER_ACCESS_LEVEL) { + return self::getActiveModulesByComponent($tree, 'tab', $access_level); } /** * Get a list of modules which (a) provide a theme and (b) we have permission to see. * - * @param integer $tree_id + * @param Tree $tree * @param integer $access_level * * @return ModuleThemeInterface[] */ - public static function getActiveThemes($tree_id = WT_GED_ID, $access_level = WT_USER_ACCESS_LEVEL) { - static $themes; + public static function getActiveThemes(Tree $tree, $access_level = WT_USER_ACCESS_LEVEL) { + return self::getActiveModulesByComponent($tree, 'theme', $access_level); + } - if ($themes === null) { - $themes = self::getActiveModulesByComponent('theme', $tree_id, $access_level); + /** + * Find a specified module, if it is currently active. + * + * @param string $module_name + * + * @return Module|null + */ + public static function getModuleByName($module_name) { + $modules = self::getActiveModules(); + if (array_key_exists($module_name, $modules)) { + return $modules[$module_name]; + } else { + return null; } - - return $themes; } /** @@ -413,12 +366,9 @@ abstract class Module { public static function getInstalledModules($default_status) { $modules = array(); - $dir = opendir(WT_ROOT . WT_MODULES_DIR); - while (($module_name = readdir($dir)) !== false) { - if (preg_match('/^[a-zA-Z0-9_]+$/', $module_name) && file_exists(WT_ROOT . WT_MODULES_DIR . $module_name . '/module.php')) { - require_once WT_ROOT . WT_MODULES_DIR . $module_name . '/module.php'; - $class = __NAMESPACE__ . '\\' . $module_name . '_WT_Module'; - $module = new $class; + foreach (glob(WT_ROOT . WT_MODULES_DIR . '*/module.php') as $file) { + try { + $module = require $file; $modules[$module->getName()] = $module; Database::prepare("INSERT IGNORE INTO `##module` (module_name, status, menu_order, sidebar_order, tab_order) VALUES (?, ?, ?, ?, ?)") ->execute(array( @@ -479,6 +429,8 @@ abstract class Module { " FROM `##gedcom`" )->execute(array($module->getName(), $module->defaultAccessLevel())); } + } catch (\Exception $ex) { + // Probably an old third-party module. } } |
