Feature add: new page group type: regular expression match (PCRE)
authorDan
Sun, 30 Sep 2007 20:20:07 -0400
changeset 156 edbff85d43e8
parent 155 87bffacdfb92
child 157 6df5f7a55a30
Feature add: new page group type: regular expression match (PCRE)
includes/constants.php
includes/paths.php
includes/sessions.php
plugins/admin/PageGroups.php
upgrade.sql
--- a/includes/constants.php	Sun Sep 30 19:40:07 2007 -0400
+++ b/includes/constants.php	Sun Sep 30 20:20:07 2007 -0400
@@ -37,6 +37,7 @@
 define('PAGE_GRP_CATLINK', 1);
 define('PAGE_GRP_TAGGED', 2);
 define('PAGE_GRP_NORMAL', 3);
+define('PAGE_GRP_REGEX', 4);
 
 //
 // User types - don't touch these
--- a/includes/paths.php	Sun Sep 30 19:40:07 2007 -0400
+++ b/includes/paths.php	Sun Sep 30 20:20:07 2007 -0400
@@ -855,14 +855,35 @@
   {
     global $db, $session, $paths, $template, $plugins; // Common objects
     
-    $page_id = $db->escape(sanitize_page_id($page_id));
+    static $cache = array();
+    
+    if ( count($cache) == 0 )
+    {
+      foreach ( $this->nslist as $key => $_ )
+      {
+        $cache[$key] = array();
+      }
+    }
+    
     if ( !isset($this->nslist[$namespace]) )
       die('$paths->get_page_groups(): HACKING ATTEMPT: namespace "'. htmlspecialchars($namespace) .'" doesn\'t exist');
     
+    $page_id_unescaped = $paths->nslist[$namespace] .
+                         dirtify_page_id($page_id);
+    $page_id_str       = $paths->nslist[$namespace] .
+                         sanitize_page_id($page_id);
+    
+    $page_id = $db->escape(sanitize_page_id($page_id));
+    
+    if ( isset($cache[$namespace][$page_id]) )
+    {
+      return $cache[$namespace][$page_id];
+    }
+    
     $group_list = array();
     
     // What linked categories have this page?
-    $q = $db->sql_query('SELECT g.pg_id FROM '.table_prefix.'page_groups AS g
+    $q = $db->sql_unbuffered_query('SELECT g.pg_id, g.pg_type, g.pg_target FROM '.table_prefix.'page_groups AS g
   LEFT JOIN '.table_prefix.'categories AS c
     ON ( ( c.category_id = g.pg_target AND g.pg_type = ' . PAGE_GRP_CATLINK . ' ) OR c.category_id IS NULL )
   LEFT JOIN '.table_prefix.'page_group_members AS m
@@ -872,47 +893,32 @@
   WHERE
     ( c.page_id=\'' . $page_id . '\' AND c.namespace=\'' . $namespace . '\' ) OR
     ( t.page_id=\'' . $page_id . '\' AND t.namespace=\'' . $namespace . '\' ) OR
-    ( m.page_id=\'' . $page_id . '\' AND m.namespace=\'' . $namespace . '\' );');
+    ( m.page_id=\'' . $page_id . '\' AND m.namespace=\'' . $namespace . '\' ) OR
+    ( g.pg_type = ' . PAGE_GRP_REGEX . ' );');
     if ( !$q )
       $db->_die();
     
     while ( $row = $db->fetchrow() )
     {
-      $group_list[] = $row['pg_id'];
+      if ( $row['pg_type'] == PAGE_GRP_REGEX )
+      {
+        //echo "&lt;debug&gt; matching page " . htmlspecialchars($page_id_unescaped) . " against regex <tt>" . htmlspecialchars($row['pg_target']) . "</tt>.";
+        if ( @preg_match($row['pg_target'], $page_id_unescaped) || @preg_match($row['pg_target'], $page_id_str) )
+        {
+          //echo "..matched";
+          $group_list[] = $row['pg_id'];
+        }
+        //echo "<br />";
+      }
+      else
+      {
+        $group_list[] = $row['pg_id'];
+      }
     }
     
     $db->free_result();
     
-    /*
-    // Static-page groups
-    $q = $db->sql_query('SELECT g.pg_id FROM '.table_prefix.'page_groups AS g
-                           LEFT JOIN '.table_prefix.'page_group_members AS m
-                             ON ( g.pg_id = m.pg_id )
-                           WHERE m.page_id=\'' . $page_id . '\' AND m.namespace=\'' . $namespace . '\'
-                           GROUP BY g.pg_id;');
-    
-    if ( !$q )
-      $db->_die();
-    
-    while ( $row = $db->fetchrow() )
-    {
-      $group_list[] = $row['pg_id'];
-    }
-    
-    // Tag groups
-    
-    $q = $db->sql_query('SELECT g.pg_id FROM '.table_prefix.'page_groups AS g
-                           LEFT JOIN '.table_prefix.'tags AS t
-                             ON ( t.tag_name = g.pg_target AND pg_type = ' . PAGE_GRP_TAGGED . ' )
-                           WHERE t.page_id = \'' . $page_id . '\' AND t.namespace = \'' . $namespace . '\';');
-    if ( !$q )
-      $db->_die();
-    
-    while ( $row = $db->fetchrow() )
-    {
-      $group_list[] = $row['pg_id'];
-    }
-    */
+    $cache[$namespace][$page_id] = $group_list;
     
     return $group_list;
     
--- a/includes/sessions.php	Sun Sep 30 19:40:07 2007 -0400
+++ b/includes/sessions.php	Sun Sep 30 20:20:07 2007 -0400
@@ -2117,13 +2117,30 @@
       return false;
     }
     
+    // cache of permission objects (to save RAM and SQL queries)
+    static $objcache = array();
+    
+    if ( count($objcache) == 0 )
+    {
+      foreach ( $paths->nslist as $key => $_ )
+      {
+        $objcache[$key] = array();
+      }
+    }
+    
+    if ( isset($objcache[$namespace][$page_id]) )
+    {
+      return $objcache[$namespace][$page_id];
+    }
+    
     //if ( !isset( $paths->pages[$paths->nslist[$namespace] . $page_id] ) )
     //{
     //  // Page does not exist
     //  return false;
     //}
     
-    $object = new Session_ACLPageInfo( $page_id, $namespace, $this->acl_types, $this->acl_descs, $this->acl_deps, $this->acl_base_cache );
+    $objcache[$namespace][$page_id] = new Session_ACLPageInfo( $page_id, $namespace, $this->acl_types, $this->acl_descs, $this->acl_deps, $this->acl_base_cache );
+    $object =& $objcache[$namespace][$page_id];
     
     return $object;
     
--- a/plugins/admin/PageGroups.php	Sun Sep 30 19:40:07 2007 -0400
+++ b/plugins/admin/PageGroups.php	Sun Sep 30 20:20:07 2007 -0400
@@ -48,7 +48,12 @@
             echo '<div class="error-box">Please specify at least one page to place in this group.</div>';
             return;
           }
-          if ( $_POST['group_type'] != PAGE_GRP_TAGGED && $_POST['group_type'] != PAGE_GRP_CATLINK && $_POST['group_type'] != PAGE_GRP_NORMAL )
+          if ( $_POST['group_type'] == PAGE_GRP_REGEX && empty($_POST['regex']) )
+          {
+            echo '<div class="error-box">Please specify a regular expression to match page IDs against.</div>';
+            return;
+          }
+          if ( $_POST['group_type'] != PAGE_GRP_TAGGED && $_POST['group_type'] != PAGE_GRP_CATLINK && $_POST['group_type'] != PAGE_GRP_NORMAL && $_POST['group_type'] != PAGE_GRP_REGEX )
           {
             echo '<div class="error-box">Umm, you sent an invalid group type. I\'d put a real error message here but this will only be shown if you try to hack the system.</div>';
             return;
@@ -103,6 +108,14 @@
               if ( !$q )
                 $db->_die();
               break;
+            case PAGE_GRP_REGEX:
+              $name  = $db->escape($_POST['pg_name']);
+              $regex = $db->escape($_POST['regex']);
+              $sql = 'INSERT INTO '.table_prefix.'page_groups(pg_type,pg_name,pg_target) VALUES(' . PAGE_GRP_REGEX . ', \'' . $name . '\', \'' . $regex . '\');';
+              $q = $db->sql_query($sql);
+              if ( !$q )
+                $db->_die();
+              break;
           }
           echo '<div class="info-box">The page group "' . htmlspecialchars($_POST['pg_name']) . '" has been created.</div>';
           break;
@@ -115,6 +128,7 @@
           var pg_normal  = <?php echo PAGE_GRP_NORMAL; ?>;
           var pg_tagged  = <?php echo PAGE_GRP_TAGGED; ?>;
           var pg_catlink = <?php echo PAGE_GRP_CATLINK; ?>;
+          var pg_regex   = <?php echo PAGE_GRP_REGEX; ?>;
           var selection = false;
           // Get selection
           for ( var i = 0; i < selector.childNodes.length; i++ )
@@ -135,7 +149,7 @@
             return true;
           }
           selection = parseInt(selection);
-          if ( selection != pg_normal && selection != pg_tagged && selection != pg_catlink )
+          if ( selection != pg_normal && selection != pg_tagged && selection != pg_catlink && selection != pg_regex )
           {
             alert('Invalid field value');
             return true;
@@ -156,6 +170,10 @@
             document.getElementById('pg_create_title_normal').style.display = 'inline';
             document.getElementById('pg_create_normal_1').style.display = 'block';
             document.getElementById('pg_create_normal_2').style.display = 'block';
+            
+            document.getElementById('pg_create_title_regex').style.display = 'none';
+            document.getElementById('pg_create_regex_1').style.display = 'none';
+            document.getElementById('pg_create_regex_2').style.display = 'none';
           }
           else if ( selection == pg_catlink )
           {
@@ -170,6 +188,10 @@
             document.getElementById('pg_create_title_normal').style.display = 'none';
             document.getElementById('pg_create_normal_1').style.display = 'none';
             document.getElementById('pg_create_normal_2').style.display = 'none';
+            
+            document.getElementById('pg_create_title_regex').style.display = 'none';
+            document.getElementById('pg_create_regex_1').style.display = 'none';
+            document.getElementById('pg_create_regex_2').style.display = 'none';
           }
           else if ( selection == pg_tagged )
           {
@@ -184,6 +206,28 @@
             document.getElementById('pg_create_title_normal').style.display = 'none';
             document.getElementById('pg_create_normal_1').style.display = 'none';
             document.getElementById('pg_create_normal_2').style.display = 'none';
+            
+            document.getElementById('pg_create_title_regex').style.display = 'none';
+            document.getElementById('pg_create_regex_1').style.display = 'none';
+            document.getElementById('pg_create_regex_2').style.display = 'none';
+          }
+          else if ( selection == pg_regex )
+          {
+            document.getElementById('pg_create_title_catlink').style.display = 'none';
+            document.getElementById('pg_create_catlink_1').style.display = 'none';
+            document.getElementById('pg_create_catlink_2').style.display = 'none';
+            
+            document.getElementById('pg_create_title_tagged').style.display = 'none';
+            document.getElementById('pg_create_tagged_1').style.display = 'none';
+            document.getElementById('pg_create_tagged_2').style.display = 'none';
+            
+            document.getElementById('pg_create_title_normal').style.display = 'none';
+            document.getElementById('pg_create_normal_1').style.display = 'none';
+            document.getElementById('pg_create_normal_2').style.display = 'none';
+            
+            document.getElementById('pg_create_title_regex').style.display = 'inline';
+            document.getElementById('pg_create_regex_1').style.display = 'block';
+            document.getElementById('pg_create_regex_2').style.display = 'block';
           }
         
         }
@@ -199,6 +243,10 @@
           document.getElementById('pg_create_tagged_1').style.display = 'none';
           document.getElementById('pg_create_tagged_2').style.display = 'none';
           
+          document.getElementById('pg_create_title_regex').style.display = 'none';
+          document.getElementById('pg_create_regex_1').style.display = 'none';
+          document.getElementById('pg_create_regex_2').style.display = 'none';
+          
           document.getElementById('pg_create_title_normal').style.display = 'inline';
           document.getElementById('pg_create_normal_1').style.display = 'block';
           document.getElementById('pg_create_normal_2').style.display = 'block';
@@ -292,6 +340,7 @@
                 <option value="' . PAGE_GRP_NORMAL  . '" selected="selected">Static group of pages</option>
                 <option value="' . PAGE_GRP_TAGGED  . '">Group of pages with one tag</option>
                 <option value="' . PAGE_GRP_CATLINK . '">Link to category</option>
+                <option value="' . PAGE_GRP_REGEX   . '">Perl-compatible regular expression (advanced)</option>
               </select>
               </td>
             </tr>';
@@ -308,6 +357,9 @@
                 <span id="pg_create_title_catlink">
                   Mirror a category
                 </span>
+                <span id="pg_create_title_regex">
+                  Filter through a regular expression
+                </span>
               </th>
             </tr>';
       
@@ -324,6 +376,14 @@
                 <div id="pg_create_tagged_1">
                   Include pages with this tag:
                 </div>
+                <div id="pg_create_regex_1">
+                  Regular expression:<br />
+                  <small>Be sure to include the starting and ending delimiters and any flags you might need.<br />
+                         These pages might help: <a href="http://us.php.net/manual/en/reference.pcre.pattern.modifiers.php">Pattern modifiers</a> &bull;
+                         <a href="http://us.php.net/manual/en/reference.pcre.pattern.syntax.php">Pattern syntax</a><br />
+                         Examples: <tt>/^(Special|Admin):/i</tt> &bull; <tt>/^Image:([0-9]+)$/</tt><br />
+                         Developers, remember that this will be matched against the full page identifier string. This means that <tt>/^About_Enano$/</tt>
+                         will NOT match the page Special:About_Enano.</small>
               </td>';
             
       echo '  <td class="row1">
@@ -341,6 +401,9 @@
                 <div id="pg_create_catlink_2">
                   ' . $catlist . '
                 </div>
+                <div id="pg_create_regex_2">
+                  <input type="text" name="regex" size="60" /> 
+                </div>
               </td>
             </tr>';
             
@@ -911,6 +974,9 @@
         case PAGE_GRP_NORMAL:
           $type = 'Static set of pages';
           break;
+        case PAGE_GRP_REGEX:
+          $type = 'Regular expression match';
+          break;
       }
       $target = '';
       if ( $row['pg_type'] == PAGE_GRP_TAGGED )
@@ -921,6 +987,10 @@
       {
         $target = 'Category: ' . htmlspecialchars(get_page_title($paths->nslist['Category'] . sanitize_page_id($row['pg_target'])));
       }
+      else if ( $row['pg_type'] == PAGE_GRP_REGEX )
+      {
+        $target = 'Expression: <tt>' . htmlspecialchars($row['pg_target']) . '</tt>';
+      }
       $btn_edit = '<input type="submit" name="action[edit][' . $row['pg_id'] . ']" value="Edit" />';
       $btn_del = '<input type="submit" name="action[del][' . $row['pg_id'] . ']" value="Delete" />';
       // stupid jEdit bug/hack
--- a/upgrade.sql	Sun Sep 30 19:40:07 2007 -0400
+++ b/upgrade.sql	Sun Sep 30 20:20:07 2007 -0400
@@ -5,6 +5,8 @@
 DELETE FROM {{TABLE_PREFIX}}config WHERE config_name='enano_version' OR config_name='enano_beta_version' OR config_name='enano_alpha_version' OR config_name='enano_rc_version';
 INSERT INTO {{TABLE_PREFIX}}config (config_name, config_value) VALUES( 'enano_version', '1.0.2' );
 ---BEGIN 1.0.2b1---
+-- This is really optional, but could reduce confusion if regex page groups get truncated for no apparent reason.
+ALTER TABLE {{TABLE_PREFIX}}page_groups MODIFY COLUMN pg_target text DEFAULT NULL;
 ---END 1.0.2b1---
 ---BEGIN 1.0.1.1---
 ---END 1.0.1.1---