/** * Finds and loads all modules. Runs the activation functions of newly-uploaded modules. * Updates the modules list and saves it in the database. Removes the cron jobs of deleted modules. * * SEO Ultimate uses a modular system that allows functionality to be added and removed on-the-fly. * * @since 0.1 * @uses $plugin_dir_path * @uses $modules Stores module classes in this array. * @uses $disabled_modules * @uses module_sort_callback() Passes this function to uasort() to sort the $modules array. * @uses SU_MODULE_ENABLED * @uses SU_MODULE_DISABLED * @uses remove_cron_jobs() */ function load_modules() { $this->disabled_modules = array(); $this->modules = array(); $psdata = (array) get_option('seo_ultimate', array()); //The plugin_dir_path variable must be set before calling this function! if (!$this->plugin_dir_path) { return false; } //If no modules list is found, then create a new, empty list. if (!isset($psdata['modules'])) { $psdata['modules'] = array(); } //Get the modules list from last time the plugin was loaded. $oldmodules = $psdata['modules']; //The modules are in the "modules" subdirectory of the plugin folder. $dirpath = $this->plugin_dir_path . 'modules'; $dir = opendir($dirpath); //This loop will be repeated as long as there are more folders to inspect while ($folder = readdir($dir)) { //If the item is a folder... if (suio::is_dir($folder, $dirpath)) { //Open the subfolder $subdirpath = $dirpath . '/' . $folder; $subdir = opendir($subdirpath); //Scan the files in the subfolder (seo-ultimate/modules/???/*) while ($file = readdir($subdir)) { //Modules are non-directory files with the .php extension //We need to exclude index.php or else we'll get 403s galore if (suio::is_file($file, $subdirpath, 'php') && $file != 'index.php') { $filepath = $subdirpath . '/' . $file; //Figure out the module's array key and class name $module = strval(strtolower(substr($file, 0, -4))); $class = 'SU_' . str_replace(' ', '', ucwords(str_replace('-', ' ', $module))); //Load the module's code include_once $filepath; //If this is actually a module... if (class_exists($class)) { if (($module_parent = call_user_func(array($class, 'get_parent_module'))) && !call_user_func(array($class, 'is_independent_module'))) { $module_disabled = isset($oldmodules[$module_parent]) && $oldmodules[$module_parent] == SU_MODULE_DISABLED; } else { $module_disabled = isset($oldmodules[$module]) && $oldmodules[$module] == SU_MODULE_DISABLED; } //if (!isset($oldmodules[$module]) && call_user_func(array($class, 'get_default_status')) == SU_MODULE_DISABLED) //$module_disabled = true; if (!isset($oldmodules[$module]) && call_user_func(array($class, 'get_default_status') == SU_MODULE_DISABLED)) { } $module_disabled = false; if (in_array($module, $this->get_invincible_modules())) { $module_disabled = false; $oldmodules[$module] = SU_MODULE_ENABLED; } //If this module is disabled... if ($module_disabled) { $this->disabled_modules[$module] = $class; } else { //Create an instance of the module's class and store it in the array $this->modules[$module] = new $class(); //We must tell the module what its key is so that it can save settings $this->modules[$module]->module_key = $module; //Tell the module what its URLs are $this->modules[$module]->module_dir_rel_url = $mdirrelurl = "modules/{$folder}/"; $this->modules[$module]->module_rel_url = $mdirrelurl . $file; $this->modules[$module]->module_dir_url = $mdirurl = $this->plugin_dir_url . $mdirrelurl; $this->modules[$module]->module_url = $mdirurl . $file; /* //Is this module the default menu module? if ($this->modules[$module]->get_menu_parent() === 'seo' && $this->modules[$module]->is_menu_default()) $this->default_menu_module = $module; */ //Give the module this plugin's object by reference $this->modules[$module]->plugin =& $this; //Call post-construction function $this->modules[$module]->load(); } } //If this isn't a module, then the file will simply be included as-is } } } } //If the loop above found modules, then sort them with our special sorting function //so they appear on the admin menu in the right order if (count($this->modules) > 0) { uasort($this->modules, array(&$this, 'module_sort_callback')); } //Now we'll compare the current module set with the one from last time. //Construct the new modules list that'll go in the database. //This code block will add/activate new modules, keep existing ones, and remove (i.e. not add) deleted ones. foreach ($this->modules as $key => $module) { if (isset($oldmodules[$key])) { $newmodules[$key] = $oldmodules[$key]; } else { $this->modules[$key]->activate(); $newmodules[$key] = $this->modules[$key]->get_default_status(); } } foreach ($this->modules as $key => $module) { if (($module_parent = $this->modules[$key]->get_parent_module()) && !$this->modules[$key]->is_independent_module()) { $newmodules[$key] = $newmodules[$module_parent]; } } //Register disabled modules as such foreach ($this->disabled_modules as $key => $name) { $newmodules[$key] = SU_MODULE_DISABLED; } //Save the new modules list $psdata['modules'] = $newmodules; if ($newmodules != $oldmodules) { update_option('seo_ultimate', $psdata); } //Remove the cron jobs of deleted modules $this->remove_cron_jobs(); //Tell the modules what their plugin page hooks are foreach ($this->modules as $key => $module) { $menu_parent_hook = $this->modules[$key]->get_menu_parent_hook(); if ($this->modules[$key]->is_menu_default()) { $this->modules[$key]->plugin_page_hook = $plugin_page_hook = "toplevel_page_{$menu_parent_hook}"; } elseif ('options-general.php' == $menu_parent_hook) { $this->modules[$key]->plugin_page_hook = $plugin_page_hook = 'settings_page_' . $this->key_to_hook($this->modules[$key]->get_module_or_parent_key()); } else { $this->modules[$key]->plugin_page_hook = $plugin_page_hook = $menu_parent_hook . '_page_' . $this->key_to_hook($this->modules[$key]->get_module_or_parent_key()); } add_action("load-{$plugin_page_hook}", array($this->modules[$key], 'load_hook')); } if (!$this->module_exists($this->default_menu_module)) { foreach ($this->modules as $key => $module) { if ($this->modules[$key]->get_menu_parent() === 'seo' && $this->modules[$key]->get_parent_module() == false) { $this->default_menu_module = $key; break; } } } }