]> git.mjollnir.org Git - s9y.git/commitdiff
* plugin categories
authorgarvinhicking <garvinhicking>
Fri, 8 Jul 2005 13:31:58 +0000 (13:31 +0000)
committergarvinhicking <garvinhicking>
Fri, 8 Jul 2005 13:31:58 +0000 (13:31 +0000)
* new spartacus integration
* themes handled by spartacus

docs/NEWS
include/admin/plugins.inc.php
include/admin/templates.inc.php
include/functions_images.inc.php
include/plugin_api.inc.php
include/plugin_internal.inc.php
serendipity_config.inc.php
sql/db.sql
sql/db_update_0.9-alpha3_0.9-alpha4_mysql.sql [new file with mode: 0644]
templates/default/admin/style.css

index f37311d1f1cac1ab88c122057cf72422c8053b4f..d81629ce4d851d2b007b2d7e692f1e3a8dc38067 100644 (file)
--- a/docs/NEWS
+++ b/docs/NEWS
@@ -3,6 +3,11 @@
 Version 0.9 ()
 ------------------------------------------------------------------------
 
+    * Templates can now be handled via Spartacus (garvinhicking)        
+    
+    * Plugin Manager: Improve Spartacus interface and include plugin      
+      categories (garvinhicking)
+
     * Support different WYSIWYG editors via new plugin hooks. TinyMCE
       plugin available. (garvinhicking)
 
@@ -100,9 +105,6 @@ Version 0.9 ()
       that within templates you can still use the $CONST shortcut
       (garvinhicking)
 
-    * Pagination of plugins to install to save memory allocation if many
-      plugins are downloaded (garvinhicking)
-
     * Added new event hook to the trackback sending facility so that
       plugins like serendipity_event_trackback (additional_plugins)
       can send trackbacks to Blogs without RDF-metadata (garvinhicking)
