Skip to content
Snippets Groups Projects
Commit a7d10318 authored by Peter Rotich's avatar Peter Rotich
Browse files

Merge pull request #367 from greezybacon/issue/plugins-revisited


Revisit plugin manager

Reviewed-By: default avatarPeter Rotich <peter@osticket.com>
parents 653a10cf a6e54770
No related branches found
No related tags found
No related merge requests found
...@@ -39,5 +39,6 @@ $dispatcher = patterns('', ...@@ -39,5 +39,6 @@ $dispatcher = patterns('',
url_get('^help-topic/(?P<id>\d+)$', 'getClientFormsForHelpTopic') url_get('^help-topic/(?P<id>\d+)$', 'getClientFormsForHelpTopic')
)) ))
); );
Signal::send('ajax.client', $dispatcher);
print $dispatcher->resolve($ost->get_path_info()); print $dispatcher->resolve($ost->get_path_info());
?> ?>
...@@ -153,7 +153,10 @@ class UrlMatcher { ...@@ -153,7 +153,10 @@ class UrlMatcher {
function apply_prefix() { function apply_prefix() {
if (is_array($this->func)) { list($class, $func) = $this->func; } if (is_array($this->func)) { list($class, $func) = $this->func; }
else { $func = $this->func; $class = ""; } else { $func = $this->func; $class = ""; }
$class = $this->prefix . $class; if (is_object($class))
return array(false, $this->func);
if ($this->prefix)
$class = $this->prefix . $class;
if (strpos($class, ":")) { if (strpos($class, ":")) {
list($file, $class) = explode(":", $class, 2); list($file, $class) = explode(":", $class, 2);
......
...@@ -114,25 +114,39 @@ class PluginManager { ...@@ -114,25 +114,39 @@ class PluginManager {
if (!($res = db_query($sql))) if (!($res = db_query($sql)))
return static::$plugin_list; return static::$plugin_list;
$infos = static::allInfos();
while ($ht = db_fetch_array($res)) { while ($ht = db_fetch_array($res)) {
// XXX: Only read active plugins here. allInfos() will // XXX: Only read active plugins here. allInfos() will
// read all plugins // read all plugins
if (isset($infos[$ht['install_path']])) { $info = static::getInfoForPath(
$info = $infos[$ht['install_path']]; INCLUDE_DIR . $ht['install_path'], $ht['isphar']);
if ($ht['isactive']) { list($path, $class) = explode(':', $info['plugin']);
list($path, $class) = explode(':', $info['plugin']); if (!$class)
if (!$class) $class = $path;
$class = $path; elseif ($ht['isphar'])
else require_once('phar://' . INCLUDE_DIR . $ht['install_path']
require_once(INCLUDE_DIR . $ht['install_path'] . '/' . $path);
. '/' . $path); else
static::$plugin_list[$ht['install_path']] require_once(INCLUDE_DIR . $ht['install_path']
= new $class($ht['id']); . '/' . $path);
} if ($ht['isactive']) {
else { static::$plugin_list[$ht['install_path']]
static::$plugin_list[$ht['install_path']] = $ht; = new $class($ht['id']);
} }
else {
// Get instance without calling the constructor. Thanks
// http://stackoverflow.com/a/2556089
$a = unserialize(
sprintf(
'O:%d:"%s":0:{}',
strlen($class), $class
)
);
// Simulate __construct() and load()
$a->id = $ht['id'];
$a->ht = $ht;
$a->info = $info;
static::$plugin_list[$ht['install_path']] = &$a;
unset($a);
} }
} }
return static::$plugin_list; return static::$plugin_list;
...@@ -146,6 +160,10 @@ class PluginManager { ...@@ -146,6 +160,10 @@ class PluginManager {
return $plugins; return $plugins;
} }
function throwException($errno, $errstr) {
throw new RuntimeException($errstr);
}
/** /**
* allInfos * allInfos
* *
...@@ -158,34 +176,62 @@ class PluginManager { ...@@ -158,34 +176,62 @@ class PluginManager {
* queried to determine if the plugin is installed * queried to determine if the plugin is installed
*/ */
static function allInfos() { static function allInfos() {
static $defaults = array( foreach (glob(INCLUDE_DIR . 'plugins/*',
'include' => 'include/', GLOB_NOSORT|GLOB_BRACE) as $p) {
'stream' => false, $is_phar = false;
); if (substr($p, strlen($p) - 5) == '.phar'
&& Phar::isValidPharFilename($p)) {
try {
// When public key is invalid, openssl throws a
// 'supplied key param cannot be coerced into a public key' warning
// and phar ignores sig verification.
// We need to protect from that by catching the warning
// Thanks, https://github.com/koto/phar-util
set_error_handler(array('self', 'throwException'));
$ph = new Phar($p);
restore_error_handler();
// Verify the signature
$ph->getSignature();
$p = 'phar://' . $p;
$is_phar = true;
} catch (UnexpectedValueException $e) {
// Cannot find signature file
} catch (RuntimeException $e) {
// Invalid signature file
}
if (static::$plugin_info) }
return static::$plugin_info;
foreach (glob(INCLUDE_DIR . 'plugins/*', GLOB_ONLYDIR) as $p) {
if (!is_file($p . '/plugin.php')) if (!is_file($p . '/plugin.php'))
// Invalid plugin -- must define "/plugin.php" // Invalid plugin -- must define "/plugin.php"
continue; continue;
// plugin.php is require to return an array of informaiton about
// the plugin.
$info = array_merge($defaults, (include $p . '/plugin.php'));
$info['install_path'] = str_replace(INCLUDE_DIR, '', $p);
// XXX: Ensure 'id' key isset // Cache the info into static::$plugin_info
static::$plugin_info[$info['install_path']] = $info; static::getInfoForPath($p, $is_phar);
} }
return static::$plugin_info; return static::$plugin_info;
} }
static function getInfoForPath($path) { static function getInfoForPath($path, $is_phar=false) {
$infos = static::allInfos(); static $defaults = array(
if (isset($infos[$path])) 'include' => 'include/',
return $infos[$path]; 'stream' => false,
return null; );
$install_path = str_replace(INCLUDE_DIR, '', $path);
$install_path = str_replace('phar://', '', $install_path);
if ($is_phar && substr($path, 0, 7) != 'phar://')
$path = 'phar://' . $path;
if (!isset(static::$plugin_info[$install_path])) {
// plugin.php is require to return an array of informaiton about
// the plugin.
$info = array_merge($defaults, (include $path . '/plugin.php'));
$info['install_path'] = $install_path;
// XXX: Ensure 'id' key isset
static::$plugin_info[$install_path] = $info;
}
return static::$plugin_info[$install_path];
} }
function getInstance($path) { function getInstance($path) {
...@@ -215,17 +261,22 @@ class PluginManager { ...@@ -215,17 +261,22 @@ class PluginManager {
* registered in the plugin registry -- the %plugin table. * registered in the plugin registry -- the %plugin table.
*/ */
function install($path) { function install($path) {
if (!($info = $this->getInfoForPath($path))) $is_phar = substr($path, strlen($path) - 5) == '.phar';
if (!($info = $this->getInfoForPath(INCLUDE_DIR . $path, $is_phar)))
return false; return false;
$sql='INSERT INTO '.PLUGIN_TABLE.' SET installed=NOW() ' $sql='INSERT INTO '.PLUGIN_TABLE.' SET installed=NOW() '
.', install_path='.db_input($path) .', install_path='.db_input($path)
.', name='.db_input($info['name']); .', name='.db_input($info['name'])
.', isphar='.db_input($is_phar);
if (!db_query($sql) || !db_affected_rows()) if (!db_query($sql) || !db_affected_rows())
return false; return false;
static::clearCache();
return true;
}
static function clearCache() {
static::$plugin_list = array(); static::$plugin_list = array();
return true;
} }
} }
...@@ -255,7 +306,8 @@ class Plugin { ...@@ -255,7 +306,8 @@ class Plugin {
`id`='.db_input($this->id); `id`='.db_input($this->id);
if (($res = db_query($sql)) && ($ht=db_fetch_array($res))) if (($res = db_query($sql)) && ($ht=db_fetch_array($res)))
$this->ht = $ht; $this->ht = $ht;
$this->info = PluginManager::getInfoForPath($this->ht['install_path']); $this->info = PluginManager::getInfoForPath($this->ht['install_path'],
$this->isPhar());
} }
function getId() { return $this->id; } function getId() { return $this->id; }
...@@ -283,6 +335,7 @@ class Plugin { ...@@ -283,6 +335,7 @@ class Plugin {
$sql = 'DELETE FROM '.PLUGIN_TABLE $sql = 'DELETE FROM '.PLUGIN_TABLE
.' WHERE id='.db_input($this->getId()); .' WHERE id='.db_input($this->getId());
PluginManager::clearCache();
if (db_query($sql) && db_affected_rows()) if (db_query($sql) && db_affected_rows())
return $this->getConfig()->purge(); return $this->getConfig()->purge();
return false; return false;
...@@ -302,12 +355,14 @@ class Plugin { ...@@ -302,12 +355,14 @@ class Plugin {
function enable() { function enable() {
$sql = 'UPDATE '.PLUGIN_TABLE $sql = 'UPDATE '.PLUGIN_TABLE
.' SET isactive=1 WHERE id='.db_input($this->getId()); .' SET isactive=1 WHERE id='.db_input($this->getId());
PluginManager::clearCache();
return (db_query($sql) && db_affected_rows()); return (db_query($sql) && db_affected_rows());
} }
function disable() { function disable() {
$sql = 'UPDATE '.PLUGIN_TABLE $sql = 'UPDATE '.PLUGIN_TABLE
.' SET isactive=0 WHERE id='.db_input($this->getId()); .' SET isactive=0 WHERE id='.db_input($this->getId());
PluginManager::clearCache();
return (db_query($sql) && db_affected_rows()); return (db_query($sql) && db_affected_rows());
} }
......
...@@ -35,19 +35,11 @@ foreach ($ost->plugins->allInstalled() as $p) { ...@@ -35,19 +35,11 @@ foreach ($ost->plugins->allInstalled() as $p) {
<?php echo $sel?'checked="checked"':''; ?>></td> <?php echo $sel?'checked="checked"':''; ?>></td>
<td><a href="plugins.php?id=<?php echo $p->getId(); ?>" <td><a href="plugins.php?id=<?php echo $p->getId(); ?>"
><?php echo $p->getName(); ?></a></td> ><?php echo $p->getName(); ?></a></td>
<td>Enabled</td> <td><?php echo ($p->isActive())
? 'Enabled' : '<strong>Disabled</strong>'; ?></td>
<td><?php echo Format::db_datetime($p->getInstallDate()); ?></td> <td><?php echo Format::db_datetime($p->getInstallDate()); ?></td>
</tr> </tr>
<?php } else { <?php } else {} ?>
$p = $ost->plugins->getInfoForPath($p['install_path']); ?>
<tr>
<td><input type="checkbox" class="ckb" name="ids[]" value="<?php echo $p['install_path']; ?>"
<?php echo $sel?'checked="checked"':''; ?>></td>
<td><?php echo $p['name']; ?></td>
<td><strong>Disabled</strong></td>
<td></td>
</tr>
<?php } ?>
<?php } ?> <?php } ?>
</tbody> </tbody>
<tfoot> <tfoot>
......
...@@ -19,8 +19,8 @@ if($_POST) { ...@@ -19,8 +19,8 @@ if($_POST) {
$count = count($_POST['ids']); $count = count($_POST['ids']);
switch(strtolower($_POST['a'])) { switch(strtolower($_POST['a'])) {
case 'enable': case 'enable':
foreach ($_POST['ids'] as $path) { foreach ($_POST['ids'] as $id) {
if ($p = $ost->plugins->getInstance($path)) { if ($p = Plugin::lookup($id)) {
$p->enable(); $p->enable();
} }
} }
...@@ -35,7 +35,6 @@ if($_POST) { ...@@ -35,7 +35,6 @@ if($_POST) {
case 'delete': case 'delete':
foreach ($_POST['ids'] as $id) { foreach ($_POST['ids'] as $id) {
if ($p = Plugin::lookup($id)) { if ($p = Plugin::lookup($id)) {
var_dump($p);
$p->uninstall(); $p->uninstall();
} }
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment