diff options
author | Bharat Mediratta <bharat@menalto.com> | 2009-05-26 05:28:59 +0000 |
---|---|---|
committer | Bharat Mediratta <bharat@menalto.com> | 2009-05-26 05:28:59 +0000 |
commit | 7aed9239088b582a065da3fb63796ff66cd357c8 (patch) | |
tree | 8be9bc4faec21b20cbcc060ad5e9ca128465d09e /core/helpers | |
parent | 2966289b147ceae2fed79b9534840607bf38e0d8 (diff) |
Restructure the module lifecycle.
Install: <module>_installer::install() is called, any necessary tables
are created.
Activate: <module>_installer::activate() is called. Module
controllers are routable, helpers are accessible, etc. The module is
in use.
Deactivate: <module>_installer::deactivate() is called. Module code
is not accessible or routable. Module is *not* in use, but its tables
are still around.
Uninstall: <module>_installer::uninstall() is called. Module is
completely removed from the database.
Admin > Modules will install and activate modules, but will only
deactivate (will NOT uninstall modules).
Diffstat (limited to 'core/helpers')
-rw-r--r-- | core/helpers/access.php | 4 | ||||
-rw-r--r-- | core/helpers/block_manager.php | 2 | ||||
-rw-r--r-- | core/helpers/core.php | 22 | ||||
-rw-r--r-- | core/helpers/core_installer.php | 40 | ||||
-rw-r--r-- | core/helpers/core_menu.php | 2 | ||||
-rw-r--r-- | core/helpers/graphics.php | 32 | ||||
-rw-r--r-- | core/helpers/log.php | 2 | ||||
-rw-r--r-- | core/helpers/module.php | 176 | ||||
-rw-r--r-- | core/helpers/task.php | 4 |
9 files changed, 195 insertions, 89 deletions
diff --git a/core/helpers/access.php b/core/helpers/access.php index b9472aa0..64ce91fa 100644 --- a/core/helpers/access.php +++ b/core/helpers/access.php @@ -389,7 +389,9 @@ class access_Core { * @return ORM_Iterator */ private static function _get_all_groups() { - if (module::is_installed("user")) { + // When we build the core package, it's possible that the user module is not installed yet. + // This is ok at packaging time, so work around it. + if (module::is_active("user")) { return ORM::factory("group")->find_all(); } else { return array(); diff --git a/core/helpers/block_manager.php b/core/helpers/block_manager.php index 9e8ab877..022626e5 100644 --- a/core/helpers/block_manager.php +++ b/core/helpers/block_manager.php @@ -41,7 +41,7 @@ class block_manager_Core { static function get_available() { $blocks = array(); - foreach (module::installed() as $module) { + foreach (module::active() as $module) { $class_name = "{$module->name}_block"; if (method_exists($class_name, "get_list")) { foreach (call_user_func(array($class_name, "get_list")) as $id => $title) { diff --git a/core/helpers/core.php b/core/helpers/core.php index 5023bb15..63f51f86 100644 --- a/core/helpers/core.php +++ b/core/helpers/core.php @@ -18,6 +18,10 @@ * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ class core_Core { + /** + * If Gallery is in maintenance mode, then force all non-admins to get routed to a "This site is + * down for maintenance" page. + */ static function maintenance_mode() { $maintenance_mode = Kohana::config("core.maintenance_mode", false, false); @@ -27,4 +31,22 @@ class core_Core { Router::$method = "index"; } } + + /** + * This function is called when the Gallery is fully initialized. We relay it to modules as the + * "gallery_ready" event. Any module that wants to perform an action at the start of every + * request should implement the <module>_event::gallery_ready() handler. + */ + static function ready() { + module::event("gallery_ready"); + } + + /** + * This function is called right before the Kohana framework shuts down. We relay it to modules + * as the "gallery_shutdown" event. Any module that wants to perform an action at the start of + * every request should implement the <module>_event::gallery_shutdown() handler. + */ + static function shutdown() { + module::event("gallery_shutdown"); + } }
\ No newline at end of file diff --git a/core/helpers/core_installer.php b/core/helpers/core_installer.php index fc4dc1a6..81246359 100644 --- a/core/helpers/core_installer.php +++ b/core/helpers/core_installer.php @@ -41,44 +41,45 @@ class core_installer { $db->query("CREATE TABLE {graphics_rules} ( `id` int(9) NOT NULL auto_increment, - `priority` int(9) NOT NULL, + `active` BOOLEAN default 0, + `args` varchar(255) default NULL, `module_name` varchar(64) NOT NULL, - `target` varchar(32) NOT NULL, `operation` varchar(64) NOT NULL, - `args` varchar(255) default NULL, + `priority` int(9) NOT NULL, + `target` varchar(32) NOT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;"); $db->query("CREATE TABLE {items} ( + `id` int(9) NOT NULL auto_increment, `album_cover_item_id` int(9) default NULL, `captured` int(9) default NULL, `created` int(9) default NULL, `description` varchar(2048) default NULL, `height` int(9) default NULL, - `id` int(9) NOT NULL auto_increment, `left` int(9) NOT NULL, `level` int(9) NOT NULL, `mime_type` varchar(64) default NULL, `name` varchar(255) default NULL, `owner_id` int(9) default NULL, `parent_id` int(9) NOT NULL, + `rand_key` float default NULL, + `relative_path_cache` varchar(255) default NULL, + `resize_dirty` boolean default 1, `resize_height` int(9) default NULL, `resize_width` int(9) default NULL, - `resize_dirty` boolean default 1, `right` int(9) NOT NULL, + `sort_column` varchar(64) default NULL, + `sort_order` char(4) default 'ASC', + `thumb_dirty` boolean default 1, `thumb_height` int(9) default NULL, `thumb_width` int(9) default NULL, - `thumb_dirty` boolean default 1, `title` varchar(255) default NULL, `type` varchar(32) NOT NULL, `updated` int(9) default NULL, `view_count` int(9) default 0, - `width` int(9) default NULL, - `rand_key` float default NULL, - `relative_path_cache` varchar(255) default NULL, - `sort_column` varchar(64) default NULL, - `sort_order` char(4) default 'ASC', `weight` int(9) NOT NULL default 0, + `width` int(9) default NULL, PRIMARY KEY (`id`), KEY `parent_id` (`parent_id`), KEY `type` (`type`), @@ -101,14 +102,15 @@ class core_installer { $db->query("CREATE TABLE {messages} ( `id` int(9) NOT NULL auto_increment, `key` varchar(255) default NULL, - `value` varchar(255) default NULL, `severity` varchar(32) default NULL, + `value` varchar(255) default NULL, PRIMARY KEY (`id`), UNIQUE KEY(`key`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;"); $db->query("CREATE TABLE {modules} ( `id` int(9) NOT NULL auto_increment, + `active` BOOLEAN default 0, `name` varchar(64) default NULL, `version` int(9) default NULL, PRIMARY KEY (`id`), @@ -125,8 +127,8 @@ class core_installer { $db->query("CREATE TABLE {permissions} ( `id` int(9) NOT NULL auto_increment, - `name` varchar(64) default NULL, `display_name` varchar(64) default NULL, + `name` varchar(64) default NULL, PRIMARY KEY (`id`), UNIQUE KEY(`name`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;"); @@ -136,8 +138,8 @@ class core_installer { `key` char(32) NOT NULL, `locale` char(10) NOT NULL, `message` text NOT NULL, - `translation` text, `revision` int(9) DEFAULT NULL, + `translation` text, PRIMARY KEY (`id`), UNIQUE KEY(`key`, `locale`), KEY `locale_key` (`locale`, `key`)) @@ -145,11 +147,11 @@ class core_installer { $db->query("CREATE TABLE {outgoing_translations} ( `id` int(9) NOT NULL auto_increment, + `base_revision` int(9) DEFAULT NULL, `key` char(32) NOT NULL, `locale` char(10) NOT NULL, `message` text NOT NULL, `translation` text, - `base_revision` int(9) DEFAULT NULL, PRIMARY KEY (`id`), UNIQUE KEY(`key`, `locale`), KEY `locale_key` (`locale`, `key`)) @@ -157,22 +159,22 @@ class core_installer { $db->query("CREATE TABLE {sessions} ( `session_id` varchar(127) NOT NULL, - `last_activity` int(10) UNSIGNED NOT NULL, `data` text NOT NULL, + `last_activity` int(10) UNSIGNED NOT NULL, PRIMARY KEY (`session_id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;"); $db->query("CREATE TABLE {tasks} ( + `id` int(9) NOT NULL auto_increment, `callback` varchar(128) default NULL, `context` text NOT NULL, `done` boolean default 0, - `id` int(9) NOT NULL auto_increment, - `updated` int(9) default NULL, `name` varchar(128) default NULL, + `owner_id` int(9) default NULL, `percent_complete` int(9) default 0, `state` varchar(32) default NULL, `status` varchar(255) default NULL, - `owner_id` int(9) default NULL, + `updated` int(9) default NULL, PRIMARY KEY (`id`), KEY (`owner_id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;"); diff --git a/core/helpers/core_menu.php b/core/helpers/core_menu.php index f7db2104..eb208560 100644 --- a/core/helpers/core_menu.php +++ b/core/helpers/core_menu.php @@ -73,7 +73,7 @@ class core_menu_Core { ->id("admin_menu") ->label(t("Admin"))); self::admin($admin_menu, $theme); - foreach (module::installed() as $module) { + foreach (module::active() as $module) { if ($module->name == "core") { continue; } diff --git a/core/helpers/graphics.php b/core/helpers/graphics.php index b82b6ba8..6d51e60d 100644 --- a/core/helpers/graphics.php +++ b/core/helpers/graphics.php @@ -46,6 +46,7 @@ class graphics_Core { $rule->operation = $operation; $rule->priority = $priority; $rule->args = serialize($args); + $rule->active = true; $rule->save(); self::mark_dirty($target == "thumb", $target == "resize"); @@ -72,14 +73,33 @@ class graphics_Core { * @param string $module_name */ static function remove_rules($module_name) { - $db = Database::instance(); - $status = $db->delete("graphics_rules", array("module_name" => $module_name)); + $status = Database::instance()->delete("graphics_rules", array("module_name" => $module_name)); if (count($status)) { self::mark_dirty(true, true); } } /** + * Activate the rules for this module, typically done when the module itself is deactivated. + * Note that this does not mark images as dirty so that if you deactivate and reactivate a + * module it won't cause all of your images to suddenly require a rebuild. + */ + static function activate_rules($module_name) { + Database::instance() + ->update("graphics_rules",array("active" => true), array("module_name" => $module_name)); + } + + /** + * Deactivate the rules for this module, typically done when the module itself is deactivated. + * Note that this does not mark images as dirty so that if you deactivate and reactivate a + * module it won't cause all of your images to suddenly require a rebuild. + */ + static function deactivate_rules($module_name) { + Database::instance() + ->update("graphics_rules",array("active" => false), array("module_name" => $module_name)); + } + + /** * Rebuild the thumb and resize for the given item. * @param Item_Model $item */ @@ -106,6 +126,7 @@ class graphics_Core { return; } + try { foreach ($ops as $target => $output_file) { if ($input_item->is_movie()) { // Convert the movie to a JPG first @@ -118,6 +139,7 @@ class graphics_Core { foreach (ORM::factory("graphics_rule") ->where("target", $target) + ->where("active", true) ->orderby("priority", "asc") ->find_all() as $rule) { $args = array($working_file, $output_file, unserialize($rule->args)); @@ -140,6 +162,12 @@ class graphics_Core { $item->resize_dirty = 0; } $item->save(); + } catch (Kohana_Exception $e) { + // Something went wrong rebuilding the image. Leave it dirty and move on. + // @todo we should handle this better. + Kohana::log("error", "Caught exception rebuilding image: {$item->title}\n" . + $e->getTraceAsString()); + } } /** diff --git a/core/helpers/log.php b/core/helpers/log.php index cd04e0c5..d0581bf3 100644 --- a/core/helpers/log.php +++ b/core/helpers/log.php @@ -80,9 +80,7 @@ class log_Core { $log->url = substr(url::abs_current(true), 0, 255); $log->referer = request::referrer(null); $log->timestamp = time(); - if (module::is_installed("user")) { $log->user_id = user::active()->id; - } $log->save(); } diff --git a/core/helpers/module.php b/core/helpers/module.php index a6fe64b0..539b003c 100644 --- a/core/helpers/module.php +++ b/core/helpers/module.php @@ -24,23 +24,20 @@ * Note: by design, this class does not do any permission checking. */ class module_Core { - public static $module_names = array(); + public static $active = array(); public static $modules = array(); public static $var_cache = null; - static function get_version($module_name) { - return ORM::factory("module")->where("name", $module_name)->find()->version; - } - /** * Set the version of the corresponding Module_Model * @param string $module_name * @param integer $version */ static function set_version($module_name, $version) { - $module = ORM::factory("module")->where("name", $module_name)->find(); + $module = self::get($module_name); if (!$module->loaded) { $module->name = $module_name; + $module->active = $module_name == "core"; // only core is active by default } $module->version = 1; $module->save(); @@ -52,25 +49,8 @@ class module_Core { * @param string $module_name */ static function get($module_name) { - return model_cache::get("module", $module_name, "name"); - } - - /** - * Delete the corresponding Module_Model - * @param string $module_name - */ - static function delete($module_name) { - $module = ORM::factory("module")->where("name", $module_name)->find(); - if ($module->loaded) { - $db = Database::instance(); - $db->delete("graphics_rules", array("module_name" => $module->name)); - $module->delete(); - - // We could delete the module vars here too, but it's nice to leave them around in case the - // module gets reinstalled. - - Kohana::log("debug", "$module_name: module deleted"); - } + // @todo can't easily use model_cache here because it throw an exception on missing models. + return ORM::factory("module", array("name" => $module_name)); } /** @@ -78,27 +58,29 @@ class module_Core { * @param string $module_name */ static function is_installed($module_name) { - return !empty(self::$module_names[$module_name]); + return array_key_exists($module_name, self::$modules); } /** - * Return the list of installed modules. + * Check to see if a module is active + * @param string $module_name */ - static function installed() { - return self::$modules; + static function is_active($module_name) { + return array_key_exists($module_name, self::$modules) && + self::$modules[$module_name]->active; } /** - * Return the list of available modules. + * Return the list of available modules, including uninstalled modules. */ static function available() { $modules = new ArrayObject(array(), ArrayObject::ARRAY_AS_PROPS); foreach (array_merge(array("core/module.info"), glob(MODPATH . "*/module.info")) as $file) { $module_name = basename(dirname($file)); $modules->$module_name = new ArrayObject(parse_ini_file($file), ArrayObject::ARRAY_AS_PROPS); - $modules->$module_name->installed = - empty(self::$modules[$module_name]) ? - null : self::$modules[$module_name]->version; + $modules->$module_name->installed = self::is_installed($module_name); + $modules->$module_name->active = self::is_active($module_name); + $modules->$module_name->version = self::get_version($module_name); $modules->$module_name->locked = false; } @@ -111,35 +93,108 @@ class module_Core { } /** - * Install a module. + * Return a list of all the active modules in no particular order. */ - static function install($module_name) { - $installer_class = "{$module_name}_installer"; - Kohana::log("debug", "$installer_class install (initial)"); - if ($module_name != "core") { - require_once(DOCROOT . "modules/${module_name}/helpers/{$installer_class}.php"); + static function active() { + return self::$active; } + + /** + * Install a module. This will call <module>_installer::install(), which is responsible for + * creating database tables, setting module variables and and calling module::set_version(). + * Note that after installing, the module must be activated before it is available for use. + * @param string $module_name + */ + static function install($module_name) { $kohana_modules = Kohana::config("core.modules"); $kohana_modules[] = MODPATH . $module_name; Kohana::config_set("core.modules", $kohana_modules); + $installer_class = "{$module_name}_installer"; if (method_exists($installer_class, "install")) { call_user_func_array(array($installer_class, "install"), array()); } - self::load_modules(); + // Now the module is installed but inactive, so don't leave it in the active path + array_pop($kohana_modules); + Kohana::config_set("core.modules", $kohana_modules); + log::success( "module", t("Installed module %module_name", array("module_name" => $module_name))); } /** - * Uninstall a module. + * Activate an installed module. This will call <module>_installer::activate() which should take + * any steps to make sure that the module is ready for use. This will also activate any + * existing graphics rules for this module. + * @param string $module_name + */ + static function activate($module_name) { + $kohana_modules = Kohana::config("core.modules"); + $kohana_modules[] = MODPATH . $module_name; + Kohana::config_set("core.modules", $kohana_modules); + + $installer_class = "{$module_name}_installer"; + if (method_exists($installer_class, "activate")) { + call_user_func_array(array($installer_class, "activate"), array()); + } + + $module = self::get($module_name); + if ($module->loaded) { + $module->active = true; + $module->save(); + } + + self::load_modules(); + graphics::activate_rules($module_name); + log::success( + "module", t("Activated module %module_name", array("module_name" => $module_name))); + } + + /** + * Deactivate an installed module. This will call <module>_installer::deactivate() which + * should take any cleanup steps to make sure that the module isn't visible in any way. + * @param string $module_name + */ + static function deactivate($module_name) { + $installer_class = "{$module_name}_installer"; + if (method_exists($installer_class, "deactivate")) { + call_user_func_array(array($installer_class, "deactivate"), array()); + } + $module = self::get($module_name); + if ($module->loaded) { + $module->active = false; + $module->save(); + } + + self::load_modules(); + graphics::deactivate_rules($module_name); + log::success( + "module", t("Deactivated module %module_name", array("module_name" => $module_name))); + } + + /** + * Uninstall a deactivated module. This will call <module>_installer::uninstall() which should + * take whatever steps necessary to make sure that all traces of a module are gone. + * @param string $module_name */ static function uninstall($module_name) { $installer_class = "{$module_name}_installer"; - Kohana::log("debug", "$installer_class uninstall"); + if (method_exists($installer_class, "uninstall")) { call_user_func(array($installer_class, "uninstall")); + } + + graphics::remove_rule($module_name); + $module = self::get($module_name); + if ($module->loaded) { + $module->delete(); + } + + // We could delete the module vars here too, but it's nice to leave them around + // in case the module gets reinstalled. + + self::load_modules(); log::success( "module", t("Uninstalled module %module_name", array("module_name" => $module_name))); } @@ -153,19 +208,18 @@ class module_Core { $kohana_modules = $core["modules"]; $modules = ORM::factory("module")->find_all(); + self::$modules = array(); + self::$active = array(); foreach ($modules as $module) { - self::$module_names[$module->name] = $module->name; self::$modules[$module->name] = $module; - - // @todo For some reason if we don't load the core module here, the test framework fails. - // This requires some investigation. + if ($module->active) { + self::$active[] = $module; + } if ($module->name != "core") { $kohana_modules[] = MODPATH . $module->name; } } Kohana::config_set("core.modules", $kohana_modules); - - self::event("gallery_ready"); } /** @@ -178,7 +232,11 @@ class module_Core { array_shift($args); $function = str_replace(".", "_", $name); - foreach (self::installed() as $module) { + foreach (self::$modules as $module) { + if (!$module->active) { + continue; + } + $class = "{$module->name}_event"; if (method_exists($class, $function)) { call_user_func_array(array($class, $function), $args); @@ -187,17 +245,6 @@ class module_Core { } /** - * Kohana shutdown event handler - * @param string $module_name - * @param string $name - * @param string $default_value - * @return the value - */ - static function shutdown() { - self::event("gallery_shutdown"); - } - - /** * Get a variable from this module * @param string $module_name * @param string $name @@ -256,7 +303,6 @@ class module_Core { ->where("name", $name) ->find(); if (!$var->loaded) { - $var = ORM::factory("var"); $var->module_name = $module_name; $var->name = $name; } @@ -300,4 +346,12 @@ class module_Core { Database::instance()->delete("vars", array("module_name" => "core", "name" => "_cache")); self::$var_cache = null; } + + /** + * Return the version of the installed module. + * @param string $module_name + */ + static function get_version($module_name) { + return self::get($module_name)->version; + } } diff --git a/core/helpers/task.php b/core/helpers/task.php index 1bc2996a..a8a004ab 100644 --- a/core/helpers/task.php +++ b/core/helpers/task.php @@ -23,8 +23,8 @@ class task_Core { */ static function get_definitions() { $tasks = array(); - foreach (module::installed() as $module_name => $module_info) { - $class_name = "{$module_name}_task"; + foreach (module::active() as $module) { + $class_name = "{$module->name}_task"; if (method_exists($class_name, "available_tasks")) { foreach (call_user_func(array($class_name, "available_tasks")) as $task) { $tasks[$task->callback] = $task; |