index 96abd444ed4d48dc51b84305646a70979931f37d..cbecfdb7a83b2c617e0cf6e2ddaa1b5f96d544b4 100644 (file)
@@ -13,8 +13,16 @@ if (!serendipity_checkPermission('adminPlugins')) {
 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 @@ if (isset($_GET['serendipity']['plugin_to_conf'])) {
                 foreach($select AS $select_value => $select_desc) {
                     $id = htmlspecialchars($config_item . $select_value);
 ?>
-                        <option value="<?php echo $select_value; ?>" <?php echo ($select_value == $hvalue ? 'selected="selected"' : ''); ?> title="<?php echo htmlspecialchars($select_desc); ?>" />
+                        <option value="<?php echo $select_value; ?>" <?php echo ($select_value == $hvalue ? 'selected="selected"' : ''); ?> title="<?php echo htmlspecialchars($select_desc); ?>">
                             <?php echo htmlspecialchars($select_desc); ?>
                         </option>
 <?php
@@ -506,132 +514,152 @@ if (isset($_GET['serendipity']['plugin_to_conf'])) {
 <?php } else { ?>
     <h2><?php echo SIDEBAR_PLUGINS ?></h2>
 <?php } ?>
-<?php echo SELECT_A_PLUGIN_TO_ADD; ?>
-<br />
 <br />
 <?php
-    $foreignPlugins = array();
+    $foreignPlugins = $pluginstack = $errorstack = array();
     serendipity_plugin_api::hook_event('backend_plugins_fetchlist', $foreignPlugins);
-?>
-<table cellspacing="0" cellpadding="0" border="0" width="100%">
-    <tr>
-        <td><strong>Plugin</strong></td>
-        <td width="100" align="center"><strong>Action</strong></td>
-    </tr>
-<?php
-    $plugin_navigation = '';
+    $pluginstack = array_merge($foreignPlugins['pluginstack'], $pluginstack);
+    $errorstack  = array_merge($foreignPlugins['errorstack'], $errorstack);
 
-    if (count($foreignPlugins) > 0) {
-        $pluginstack = $foreignPlugins['pluginstack'];
-        $errorstack  = $foreignPlugins['errorstack'];
-    } else {
-        $pluginsPerPage = 45;
-        $currentPage    = (int)(!empty($serendipity['GET']['page']) ? $serendipity['GET']['page'] : 1);
-        $countStart     = ($currentPage-1) * $pluginsPerPage;
-        $countEnd       = ($currentPage)   * $pluginsPerPage; 
-
-        $plugins = serendipity_plugin_api::get_installed_plugins();
-
-        $errorstack = $pluginstack = array();
-        $classes    = serendipity_plugin_api::enum_plugin_classes(($serendipity['GET']['type'] == 'event'));
-        // TODO: With pagination of the plugins we cannot get the localized title of the plugins before sorting it.
-        //       This means we get a weird order of the plugins. We need to find a way
-        //       to do the sorting on the real plugin name WITHOUT loading ALL dozen plugins
-        usort($classes, 'serendipity_pluginListSort'); 
-
-        $maxPage           = ceil(count($classes)/$pluginsPerPage);
-        $plugin_navigation = '<tr><td colspan="2" align="center">' . sprintf(PAGE_BROWSE_PLUGINS, $currentPage, $maxPage, count($classes)) . '<br />';
-        $plugin_pages      = array();
-        for ($i = 1; $i <= $maxPage; $i++) {
-            $plugin_page = '';
-            if ($i == $currentPage) {
-                $plugin_page .= '<strong>';
-            }
+    $plugins = serendipity_plugin_api::get_installed_plugins();
+    $classes = serendipity_plugin_api::enum_plugin_classes(($serendipity['GET']['type'] == 'event'));
+    usort($classes, 'serendipity_pluginListSort'); 
 
-            $plugin_page .= '<a href="?serendipity[adminModule]=plugins&amp;serendipity[adminAction]=addnew&amp;serendipity[type]=' . $serendipity['GET']['type'] . '&amp;serendipity[page]=' . $i . '">' . $i . '</a>';
+    $counter    = 0;
+    foreach ($classes as $class_data) {
 
-            if ($i == $currentPage) {
-                $plugin_page .= '</strong>';
-            }
-            
-            $plugin_pages[] = $plugin_page;
-        }
-        $plugin_navigation .= implode(' | ', $plugin_pages);
-      
-        echo $plugin_navigation;
+        $pluginFile =  serendipity_plugin_api::probePlugin($class_data['name'], $class_data['classname'], $class_data['pluginPath']);
+        $plugin     =& serendipity_plugin_api::getPluginInfo($pluginFile, $class_data, $serendipity['GET']['type']);
 
-        $counter    = 0;
-        foreach ($classes as $class_data) {
+        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++;
-
-            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'];
+        } 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']);
+
+            $pluginstack[$class_data['true_name']] = $props;
+        } else {
+            // False is returned if a plugin could not be instantiated
+            $errorstack[] = $class_data['true_name'];
+        }
+    }
+    
+    usort($pluginstack, 'serendipity_pluginListSort');
+    $pluggroups     = array();
+    $pluggroups[''] = array();
+    foreach($pluginstack AS $plugname => $plugdata) {
+        if (is_array($plugdata['groups'])) {
+            foreach($plugdata['groups'] AS $group) {
+                $pluggroups[$group][] = $plugdata;
             }
+        } else {
+            $pluggroups[''][] = $plugdata;
         }
     }
+    ksort($pluggroups);
 
-    usort($pluginstack, 'serendipity_pluginListSort');
     foreach($errorstack as $e_idx => $e_name) {
         echo ERROR . ': ' . $e_name . '<br />';
     }
-
-    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'];
-        }
-
-        if (!empty($plug['version'])) {
-            $pluginInfo[] = VERSION  . ': ' . $plug['version'];
-        }
-
-        if (!empty($plug['upgrade_version'])) {
-            $pluginInfo[] = sprintf(UPGRADE_TO_VERSION, $plug['upgrade_version']);
-        }
-
-        if (!isset($plug['customURI'])) {
-            $plug['customURI'] = '';
-        }
-
-        if ( !empty($plug['requirements']['serendipity']) && version_compare($plug['requirements']['serendipity'], serendipity_getCoreVersion($serendipity['version']), '>') ) {
-            $notice['requirements_failures'][] = 's9y ' . $plug['requirements']['serendipity'];
-        }
-
-        if ( !empty($plug['requirements']['php']) && version_compare($plug['requirements']['php'], phpversion(), '>') ) {
-            $notice['requirements_failures'][] = 'PHP ' . $plug['requirements']['php'];
-        }
-
-        /* Enable after Smarty 2.6.7 upgrade.
-         * TODO: How can we get current Smarty version here? $smarty is not created!
-        if ( !empty($plug['requirements']['smarty']) && version_compare($plug['requirements']['smarty'], '2.6.7', '>') ) {
-            $notice['requirements_failures'][] = 'Smarty: ' . $plug['requirements']['smarty'];
-        }
-        */
-
-        if (count($notice['requirements_failures']) > 0) {
-            $plug['requirements_fail'] = true;
+?>
+<table cellspacing="0" cellpadding="0" border="0" width="100%">
+<?php
+    $available_groups = array_keys($pluggroups);
+    foreach($pluggroups AS $pluggroup => $groupstack) {
+        if (empty($pluggroup)) {
+        ?>
+    <tr>
+        <td colspan="2" class="serendipity_pluginlist_header">
+            <form action="serendipity_admin.php" method="get">
+                <input type="hidden" name="serendipity[adminModule]" value="plugins" />
+                <input type="hidden" name="serendipity[adminAction]" value="addnew" />
+                <input type="hidden" name="serendipity[type]" value="<?php echo htmlspecialchars($serendipity['GET']['type']); ?>" />
+                <?php echo FILTERS; ?>: <select name="serendipity[only_group]">
+            <?php foreach((array)$available_groups AS $available_group) { 
+                    ?>
+                    <option value="<?php echo $available_group; ?>" <?php echo ($serendipity['GET']['only_group'] == $available_group ? 'selected="selected"' : ''); ?>><?php echo serendipity_groupname($available_group); ?>
+            <?php } ?>
+                </select>
+                <input type="submit" value="<?php echo GO; ?>" />
+            </form>
+        </td>
+    </tr>
+        <?php
+            if (!empty($serendipity['GET']['only_group'])) {
+                continue;
+            }
+        } elseif (!empty($serendipity['GET']['only_group']) && $pluggroup != $serendipity['GET']['only_group']) {
+            continue;
+        } else {
+        ?>
+    <tr>
+        <td colspan="2" class="serendipity_pluginlist_section"><strong><?php echo serendipity_groupname($pluggroup); ?></strong></td>
+    </tr>
+        <?php
         }
+?>
+    <tr>
+        <td><strong>Plugin</strong></td>
+        <td width="100" align="center"><strong>Action</strong></td>
+    </tr>
+<?php
+        foreach ($groupstack 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'];
+            }
+    
+            if (!empty($plug['version'])) {
+                $pluginInfo[] = VERSION  . ': ' . $plug['version'];
+            }
+    
+            if (!empty($plug['upgrade_version']) && $plug['upgrade_version'] != $plug['version']) {
+                $pluginInfo[] = sprintf(UPGRADE_TO_VERSION, $plug['upgrade_version']);
+            }
+            
+            if (!empty($plug['pluginlocation']) && $plug['pluginlocation'] != 'local') {
+                $pluginInfo[] = '(' . htmlspecialchars($plug['pluginlocation']) . ')';
+                $installimage = serendipity_getTemplateFile('admin/img/install_now_' . strtolower($plug['pluginlocation']) . '.png');
+            } else {
+                $installimage = serendipity_getTemplateFile('admin/img/install_now.png');
+            }
+    
+            if (!isset($plug['customURI'])) {
+                $plug['customURI'] = '';
+            }
+    
+            if ( !empty($plug['requirements']['serendipity']) && version_compare($plug['requirements']['serendipity'], serendipity_getCoreVersion($serendipity['version']), '>') ) {
+                $notice['requirements_failures'][] = 's9y ' . $plug['requirements']['serendipity'];
+            }
+    
+            if ( !empty($plug['requirements']['php']) && version_compare($plug['requirements']['php'], phpversion(), '>') ) {
+                $notice['requirements_failures'][] = 'PHP ' . $plug['requirements']['php'];
+            }
+    
+            /* Enable after Smarty 2.6.7 upgrade.
+             * TODO: How can we get current Smarty version here? $smarty is not created!
+            if ( !empty($plug['requirements']['smarty']) && version_compare($plug['requirements']['smarty'], '2.6.7', '>') ) {
+                $notice['requirements_failures'][] = 'Smarty: ' . $plug['requirements']['smarty'];
+            }
+            */
+    
+            if (count($notice['requirements_failures']) > 0) {
+                $plug['requirements_fail'] = true;
+            }
 
 ?>
     <tr id="serendipity_plugin_<?php echo $plug['class_name']; ?>">
@@ -645,27 +673,26 @@ if (isset($_GET['serendipity']['plugin_to_conf'])) {
                         <?php } elseif ( $plug['upgradable'] == true ) { ?>
                             <a href="?serendipity[adminModule]=plugins&amp;serendipity[pluginPath]=<?php echo $plug['pluginPath']; ?>&amp;serendipity[install_plugin]=<?php echo $plug['plugin_class'] . $plug['customURI'] ?>"><img src="<?php echo serendipity_getTemplateFile('admin/img/upgrade_now.png') ?>" title="<?php echo UPGRADE ?>" alt="<?php echo UPGRADE ?>" border="0"></a>
                         <?php } elseif ($plug['installable'] == true) { ?>
-                            <a href="?serendipity[adminModule]=plugins&amp;serendipity[pluginPath]=<?php echo $plug['pluginPath']; ?>&amp;serendipity[install_plugin]=<?php echo $plug['plugin_class'] . $plug['customURI'] ?>"><img src="<?php echo serendipity_getTemplateFile('admin/img/install_now.png') ?>" title="<?php echo INSTALL ?>" alt="<?php echo INSTALL ?>" border="0"></a>
+                            <a href="?serendipity[adminModule]=plugins&amp;serendipity[pluginPath]=<?php echo $plug['pluginPath']; ?>&amp;serendipity[install_plugin]=<?php echo $plug['plugin_class'] . $plug['customURI'] ?>"><img src="<?php echo $installimage ?>" title="<?php echo INSTALL ?>" alt="<?php echo INSTALL ?>" border="0"></a>
                         <?php } else { ?>
                             <span style="color: #cccccc"><?php echo ALREADY_INSTALLED ?></span>
                         <?php } ?>
                     </td>
                 </tr>
                 <tr>
-                    <td style="padding-left: 10px"><?php echo $plug['desc'] ?></td>
+                    <td style="padding-left: 10px"><?php echo $plug['description'] ?></td>
                 </tr>
-<?php if (count($pluginInfo) > 0) { ?>
+<?php       if (count($pluginInfo) > 0) { ?>
                 <tr>
                     <td style="padding-left: 10px; font-size: x-small"><?php echo implode('; ', $pluginInfo); ?></td>
                 </tr>
-<?php } ?>
+<?php       } ?>
             </table>
         </td>
     </tr>
 <?php
+        }
     }
-
-    echo $plugin_navigation;
 ?>
 </table>
 
index cd7bdec2fe670897b85d899c4688be2978936a22..dea9b863f6a121e9b8f1e64f4916020eb618459a 100644 (file)
@@ -11,6 +11,8 @@ if (!serendipity_checkPermission('adminTemplates')) {
 }
 
 if ($serendipity['GET']['adminAction'] == 'install' ) {
+    serendipity_plugin_api::hook_event('backend_templates_fetchtemplate', $serendipity);
+
     $themeInfo = serendipity_fetchTemplateInfo($serendipity['GET']['theme']);
 
     serendipity_set_config_var('template', $serendipity['GET']['theme']);
@@ -28,11 +30,19 @@ if ($serendipity['GET']['adminAction'] == 'install' ) {
 
 
 <?php echo SELECT_TEMPLATE; ?>
+<br /><br />
 <?php
     $i = 0;
-    foreach (serendipity_fetchTemplates() as $theme) {
+    $stack = array();
+    serendipity_plugin_api::hook_event('backend_templates_fetchlist', $stack);
+    $themes = serendipity_fetchTemplates();
+    foreach($themes AS $theme) {
+        $stack[$theme] = serendipity_fetchTemplateInfo($theme);
+    }
+    ksort($stack);
+
+    foreach ($stack as $theme => $info) {
         $i++;
-        $info = serendipity_fetchTemplateInfo($theme);
 
         /* Sorry, but we don't display engines */
         if ( strtolower($info['engine']) == 'yes' ) {
@@ -42,9 +52,15 @@ if ($serendipity['GET']['adminAction'] == 'install' ) {
 
         if (file_exists($serendipity['serendipityPath'] . $serendipity['templatePath'] . $theme . '/preview.png')) {
             $preview = '<img src="' . $serendipity['templatePath'] . $theme . '/preview.png" width="100" style="border: 1px #000000 solid" />';
+        } elseif (!empty($info['previewURL'])) {
+            $preview = '<img src="' . $info['previewURL'] . '" width="100" style="border: 1px #000000 solid" />';        
         } else {
             $preview = '&nbsp;';
         }
+        
+        if (empty($info['customURI'])) {
+            $info['customURI'] = '';
+        }
 
         $unmetRequirements = array();
         if ( isset($info['require serendipity']) && version_compare($info['require serendipity'], serendipity_getCoreVersion($serendipity['version']), '>') ) {
@@ -65,7 +81,7 @@ if ($serendipity['GET']['adminAction'] == 'install' ) {
     if ( $serendipity['template'] != $theme ) {
         if ( !sizeof($unmetRequirements) ) {
 ?>
-            <a href="?serendipity[adminModule]=templates&amp;serendipity[adminAction]=install&amp;serendipity[theme]=<?php echo $theme ?>"><img src="<?php echo serendipity_getTemplateFile('admin/img/install_now.png') ?>" alt="<?php echo SET_AS_TEMPLATE ?>" title="<?php echo SET_AS_TEMPLATE ?>" border="0" /></a>
+            <a href="?serendipity[adminModule]=templates&amp;serendipity[adminAction]=install&amp;serendipity[theme]=<?php echo $theme . $info['customURI']; ?>"><img src="<?php echo serendipity_getTemplateFile('admin/img/install_now' . $info['customIcon'] . '.png') ?>" alt="<?php echo SET_AS_TEMPLATE ?>" title="<?php echo SET_AS_TEMPLATE ?>" border="0" /></a>
 <?php   } else { ?>
         <span style="color: #cccccc"><?php echo sprintf(UNMET_REQUIREMENTS, implode(', ', $unmetRequirements)); ?></span>
 <?php
index f3018a61ff0ebd3a097e67932e41202b7498c625..9dc7c9d99af167ac3e511143b5ceed5135d53927 100644 (file)
@@ -1190,7 +1190,7 @@ function serendipity_killPath($basedir, $directory = '', $forceDelete = false) {
 }
 
 
-function serendipity_traversePath($basedir, $dir='', $onlyDirs=true, $pattern = NULL, $depth = 1) {
+function serendipity_traversePath($basedir, $dir='', $onlyDirs=true, $pattern = NULL, $depth = 1, $max_depth = null) {
 
 
     $dh = @opendir($basedir . '/' . $dir);
@@ -1210,8 +1210,8 @@ function serendipity_traversePath($basedir, $dir='', $onlyDirs=true, $pattern =
                     );
                 }
             }
-            if ( is_dir($basedir . '/' . $dir . '/' . $file) ) {
-                $files = array_merge($files, serendipity_traversePath($basedir, $dir . '/' . basename($file) . '/', $onlyDirs, $pattern, ($depth+1)));
+            if ( is_dir($basedir . '/' . $dir . '/' . $file) && ($max_depth === null || $depth < $max_depth)) {
+                $files = array_merge($files, serendipity_traversePath($basedir, $dir . '/' . basename($file) . '/', $onlyDirs, $pattern, ($depth+1), $max_depth));
             }
         }
     }
index 6bc814b325a9af2be74e93b3c8dd453515f04c63..6b1b31f8a62dc002a7535584362177799d353474 100644 (file)
@@ -152,9 +152,13 @@ class serendipity_plugin_api {
 
             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 @@ class serendipity_plugin_api {
                 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 @@ class serendipity_plugin_api {
                         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 @@ class serendipity_plugin_api {
         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,40 @@ class serendipity_plugin_api {
                 }
 
                 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);
         }
 
+        if (!class_exists($class_name)) {
+            return false;
+        }
+        
         $p =& new $class_name($instance_id);
         if (!is_null($authorid)) {
             $p->serendipity_owner = $authorid;
@@ -358,6 +407,99 @@ class serendipity_plugin_api {
         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
+            );
+            serendipity_db_insert('plugincategories', $cat);
+        }
+        
+        $data['groups'] = $groups;
+
+        return $data;
+    }
+
     function update_plugin_placement($name, $placement, $order=null)
     {
         global $serendipity;
index cf115553526c5d699ff700cc04133382d1ab8360..3f6e2f110e34c461e7441327d45ca95b4867a272 100644 (file)
@@ -13,6 +13,7 @@ class serendipity_calendar_plugin extends serendipity_plugin {
         $propbag->add('stackable',     false);
         $propbag->add('author',        'Serendipity Team');
         $propbag->add('version',       '1.0');
+        $propbag->add('groups',        array('FRONTEND_VIEWS'));
     }
 
     function introspect_config_item($name, &$propbag)
@@ -300,6 +301,7 @@ class serendipity_quicksearch_plugin extends serendipity_plugin {
         $propbag->add('stackable',     false);
         $propbag->add('author',        'Serendipity Team');
         $propbag->add('version',       '1.0');
+        $propbag->add('groups',        array('FRONTEND_ENTRY_RELATED'));
     }
 
     function generate_content(&$title)
@@ -331,6 +333,7 @@ class serendipity_archives_plugin extends serendipity_plugin {
         $propbag->add('author',        'Serendipity Team');
         $propbag->add('version',       '1.0');
         $propbag->add('configuration', array('frequency', 'count'));
+        $propbag->add('groups',        array('FRONTEND_VIEWS'));
     }
 
     function introspect_config_item($name, &$propbag)
@@ -405,6 +408,7 @@ class serendipity_topreferrers_plugin extends serendipity_plugin {
         $propbag->add('author',        'Serendipity Team');
         $propbag->add('version',       '1.0');
         $propbag->add('configuration', array('limit', 'use_links', 'interval'));
+        $propbag->add('groups',        array('STATISTICS'));
     }
 
     function introspect_config_item($name, &$propbag)
@@ -470,6 +474,7 @@ class serendipity_topexits_plugin extends serendipity_plugin {
         $propbag->add('author',        'Serendipity Team');
         $propbag->add('version',       '1.0');
         $propbag->add('configuration', array('limit', 'use_links', 'interval'));
+        $propbag->add('groups',        array('STATISTICS'));
     }
 
     function introspect_config_item($name, &$propbag)
@@ -560,6 +565,7 @@ class serendipity_syndication_plugin extends serendipity_plugin {
                                         'fb_img',
                                        )
         );
+        $propbag->add('groups',        array('FRONTEND_VIEWS'));
     }
 
     function introspect_config_item($name, &$propbag)
@@ -888,6 +894,7 @@ class serendipity_superuser_plugin extends serendipity_plugin {
         $propbag->add('author',        'Serendipity Team');
         $propbag->add('version',       '1.0');
         $propbag->add('configuration', array('https'));
+        $propbag->add('groups',        array('FRONTEND_FEATURES'));
     }
 
     function generate_content(&$title)
@@ -936,6 +943,7 @@ class serendipity_plug_plugin extends serendipity_plugin {
         $propbag->add('configuration', array(
                                         'image',
                                         'text'));
+        $propbag->add('groups',        array('FRONTEND_VIEWS'));
     }
 
     function introspect_config_item($name, &$propbag)
@@ -1006,6 +1014,7 @@ class serendipity_html_nugget_plugin extends serendipity_plugin {
                                         'show_where'
                                        )
         );
+        $propbag->add('groups',        array('FRONTEND_VIEWS'));
 
         $this->protected = TRUE; // If set to TRUE, only allows the owner of the plugin to modify its configuration
     }
@@ -1091,6 +1100,7 @@ class serendipity_categories_plugin extends serendipity_plugin {
         $propbag->add('author',        'Serendipity Team');
         $propbag->add('version',       '1.0');
         $propbag->add('configuration', array('authorid', 'image', 'sort_order', 'sort_method', 'allow_select'));
+        $propbag->add('groups',        array('FRONTEND_VIEWS'));
     }
 
     function introspect_config_item($name, &$propbag)
index abdc912b6520c29dafcb65cfb046db5c5d6b60d7..d2caa6f3145dc9891d3de29135db82751bfaee44 100644 (file)
@@ -21,7 +21,7 @@ if (IS_installed === true && !defined('IN_serendipity')) {
 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 7d4b31ca0a3df6a3699fe9329278886290c9a3cd..4c9e4c8286320882e9bacb35534391fee8eea869 100644 (file)
@@ -245,3 +245,33 @@ CREATE INDEX pl_idx ON {PREFIX}permalinks (permalink);
 CREATE INDEX ple_idx ON {PREFIX}permalinks (entry_id);
 CREATE INDEX plt_idx ON {PREFIX}permalinks (type);
 CREATE INDEX plcomb_idx ON {PREFIX}permalinks (permalink, type);
+
+create table {PREFIX}plugincategories (
+  class_name varchar(250) default null,
+  category varchar(250) default null
+);
+
+CREATE INDEX plugincat_idx ON {PREFIX}plugincategories(class_name, category);
+
+create table {PREFIX}pluginlist (
+  plugin_file varchar(255) NOT NULL default '',
+  class_name varchar(255) NOT NULL default '',
+  plugin_class varchar(255) NOT NULL default '',
+  pluginPath varchar(255) NOT NULL default '',
+  name varchar(255) NOT NULL default '',
+  description text NOT NULL,
+  version varchar(12) NOT NULL default '',
+  upgrade_version varchar(12) NOT NULL default '',
+  plugintype varchar(255) NOT NULL default '',
+  pluginlocation varchar(255) NOT NULL default '',
+  stackable int(1) NOT NULL default '0',
+  author varchar(255) NOT NULL default '',
+  requirements text NOT NULL,
+  website varchar(255) NOT NULL default '',
+  last_modified int(11) NOT NULL default '0'
+);
+
+CREATE INDEX pluginlist_f_idx ON {PREFIX}pluginlist(plugin_file);
+CREATE INDEX pluginlist_cn_idx ON {PREFIX}pluginlist(class_name);
+CREATE INDEX pluginlist_pt_idx ON {PREFIX}pluginlist(plugintype);
+CREATE INDEX pluginlist_pl_idx ON {PREFIX}pluginlist(pluginlocation);
diff --git a/sql/db_update_0.9-alpha3_0.9-alpha4_mysql.sql b/sql/db_update_0.9-alpha3_0.9-alpha4_mysql.sql
new file mode 100644 (file)
index 0000000..db90767
--- /dev/null
@@ -0,0 +1,29 @@
+create table {PREFIX}plugincategories (
+  class_name varchar(250) default null,
+  category varchar(250) default null
+);
+
+CREATE INDEX plugincat_idx ON {PREFIX}plugincategories(class_name, category);
+
+create table {PREFIX}pluginlist (
+  plugin_file varchar(255) NOT NULL default '',
+  class_name varchar(255) NOT NULL default '',
+  plugin_class varchar(255) NOT NULL default '',
+  pluginPath varchar(255) NOT NULL default '',
+  name varchar(255) NOT NULL default '',
+  description text NOT NULL,
+  version varchar(12) NOT NULL default '',
+  upgrade_version varchar(12) NOT NULL default '',
+  plugintype varchar(255) NOT NULL default '',
+  pluginlocation varchar(255) NOT NULL default '',
+  stackable int(1) NOT NULL default '0',
+  author varchar(255) NOT NULL default '',
+  requirements text NOT NULL,
+  website varchar(255) NOT NULL default '',
+  last_modified int(11) NOT NULL default '0'
+);
+
+CREATE INDEX pluginlist_f_idx ON {PREFIX}pluginlist(plugin_file);
+CREATE INDEX pluginlist_cn_idx ON {PREFIX}pluginlist(class_name);
+CREATE INDEX pluginlist_pt_idx ON {PREFIX}pluginlist(plugintype);
+CREATE INDEX pluginlist_pl_idx ON {PREFIX}pluginlist(pluginlocation);
index cb8a4c41d980881ace1279e5219b7209daa7b746..069ffa0ca1ba2284346bccaa6f9c5ccf566cdaa7 100644 (file)
@@ -255,3 +255,20 @@ a.serendipityPrettyButton {
 .direction_rtl {
     direction: rtl;
 }
+
+.serendipity_pluginlist_header {
+    height: 30px; 
+    background-color: white; 
+    color: black; 
+    vertical-align: middle; 
+    padding: 10px 0px 5px 10px;
+}
+
+.serendipity_pluginlist_section {
+    height: 50px; 
+    border: 1px solid black; 
+    background-color: #E0E0E0; 
+    color: black; 
+    vertical-align: middle; 
+    padding: 10px 0px 5px 10px;
+}
\ No newline at end of file