@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':
@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)
{
$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('BACKEND_FEATURES'));
+ $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 . '<br />', $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);
}
// 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 = '';
return true;
}
- function &fetchfile($url, $target, $cacheTimeout = 0) {
+ function &fetchfile($url, $target, $cacheTimeout = 0, $decode_utf8 = false, $sub = 'plugins') {
printf(PLUGIN_EVENT_SPARTACUS_FETCHING, '<a href="' . $url . '">' . basename($url) . '</a>');
echo '<br />';
printf(PLUGIN_EVENT_SPARTACUS_FETCHED_BYTES_URL, strlen($data), $target);
echo '<br />';
$tdir = dirname($target);
- if (!is_dir($tdir) && !$this->rmkdir($tdir)) {
+ if (!is_dir($tdir) && !$this->rmkdir($tdir, $sub)) {
printf(FILE_WRITE_ERROR, $tdir);
echo '<br />';
return false;
echo '<br />';
return false;
}
+
+ if ($decode_utf8) {
+ $this->decode($data);
+ }
fwrite($fp, $data);
fclose($fp);
echo PLUGIN_EVENT_SPARTACUS_FETCHED_DONE;
echo '<br />';
+ $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 '<br /><br />';
+ $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);
'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++;
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':
break;
}
}
+
+ $this->checkPlugin($pluginstack[$i], $plugins, $type);
+
+ 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]);
+ }
+ }
- $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';
- }
+ 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 '<br />';
}
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;
}
}
}
+ $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);
if (isset($hooks[$event])) {
switch($event) {
- case 'backend_plugins_sidebar_header':
-?>
- <br /><a href="?serendipity[adminModule]=plugins&serendipity[adminAction]=addnew&serendipity[source]=spartacus" class="serendipityIconLink"><img src="<?php echo serendipity_getTemplateFile('admin/img/install.png') ?>" style="border: 0px none ; vertical-align: middle; display: inline;" alt=""><?php echo sprintf(PLUGIN_EVENT_SPARTACUS_FETCH, SIDEBAR_PLUGIN) ?></a>
-<?php
- return true;
- break;
+ case 'backend_templates_fetchlist':
+ $eventData = $this->buildTemplateList($this->fetchOnline('template', true), 'template');
- case 'backend_plugins_event_header':
-?>
- <br /><a href="?serendipity[adminModule]=plugins&serendipity[adminAction]=addnew&serendipity[type]=event&serendipity[source]=spartacus" class="serendipityIconLink"><img src="<?php echo serendipity_getTemplateFile('admin/img/install.png') ?>" style="border: 0px none ; vertical-align: middle; display: inline;" alt=""><?php echo sprintf(PLUGIN_EVENT_SPARTACUS_FETCH, EVENT_PLUGIN) ?></a>
-<?php
return true;
break;
- case 'backend_plugins_fetchlist':
- if ($serendipity['GET']['source'] != 'spartacus') {
- return false;
+ case 'backend_templates_fetchtemplate':
+ if (!empty($eventData['GET']['spartacus_fetch'])) {
+ $this->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;
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 {
}
/* vim: set sts=4 ts=4 expandtab : */
-?>
+?>
\ No newline at end of file