]> git.mjollnir.org Git - s9y.git/commitdiff
Larger rework of spartacus plugin to support mirrors and categories
authorgarvinhicking <garvinhicking>
Fri, 8 Jul 2005 13:29:03 +0000 (13:29 +0000)
committergarvinhicking <garvinhicking>
Fri, 8 Jul 2005 13:29:03 +0000 (13:29 +0000)
plugins/serendipity_event_spartacus/serendipity_event_spartacus.php

index b9bd09ebd834a8ec42c3f6fa2f1c51c96e95663f..407d135f07936850ddc4494c9a5559cc47e83ea3 100644 (file)
@@ -24,6 +24,9 @@ switch ($serendipity['lang']) {
         @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,12 +39,21 @@ switch ($serendipity['lang']) {
         @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)
     {
@@ -51,25 +63,103 @@ class serendipity_event_spartacus extends serendipity_event
         $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);
@@ -104,10 +194,10 @@ class serendipity_event_spartacus extends serendipity_event
     }
 
     // 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 @@ class serendipity_event_spartacus extends serendipity_event
         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 />';
 
@@ -152,7 +242,7 @@ class serendipity_event_spartacus extends serendipity_event
                 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;
@@ -165,38 +255,90 @@ class serendipity_event_spartacus extends serendipity_event
                     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);
@@ -212,14 +354,80 @@ class serendipity_event_spartacus extends serendipity_event
             '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             = '&amp;serendipity[spartacus_upgrade]=true';
+                }
+            }
+        }
+
+        $data['installable']     = $installable;
+        $data['pluginPath']      = 'online_repository';
+        $data['pluginlocation']  = 'Spartacus';
+        $data['plugintype']      = $type;
+        $data['customURI']       = '&amp;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 @@ class serendipity_event_spartacus extends serendipity_event
                 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 @@ class serendipity_event_spartacus extends serendipity_event
                             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                        = '&amp;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']   = '&amp;serendipity[spartacus_fetch]=' . $type . $upgradeLink;
+                $plugname = $pluginstack[$i]['template'];
+                $pluginstack[$i]['previewURL'] = $mirror . '/additional_themes/' . $plugname . '/preview.png?rev=1.9999';
+                $pluginstack[$i]['customURI']  = '&amp;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 />';
@@ -306,7 +589,7 @@ class serendipity_event_spartacus extends serendipity_event
             }
 
             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 @@ class serendipity_event_spartacus extends serendipity_event
             }
         }
 
+        $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 @@ class serendipity_event_spartacus extends serendipity_event
 
         if (isset($hooks[$event])) {
             switch($event) {
-                case 'backend_plugins_sidebar_header':
-?>
-    <br /><a href="?serendipity[adminModule]=plugins&amp;serendipity[adminAction]=addnew&amp;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&amp;serendipity[adminAction]=addnew&amp;serendipity[type]=event&amp;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;
@@ -384,7 +670,7 @@ class serendipity_event_spartacus extends serendipity_event
 
                 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 @@ class serendipity_event_spartacus extends serendipity_event
 }
 
 /* vim: set sts=4 ts=4 expandtab : */
-?>
+?>
\ No newline at end of file