Index: plugins/serendipity_event_bbcode/serendipity_event_bbcode.php
===================================================================
--- plugins/serendipity_event_bbcode/serendipity_event_bbcode.php (revision 210)
+++ plugins/serendipity_event_bbcode/serendipity_event_bbcode.php (working copy)
@@ -40,6 +40,7 @@
));
$propbag->add('cachable_events', array('frontend_display' => true));
$propbag->add('event_hooks', array('frontend_display' => true, 'frontend_comment' => true, 'css' => true));
+ $propbag->add('groups', array('MARKUP'));
$this->markup_elements = array(
array(
Index: plugins/serendipity_event_karma/serendipity_event_karma.php
===================================================================
--- plugins/serendipity_event_karma/serendipity_event_karma.php (revision 210)
+++ plugins/serendipity_event_karma/serendipity_event_karma.php (working copy)
@@ -123,7 +123,7 @@
));
$propbag->add('event_hooks', array('frontend_configure' => true, 'entry_display' => true, 'css' => true, 'event_additional_statistics' => true));
$propbag->add('scrambles_true_content', true);
-
+ $propbag->add('groups', array('STATISTICS', 'FRONTEND_ENTRY'));
$propbag->add('configuration', array('karma_active', 'visits_active', 'max_entrytime', 'max_votetime', 'extended_only', 'max_karmatime', 'logging'));
}
Index: plugins/serendipity_event_s9ymarkup/serendipity_event_s9ymarkup.php
===================================================================
--- plugins/serendipity_event_s9ymarkup/serendipity_event_s9ymarkup.php (revision 210)
+++ plugins/serendipity_event_s9ymarkup/serendipity_event_s9ymarkup.php (working copy)
@@ -41,6 +41,7 @@
));
$propbag->add('cachable_events', array('frontend_display' => true));
$propbag->add('event_hooks', array('frontend_display' => true, 'frontend_comment' => true));
+ $propbag->add('groups', array('MARKUP'));
$this->markup_elements = array(
array(
Index: plugins/serendipity_event_spartacus/serendipity_event_spartacus.php
===================================================================
--- plugins/serendipity_event_spartacus/serendipity_event_spartacus.php (revision 210)
+++ plugins/serendipity_event_spartacus/serendipity_event_spartacus.php (working copy)
@@ -24,6 +24,9 @@
@define('PLUGIN_EVENT_SPARTACUS_FETCHED_BYTES_URL', '%s bytes von obiger URL geladen. Speichere Inhalt als %s...');
@define('PLUGIN_EVENT_SPARTACUS_FETCHED_BYTES_CACHE', '%s bytes von bereits bestehender Datei geladen. Speichere Inhalt als %s...');
@define('PLUGIN_EVENT_SPARTACUS_FETCHED_DONE', 'Daten erfolgreich geladen.');
+ @define('PLUGIN_EVENT_SPARTACUS_MIRROR_XML', 'Datei/Mirror Speicherort (XML-Metadaten)');
+ @define('PLUGIN_EVENT_SPARTACUS_MIRROR_FILES', 'Datei/Mirror Speicherort (Downloads)');
+ @define('PLUGIN_EVENT_SPARTACUS_MIRROR_DESC', 'Wählen Sie den Download-Server. Ändern Sie diesen Wert nur, wenn Sie wissen, was Sie tun und ein Server nicht mehr reagiert. Diese Option ist hauptsächlich für zukünftige Server reserviert.');
break;
case 'en':
@@ -36,13 +39,22 @@
@define('PLUGIN_EVENT_SPARTACUS_FETCHED_BYTES_URL', 'Fetched %s bytes from the URL above. Saving file as %s...');
@define('PLUGIN_EVENT_SPARTACUS_FETCHED_BYTES_CACHE', 'Fetched %s bytes from already existing file on your server. Saving file as %s...');
@define('PLUGIN_EVENT_SPARTACUS_FETCHED_DONE', 'Data successfully fetched.');
+ @define('PLUGIN_EVENT_SPARTACUS_MIRROR_XML', 'File/Mirror location (XML metadata)');
+ @define('PLUGIN_EVENT_SPARTACUS_MIRROR_FILES', 'File/Mirror location (files)');
+ @define('PLUGIN_EVENT_SPARTACUS_MIRROR_DESC', 'Choose a download location. Do NOT change this value unless you know what you are doing and if servers get oudated. This option is available mainly for forward compatibility.');
break;
}
class serendipity_event_spartacus extends serendipity_event
{
var $title = PLUGIN_EVENT_SPARTACUS_NAME;
+ var $purgeCache = false;
+ function microtime_float() {
+ list($usec, $sec) = explode(" ", microtime());
+ return ((float)$usec + (float)$sec);
+ }
+
function introspect(&$propbag)
{
global $serendipity;
@@ -51,25 +63,103 @@
$propbag->add('description', PLUGIN_EVENT_SPARTACUS_DESC);
$propbag->add('stackable', false);
$propbag->add('author', 'Garvin Hicking');
- $propbag->add('version', '1.2');
+ $propbag->add('version', '2.0');
$propbag->add('requirements', array(
- 'serendipity' => '0.8',
+ 'serendipity' => '0.9',
'smarty' => '2.6.7',
'php' => '4.1.0'
));
$propbag->add('event_hooks', array(
- 'backend_plugins_sidebar_header' => true,
- 'backend_plugins_event_header' => true,
+ 'backend_plugins_fetchlist' => true,
+ 'backend_plugins_fetchplugin' => true,
- 'backend_plugins_fetchlist' => true,
- 'backend_plugins_fetchplugin' => true
+ 'backend_templates_fetchlist' => true,
+ 'backend_templates_fetchtemplate' => true
));
+ $propbag->add('groups', array('SYSTEM'));
+ $propbag->add('configuration', array('mirror_xml', 'mirror_files'));
}
function generate_content(&$title) {
$title = $this->title;
}
+ function cleanup() {
+ // Purge cached XML files.
+ $files = serendipity_traversePath($serendipity['serendipityPath'] . PATH_SMARTY_COMPILE, '', false, '/package_.+\.xml$/');
+
+ if (!is_array($files)) {
+ return false;
+ }
+
+ foreach ($files as $file) {
+ printf(DELETING_FILE . '
', $file['name']);
+ @unlink($serendipity['serendipityPath'] . PATH_SMARTY_COMPILE . '/' . $file['name']);
+ }
+ }
+
+ function &getMirrors($type = 'xml', $loc = false) {
+ static $mirror = array(
+ 'xml' => array(
+ 'Netmirror.org',
+ 's9y.org'
+ ),
+
+ 'files' => array(
+ 'SourceForge.net',
+ 'Netmirror.org',
+ 's9y.org',
+ 'BerliOS.de'
+ )
+ );
+
+ static $http = array(
+ 'xml' => array(
+ 'http://netmirror.org/mirror/serendipity/',
+ 'http://s9y.org/mirror/'
+ ),
+
+ 'files' => array(
+ 'http://cvs.sourceforge.net/viewcvs.py/*checkout*/php-blog/',
+ 'http://netmirror.org/mirror/serendipity/',
+ 'http://s9y.org/mirror/',
+ 'http://svn.berlios.de/viewcvs/serendipity/'
+ )
+ );
+
+ if ($loc) {
+ return $http[$type];
+ } else {
+ return $mirror[$type];
+ }
+ }
+
+ function introspect_config_item($name, &$propbag) {
+ global $serendipity;
+
+ switch($name) {
+ case 'mirror_xml':
+ $propbag->add('type', 'select');
+ $propbag->add('name', PLUGIN_EVENT_SPARTACUS_MIRROR_XML);
+ $propbag->add('description', PLUGIN_EVENT_SPARTACUS_MIRROR_DESC);
+ $propbag->add('select_values', $this->getMirrors('xml'));
+ $propbag->add('default', 0);
+ break;
+
+ case 'mirror_files':
+ $propbag->add('type', 'select');
+ $propbag->add('name', PLUGIN_EVENT_SPARTACUS_MIRROR_FILES);
+ $propbag->add('description', PLUGIN_EVENT_SPARTACUS_MIRROR_DESC);
+ $propbag->add('select_values', $this->getMirrors('files'));
+ $propbag->add('default', 0);
+ break;
+
+ default:
+ return false;
+ }
+ return true;
+ }
+
function GetChildren(&$vals, &$i) {
$children = array();
$cnt = sizeof($vals);
@@ -104,10 +194,10 @@
}
// Create recursive directories; begins at serendipity plugin root folder level
- function rmkdir($dir) {
+ function rmkdir($dir, $sub = 'plugins') {
global $serendipity;
- $spaths = explode('/', $serendipity['serendipityPath'] . 'plugins/');
+ $spaths = explode('/', $serendipity['serendipityPath'] . $sub . '/');
$paths = explode('/', $dir);
$stack = '';
@@ -126,7 +216,7 @@
return true;
}
- function &fetchfile($url, $target, $cacheTimeout = 0) {
+ function &fetchfile($url, $target, $cacheTimeout = 0, $decode_utf8 = false, $sub = 'plugins') {
printf(PLUGIN_EVENT_SPARTACUS_FETCHING, '' . basename($url) . '');
echo '
';
@@ -152,7 +242,7 @@
printf(PLUGIN_EVENT_SPARTACUS_FETCHED_BYTES_URL, strlen($data), $target);
echo '
';
$tdir = dirname($target);
- if (!is_dir($tdir) && !$this->rmkdir($tdir)) {
+ if (!is_dir($tdir) && !$this->rmkdir($tdir, $sub)) {
printf(FILE_WRITE_ERROR, $tdir);
echo '
';
return false;
@@ -165,38 +255,90 @@
echo '
';
return false;
}
+
+ if ($decode_utf8) {
+ $this->decode($data);
+ }
fwrite($fp, $data);
fclose($fp);
echo PLUGIN_EVENT_SPARTACUS_FETCHED_DONE;
echo '
';
+ $this->purgeCache = true;
}
}
return $data;
}
- function &fetchOnline($type) {
+ function decode(&$data) {
+ switch (strtolower(LANG_CHARSET)) {
+ case 'utf-8':
+ // The XML file is UTF-8 format. No changes needed.
+ break;
+
+ case 'iso-8859-1':
+ $data = utf8_decode($data);
+ break;
+
+ default:
+ if (function_exists('iconv')) {
+ $data = iconv('UTF-8', LANG_CHARSET, $data);
+ } elseif (function_exists('recode')) {
+ $data = recode('utf-8..' . LANG_CHARSET, $data);
+ }
+ break;
+ }
+ }
+
+ function &fetchOnline($type, $no_cache = false) {
+ global $serendipity;
+
switch($type) {
// Sanitize to not fetch other URLs
default:
case 'event':
$url_type = 'event';
+ $i18n = true;
break;
case 'sidebar':
$url_type = 'sidebar';
+ $i18n = true;
break;
+
+ case 'template':
+ $url_type = 'template';
+ $i18n = false;
+ break;
}
+
+ if (!$i18n) {
+ $lang = '';
+ } elseif (isset($serendipity['languages'][$serendipity['lang']])) {
+ $lang = '_' . $serendipity['lang'];
+ } else {
+ $lang = '_en';
+ }
- $url = 'http://netmirror.org/mirror/serendipity/package_' . $url_type . '.xml';
+ $mirrors = $this->getMirrors('xml', true);
+ $mirror = $mirrors[$this->get_config('mirror_xml', 0)];
+
+ $url = $mirror . '/package_' . $url_type . $lang . '.xml';
$cacheTimeout = 60*60*12; // XML file is cached for half a day
- $target = $serendipity['serendipityPath'] . 'templates_c/package_' . $url_type . '.xml';
+ $target = $serendipity['serendipityPath'] . PATH_SMARTY_COMPILE . '/package_' . $url_type . $lang . '.xml';
- $xml = $this->fetchfile($url, $target, $cacheTimeout);
+ $xml = $this->fetchfile($url, $target, $cacheTimeout, true);
echo '
';
+ $new_crc = md5($xml);
+ $last_crc = $this->get_config('last_crc_' . $url_type);
+
+ if (!$no_cache && !$this->purgeCache && $last_crc == $new_crc) {
+ return 'cached';
+ }
+
// XML functions
$p = xml_parser_create();
xml_parser_set_option($p, XML_OPTION_CASE_FOLDING, 0);
@@ -212,14 +354,80 @@
'children' => $this->GetChildren($vals, $i)
);
+ $this->set_config('last_crc_' . $url_type, $new_crc);
+
return $tree;
}
+ function &getCachedPlugins(&$plugins, $type) {
+ global $serendipity;
+ static $pluginlist = null;
+
+ if ($pluginlist === null) {
+ $data = serendipity_db_query("SELECT p.*,
+ pc.category
+ FROM {$serendipity['dbPrefix']}pluginlist AS p
+ LEFT OUTER JOIN {$serendipity['dbPrefix']}plugincategories AS pc
+ ON pc.class_name = p.class_name
+ WHERE p.pluginlocation = 'Spartacus' AND
+ p.plugintype = '" . serendipity_db_escape_string($type) . "'");
+
+ if (is_array($data)) {
+ foreach($data AS $p) {
+ $p['stackable'] = serendipity_db_bool($p['stackable']);
+ $p['requirements'] = unserialize($p['requirements']);
+ $this->checkPlugin($p, $plugins, $p['pluginlocation']);
+
+ if (!isset($pluginlist[$p['plugin_file']])) {
+ $pluginlist[$p['plugin_file']] = $p;
+ }
+
+ $pluginlist[$p['plugin_file']]['groups'][] = $p['category'];
+ }
+ }
+ }
+
+ return $pluginlist;
+ }
+
+ function checkPlugin(&$data, &$plugins, $type) {
+ $installable = true;
+ $upgradeLink = '';
+ if (in_array($data['class_name'], $plugins)) {
+ $infoplugin =& serendipity_plugin_api::load_plugin($data['class_name']);
+ if (is_object($infoplugin)) {
+ $bag = new serendipity_property_bag;
+ $infoplugin->introspect($bag);
+ if ($bag->get('version') == $data['version']) {
+ $installable = false;
+ } elseif (version_compare($bag->get('version'), $data['version'], '<')) {
+ $data['upgradable'] = true;
+ $data['upgrade_version'] = $pluginstack[$i]['version'];
+ $data['version'] = $bag->get('version');
+ $upgradeLink = '&serendipity[spartacus_upgrade]=true';
+ }
+ }
+ }
+
+ $data['installable'] = $installable;
+ $data['pluginPath'] = 'online_repository';
+ $data['pluginlocation'] = 'Spartacus';
+ $data['plugintype'] = $type;
+ $data['customURI'] = '&serendipity[spartacus_fetch]=' . $type . $upgradeLink;
+
+ return true;
+ }
+
function &buildList(&$tree, $type) {
$plugins = serendipity_plugin_api::get_installed_plugins();
+
+ if ($tree === 'cached') {
+ return $this->getCachedPlugins($plugins, $type);
+ }
+
$pluginstack = array();
$i = 0;
-
+
foreach($tree[0]['children'] AS $idx => $subtree) {
if ($subtree['tag'] == 'package') {
$i++;
@@ -227,16 +435,22 @@
foreach($subtree['children'] AS $child => $childtree) {
switch($childtree['tag']) {
case 'name':
- $pluginstack[$i]['plugin_class'] = $childtree['value'];
- $pluginstack[$i]['class_name'] = $childtree['value'];
+ $pluginstack[$i]['plugin_class'] =
+ $pluginstack[$i]['plugin_file'] =
+ $pluginstack[$i]['class_name'] =
+ $pluginstack[$i]['true_name'] = $childtree['value'];
break;
case 'summary':
$pluginstack[$i]['name'] = $childtree['value'];
break;
+ case 'groups':
+ $pluginstack[$i]['groups'] = explode(',', $childtree['value']);
+ break;
+
case 'description':
- $pluginstack[$i]['desc'] = $childtree['value'];
+ $pluginstack[$i]['description'] = $childtree['value'];
break;
case 'release':
@@ -260,38 +474,107 @@
break;
}
}
+
+ $this->checkPlugin($pluginstack[$i], $plugins, $type);
- $installable = true;
- $upgradeLink = '';
- if (in_array($pluginstack[$i]['class_name'], $plugins)) {
- $infoplugin =& serendipity_plugin_api::load_plugin($pluginstack[$i]['class_name']);
- if (is_object($infoplugin)) {
- $bag = new serendipity_property_bag;
- $infoplugin->introspect($bag);
- if ($bag->get('version') == $pluginstack[$i]['version']) {
- $installable = false;
- } elseif (version_compare($bag->get('version'), $pluginstack[$i]['version'], '<')) {
- $pluginstack[$i]['upgradable'] = true;
- $pluginstack[$i]['upgrade_version'] = $pluginstack[$i]['version'];
- $pluginstack[$i]['version'] = $bag->get('version');
- $upgradeLink = '&serendipity[spartacus_upgrade]=true';
- }
+ serendipity_plugin_api::setPluginInfo($pluginstack[$i], $pluginstack[$i]['plugin_file'], $i, $i, 'Spartacus');
+ // Remove the temporary $i reference, as the array should be associative
+ $plugname = $pluginstack[$i]['true_name'];
+ $pluginstack[$plugname] = $pluginstack[$i];
+ unset($pluginstack[$i]);
+ }
+ }
+
+ return $pluginstack;
+ }
+
+ function &buildTemplateList(&$tree) {
+ $pluginstack = array();
+ $i = 0;
+
+ $mirrors = $this->getMirrors('files', true);
+ $mirror = $mirrors[$this->get_config('mirror_files', 0)];
+
+ foreach($tree[0]['children'] AS $idx => $subtree) {
+ if ($subtree['tag'] == 'package') {
+ $i++;
+
+ foreach($subtree['children'] AS $child => $childtree) {
+ switch($childtree['tag']) {
+ case 'name':
+ $pluginstack[$i]['name'] = $childtree['value'];
+ break;
+
+ case 'summary':
+ $pluginstack[$i]['summary'] = $childtree['value'];
+ break;
+
+ case 'template':
+ $pluginstack[$i]['template'] = $childtree['value'];
+ break;
+
+ case 'description':
+ $pluginstack[$i]['description'] = $childtree['value'];
+ break;
+
+ case 'release':
+ $pluginstack[$i]['version'] = $childtree['children'][0]['value'];
+
+ $pluginstack[$i]['requirements'] = array(
+ 'serendipity' => '',
+ 'php' => '',
+ 'smarty' => ''
+ );
+
+ foreach($childtree['children'] AS $relInfo) {
+ if ($relInfo['tag'] == 'requirements:s9yVersion') {
+ $pluginstack[$i]['requirements']['serendipity'] = $relInfo['value'];
+ }
+
+ if ($relInfo['tag'] == 'date') {
+ $pluginstack[$i]['date'] = $relInfo['value'];
+ }
+
+ }
+
+ $pluginstack[$i]['require serendipity'] = $pluginstack[$i]['requirements']['serendipity'];
+ break;
+
+ case 'maintainers':
+ $pluginstack[$i]['author'] = $childtree['children'][0]['children'][0]['value']; // I dig my PHP arrays ;-)
+ break;
}
}
- $pluginstack[$i]['installable'] = $installable;
- $pluginstack[$i]['pluginPath'] = 'online_repository';
- $pluginstack[$i]['customURI'] = '&serendipity[spartacus_fetch]=' . $type . $upgradeLink;
+ $plugname = $pluginstack[$i]['template'];
+ $pluginstack[$i]['previewURL'] = $mirror . '/additional_themes/' . $plugname . '/preview.png?rev=1.9999';
+ $pluginstack[$i]['customURI'] = '&serendipity[spartacus_fetch]=' . $plugname;
+ $pluginstack[$i]['customIcon'] = '_spartacus';
+
+ // Remove the temporary $i reference, as the array should be associative
+ $pluginstack[$plugname] = $pluginstack[$i];
+ unset($pluginstack[$i]);
}
}
return $pluginstack;
}
- function download(&$tree, $plugin_to_install) {
+ function download(&$tree, $plugin_to_install, $sub = 'plugins') {
global $serendipity;
- $pdir = $serendipity['serendipityPath'] . '/plugins/';
+ switch($sub) {
+ case 'plugins':
+ default:
+ $sfloc = 'additional_plugins';
+ break;
+
+ case 'templates':
+ $sfloc = 'additional_themes';
+ break;
+ }
+
+ $pdir = $serendipity['serendipityPath'] . '/' . $sub . '/';
if (!is_writable($pdir)) {
printf(DIRECTORY_WRITE_ERROR, $pdir);
echo '
';
@@ -306,7 +589,7 @@
}
foreach($subtree['children'] AS $child => $childtree) {
- if ($childtree['tag'] == 'name' && $childtree['value'] == $plugin_to_install) {
+ if ($childtree['tag'] == 'template' && $childtree['value'] == $plugin_to_install) {
$found = true;
}
@@ -330,8 +613,11 @@
}
}
+ $mirrors = $this->getMirrors('files', true);
+ $mirror = $mirrors[$this->get_config('mirror_files', 0)];
+
foreach($files AS $file) {
- $url = 'http://cvs.sourceforge.net/viewcvs.py/*checkout*/php-blog/additional_plugins/' . $file . '?rev=1.9999';
+ $url = $mirror . '/' . $sfloc . '/' . $file . '?rev=1.9999';
$target = $pdir . $file;
@mkdir($pdir . $plugin_to_install);
$this->fetchfile($url, $target);
@@ -353,30 +639,30 @@
if (isset($hooks[$event])) {
switch($event) {
- case 'backend_plugins_sidebar_header':
-?>
-
-buildTemplateList($this->fetchOnline('template', true), 'template');
- case 'backend_plugins_event_header':
-?>
-
-download(
+ $this->fetchOnline('template', true),
+ $eventData['GET']['theme'],
+ 'templates'
+ );
}
+ return false;
+ break;
+
+ case 'backend_plugins_fetchlist':
$type = (isset($serendipity['GET']['type']) ? $serendipity['GET']['type'] : 'sidebar');
$eventData = array(
- 'pluginstack' => $this->buildList($this->fetchOnline($type), $type),
- 'errorstack' => array()
+ 'pluginstack' => $this->buildList($this->fetchOnline($type), $type),
+ 'errorstack' => array()
);
return true;
@@ -384,7 +670,7 @@
case 'backend_plugins_fetchplugin':
if (!empty($eventData['GET']['spartacus_fetch'])) {
- $baseDir = $this->download($this->fetchOnline($eventData['GET']['spartacus_fetch']), $eventData['GET']['install_plugin']);
+ $baseDir = $this->download($this->fetchOnline($eventData['GET']['spartacus_fetch'], true), $eventData['GET']['install_plugin']);
if (!empty($baseDir)) {
$eventData['GET']['pluginPath'] = $baseDir;
} else {
@@ -410,4 +696,4 @@
}
/* vim: set sts=4 ts=4 expandtab : */
-?>
+?>
\ No newline at end of file
Index: plugins/serendipity_event_nl2br/serendipity_event_nl2br.php
===================================================================
--- plugins/serendipity_event_nl2br/serendipity_event_nl2br.php (revision 210)
+++ plugins/serendipity_event_nl2br/serendipity_event_nl2br.php (working copy)
@@ -39,6 +39,7 @@
));
$propbag->add('cachable_events', array('frontend_display' => true));
$propbag->add('event_hooks', array('frontend_display' => true));
+ $propbag->add('groups', array('MARKUP'));
$this->markup_elements = array(
array(
Index: serendipity_config.inc.php
===================================================================
--- serendipity_config.inc.php (revision 210)
+++ serendipity_config.inc.php (working copy)
@@ -21,7 +21,7 @@
include_once(S9Y_INCLUDE_PATH . 'include/compat.inc.php');
// The version string
-$serendipity['version'] = '0.9-alpha3';
+$serendipity['version'] = '0.9-alpha4';
// Name of folder for the default theme
$serendipity['defaultTemplate'] = 'default';
Index: include/plugin_api.inc.php
===================================================================
--- include/plugin_api.inc.php (revision 210)
+++ include/plugin_api.inc.php (working copy)
@@ -152,9 +152,13 @@
if ($p == 'serendipity_plugin' && $class_name != 'serendipity_event' && (!$event_only || is_null($event_only))) {
$classes[$class_name] = array('name' => '@' . $class_name,
+ 'type' => 'internal_event',
+ 'true_name' => $class_name,
'pluginPath' => '');
} elseif ($p == 'serendipity_event' && $class_name != 'serendipity_event' && ($event_only || is_null($event_only))) {
$classes[$class_name] = array('name' => '@' . $class_name,
+ 'type' => 'internal_plugin',
+ 'true_name' => $class_name,
'pluginPath' => '');
}
}
@@ -179,35 +183,40 @@
if ($f{0} == '.' || $f == 'CVS' || !is_dir($ppath . '/' . $f)) {
continue;
}
-
+
$subd = opendir($ppath . '/' . $f);
if (!$subd) {
continue;
}
// Instead of only looking for directories, search for files within subdirectories
+ $final_loop = false;
while (($subf = readdir($subd)) !== false) {
+
if ($subf{0} == '.' || $subf == 'CVS') {
continue;
}
- if (is_dir($ppath . '/' . $f . '/' . $subf) && $maindir != $ppath . '/' . $f) {
+ if (!$final_loop && is_dir($ppath . '/' . $f . '/' . $subf) && $maindir != $ppath . '/' . $f) {
// Search for another level of subdirectories
serendipity_plugin_api::traverse_plugin_dir($ppath . '/' . $f, $classes, $event_only, $f . '/');
+ // We can break after that operation because the current directory has been fully checked already.
+ $final_loop = true;
}
if (!preg_match('@^[^_]+_(event|plugin)_.+\.php$@i', $subf)) {
continue;
}
+ $class_name = str_replace('.php', '', $subf);
// If an external plugin/event already exists as internal, remove the internal reference because its redundant
- if (isset($classes['@' . $subf])) {
- unset($classes['@' . $subf]);
+ if (isset($classes['@' . $class_name])) {
+ unset($classes['@' . $class_name]);
}
// A local plugin will be preferred over general plugins [used when calling this function the second time]
- if (isset($classes[$subf])) {
- unset($classes[$subf]);
+ if (isset($classes[$class_name])) {
+ unset($classes[$class_name]);
}
if (!is_null($event_only) && $event_only && !serendipity_plugin_api::is_event_plugin($subf)) {
@@ -218,11 +227,14 @@
continue;
}
- $class_name = str_replace('.php', '', $subf);
$classes[$class_name] = array('name' => $class_name,
+ 'true_name' => $class_name,
+ 'type' => 'additional_plugin',
'pluginPath' => $maindir . $f);
}
+ closedir($subd);
}
+ closedir($d);
}
}
@@ -301,29 +313,45 @@
if (empty($pluginPath)) {
$pluginPath = $name;
}
+
+ $file = false;
// First try the local path, and then (if existing) a shared library repository ...
if (file_exists($serendipity['serendipityPath'] . 'plugins/' . $pluginPath . '/' . $name . '.php')) {
- include_once $serendipity['serendipityPath'] . 'plugins/' . $pluginPath . '/' . $name . '.php';
+ $file = $serendipity['serendipityPath'] . 'plugins/' . $pluginPath . '/' . $name . '.php';
} elseif (file_exists(S9Y_INCLUDE_PATH . 'plugins/' . $pluginPath . '/' . $name . '.php')) {
- include_once S9Y_INCLUDE_PATH . 'plugins/' . $pluginPath . '/' . $name . '.php';
+ $file = S9Y_INCLUDE_PATH . 'plugins/' . $pluginPath . '/' . $name . '.php';
}
+
+ return $file;
}
- /* Creates an instance of a named plugin */
- function &load_plugin($instance_id, $authorid = null, $pluginPath = '')
- {
- global $serendipity;
-
+ function getClassByInstanceID($instance_id, &$is_internal) {
$instance = explode(':', $instance_id);
$name = $instance[0];
if ($name{0} == '@') {
$class_name = substr($name, 1);
} else {
+ $class_name =& $name;
+ }
+
+ return $class_name;
+ }
+
+ /* Probes for the plugin filename */
+ function probePlugin($instance_id, &$class_name, &$pluginPath) {
+ global $serendipity;
+
+ $filename = false;
+ $is_internal = false;
+
+ $class_name = serendipity_plugin_api::getClassByInstanceID($instance_id, $is_internal);
+
+ if (!$is_internal) {
/* plugin from the plugins/ dir */
- serendipity_plugin_api::includePlugin($name, $pluginPath);
- if (!class_exists($name) && empty($pluginPath)) {
+ $filename = serendipity_plugin_api::includePlugin($class_name, $pluginPath);
+ if (empty($filename) && !empty($instance_id)) {
$sql = "SELECT path from {$serendipity['dbPrefix']}plugins WHERE name = '" . $instance_id . "'";
$plugdata = serendipity_db_query($sql, true, 'both', false, false, false, true);
if (is_array($plugdata) && isset($plugdata[0])) {
@@ -331,19 +359,36 @@
}
if (empty($pluginPath)) {
- $pluginPath = $name;
+ $pluginPath = $class_name;
}
- serendipity_plugin_api::includePlugin($name, $pluginPath);
+ $filename = serendipity_plugin_api::includePlugin($class_name, $pluginPath);
}
- if (!class_exists($name)) {
+ if (empty($filename)) {
return false;
}
+ }
- $class_name =& $name;
+ return $filename;
+ }
+
+ /* Creates an instance of a named plugin */
+ function &load_plugin($instance_id, $authorid = null, $pluginPath = '', $pluginFile = null) {
+ global $serendipity;
+
+ if ($pluginFile === null) {
+ $class_name = '';
+ $pluginFile = serendipity_plugin_api::probePlugin($instance_id, $class_name, $pluginPath);
+ } else {
+ $is_internal = false;
+ $class_name = serendipity_plugin_api::getClassByInstanceID($instance_id, $is_internal);
}
-
+
+ if (!class_exists($class_name) && (empty($pluginFile) || !include_once($pluginFile))) {
+ return false;
+ }
+
$p =& new $class_name($instance_id);
if (!is_null($authorid)) {
$p->serendipity_owner = $authorid;
@@ -358,6 +403,98 @@
return $p;
}
+ function &getPluginInfo(&$pluginFile, &$class_data, $type) {
+ global $serendipity;
+
+ static $pluginlist = null;
+
+ if ($pluginlist === null) {
+ $data = serendipity_db_query("SELECT p.*,
+ pc.category
+ FROM {$serendipity['dbPrefix']}pluginlist AS p
+ LEFT OUTER JOIN {$serendipity['dbPrefix']}plugincategories AS pc
+ ON pc.class_name = p.class_name
+ WHERE p.pluginlocation = 'local' AND
+ p.plugintype = '" . serendipity_db_escape_string($type) . "'");
+ if (is_array($data)) {
+ foreach($data AS $p) {
+ if (!isset($pluginlist[$p['plugin_file']])) {
+ $pluginlist[$p['plugin_file']] = $p;
+ }
+
+ $pluginlist[$p['plugin_file']]['groups'][] = $p['category'];
+ }
+ }
+ }
+
+ if (is_array($pluginlist[$pluginFile])) {
+ $data = $pluginlist[$pluginFile];
+ if ((int)filemtime($pluginFile) == (int)$data['last_modified']) {
+ $data['stackable'] = serendipity_db_bool($data['stackable']);
+
+ $plugin = $data;
+ return $plugin;
+ }
+ }
+
+ $plugin =& serendipity_plugin_api::load_plugin($class_data['name'], null, $class_data['pluginPath'], $pluginFile);
+
+ return $plugin;
+ }
+
+ function &setPluginInfo(&$plugin, &$pluginFile, &$bag, &$class_data, $pluginlocation = 'local') {
+ global $serendipity;
+
+ serendipity_db_query("DELETE FROM {$serendipity['dbPrefix']}pluginlist WHERE plugin_file = '" . serendipity_db_escape_string($pluginFile) . "' AND pluginlocation = '" . serendipity_db_escape_string($pluginlocation) . "'");
+
+ if (is_object($plugin)) {
+ $data = array(
+ 'class_name' => get_class($plugin),
+ 'stackable' => $bag->get('stackable'),
+ 'name' => $bag->get('name'),
+ 'description' => $bag->get('description'),
+ 'author' => $bag->get('author'),
+ 'version' => $bag->get('version'),
+ 'upgrade_version' => $bag->get('version'),
+ 'requirements' => serialize($bag->get('requirements')),
+ 'website' => $bag->get('website'),
+ 'plugin_class' => $class_data['name'],
+ 'pluginPath' => $class_data['pluginPath'],
+ 'plugin_file' => $pluginFile,
+ 'pluginlocation' => $pluginlocation,
+ 'plugintype' => $serendipity['GET']['type'],
+ 'last_modified' => filemtime($pluginFile)
+ );
+ $groups = $bag->get('groups');
+ } elseif (is_array($plugin)) {
+ $data = $plugin;
+ $groups = $data['groups'];
+ unset($data['installable']);
+ unset($data['true_name']);
+ unset($data['customURI']);
+ unset($data['groups']);
+ $data['requirements'] = serialize($data['requirements']);
+ }
+
+ serendipity_db_insert('pluginlist', $data);
+
+ serendipity_db_query("DELETE FROM {$serendipity['dbPrefix']}plugincategories WHERE class_name = '" . serendipity_db_escape_string($data['class_name']) . "'");
+ foreach((array)$groups AS $group) {
+ if (empty($group)) {
+ continue;
+ }
+
+ $cat = array(
+ 'class_name' => $data['class_name'],
+ 'category' => $group
+ );
+ }
+
+ $data['groups'] = $groups;
+
+ return $data;
+ }
+
function update_plugin_placement($name, $placement, $order=null)
{
global $serendipity;
Index: include/admin/plugins.inc.php
===================================================================
--- include/admin/plugins.inc.php (revision 210)
+++ include/admin/plugins.inc.php (working copy)
@@ -13,8 +13,16 @@
include_once S9Y_INCLUDE_PATH . 'include/plugin_api.inc.php';
include_once S9Y_INCLUDE_PATH . 'include/plugin_internal.inc.php';
+function serendipity_groupname($group) {
+ if (defined('PLUGIN_GROUP_' . $group)) {
+ return constant('PLUGIN_GROUP_' . $group);
+ } else {
+ return $group;
+ }
+}
+
function serendipity_pluginListSort($x, $y) {
- return strnatcasecmp($x['name'] . ' - ' . $x['desc'], $y['name'] . ' - ' . $y['desc']);
+ return strnatcasecmp($x['name'] . ' - ' . $x['description'], $y['name'] . ' - ' . $y['description']);
}
function show_plugins($event_only = false)
@@ -348,7 +356,7 @@
foreach($select AS $select_value => $select_desc) {
$id = htmlspecialchars($config_item . $select_value);
?>
-
Plugin | -Action | -
' . sprintf(PAGE_BROWSE_PLUGINS, $currentPage, $maxPage, count($classes)) . ' '; - $plugin_pages = array(); - for ($i = 1; $i <= $maxPage; $i++) { - $plugin_page = ''; - if ($i == $currentPage) { - $plugin_page .= ''; - } + if (is_object($plugin)) { + // Object is returned when a plugin could not be cached. + $bag = new serendipity_property_bag; + $plugin->introspect($bag); + $props = serendipity_plugin_api::setPluginInfo($plugin, $pluginFile, $bag, $class_data); + $counter++; + } elseif (is_array($plugin)) { + // Array is returned if a plugin could be fetched from info cache + $props = $plugin; + } else { + $props = false; + } + + if (is_array($props)) { + $props['installable'] = !($props['stackable'] === false && in_array($class_data['true_name'], $plugins)); + $props['requirements'] = unserialize($props['requirements']); - $plugin_page .= '' . $i . ''; - - if ($i == $currentPage) { - $plugin_page .= ''; - } - - $plugin_pages[] = $plugin_page; + $pluginstack[$class_data['true_name']] = $props; + } else { + // False is returned if a plugin could not be instantiated + $errorstack[] = $class_data['true_name']; } - $plugin_navigation .= implode(' | ', $plugin_pages); - - echo $plugin_navigation; + } - $counter = 0; - foreach ($classes as $class_data) { - $counter++; - - if ($counter < $countStart || $counter > $countEnd) { - continue; - } - - $plugin =& serendipity_plugin_api::load_plugin($class_data['name'], null, $class_data['pluginPath']); - if (is_object($plugin)) { - $bag = new serendipity_property_bag; - $plugin->introspect($bag); - $pluginstack[] = array('plugin_class' => $class_data['name'], - 'class_name' => get_class($plugin), - 'name' => $bag->get('name'), - 'desc' => $bag->get('description'), - 'installable' => !($bag->get('stackable') === false && in_array($class_data['name'], $plugins)), - 'author' => $bag->get('author'), - 'version' => $bag->get('version'), - 'requirements' => $bag->get('requirements'), - 'website' => $bag->get('website'), - 'pluginPath' => $class_data['pluginPath']); - } else { - $errorstack[] = $class_data['name']; - } + usort($pluginstack, 'serendipity_pluginListSort'); + $pluggroups = array(); + foreach($pluginstack AS $plugname => $plugdata) { + foreach((array)$plugdata['groups'] AS $group) { + $pluggroups[$group][] = $plugdata; } } - usort($pluginstack, 'serendipity_pluginListSort'); foreach($errorstack as $e_idx => $e_name) { echo ERROR . ': ' . $e_name . ' '; } - - foreach ($pluginstack as $plug) { - $jsLine = " onmouseout=\"document.getElementById('serendipity_plugin_". $plug['class_name'] ."').className='';\""; - $jsLine .= " onmouseover=\"document.getElementById('serendipity_plugin_". $plug['class_name'] ."').className='serendipity_admin_list_item_uneven';\""; - - $pluginInfo = $notice = array(); - if (!empty($plug['author'])) { - $pluginInfo[] = AUTHOR . ': ' . $plug['author']; +?> + |