http://www.mediawiki.org/wiki/Special:Code/MediaWiki/93769

Revision: 93769
Author:   flohack
Date:     2011-08-02 16:56:29 +0000 (Tue, 02 Aug 2011)
Log Message:
-----------
Experimental support for memcached enhanced category tree building; Added an 
option to disable the recursive category scan; Changed the DB schema to avoid 
having to add a primary key to change_tag; Added a dummy test case

Modified Paths:
--------------
    trunk/extensions/CollabWatchlist/CollabWatchlist.php
    trunk/extensions/CollabWatchlist/includes/CategoryTreeManip.php
    trunk/extensions/CollabWatchlist/includes/CollabWatchlistEditor.php
    trunk/extensions/CollabWatchlist/includes/SpecialCollabWatchlist.php
    trunk/extensions/CollabWatchlist/sql/collabwatchlistrevisiontag.sql

Added Paths:
-----------
    trunk/extensions/CollabWatchlist/sql/patch-collabwatchlist_noctid.sql
    trunk/extensions/CollabWatchlist/tests/
    trunk/extensions/CollabWatchlist/tests/CollabWatchlistTest.php

Removed Paths:
-------------
    trunk/extensions/CollabWatchlist/sql/patch-change_tag_id.sql

Modified: trunk/extensions/CollabWatchlist/CollabWatchlist.php
===================================================================
--- trunk/extensions/CollabWatchlist/CollabWatchlist.php        2011-08-02 
16:48:14 UTC (rev 93768)
+++ trunk/extensions/CollabWatchlist/CollabWatchlist.php        2011-08-02 
16:56:29 UTC (rev 93769)
@@ -46,15 +46,16 @@
 $wgHooks['GetPreferences'][] = 'fnCollabWatchlistPreferences';
 
 function fnCollabWatchlistDbSchema() {
+       global $updater;
        $wgSql = dirname(__FILE__) . '/sql/';
        if ( $updater === null ) { // <= 1.16 support
-               global $wgExtNewTables;
+               global $wgExtNewTables, $wgExtNewFields;
                $wgExtNewTables[] = array('collabwatchlist',  $wgSql . 
'collabwatchlist.sql');
                $wgExtNewTables[] = array('collabwatchlistuser',  $wgSql . 
'collabwatchlistuser.sql');
                $wgExtNewTables[] = array('collabwatchlistcategory',  $wgSql . 
'collabwatchlistcategory.sql');
                $wgExtNewTables[] = array('collabwatchlistrevisiontag', $wgSql 
. 'collabwatchlistrevisiontag.sql');
                $wgExtNewTables[] = array('collabwatchlisttag', $wgSql . 
'collabwatchlisttag.sql');
-               $wgExtNewFields[] = array('change_tag', 'ct_id', $wgSql . 
'patch-change_tag_id.sql');
+               $wgExtNewFields[] = array('collabwatchlistrevisiontag', 
'ct_rc_id', $wgSql . 'patch-collabwatchlist_noctid.sql');
        } else { // >= 1.17 support
                $updater->addExtensionUpdate( array ( 'addTable', 
'collabwatchlist',
                        $wgSql . 'collabwatchlist.sql', true ) );
@@ -66,8 +67,8 @@
                        $wgSql . 'collabwatchlistrevisiontag.sql', true ) );
                $updater->addExtensionUpdate( array ( 'addTable', 
'collabwatchlisttag',
                        $wgSql . 'collabwatchlisttag.sql', true ) );
-               $updater->addExtensionUpdate( array( 'modifyField', 
'change_tag', 'ct_id',
-                       $wgSql . 'patch-change_tag_id.sql', true ) );
+               $updater->addExtensionUpdate( array( 'modifyField', 
'collabwatchlistrevisiontag', 'ct_rc_id',
+                       $wgSql . 'patch-collabwatchlist_noctid.sql', true ) );
        }
        return true;
 }
@@ -81,9 +82,23 @@
        return true;
 }
 
+// You might want to disable that, as it causes quite a bit of database
+// and (if enabled) cache load and size
+$wgCollabWatchlistRecursiveCatScan = true;
+// The depth of the category tree we are building. -1 means infinite
+// 0 fetches no child categories at all
+$wgCollabWatchlistRecursiveCatMaxDepth = -1;
 $wgCollabWatchlistNSPrefix = 'CollabWatchlist';
 $wgCollabWatchlistPermissionDeniedPage = 'CollabWatchlistPermissionDenied';
 
