-136 lines of worthless code. Even if the idea was hypothetically good, which I...
authorAryeh Gregor <simetrical@users.mediawiki.org>
Thu, 22 May 2008 17:24:46 +0000 (17:24 +0000)
committerAryeh Gregor <simetrical@users.mediawiki.org>
Thu, 22 May 2008 17:24:46 +0000 (17:24 +0000)
includes/AutoLoader.php
includes/Category.php

index 56881c1..5ba5fb8 100644 (file)
@@ -27,7 +27,6 @@ function __autoload($className) {
                'BrokenRedirectsPage' => 'includes/SpecialBrokenRedirects.php',
                'Category' => 'includes/Category.php',
                'Categoryfinder' => 'includes/Categoryfinder.php',
-               'CategoryList' => 'includes/Category.php',
                'CategoryPage' => 'includes/CategoryPage.php',
                'CategoryViewer' => 'includes/CategoryPage.php',
                'ChangesList' => 'includes/ChangesList.php',
index 15e56b1..f386bee 100644 (file)
 <?php
 /**
- * Two classes, Category and CategoryList, to deal with categories.  To reduce
- * code duplication, most of the logic is implemented for lists of categories,
- * and then single categories are a special case.  We use a separate class for
- * CategoryList so as to discourage stupid slow memory-hogging stuff like manu-
- * ally iterating through arrays of Titles and Articles, which we do way too
- * much, when a smarter class can do stuff all in one query.
- *
- * Category(List) objects are immutable, strictly speaking.  If you call me-
- * thods that change the database, like to refresh link counts, the objects
- * will be appropriately reinitialized.  Member variables are lazy-initialized.
+ * Category objects are immutable, strictly speaking.  If you call methods that change the database, like to refresh link counts, the objects will be appropriately reinitialized.  Member variables are lazy-initialized.
  *
  * TODO: Move some stuff from CategoryPage.php to here, and use that.
  *
  * @author Simetrical
  */
 
-abstract class CategoryListBase {
-       # FIXME: Is storing all member variables as simple arrays a good idea?
-       # Should we use some kind of associative array instead?
-       /** Names of all member categories, normalized to DB-key form */
-       protected $mNames = null;
-       /** IDs of all member categories */
-       protected $mIDs = null;
-       /**
-        * Counts of membership (cat_pages, cat_subcats, cat_files) for all member
-        * categories
-        */
-       protected $mPages = null, $mSubcats = null, $mFiles = null;
-
-       protected function __construct() {}
-
-       /** See CategoryList::newFromNames for details. */
-       protected function setNames( $names ) {
-               if( !is_array( $names ) ) {
-                       throw new MWException( __METHOD__.' passed non-array' );
-               }
-               $this->mNames = array_diff(
-                       array_map(
-                               array( 'CategoryListBase', 'setNamesCallback' ),
-                               $names
-                       ),
-                       array( false )
-               );
-       }
+class Category {
+       /** Name of the category, normalized to DB-key form */
+       private $mName = null;
+       private $mID = null;
+       /** Counts of membership (cat_pages, cat_subcats, cat_files) */
+       private $mPages = null, $mSubcats = null, $mFiles = null;
 
-       /**
-        * @param string $name Name of a putative category
-        * @return mixed Normalized name, or false if the name was invalid.
-        */
-       private static function setNamesCallback( $name ) {
-               $title = Title::newFromText( "Category:$name" );
-               if( !is_object( $title ) ) {
-                       return false;
-               }
-               return $title->getDBKey();
-       }
+       private function __construct() {}
 
        /**
         * Set up all member variables using a database query.
         * @return bool True on success, false on failure.
         */
        protected function initialize() {
-               if( $this->mNames === null && $this->mIDs === null ) {
+               if( $this->mName === null && $this->mID === null ) {
                        throw new MWException( __METHOD__.' has both names and IDs null' );
                }
                $dbr = wfGetDB( DB_SLAVE );
-               if( $this->mIDs === null ) {
-                       $where = array( 'cat_title' => $this->mNames );
-               } elseif( $this->mNames === null ) {
-                       $where = array( 'cat_id' => $this->mIDs );
+               if( $this->mID === null ) {
+                       $where = array( 'cat_title' => $this->mName );
+               } elseif( $this->mName === null ) {
+                       $where = array( 'cat_id' => $this->mID );
                } else {
                        # Already initialized
                        return true;
                }
-               $res = $dbr->select(
+               $row = $dbr->selectRow(
                        'category',
                        array( 'cat_id', 'cat_title', 'cat_pages', 'cat_subcats',
                                'cat_files' ),
                        $where,
                        __METHOD__
                );
-               if( !$res->fetchRow() ) {
+               if( !$row ) {
                        # Okay, there were no contents.  Nothing to initialize.
                        return false;
                }
-               $res->rewind();
-               $this->mIDs = $this->mNames = $this->mPages = $this->mSubcats =
-               $this->mFiles = array();
-               while( $row = $res->fetchRow() ) {
-                       $this->mIDs     []= $row['cat_id'];
-                       $this->mNames   []= $row['cat_title'];
-                       $this->mPages   []= $row['cat_pages'];
-                       $this->mSubcats []= $row['cat_subcats'];
-                       $this->mFiles   []= $row['cat_files'];
-               }
-               $res->free();
-       }
-}
+               $this->mID      = $row->cat_id;
+               $this->mName    = $row->cat_title;
+               $this->mPages   = $row->cat_pages;
+               $this->mSubcats = $row->cat_subcats;
+               $this->mFiles   = $row->cat_files;
 
-/** @todo make iterable. */
-class CategoryList extends CategoryListBase {
-       /**
-        * Factory function.  Any provided elements that don't correspond to a cat-
-        * egory that actually exists will be silently dropped.  FIXME: Is this
-        * sane error-handling?
-        *
-        * @param array $names An array of category names.  They need not be norma-
-        *   lized, with spaces replaced by underscores.
-        * @return CategoryList
-        */
-       public static function newFromNames( $names ) {
-               $cat = new self();
-               $cat->setNames( $names );
-               return $cat;
-       }
-
-       /**
-        * Factory function.  Any provided elements that don't correspond to a cat-
-        * egory that actually exists will be silently dropped.  FIXME: Is this
-        * sane error-handling?
-        *
-        * @param array $ids An array of category ids
-        * @return CategoryList
-        */
-       public static function newFromIDs( $ids ) {
-               if( !is_array( $ids ) ) {
-                       throw new MWException( __METHOD__.' passed non-array' );
+               # (bug 13683) If the count is negative, then 1) it's obviously wrong
+               # and should not be kept, and 2) we *probably* don't have to scan many
+               # rows to obtain the correct figure, so let's risk a one-time recount.
+               if( $this->mPages < 0 || $this->mSubcats < 0 ||
+               $this->mFiles < 0 ) {
+                       $this->refreshCounts();
                }
-               $cat = new self();
-               $cat->mIds = $ids;
-               return $cat;
-       }
 
-       /** @return array Simple array of DB key names */
-       public function getNames() {
-               $this->initialize();
-               return $this->mNames;
-       }
-       /**
-        * FIXME: Is this a good return type?
-        *
-        * @return array Associative array of DB key name => ID
-        */
-       public function getIDs() {
-               $this->initialize();
-               return array_fill_keys( $this->mNames, $this->mIDs );
-       }
-       /**
-        * FIXME: Is this a good return type?
-        *
-        * @return array Associative array of DB key name => array(pages, subcats,
-        *   files)
-        */
-       public function getCounts() {
-               $this->initialize();
-               $ret = array();
-               foreach( array_keys( $this->mNames ) as $i ) {
-                       $ret[$this->mNames[$i]] = array(
-                               $this->mPages[$i],
-                               $this->mSubcats[$i],
-                               $this->mFiles[$i]
-                       );
-               }
-               return $ret;
+               return true;
        }
-}
 
-class Category extends CategoryListBase {
        /**
         * Factory function.
         *
@@ -177,10 +70,12 @@ class Category extends CategoryListBase {
         */
        public static function newFromName( $name ) {
                $cat = new self();
-               $cat->setNames( array( $name ) );
-               if( count( $cat->mNames ) !== 1 ) {
+               $title = Title::newFromText( "Category:$name" );
+               if( !is_object( $title ) ) {
                        return false;
                }
+               $cat->mName = $title->getDBKey();
+
                return $cat;
        }
 
@@ -190,16 +85,16 @@ class Category extends CategoryListBase {
         * @param array $id A category id
         * @return Category
         */
-       public static function newFromIDs( $id ) {
+       public static function newFromID( $id ) {
                $cat = new self();
-               $cat->mIDs = array( $id );
+               $cat->mID = intval( $id );
                return $cat;
        }
 
        /** @return mixed DB key name, or false on failure */
-       public function getName() { return $this->getX( 'mNames' ); }
+       public function getName() { return $this->getX( 'mName' ); }
        /** @return mixed Category ID, or false on failure */
-       public function getID() { return $this->getX( 'mIDs' ); }
+       public function getID() { return $this->getX( 'mID' ); }
        /** @return mixed Total number of member pages, or false on failure */
        public function getPageCount() { return $this->getX( 'mPages' ); }
        /** @return mixed Number of subcategories, or false on failure */
@@ -208,16 +103,13 @@ class Category extends CategoryListBase {
        public function getFileCount() { return $this->getX( 'mFiles' ); }
 
        /**
-        * This is not implemented in the base class, because arrays of Titles are
-        * evil.
-        *
         * @return mixed The Title for this category, or false on failure.
         */
        public function getTitle() {
                if( !$this->initialize() ) {
                        return false;
                }
-               return Title::makeTitleSafe( NS_CATEGORY, $this->mNames[0] );
+               return Title::makeTitleSafe( NS_CATEGORY, $this->mName );
        }
 
        /** Generic accessor */
@@ -225,39 +117,12 @@ class Category extends CategoryListBase {
                if( !$this->initialize() ) {
                        return false;
                }
-               return $this->{$key}[0];
-       }
-
-       /**
-        * Override the parent class so that we can return false if things muck
-        * up, i.e., the name/ID we got was invalid.  Currently CategoryList si-
-        * lently eats errors so as not to kill the whole array for one bad name.
-        *
-        * @return bool True on success, false on failure.
-        */
-       protected function initialize() {
-               parent::initialize();
-
-               # (bug 13683) If the count is negative, then 1) it's obviously wrong
-               # and should not be kept, and 2) we *probably* don't have to scan many
-               # rows to obtain the correct figure, so let's risk a one-time recount.
-               if( $this->mPages[0] < 0 || $this->mSubcats[0] < 0 ||
-               $this->mFiles[0] < 0 ) {
-                       $this->refreshCounts();
-               }
-
-               if( count( $this->mNames ) != 1 || count( $this->mIDs ) != 1 ) {
-                       return false;
-               }
-               return true;
+               return $this->{$key};
        }
 
        /**
         * Refresh the counts for this category.
         *
-        * FIXME: If there were some way to do this in MySQL 4 without an UPDATE
-        * for every row, it would be nice to move this to the parent class.
-        *
         * @return bool True on success, false on failure
         */
        public function refreshCounts() {
@@ -267,7 +132,7 @@ class Category extends CategoryListBase {
                $dbw = wfGetDB( DB_MASTER );
                $dbw->begin();
                # Note, we must use names for this, since categorylinks does.
-               if( $this->mNames === null ) {
+               if( $this->mName === null ) {
                        if( !$this->initialize() ) {
                                return false;
                        }
@@ -276,7 +141,7 @@ class Category extends CategoryListBase {
                        # do this if we got the row from the table in initialization!
                        $dbw->insert(
                                'category',
-                               array( 'cat_title' => $this->mNames[0] ),
+                               array( 'cat_title' => $this->mName ),
                                __METHOD__,
                                'IGNORE'
                        );
@@ -290,7 +155,7 @@ class Category extends CategoryListBase {
                                   "COUNT($cond1) AS subcats",
                                   "COUNT($cond2) AS files"
                        ),
-                       array( 'cl_to' => $this->mNames[0], 'page_id = cl_from' ),
+                       array( 'cl_to' => $this->mName, 'page_id = cl_from' ),
                        __METHOD__,
                        'LOCK IN SHARE MODE'
                );
@@ -301,15 +166,15 @@ class Category extends CategoryListBase {
                                'cat_subcats' => $result->subcats,
                                'cat_files' => $result->files
                        ),
-                       array( 'cat_title' => $this->mNames[0] ),
+                       array( 'cat_title' => $this->mName ),
                        __METHOD__
                );
                $dbw->commit();
 
                # Now we should update our local counts.
-               $this->mPages   = array( $result->pages );
-               $this->mSubcats = array( $result->subcats );
-               $this->mFiles   = array( $result->files );
+               $this->mPages   = $result->pages;
+               $this->mSubcats = $result->subcats;
+               $this->mFiles   = $result->files;
 
                return $ret;
        }