/** * Returns all directories of installed plugins except for local * from the current codebase. * * This is relatively slow and not fully cached, use with care! * * @return array ('plugintkey' => path, ...) * For example, array ( * 'artefact.blog' => $CFG->docroot . 'artefact/blog', * 'blocktype.blog' => $CFG->docroot . 'artefact/blog/blocktype/blog', * ... * ) */ function get_installed_plugins_paths() { $versions = array(); // All installed plugins $plugins = array(); foreach (plugin_types_installed() as $plugin) { $dirhandle = opendir(get_config('docroot') . $plugin); while (false !== ($dir = readdir($dirhandle))) { if (strpos($dir, '.') === 0 || 'CVS' == $dir) { continue; } if (!is_dir(get_config('docroot') . $plugin . '/' . $dir)) { continue; } try { validate_plugin($plugin, $dir); $plugins[] = array($plugin, $dir); } catch (InstallationException $_e) { log_warn("Plugin {$plugin} {$dir} is not installable: " . $_e->GetMessage()); } if ($plugin === 'artefact') { // go check it for blocks as well $btlocation = get_config('docroot') . $plugin . '/' . $dir . '/blocktype'; if (!is_dir($btlocation)) { continue; } $btdirhandle = opendir($btlocation); while (false !== ($btdir = readdir($btdirhandle))) { if (strpos($btdir, '.') === 0 || 'CVS' == $btdir) { continue; } if (!is_dir(get_config('docroot') . $plugin . '/' . $dir . '/blocktype/' . $btdir)) { continue; } $plugins[] = array('blocktype', $dir . '/' . $btdir); } } } } $pluginpaths = array(); foreach ($plugins as $plugin) { $plugintype = $plugin[0]; $pluginname = $plugin[1]; $pluginpath = "{$plugin['0']}/{$plugin['1']}"; $pluginkey = "{$plugin['0']}.{$plugin['1']}"; if ($plugintype == 'blocktype' && strpos($pluginname, '/') !== false) { $bits = explode('/', $pluginname); $pluginpath = 'artefact/' . $bits[0] . '/blocktype/' . $bits[1]; } $pluginpaths[$pluginkey] = get_config('docroot') . $pluginpath; } return $pluginpaths; }
/** * Return structure info of tables from mahara xmldb files * * @return array(XMLDBTable) */ function get_tables_from_xmldb() { static $tables = array(); if (!empty($tables)) { return $tables; } // Get database structure from plugins' tables foreach (array_reverse(plugin_types_installed()) as $t) { if ($installed = plugins_installed($t, true)) { foreach ($installed as $p) { $location = get_config('docroot') . $t . '/' . $p->name . '/db/'; if (is_readable($location . 'install.xml')) { $tables = array_merge($tables, get_tables_from_xmldb_file($location . 'install.xml')); } } } } $tables = array_merge($tables, get_tables_from_xmldb_file(get_config('docroot') . 'lib/db/install.xml')); return $tables; }
/** * Fires an event which can be handled by different parts of the system */ function handle_event($event, $data) { global $USER; static $event_types = array(), $coreevents_cache = array(), $eventsubs_cache = array(); if (empty($event_types)) { $event_types = array_fill_keys(get_column('event_type', 'name'), true); } $e = $event_types[$event]; if (is_null($e)) { throw new SystemException("Invalid event"); } if ($data instanceof ArtefactType) { // leave $data alone, but convert for the event log $logdata = $data->to_stdclass(); } else { if ($data instanceof BlockInstance) { // leave $data alone, but convert for the event log $logdata = array('id' => $data->get('id'), 'blocktype' => $data->get('blocktype')); } else { if (is_object($data)) { $data = (array) $data; } else { if (is_numeric($data)) { $data = array('id' => $data); } } } } $parentuser = $USER->get('parentuser'); $eventloglevel = get_config('eventloglevel'); if ($eventloglevel === 'all' or $parentuser and $eventloglevel === 'masq') { $logentry = (object) array('usr' => $USER->get('id'), 'realusr' => $parentuser ? $parentuser->id : $USER->get('id'), 'event' => $event, 'data' => json_encode(isset($logdata) ? $logdata : $data), 'time' => db_format_timestamp(time())); insert_record('event_log', $logentry); } if (empty($coreevents_cache)) { $rs = get_recordset('event_subscription'); foreach ($rs as $record) { $coreevents_cache[$record['event']][] = $record['callfunction']; } $rs->close(); } $coreevents = isset($coreevents_cache[$event]) ? $coreevents_cache[$event] : array(); if (!empty($coreevents)) { require_once 'activity.php'; // core events can generate activity. foreach ($coreevents as $ce) { if (function_exists($ce)) { call_user_func($ce, $data); } else { log_warn("Event {$event} caused a problem with a core subscription " . " {$ce}, which wasn't callable. Continuing with event handlers"); } } } $plugintypes = plugin_types_installed(); foreach ($plugintypes as $name) { $cache_key = "{$event}__{$name}"; if (!isset($eventsubs_cache[$cache_key])) { $eventsubs_cache[$cache_key] = get_records_array($name . '_event_subscription', 'event', $event); } if ($eventsubs_cache[$cache_key]) { $pluginsinstalled = plugins_installed($name); foreach ($eventsubs_cache[$cache_key] as $sub) { if (!isset($pluginsinstalled[$sub->plugin])) { continue; } safe_require($name, $sub->plugin); $classname = 'Plugin' . ucfirst($name) . ucfirst($sub->plugin); try { call_static_method($classname, $sub->callfunction, $event, $data); } catch (Exception $e) { log_warn("Event {$event} caused an exception from plugin {$classname} " . "with function {$sub->callfunction}. Continuing with event handlers"); } } } } }
/** * List all installed component web service directories * * @return array of web service plugin directories */ function get_ws_subsystems() { static $plugindirs = null; if (!$plugindirs) { // add the root webservice first which is empty because it is docroot, and local $plugindirs = array(WEBSERVICE_DIRECTORY, 'local/' . WEBSERVICE_DIRECTORY); foreach (plugin_types_installed() as $t) { foreach (plugins_installed($t) as $name => $plugindata) { $plugindir = $t . '/' . $name; if (!empty($plugindata->authplugin)) { $plugindir = 'auth/' . $plugindata->authplugin . '/' . $plugindir; } $plugindirs[] = $plugindir . '/' . WEBSERVICE_DIRECTORY; } } } return $plugindirs; }
/** * completely uninstall mahara, drop all tables. * this just does what install does, but in reverse order * reversing the order of tables, and indexes * to respect referential integrity */ public function uninstall_mahara() { // this can't be done in a transaction because sometimes // things exist in the database that aren't in the file or the other way around // in the case where there are stale tables and then the code is upgraded foreach (array_reverse(plugin_types_installed()) as $t) { if ($installed = plugins_installed($t, true)) { foreach ($installed as $p) { $location = get_config('docroot') . $t . '/' . $p->name . '/db/'; log_info('Uninstalling ' . $location); if (is_readable($location . 'install.xml')) { uninstall_from_xmldb_file($location . 'install.xml'); } } } } // now uninstall core log_info('Uninstalling core'); // These constraints must be dropped manually as they cannot be // created with xmldb due to ordering issues if (is_postgres()) { try { execute_sql('ALTER TABLE {usr} DROP CONSTRAINT {usr_pro_fk}'); } catch (Exception $e) { } try { execute_sql('ALTER TABLE {institution} DROP CONSTRAINT {inst_log_fk}'); } catch (Exception $e) { } } else { try { execute_sql('ALTER TABLE {usr} DROP FOREIGN KEY {usr_pro_fk}'); } catch (Exception $e) { } try { execute_sql('ALTER TABLE {institution} DROP FOREIGN KEY {inst_log_fk}'); } catch (Exception $e) { } } uninstall_from_xmldb_file(get_config('docroot') . 'lib/db/install.xml'); }
/** * Fires an event which can be handled by different parts of the system */ function handle_event($event, $data) { if (!($e = get_record('event_type', 'name', $event))) { throw new Exception("Invalid event"); } if ($data instanceof ArtefactType || $data instanceof BlockInstance) { // leave it alone } else { if (is_object($data)) { $data = (array) $data; } else { if (is_numeric($data)) { $data = array('id' => $data); } } } if ($coreevents = get_records_array('event_subscription', 'event', $event)) { require_once 'activity.php'; // core events can generate activity. foreach ($coreevents as $ce) { if (function_exists($ce->callfunction)) { call_user_func($ce->callfunction, $data); } else { log_warn("Event {$event} caused a problem with a core subscription " . " {$ce->callfunction}, which wasn't callable. Continuing with event handlers"); } } } $plugintypes = plugin_types_installed(); foreach ($plugintypes as $name) { if ($subs = get_records_array($name . '_event_subscription', 'event', $event)) { foreach ($subs as $sub) { safe_require($name, $sub->plugin); $classname = 'Plugin' . ucfirst($name) . ucfirst($sub->plugin); try { call_static_method($classname, $sub->callfunction, $event, $data); } catch (Exception $e) { log_warn("Event {$event} caused an exception from plugin {$classname} " . "with function {$sub->callfunction}. Continuing with event handlers"); } } } } }