+# Unit tests
+$wgHooks['UnitTestsList'][] = 'efCollabWatchlistUnitTests';
+
+function efCollabWatchlistUnitTests( &$files ) {
+       $files[] = dirname( __FILE__ ) . '/tests/CollabWatchlistTest.php';
+       return true;
+}
+
 /**#@+
  * Collaborative watchlist user types
  * This defines constants for the collabwatchlistuser.rlu_type

Modified: trunk/extensions/CollabWatchlist/includes/CategoryTreeManip.php
===================================================================
--- trunk/extensions/CollabWatchlist/includes/CategoryTreeManip.php     
2011-08-02 16:48:14 UTC (rev 93768)
+++ trunk/extensions/CollabWatchlist/includes/CategoryTreeManip.php     
2011-08-02 16:56:29 UTC (rev 93769)
@@ -10,19 +10,31 @@
  * @author fhackenberger
  */
 class CategoryTreeManip {
+       const CACHE_KEY = 'categorytree';
+       const CACHE_KEY_CHILDCATEGORIES = 'childcats';
+       const CACHE_KEY_CATEGORYPAGEID = 'catpageid';
+       // How long the cache for child categories and category page ids should 
last
+       protected $cacheDurationSec;
+       // Whether the cache should be used to speed up building the tree
+       // We always fill the cache, though
+       protected $cacheEnabled = true;
+       // The depth of the tree we are building. -1 means infinite
+       // 0 fetches no child categories at all
+       protected $maxDepth = -1;
+       protected $root;
+       public $name;
+       public $id;
+       // Maps from the page id of a category to instances of this class
+       protected $catPageIdToNode = array();
+       protected $parents = array();
+       protected $enabled = true;
+       protected $children = array();
 
-       var $root;
-       var $name;
-       var $id;
-       var $catPageIdToNode = array();
-       var $parents = array();
-       var $enabled = true;
-       var $children = array();
-
        /**
         * Constructor
         */
        function __construct( $id = null, $name = null, $root = null, $parents 
= array() ) {
+               $this->cacheDurationSec = 15 * 60;
                $this->id = $id;
                $this->name = $name;
                if ( !is_null( $root ) ) {
@@ -32,10 +44,26 @@
                }
                $this->parents = $parents;
        }
+       
+       public function getCacheEnabled() {
+               return $this->cacheEnabled;
+       }
+       
+       public function setCacheEnabled( $enabled ) {
+               $this->cacheEnabled = $enabled;
+       }
+       
+       public function getMaxDepth() {
+               return $this->maxDepth;
+       }
+       
+       public function setMaxDepth( $maxDepth ) {
+               $this->maxDepth = $maxDepth;
+       }
 
        private function addChildren( $children ) {
                if ( !is_array( $children ) )
-                       throw new Exception( 'Argument must be an array' );
+               throw new Exception( 'Argument must be an array' );
                foreach ( $children as $child ) {
                        $this->children[$child->id] = $child;
                }
@@ -43,7 +71,7 @@
 
        private function addParents( $parents ) {
                if ( !is_array( $parents ) )
-                       throw new Exception( 'Argument must be an array' );
+               throw new Exception( 'Argument must be an array' );
                foreach ( $parents as $parent ) {
                        $this->parents[$parent->id] = $parent;
                }
@@ -71,7 +99,7 @@
 
        private function recursiveDisable( $visitedNodeIds = array() ) {
                if ( !$this->enabled || array_key_exists( $this->id, 
$visitedNodeIds ) )
-                       return; # Break the recursion
+               return; # Break the recursion
                $this->enabled = false;
                $visitedNodeIds[] = $this->id;
                foreach ( $this->children as $cat ) {
@@ -105,7 +133,7 @@
        private function recursiveGetEnabledNodeMap( &$foundNodes = array() ) {
                if ( isset( $this->id ) ) {
                        if ( !$this->enabled || array_key_exists( $this->id, 
$foundNodes ) )
-                               return $foundNodes; # Break the recursion
+                       return $foundNodes; # Break the recursion
                        $foundNodes[$this->id] = $this;
                }
                foreach ( $this->children as $cat ) {
@@ -121,12 +149,29 @@
         */
        public function getNodeForCatPageId( $catPageId ) {
                if ( array_key_exists( $catPageId, $this->root->catPageIdToNode 
) )
-                       return $this->root->catPageIdToNode[$catPageId];
+               return $this->root->catPageIdToNode[$catPageId];
        }
 
        private function addNode( $node ) {
                $this->root->catPageIdToNode[$node->id] = $node;
        }
+       
+       public function printTree() {
+               print "all categories:\n";
+               foreach( $this->catPageIdToNode as $catPageId => $node ) {
+                       print $catPageId . ": " . $node->name . " enabled: " . 
$node->enabled . "\n";
+               }
+               print "child categories:\n";
+               $this->printTreeRecursive( $this->root, '' );
+       }
+       
+       protected function printTreeRecursive( $node, $prefix ) {
+               if( $node->id )
+                       print $node->id . ": " . $node->name . " enabled: " . 
$node->enabled . "\n";
+               foreach( $node->children as $child ) {
+                       $this->printTreeRecursive( $child, $prefix . '  ' );
+               }
+       }
 
        /** Build the category tree, given a list of category names.
         * All categories and subcategories are enabled by default.
@@ -135,47 +180,46 @@
         * @return
         */
        public function initialiseFromCategoryNames( $catNames ) {
-               $dbr = wfGetDB( DB_SLAVE );
+               $currDepth = 0;
+               // This method builds the category tree breadth-first in an
+               // iterative fashion.
                while ( $catNames ) {
-                       $res = $dbr->select( array( 'categorylinks', 'page' ), 
# Tables
-                               array( 'cl_to AS parName', 'cl_from AS 
childId', 'page_title AS childName' ), # Fields
-                               array( 'cl_to' => $catNames, 'page_namespace' 
=> NS_CATEGORY ),  # Conditions
-                               __METHOD__, array(),
-                                # Join conditions
-                               array( 'page' => array( 'JOIN', 'page_id = 
cl_from' ) )
-                       );
+                       if($this->maxDepth > 0 && $currDepth > $this->maxDepth)
+                               break;
+                       // Get a list of child categories (array of hashmaps)
+                       $res = $this->getChildCategories( $catNames );
+                       // Maps parent category name -> array ( array ( child 
id , child name ) )
                        $parentList = array();
+                       // Maps child category id -> array( child id, array ( 
parent name, ... ) )
                        $childList = array();
+                       // Build $parentList and $childList
                        foreach ( $res as $row ) {
-                               $parentList[$row->parName][] = array( 
$row->childId, $row->childName );
-                               if ( array_key_exists( $row->childId, 
$childList ) ) {
-                                       $childEntry = $childList[$row->childId];
-                                       $childEntry[1][] = $row->parName;
+                               $parentList[$row['parName']][] = array( 
$row['childId'], $row['childName'] );
+                               if ( array_key_exists( $row['childId'], 
$childList ) ) {
+                                       $childEntry = 
$childList[$row['childId']];
+                                       $childEntry[1][] = $row['parName'];
                                } else {
-                                       $childList[$row->childId] = array( 
$row->childName, array( $row->parName ) );
+                                       $childList[$row['childId']] = array( 
$row['childName'], array( $row['parName'] ) );
                                }
                        }
 
+                       // Fetch the page ids of the $catNames and build the 
node objects for them
                        if ( !isset( $parentNameToNode ) && !empty( $parentList 
) ) {
-                               // Fetch the page ids of the $catNames and add 
the parent categories if needed
-                               $res = $dbr->select( array( 'page' ), # Tables
-                                       array( 'page_id, page_title' ), # Fields
-                                       array( 'page_title' => array_keys( 
$parentList ) )  # Conditions
-                               );
+                               $res = $this->getCategoryPageIds( array_keys( 
$parentList ) );
                                $parentNameToNode = array();
                                foreach ( $res as $row ) {
-                                       $node = $this->getNodeForCatPageId( 
$row->page_id );
+                                       $node = $this->getNodeForCatPageId( 
$row['page_id'] );
                                        if ( !isset( $node ) ) {
-                                               $node = new CategoryTreeManip( 
$row->page_id, $row->page_title, $this->root );
+                                               $node = new CategoryTreeManip( 
$row['page_id'], $row['page_title'], $this->root );
                                                $this->addNode( $node );
                                                $this->addChildren( array( 
$node ) );
                                        }
-                                       $parentNameToNode[$row->page_title] = 
$node;
+                                       $parentNameToNode[$row['page_title']] = 
$node;
                                }
                        }
 
                        $newChildNameToNode = array();
-                       // Add the new child nodes
+                       // Create and add the new node objects for all child 
categories
                        foreach ( $childList as $childPageId => $childInfo ) {
                                $childNode = $this->getNodeForCatPageId( 
$childPageId );
                                if ( !isset( $childNode ) ) {
@@ -193,6 +237,112 @@
                        // Prepare for the next loop
                        $parentNameToNode = $newChildNameToNode;
                        $catNames = array_keys( $parentNameToNode );
+                       $currDepth++;
                }
        }
+       
+       /** Retrieve a list of child categories for all the given category names
+        * Uses the cache if enabled
+        * @param $catNames Array: List of category names
+        * @return Mixed: Array of Maps with keys: parName, childId, childName
+        */
+       protected function getChildCategories( $catNames ) {
+               global $wgMemc;
+               $dbr = wfGetDB( DB_SLAVE );
+               $childList = array();
+               $nonCachedCatNames = array();
+               // Try cache first
+               if( $this->cacheEnabled ) {
+                       foreach( $catNames as $catName ) {
+                               $key = wfMemcKey( self::CACHE_KEY, 
self::CACHE_KEY_CHILDCATEGORIES, $catName );
+                               $res = $wgMemc->get( $key );
+                               if( $res != '' ) {
+                                       $childList = array_merge( $childList, 
$res );
+                               } else {
+                                       $nonCachedCatNames[$catName] = false;
+                               }
+                       }
+               } else {
+                       $nonCachedCatNames = array_fill_keys( $catNames, false 
);
+               }
+
+               // Select the child categories of all categories we have not 
found in the cache
+               $res = array();
+               if( !empty( $nonCachedCatNames ) ) {
+                       // Select the direct child categories of all category 
names
+                       // I.e. category name, child category id and child 
category name
+                       $res = $dbr->select( array( 'categorylinks', 'page' ), 
# Tables
+                               array( 'cl_to AS parName', 'cl_from AS 
childId', 'page_title AS childName' ), # Fields
+                               array( 'cl_to' => 
array_keys($nonCachedCatNames), 'page_namespace' => NS_CATEGORY ),  # Conditions
+                               __METHOD__, array( 'GROUP BY' => 'cl_to' ), # 
Options
+                               array( 'page' => array( 'JOIN', 'page_id = 
cl_from' ) ) # Join conditions
+                       );
+               }
+               
+               // Prepare and store cache objects
+               $cacheObj = array();
+               foreach ( $res as $row ) {
+                       unset($nonCachedCatNames[$row->parName]);
+                       if( !isset( $currCatName ) )
+                               $currCatName = $row->parName;
+                       if( $currCatName != $row->parName ) {
+                               $key = wfMemcKey( self::CACHE_KEY, 
self::CACHE_KEY_CHILDCATEGORIES, $currCatName );
+                               $wgMemc->set( $key, $cacheObj, 
$this->cacheDurationSec );
+                               $childList = array_merge( $childList, $cacheObj 
);
+                               $cacheObj = array();
+                               $currCatName = $row->parName;
+                       }
+                       $cacheObj[] = array( 'parName' => $row->parName, 
'childId' => $row->childId, 'childName' => $row->childName );
+               }
+               // Store the last bunch
+               if( !empty( $cacheObj ) ) {
+                       $key = wfMemcKey( self::CACHE_KEY, 
self::CACHE_KEY_CHILDCATEGORIES, $currCatName );
+                       $wgMemc->set( $key, $cacheObj, $this->cacheDurationSec 
);
+                       $childList = array_merge( $childList, $cacheObj );
+               }
+               // Store empty values for leaf categories, otherwise we would 
query the DB because we did not find a cache entry
+               foreach( array_keys($nonCachedCatNames ) as $currCatName ) {
+                       $key = wfMemcKey( self::CACHE_KEY, 
self::CACHE_KEY_CHILDCATEGORIES, $currCatName );
+                       $wgMemc->set( $key, array(), $this->cacheDurationSec );
+               }
+               return $childList;
+       }
+       
+       /** Retrieve the page ids of the category pages for the given categories
+        * 
+        * @param $catNames Array: A list of category names you would like to 
query for
+        * @return Array: An array of maps with keys: page_id, page_title
+        */
+       protected function getCategoryPageIds( $catNames ) {
+               global $wgMemc;
+               $dbr = wfGetDB( DB_SLAVE );
+               $pageInfo = array();
+               $nonCachedCatNames = array();
+               // Try cache first
+               if( $this->cacheEnabled ) {
+                       foreach( $catNames as $catName ) {
+                               $res = $wgMemc->get( wfMemcKey( 
self::CACHE_KEY, self::CACHE_KEY_CATEGORYPAGEID, $catName ) );
+                               if( $res != '' ) {
+                                       $pageInfo[] = array( 'page_id' => $res, 
'page_title' => $catName );
+                               } else {
+                                       $nonCachedCatNames[] = $catName;
+                               }
+                       }
+               }
+               // Select the child categories of all categories we have not 
found in the cache
+               $res = array();
+               if( !empty( $nonCachedCatNames ) ) {
+                       $res = $dbr->select( array( 'page' ), # Tables
+                               array( 'page_id, page_title' ), # Fields
+                               array( 'page_title' => $nonCachedCatNames )  # 
Conditions
+                       );
+               }
+               // Prepare and store cache object
+               foreach ( $res as $row ) {
+                       $pageInfo[] = array( 'page_id' => $row->page_id, 
'page_title' => $row->page_title );
+                       $wgMemc->set( wfMemcKey( self::CACHE_KEY, 
self::CACHE_KEY_CATEGORYPAGEID, $row->page_title ), $row->page_id, 
$this->cacheDurationSec );
+               }
+               return $pageInfo;
+       }
+
 }

Modified: trunk/extensions/CollabWatchlist/includes/CollabWatchlistEditor.php
===================================================================
--- trunk/extensions/CollabWatchlist/includes/CollabWatchlistEditor.php 
2011-08-02 16:48:14 UTC (rev 93768)
+++ trunk/extensions/CollabWatchlist/includes/CollabWatchlistEditor.php 
2011-08-02 16:56:29 UTC (rev 93769)
@@ -789,8 +789,8 @@
                                }
                        }
                        // Add the tagged revisions to the collaborative 
watchlist
-                       $sql = 'INSERT IGNORE INTO collabwatchlistrevisiontag 
(ct_id, rl_id, user_id, rrt_comment)
-                                       SELECT ct_id, ' . $dbw->strencode( 
$rlId ) . ',' .
+                       $sql = 'INSERT IGNORE INTO collabwatchlistrevisiontag 
(ct_rc_id, ct_tag, rl_id, user_id, rrt_comment)
+                                       SELECT ct_rc_id, ct_tag, ' . 
$dbw->strencode( $rlId ) . ',' .
                                                $dbw->strencode( $userId ) . 
',' .
                                                $dbw->addQuotes( $comment ) . ' 
FROM change_tag WHERE ct_tag = ? AND ct_rc_id ';
                        if ( count( $rcIds ) > 1 ) {
@@ -817,9 +817,7 @@
                                $rcIds[] = $info['rc_id'];
                        }
                        // Remove the tag from the collaborative watchlist
-                       $sql = 'delete collabwatchlistrevisiontag from 
collabwatchlistrevisiontag JOIN change_tag
-                                       ON change_tag.ct_id = 
collabwatchlistrevisiontag.ct_id
-                                       WHERE ct_tag = ? AND ct_rc_id ';
+                       $sql = 'DELETE FROM collabwatchlistrevisiontag WHERE 
ct_tag = ? AND ct_rc_id ';
                        if ( count( $rcIds ) > 1 ) {
                                $sql .= 'IN (' . $dbw->makeList( $rcIds ) . ')';
                                $params = array( $tag );

Modified: trunk/extensions/CollabWatchlist/includes/SpecialCollabWatchlist.php
===================================================================
--- trunk/extensions/CollabWatchlist/includes/SpecialCollabWatchlist.php        
2011-08-02 16:48:14 UTC (rev 93768)
+++ trunk/extensions/CollabWatchlist/includes/SpecialCollabWatchlist.php        
2011-08-02 16:56:29 UTC (rev 93769)
@@ -260,9 +260,8 @@
                        } else {
                                $filter = 'NOT EXISTS ';
                        }
-                       $filter .= '(select ct_rc_id from change_tag
-                                       JOIN collabwatchlistrevisiontag ON 
collabwatchlistrevisiontag.ct_id = change_tag.ct_id
-                                       WHERE ct_rc_id = recentchanges.rc_id 
AND ct_tag ';
+                       $filter .= '(SELECT cwlrt.ct_rc_id FROM 
collabwatchlistrevisiontag cwlrt
+                                       WHERE cwlrt.ct_rc_id = 
recentchanges.rc_id AND cwlrt.ct_tag ';
                        if ( count( $tagFilter ) > 1 )
                                $filter .= 'IN (' . $dbr->makeList( $tagFilter 
) . '))';
                        else
@@ -582,11 +581,11 @@
                }
                // $table, $vars, $conds='', $fname = 'Database::select', 
$options = array(), $join_conds = array()
                $res = $dbr->select( array( 'change_tag', 
'collabwatchlistrevisiontag', 'user' ), # Tables
-                       array( 'rl_id', 'ct_tag', 
'collabwatchlistrevisiontag.user_id', 'user_name', 'rrt_comment' ), # Fields
-                       array( 'ct_rev_id' => $rev_id ) + $cond,  # Conditions
+                       array( 'rl_id', 'collabwatchlistrevisiontag.ct_tag', 
'collabwatchlistrevisiontag.user_id', 'user_name', 'rrt_comment' ), # Fields
+                       array( 'change_tag.ct_rev_id' => $rev_id ) + $cond,  # 
Conditions
                        __METHOD__, array(),
                         # Join conditions
-                       array(  'collabwatchlistrevisiontag' => array( 'JOIN', 
'change_tag.ct_id = collabwatchlistrevisiontag.ct_id' ),
+                       array(  'collabwatchlistrevisiontag' => array( 'JOIN', 
'change_tag.ct_rc_id = collabwatchlistrevisiontag.ct_rc_id AND 
change_tag.ct_tag = collabwatchlistrevisiontag.ct_tag' ),
                                        'user' => array( 'JOIN', 
'collabwatchlistrevisiontag.user_id = user.user_id' )
                        )
                );
@@ -608,6 +607,7 @@
         * @return String: An SQL clause usable in the conditions parameter of 
$db->select()
         */
        function wlGetFilterClauseForCollabWatchlistIds( $rl_ids, $catNameCol, 
$pageIdCol ) {
+               global $wgCollabWatchlistRecursiveCatScan;
                $excludedCatPageIds = array();
                $includedCatPageIds = array();
                $includedPageIds = array();
@@ -632,8 +632,9 @@
                        }
                }
                
-               if ( $includedCatPageIds ) {
+               if ( $wgCollabWatchlistRecursiveCatScan && $includedCatPageIds 
) {
                        $catTree = new CategoryTreeManip();
+                       
$catTree->setMaxDepth($wgCollabWatchlistRecursiveCatScan);
                        $catTree->initialiseFromCategoryNames( array_values( 
$includedCatPageIds ) );
                        $catTree->disableCategoryIds( array_keys( 
$excludedCatPageIds ) );
                        $enabledCategoryNames = 
$catTree->getEnabledCategoryNames();

Modified: trunk/extensions/CollabWatchlist/sql/collabwatchlistrevisiontag.sql
===================================================================
--- trunk/extensions/CollabWatchlist/sql/collabwatchlistrevisiontag.sql 
2011-08-02 16:48:14 UTC (rev 93768)
+++ trunk/extensions/CollabWatchlist/sql/collabwatchlistrevisiontag.sql 
2011-08-02 16:56:29 UTC (rev 93769)
@@ -7,8 +7,10 @@
 CREATE TABLE IF NOT EXISTS /*$wgDBprefix*/collabwatchlistrevisiontag (
   -- The id of this entry
   rrt_id integer unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT,
-  -- Foreign key to change_tag.ct_id
-  ct_id integer unsigned NOT NULL,
+  -- See change_tag.ct_tag
+  ct_tag varbinary(255) NOT NULL,
+  -- See change_tag.ct_rc_id
+  ct_rc_id int NOT NULL default 0,
   -- Foreign key to collabwatchlist.rl_id
   rl_id integer unsigned NOT NULL,
   -- Foreign key to user.user_id
@@ -17,5 +19,5 @@
   -- Comment for the tag
   rrt_comment varchar(255),
   
-  UNIQUE KEY (ct_id, rl_id)
-) /*$wgDBTableOptions*/;
\ No newline at end of file
+  UNIQUE KEY (ct_tag, ct_rc_id, rl_id)
+) /*$wgDBTableOptions*/;

Deleted: trunk/extensions/CollabWatchlist/sql/patch-change_tag_id.sql
===================================================================
--- trunk/extensions/CollabWatchlist/sql/patch-change_tag_id.sql        
2011-08-02 16:48:14 UTC (rev 93768)
+++ trunk/extensions/CollabWatchlist/sql/patch-change_tag_id.sql        
2011-08-02 16:56:29 UTC (rev 93769)
@@ -1,5 +0,0 @@
--- Add a primary key to the change_tag table in order
--- to enable us to build the review list extension
-
-ALTER TABLE /*$wgDBprefix*/change_tag
-  ADD ct_id integer unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT;
\ No newline at end of file

Added: trunk/extensions/CollabWatchlist/sql/patch-collabwatchlist_noctid.sql
===================================================================
--- trunk/extensions/CollabWatchlist/sql/patch-collabwatchlist_noctid.sql       
                        (rev 0)
+++ trunk/extensions/CollabWatchlist/sql/patch-collabwatchlist_noctid.sql       
2011-08-02 16:56:29 UTC (rev 93769)
@@ -0,0 +1,11 @@
+-- Remove the ct_id column which was introduced in a previous revision
+-- This is intended to be used manually as there does not seem to be
+-- support
+
+ALTER TABLE /*$wgDBprefix*/collabwatchlistrevisiontag
+  ADD ct_tag varbinary(255) NOT NULL;
+ALTER TABLE /*$wgDBprefix*/collabwatchlistrevisiontag
+  ADD ct_rc_id int NOT NULL default 0;
+UPDATE /*$wgDBprefix*/collabwatchlistrevisiontag cwlrt set ct_rc_id = (select 
ct.ct_rc_id from change_tag ct where ct.ct_id = cwlrt.ct_id), ct_tag = (select 
ct.ct_tag from change_tag ct where ct.ct_id = cwlrt.ct_id);
+ALTER TABLE /*$wgDBprefix*/change_tag
+  DROP ct_id;


Property changes on: 
trunk/extensions/CollabWatchlist/sql/patch-collabwatchlist_noctid.sql
___________________________________________________________________
Added: svn:eol-style
   + native

Added: trunk/extensions/CollabWatchlist/tests/CollabWatchlistTest.php
===================================================================
--- trunk/extensions/CollabWatchlist/tests/CollabWatchlistTest.php              
                (rev 0)
+++ trunk/extensions/CollabWatchlist/tests/CollabWatchlistTest.php      
2011-08-02 16:56:29 UTC (rev 93769)
@@ -0,0 +1,11 @@
+<?php
+
+class CollabWatchlistTest extends PHPUnit_Framework_TestCase {
+       public function testCategoryTree() {
+               $catTree = new CategoryTreeManip();
+               $catNames = array( 'Test', 'Category:Root' );
+               $catTree->initialiseFromCategoryNames( $catNames );
+               //var_dump( $catTree->getEnabledCategoryNames() );
+               $catTree->printTree();
+       }
+}


Property changes on: 
trunk/extensions/CollabWatchlist/tests/CollabWatchlistTest.php
___________________________________________________________________
Added: svn:eol-style
   + native


_______________________________________________
MediaWiki-CVS mailing list
MediaWiki-CVS@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-cvs

Reply via email to