summaryrefslogtreecommitdiff
path: root/core/helpers
diff options
context:
space:
mode:
authorBharat Mediratta <bharat@menalto.com>2009-05-26 05:28:59 +0000
committerBharat Mediratta <bharat@menalto.com>2009-05-26 05:28:59 +0000
commit7aed9239088b582a065da3fb63796ff66cd357c8 (patch)
tree8be9bc4faec21b20cbcc060ad5e9ca128465d09e /core/helpers
parent2966289b147ceae2fed79b9534840607bf38e0d8 (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.php4
-rw-r--r--core/helpers/block_manager.php2
-rw-r--r--core/helpers/core.php22
-rw-r--r--core/helpers/core_installer.php40
-rw-r--r--core/helpers/core_menu.php2
-rw-r--r--core/helpers/graphics.php32
-rw-r--r--core/helpers/log.php2
-rw-r--r--core/helpers/module.php176
-rw-r--r--core/helpers/task.php4
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;