Current oav website
This commit is contained in:
745
dotclear._no/inc/core/class.dc.modules.php
Normal file
745
dotclear._no/inc/core/class.dc.modules.php
Normal file
@ -0,0 +1,745 @@
|
||||
<?php
|
||||
/**
|
||||
* @brief Modules handler
|
||||
*
|
||||
* Provides an object to handle modules (themes or plugins).
|
||||
*
|
||||
* @package Dotclear
|
||||
* @subpackage Core
|
||||
*
|
||||
* @copyright Olivier Meunier & Association Dotclear
|
||||
* @copyright GPL-2.0-only
|
||||
*/
|
||||
|
||||
if (!defined('DC_RC_PATH')) {return;}
|
||||
|
||||
class dcModules
|
||||
{
|
||||
protected $path;
|
||||
protected $ns;
|
||||
protected $modules = [];
|
||||
protected $disabled = [];
|
||||
protected $errors = [];
|
||||
protected $modules_names = [];
|
||||
protected $all_modules = [];
|
||||
protected $disabled_mode = false;
|
||||
protected $disabled_meta = [];
|
||||
protected $to_disable = [];
|
||||
|
||||
protected $id;
|
||||
protected $mroot;
|
||||
|
||||
# Inclusion variables
|
||||
protected static $superglobals = ['GLOBALS', '_SERVER', '_GET', '_POST', '_COOKIE', '_FILES', '_ENV', '_REQUEST', '_SESSION'];
|
||||
protected static $_k;
|
||||
protected static $_n;
|
||||
|
||||
protected static $type = null;
|
||||
|
||||
public $core; ///< <b>dcCore</b> dcCore instance
|
||||
|
||||
/**
|
||||
Object constructor.
|
||||
|
||||
@param core <b>dcCore</b> dcCore instance
|
||||
*/
|
||||
public function __construct($core)
|
||||
{
|
||||
$this->core = &$core;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks all modules dependencies
|
||||
* Fills in the following information in module :
|
||||
* * cannot_enable : list reasons why module cannot be enabled. Not set if module can be enabled
|
||||
* * cannot_disable : list reasons why module cannot be disabled. Not set if module can be disabled
|
||||
* * implies : reverse dependencies
|
||||
* @return array list of enabled modules with unmet dependencies, and that must be disabled.
|
||||
*/
|
||||
public function checkDependencies()
|
||||
{
|
||||
$dc_version = preg_replace('/\-dev.*$/', '', DC_VERSION);
|
||||
$this->to_disable = [];
|
||||
foreach ($this->all_modules as $k => &$m) {
|
||||
if (isset($m['requires'])) {
|
||||
$missing = [];
|
||||
foreach ($m['requires'] as &$dep) {
|
||||
if (!is_array($dep)) {
|
||||
$dep = [$dep];
|
||||
}
|
||||
// grab missing dependencies
|
||||
if (!isset($this->all_modules[$dep[0]]) && ($dep[0] != 'core')) {
|
||||
// module not present
|
||||
$missing[$dep[0]] = sprintf(__("Requires %s module which is not installed"), $dep[0]);
|
||||
} elseif ((count($dep) > 1) &&
|
||||
version_compare(($dep[0] == 'core' ? $dc_version : $this->all_modules[$dep[0]]['version']), $dep[1]) == -1) {
|
||||
// module present, but version missing
|
||||
if ($dep[0] == 'core') {
|
||||
$missing[$dep[0]] = sprintf(__("Requires Dotclear version %s, but version %s is installed"),
|
||||
$dep[1], $dc_version);
|
||||
} else {
|
||||
$missing[$dep[0]] = sprintf(__("Requires %s module version %s, but version %s is installed"),
|
||||
$dep[0], $dep[1], $this->all_modules[$dep[0]]['version']);
|
||||
}
|
||||
} elseif (($dep[0] != 'core') && !$this->all_modules[$dep[0]]['enabled']) {
|
||||
// module disabled
|
||||
$missing[$dep[0]] = sprintf(__("Requires %s module which is disabled"), $dep[0]);
|
||||
}
|
||||
$this->all_modules[$dep[0]]['implies'][] = $k;
|
||||
}
|
||||
if (count($missing)) {
|
||||
$m['cannot_enable'] = $missing;
|
||||
if ($m['enabled']) {
|
||||
$this->to_disable[] = ['name' => $k, 'reason' => $missing];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Check modules that cannot be disabled
|
||||
foreach ($this->modules as $k => &$m) {
|
||||
if (isset($m['implies']) && $m['enabled']) {
|
||||
foreach ($m['implies'] as $im) {
|
||||
if (isset($this->all_modules[$im]) && $this->all_modules[$im]['enabled']) {
|
||||
$m['cannot_disable'][] = $im;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks all modules dependencies, and disable unmet dependencies
|
||||
* @param string $redir_url URL to redirect if modules are to disable
|
||||
* @return boolean, true if a redirection has been performed
|
||||
*/
|
||||
public function disableDepModules($redir_url)
|
||||
{
|
||||
if (isset($_GET['dep'])) {
|
||||
// Avoid infinite redirects
|
||||
return false;
|
||||
}
|
||||
$reason = [];
|
||||
foreach ($this->to_disable as $module) {
|
||||
try {
|
||||
$this->deactivateModule($module['name']);
|
||||
$reason[] = sprintf("<li>%s : %s</li>", $module['name'], join(',', $module['reason']));
|
||||
} catch (Exception $e) {
|
||||
}
|
||||
}
|
||||
if (count($reason)) {
|
||||
$message = sprintf("<p>%s</p><ul>%s</ul>",
|
||||
__('The following extensions have been disabled :'),
|
||||
join('', $reason)
|
||||
);
|
||||
dcPage::addWarningNotice($message, ['divtag' => true, 'with_ts' => false]);
|
||||
$url = $redir_url . (strpos($redir_url, "?") ? '&' : '?') . 'dep=1';
|
||||
http::redirect($url);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
Loads modules. <var>$path</var> could be a separated list of paths
|
||||
(path separator depends on your OS).
|
||||
|
||||
<var>$ns</var> indicates if an additionnal file needs to be loaded on plugin
|
||||
load, value could be:
|
||||
- admin (loads module's _admin.php)
|
||||
- public (loads module's _public.php)
|
||||
- xmlrpc (loads module's _xmlrpc.php)
|
||||
|
||||
<var>$lang</var> indicates if we need to load a lang file on plugin
|
||||
loading.
|
||||
*/
|
||||
public function loadModules($path, $ns = null, $lang = null)
|
||||
{
|
||||
$this->path = explode(PATH_SEPARATOR, $path);
|
||||
$this->ns = $ns;
|
||||
|
||||
$disabled = isset($_SESSION['sess_safe_mode']) && $_SESSION['sess_safe_mode'];
|
||||
$disabled = $disabled && !get_parent_class($this) ? true : false;
|
||||
|
||||
$ignored = [];
|
||||
|
||||
foreach ($this->path as $root) {
|
||||
if (!is_dir($root) || !is_readable($root)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (substr($root, -1) != '/') {
|
||||
$root .= '/';
|
||||
}
|
||||
|
||||
if (($d = @dir($root)) === false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
while (($entry = $d->read()) !== false) {
|
||||
$full_entry = $root . $entry;
|
||||
|
||||
if ($entry != '.' && $entry != '..' && is_dir($full_entry)
|
||||
&& file_exists($full_entry . '/_define.php')) {
|
||||
if (!file_exists($full_entry . '/_disabled') && !$disabled) {
|
||||
$this->id = $entry;
|
||||
$this->mroot = $full_entry;
|
||||
ob_start();
|
||||
require $full_entry . '/_define.php';
|
||||
ob_end_clean();
|
||||
$this->all_modules[$entry] = &$this->modules[$entry];
|
||||
$this->id = null;
|
||||
$this->mroot = null;
|
||||
} else {
|
||||
if (file_exists($full_entry . '/_define.php')) {
|
||||
$this->id = $entry;
|
||||
$this->mroot = $full_entry;
|
||||
$this->disabled_mode = true;
|
||||
ob_start();
|
||||
require $full_entry . '/_define.php';
|
||||
ob_end_clean();
|
||||
$this->disabled_mode = false;
|
||||
$this->disabled[$entry] = $this->disabled_meta;
|
||||
$this->all_modules[$entry] = &$this->disabled[$entry];
|
||||
$this->id = null;
|
||||
$this->mroot = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$d->close();
|
||||
}
|
||||
$this->checkDependencies();
|
||||
# Sort plugins
|
||||
uasort($this->modules, [$this, 'sortModules']);
|
||||
|
||||
foreach ($this->modules as $id => $m) {
|
||||
# Load translation and _prepend
|
||||
if (isset($m['root']) && file_exists($m['root'] . '/_prepend.php')) {
|
||||
$r = $this->loadModuleFile($m['root'] . '/_prepend.php');
|
||||
|
||||
# If _prepend.php file returns null (ie. it has a void return statement)
|
||||
if (is_null($r)) {
|
||||
$ignored[] = $id;
|
||||
continue;
|
||||
}
|
||||
unset($r);
|
||||
}
|
||||
|
||||
$this->loadModuleL10N($id, $lang, 'main');
|
||||
if ($ns == 'admin') {
|
||||
$this->loadModuleL10Nresources($id, $lang);
|
||||
$this->core->adminurl->register('admin.plugin.' . $id, 'plugin.php', ['p' => $id]);
|
||||
}
|
||||
}
|
||||
|
||||
// Give opportunity to do something before loading context (admin,public,xmlrpc) files
|
||||
$this->core->callBehavior('coreBeforeLoadingNsFiles', $this->core, $this, $lang);
|
||||
|
||||
foreach ($this->modules as $id => $m) {
|
||||
# If _prepend.php file returns null (ie. it has a void return statement)
|
||||
if (in_array($id, $ignored)) {
|
||||
continue;
|
||||
}
|
||||
# Load ns_file
|
||||
$this->loadNsFile($id, $ns);
|
||||
}
|
||||
}
|
||||
|
||||
public function requireDefine($dir, $id)
|
||||
{
|
||||
if (file_exists($dir . '/_define.php')) {
|
||||
$this->id = $id;
|
||||
ob_start();
|
||||
require $dir . '/_define.php';
|
||||
ob_end_clean();
|
||||
$this->id = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
This method registers a module in modules list. You should use this to
|
||||
register a new module.
|
||||
|
||||
<var>$permissions</var> is a comma separated list of permissions for your
|
||||
module. If <var>$permissions</var> is null, only super admin has access to
|
||||
this module.
|
||||
|
||||
<var>$priority</var> is an integer. Modules are sorted by priority and name.
|
||||
Lowest priority comes first.
|
||||
|
||||
@param name <b>string</b> Module name
|
||||
@param desc <b>string</b> Module description
|
||||
@param author <b>string</b> Module author name
|
||||
@param version <b>string</b> Module version
|
||||
@param properties <b>array</b> extra properties
|
||||
(currently available keys : permissions, priority, type)
|
||||
*/
|
||||
public function registerModule($name, $desc, $author, $version, $properties = [])
|
||||
{
|
||||
if ($this->disabled_mode) {
|
||||
$this->disabled_meta = array_merge(
|
||||
$properties,
|
||||
[
|
||||
'root' => $this->mroot,
|
||||
'name' => $name,
|
||||
'desc' => $desc,
|
||||
'author' => $author,
|
||||
'version' => $version,
|
||||
'enabled' => false,
|
||||
'root_writable' => is_writable($this->mroot)
|
||||
]
|
||||
);
|
||||
return;
|
||||
}
|
||||
# Fallback to legacy registerModule parameters
|
||||
if (!is_array($properties)) {
|
||||
$args = func_get_args();
|
||||
$properties = [];
|
||||
if (isset($args[4])) {
|
||||
$properties['permissions'] = $args[4];
|
||||
}
|
||||
if (isset($args[5])) {
|
||||
$properties['priority'] = (integer) $args[5];
|
||||
}
|
||||
}
|
||||
|
||||
# Default module properties
|
||||
$properties = array_merge(
|
||||
[
|
||||
'permissions' => null,
|
||||
'priority' => 1000,
|
||||
'standalone_config' => false,
|
||||
'type' => null,
|
||||
'enabled' => true,
|
||||
'requires' => [],
|
||||
'settings' => []
|
||||
], $properties
|
||||
);
|
||||
|
||||
# Check module type
|
||||
if (self::$type !== null && $properties['type'] !== null && $properties['type'] != self::$type) {
|
||||
$this->errors[] = sprintf(
|
||||
__('Module "%s" has type "%s" that mismatch required module type "%s".'),
|
||||
'<strong>' . html::escapeHTML($name) . '</strong>',
|
||||
'<em>' . html::escapeHTML($properties['type']) . '</em>',
|
||||
'<em>' . html::escapeHTML(self::$type) . '</em>'
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
# Check module perms on admin side
|
||||
$permissions = $properties['permissions'];
|
||||
if ($this->ns == 'admin') {
|
||||
if ($permissions == '' && !$this->core->auth->isSuperAdmin()) {
|
||||
return;
|
||||
} elseif (!$this->core->auth->check($permissions, $this->core->blog->id)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
# Check module install on multiple path
|
||||
if ($this->id) {
|
||||
$module_exists = array_key_exists($name, $this->modules_names);
|
||||
$module_overwrite = $module_exists ? version_compare($this->modules_names[$name], $version, '<') : false;
|
||||
if (!$module_exists || ($module_exists && $module_overwrite)) {
|
||||
$this->modules_names[$name] = $version;
|
||||
$this->modules[$this->id] = array_merge(
|
||||
$properties,
|
||||
[
|
||||
'root' => $this->mroot,
|
||||
'name' => $name,
|
||||
'desc' => $desc,
|
||||
'author' => $author,
|
||||
'version' => $version,
|
||||
'root_writable' => is_writable($this->mroot)
|
||||
]
|
||||
);
|
||||
} else {
|
||||
$path1 = path::real($this->moduleInfo($name, 'root'));
|
||||
$path2 = path::real($this->mroot);
|
||||
$this->errors[] = sprintf(
|
||||
__('Module "%s" is installed twice in "%s" and "%s".'),
|
||||
'<strong>' . $name . '</strong>',
|
||||
'<em>' . $path1 . '</em>',
|
||||
'<em>' . $path2 . '</em>'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function resetModulesList()
|
||||
{
|
||||
$this->modules = [];
|
||||
$this->modules_names = [];
|
||||
$this->errors = [];
|
||||
}
|
||||
|
||||
public static function installPackage($zip_file, dcModules &$modules)
|
||||
{
|
||||
$zip = new fileUnzip($zip_file);
|
||||
$zip->getList(false, '#(^|/)(__MACOSX|\.svn|\.hg.*|\.git.*|\.DS_Store|\.directory|Thumbs\.db)(/|$)#');
|
||||
|
||||
$zip_root_dir = $zip->getRootDir();
|
||||
$define = '';
|
||||
if ($zip_root_dir != false) {
|
||||
$target = dirname($zip_file);
|
||||
$destination = $target . '/' . $zip_root_dir;
|
||||
$define = $zip_root_dir . '/_define.php';
|
||||
$has_define = $zip->hasFile($define);
|
||||
} else {
|
||||
$target = dirname($zip_file) . '/' . preg_replace('/\.([^.]+)$/', '', basename($zip_file));
|
||||
$destination = $target;
|
||||
$define = '_define.php';
|
||||
$has_define = $zip->hasFile($define);
|
||||
}
|
||||
|
||||
if ($zip->isEmpty()) {
|
||||
$zip->close();
|
||||
unlink($zip_file);
|
||||
throw new Exception(__('Empty module zip file.'));
|
||||
}
|
||||
|
||||
if (!$has_define) {
|
||||
$zip->close();
|
||||
unlink($zip_file);
|
||||
throw new Exception(__('The zip file does not appear to be a valid Dotclear module.'));
|
||||
}
|
||||
|
||||
$ret_code = 1;
|
||||
|
||||
if (!is_dir($destination)) {
|
||||
try {
|
||||
files::makeDir($destination, true);
|
||||
|
||||
$sandbox = clone $modules;
|
||||
$zip->unzip($define, $target . '/_define.php');
|
||||
|
||||
$sandbox->resetModulesList();
|
||||
$sandbox->requireDefine($target, basename($destination));
|
||||
unlink($target . '/_define.php');
|
||||
|
||||
$new_errors = $sandbox->getErrors();
|
||||
if (!empty($new_errors)) {
|
||||
$new_errors = is_array($new_errors) ? implode(" \n", $new_errors) : $new_errors;
|
||||
throw new Exception($new_errors);
|
||||
}
|
||||
|
||||
files::deltree($destination);
|
||||
} catch (Exception $e) {
|
||||
$zip->close();
|
||||
unlink($zip_file);
|
||||
files::deltree($destination);
|
||||
throw new Exception($e->getMessage());
|
||||
}
|
||||
} else {
|
||||
# test for update
|
||||
$sandbox = clone $modules;
|
||||
$zip->unzip($define, $target . '/_define.php');
|
||||
|
||||
$sandbox->resetModulesList();
|
||||
$sandbox->requireDefine($target, basename($destination));
|
||||
unlink($target . '/_define.php');
|
||||
$new_modules = $sandbox->getModules();
|
||||
|
||||
if (!empty($new_modules)) {
|
||||
$tmp = array_keys($new_modules);
|
||||
$id = $tmp[0];
|
||||
$cur_module = $modules->getModules($id);
|
||||
if (!empty($cur_module) && (defined('DC_DEV') && DC_DEV === true || dcUtils::versionsCompare($new_modules[$id]['version'], $cur_module['version'], '>', true))) {
|
||||
# delete old module
|
||||
if (!files::deltree($destination)) {
|
||||
throw new Exception(__('An error occurred during module deletion.'));
|
||||
}
|
||||
$ret_code = 2;
|
||||
} else {
|
||||
$zip->close();
|
||||
unlink($zip_file);
|
||||
throw new Exception(sprintf(__('Unable to upgrade "%s". (older or same version)'), basename($destination)));
|
||||
}
|
||||
} else {
|
||||
$zip->close();
|
||||
unlink($zip_file);
|
||||
throw new Exception(sprintf(__('Unable to read new _define.php file')));
|
||||
}
|
||||
}
|
||||
$zip->unzipAll($target);
|
||||
$zip->close();
|
||||
unlink($zip_file);
|
||||
return $ret_code;
|
||||
}
|
||||
|
||||
/**
|
||||
This method installs all modules having a _install file.
|
||||
|
||||
@see dcModules::installModule
|
||||
*/
|
||||
public function installModules()
|
||||
{
|
||||
$res = ['success' => [], 'failure' => []];
|
||||
foreach ($this->modules as $id => &$m) {
|
||||
$i = $this->installModule($id, $msg);
|
||||
if ($i === true) {
|
||||
$res['success'][$id] = true;
|
||||
} elseif ($i === false) {
|
||||
$res['failure'][$id] = $msg;
|
||||
}
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
This method installs module with ID <var>$id</var> and having a _install
|
||||
file. This file should throw exception on failure or true if it installs
|
||||
successfully.
|
||||
|
||||
<var>$msg</var> is an out parameter that handle installer message.
|
||||
|
||||
@param id <b>string</b> Module ID
|
||||
@param msg <b>string</b> Module installer message
|
||||
@return <b>boolean</b>
|
||||
*/
|
||||
public function installModule($id, &$msg)
|
||||
{
|
||||
if (!isset($this->modules[$id])) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
$i = $this->loadModuleFile($this->modules[$id]['root'] . '/_install.php');
|
||||
if ($i === true) {
|
||||
return true;
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
$msg = $e->getMessage();
|
||||
return false;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
public function deleteModule($id, $disabled = false)
|
||||
{
|
||||
if ($disabled) {
|
||||
$p = &$this->disabled;
|
||||
} else {
|
||||
$p = &$this->modules;
|
||||
}
|
||||
|
||||
if (!isset($p[$id])) {
|
||||
throw new Exception(__('No such module.'));
|
||||
}
|
||||
|
||||
if (!files::deltree($p[$id]['root'])) {
|
||||
throw new Exception(__('Cannot remove module files'));
|
||||
}
|
||||
}
|
||||
|
||||
public function deactivateModule($id)
|
||||
{
|
||||
if (!isset($this->modules[$id])) {
|
||||
throw new Exception(__('No such module.'));
|
||||
}
|
||||
|
||||
if (!$this->modules[$id]['root_writable']) {
|
||||
throw new Exception(__('Cannot deactivate plugin.'));
|
||||
}
|
||||
|
||||
if (@file_put_contents($this->modules[$id]['root'] . '/_disabled', '')) {
|
||||
throw new Exception(__('Cannot deactivate plugin.'));
|
||||
}
|
||||
}
|
||||
|
||||
public function activateModule($id)
|
||||
{
|
||||
if (!isset($this->disabled[$id])) {
|
||||
throw new Exception(__('No such module.'));
|
||||
}
|
||||
|
||||
if (!$this->disabled[$id]['root_writable']) {
|
||||
throw new Exception(__('Cannot activate plugin.'));
|
||||
}
|
||||
|
||||
if (@unlink($this->disabled[$id]['root'] . '/_disabled') === false) {
|
||||
throw new Exception(__('Cannot activate plugin.'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
This method will search for file <var>$file</var> in language
|
||||
<var>$lang</var> for module <var>$id</var>.
|
||||
|
||||
<var>$file</var> should not have any extension.
|
||||
|
||||
@param id <b>string</b> Module ID
|
||||
@param lang <b>string</b> Language code
|
||||
@param file <b>string</b> File name (without extension)
|
||||
*/
|
||||
public function loadModuleL10N($id, $lang, $file)
|
||||
{
|
||||
if (!$lang || !isset($this->modules[$id])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$lfile = $this->modules[$id]['root'] . '/locales/%s/%s';
|
||||
if (l10n::set(sprintf($lfile, $lang, $file)) === false && $lang != 'en') {
|
||||
l10n::set(sprintf($lfile, 'en', $file));
|
||||
}
|
||||
}
|
||||
|
||||
public function loadModuleL10Nresources($id, $lang)
|
||||
{
|
||||
if (!$lang || !isset($this->modules[$id])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$f = l10n::getFilePath($this->modules[$id]['root'] . '/locales', 'resources.php', $lang);
|
||||
if ($f) {
|
||||
$this->loadModuleFile($f);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Returns all modules associative array or only one module if <var>$id</var>
|
||||
is present.
|
||||
|
||||
@param id <b>string</b> Optionnal module ID
|
||||
@return <b>array</b>
|
||||
*/
|
||||
public function getModules($id = null)
|
||||
{
|
||||
if ($id && isset($this->modules[$id])) {
|
||||
return $this->modules[$id];
|
||||
}
|
||||
return $this->modules;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns true if the module with ID <var>$id</var> exists.
|
||||
|
||||
@param id <b>string</b> Module ID
|
||||
@return <b>boolean</b>
|
||||
*/
|
||||
public function moduleExists($id)
|
||||
{
|
||||
return isset($this->modules[$id]);
|
||||
}
|
||||
|
||||
/**
|
||||
Returns all disabled modules in an array
|
||||
|
||||
@return <b>array</b>
|
||||
*/
|
||||
public function getDisabledModules()
|
||||
{
|
||||
return $this->disabled;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns root path for module with ID <var>$id</var>.
|
||||
|
||||
@param id <b>string</b> Module ID
|
||||
@return <b>string</b>
|
||||
*/
|
||||
public function moduleRoot($id)
|
||||
{
|
||||
return $this->moduleInfo($id, 'root');
|
||||
}
|
||||
|
||||
/**
|
||||
Returns a module information that could be:
|
||||
- root
|
||||
- name
|
||||
- desc
|
||||
- author
|
||||
- version
|
||||
- permissions
|
||||
- priority
|
||||
|
||||
@param id <b>string</b> Module ID
|
||||
@param info <b>string</b> Information to retrieve
|
||||
@return <b>string</b>
|
||||
*/
|
||||
public function moduleInfo($id, $info)
|
||||
{
|
||||
return isset($this->modules[$id][$info]) ? $this->modules[$id][$info] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
Loads namespace <var>$ns</var> specific files for all modules.
|
||||
|
||||
@param ns <b>string</b> Namespace name
|
||||
*/
|
||||
public function loadNsFiles($ns = null)
|
||||
{
|
||||
foreach ($this->modules as $k => $v) {
|
||||
$this->loadNsFile($k, $ns);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Loads namespace <var>$ns</var> specific file for module with ID
|
||||
<var>$id</var>
|
||||
|
||||
@param id <b>string</b> Module ID
|
||||
@param ns <b>string</b> Namespace name
|
||||
*/
|
||||
public function loadNsFile($id, $ns = null)
|
||||
{
|
||||
if (!isset($this->modules[$id])) {
|
||||
return;
|
||||
}
|
||||
switch ($ns) {
|
||||
case 'admin':
|
||||
$this->loadModuleFile($this->modules[$id]['root'] . '/_admin.php');
|
||||
break;
|
||||
case 'public':
|
||||
$this->loadModuleFile($this->modules[$id]['root'] . '/_public.php');
|
||||
break;
|
||||
case 'xmlrpc':
|
||||
$this->loadModuleFile($this->modules[$id]['root'] . '/_xmlrpc.php');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public function getErrors()
|
||||
{
|
||||
return $this->errors;
|
||||
}
|
||||
|
||||
protected function loadModuleFile($________, $catch = true)
|
||||
{
|
||||
if (!file_exists($________)) {
|
||||
return;
|
||||
}
|
||||
|
||||
self::$_k = array_keys($GLOBALS);
|
||||
|
||||
foreach (self::$_k as self::$_n) {
|
||||
if (!in_array(self::$_n, self::$superglobals)) {
|
||||
global ${self::$_n};
|
||||
}
|
||||
}
|
||||
|
||||
if ($catch) {
|
||||
// Catch ouput to prevents hacked or corrupted modules
|
||||
ob_start();
|
||||
$ret = require $________;
|
||||
ob_end_clean();
|
||||
return $ret;
|
||||
}
|
||||
|
||||
return require $________;
|
||||
}
|
||||
|
||||
private function sortModules($a, $b)
|
||||
{
|
||||
if (!isset($a['priority']) || !isset($b['priority'])) {
|
||||
return 1;
|
||||
}
|
||||
if ($a['priority'] == $b['priority']) {
|
||||
return strcasecmp($a['name'], $b['name']);
|
||||
}
|
||||
|
||||
return ($a['priority'] < $b['priority']) ? -1 : 1;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user