C. Scott Ananian has uploaded a new change for review. ( 
https://gerrit.wikimedia.org/r/403318 )

Change subject: Always return some category name, even if it's just a 
placeholder
......................................................................

Always return some category name, even if it's just a placeholder

This further decouples Parsoid deploys of new linter categories from
Linter extension deploys which name them.  If Parsoid logs lints from
an as-yet-unknown category, we will just give them the special temporary
name LINT@nnn with the numeric db identifier.  This allows the API and
UX to query/display/etc them with this placeholder name while we are
waiting for the "official" name/l10n/etc to be deployed.

Add some new methods to allow enumerating all category ids from the
database, even those which aren't yet officially named.

Change-Id: Ic917fa3abb61d2f784d839f8f9e5e866640d2d4d
---
M i18n/en.json
M i18n/qqq.json
M includes/ApiQueryLintErrors.php
M includes/CategoryManager.php
M includes/Database.php
M includes/SpecialLintErrors.php
M includes/TotalsLookup.php
7 files changed, 101 insertions(+), 25 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Linter 
refs/changes/18/403318/1

diff --git a/i18n/en.json b/i18n/en.json
index 2ef9756..07a34ba 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -68,6 +68,7 @@
        "linter-heading-high-priority": "High priority",
        "linter-heading-medium-priority": "Medium priority",
        "linter-heading-low-priority": "Low priority",
+       "linter-heading-placeholder-priority": "Not yet categorized",
        "multi-part-template-block": "Output not from a single template",
        "pageinfo-linter": "Lint errors",
        "apihelp-query+linterrors-description": "Get a list of lint errors",
diff --git a/i18n/qqq.json b/i18n/qqq.json
index a650798..3ccaa5b 100644
--- a/i18n/qqq.json
+++ b/i18n/qqq.json
@@ -72,6 +72,7 @@
        "linter-heading-high-priority": "Heading on [[Special:LintErrors]]",
        "linter-heading-medium-priority": "Heading on [[Special:LintErrors]]",
        "linter-heading-low-priority": "Heading on [[Special:LintErrors]]",
+       "linter-heading-placeholder-priority": "Heading on 
[[Special:LintErrors]]",
        "multi-part-template-block": "Table cell on [[Special:LintErrors]] 
indicating that content block is not produced by a single template",
        "pageinfo-linter": "Heading on ?action=info for a page if it has lint 
errors",
        "apihelp-query+linterrors-description": 
"{{doc-apihelp-description|query+linterrors}}",
diff --git a/includes/ApiQueryLintErrors.php b/includes/ApiQueryLintErrors.php
index f057c0c..62f5976 100644
--- a/includes/ApiQueryLintErrors.php
+++ b/includes/ApiQueryLintErrors.php
@@ -98,13 +98,18 @@
        }
 
        public function getAllowedParams() {
-               $visibleCats = ( new CategoryManager() 
)->getVisibleCategories();
+               $categoryMgr = new CategoryManager();
+               $visibleCats = $categoryMgr->getVisibleCategories();
+               $placeholderCats = $categoryMgr->getPlaceholderCategories(
+                       $this->getDB()
+               );
+               $allCats = array_merge($visibleCats, $placeholderCats);
                return [
                        'categories' => [
-                               ApiBase::PARAM_TYPE => $visibleCats,
+                               ApiBase::PARAM_TYPE => $allCats,
                                ApiBase::PARAM_ISMULTI => true,
                                // Default is to show all categories
-                               ApiBase::PARAM_DFLT => implode( '|', 
$visibleCats ),
+                               ApiBase::PARAM_DFLT => implode( '|', $allCats ),
                        ],
                        'limit' => [
                                ApiBase::PARAM_DFLT => 10,
diff --git a/includes/CategoryManager.php b/includes/CategoryManager.php
index 6d1256d..bb1bb6d 100644
--- a/includes/CategoryManager.php
+++ b/includes/CategoryManager.php
@@ -56,6 +56,21 @@
         */
        private $hasNameParam = [];
 
+       /**
+        * Special form for "numeric category" names, a special form which 
allows
+        * naming/querying new Parsoid categories prior to the Linter extension
+        * being updated with information about them.
+        *
+        * @var string
+        */
+       const NUMERIC_CATID_PREFIX = 'LINT@';
+       /**
+        * A regexp to rest for "numeric category" names.
+        *
+        * @var string
+        */
+       const NUMERIC_CATID_REGEX = '/^' . self::NUMERIC_CATID_PREFIX . 
'([0-9]+)$/';
+
        public function __construct() {
                global $wgLinterCategories;
                foreach ( $wgLinterCategories as $name => $info ) {
@@ -124,8 +139,52 @@
        }
 
        /**
-        * Whether this category has a hardcoded id and can be
-        * inserted into the database
+        * Categories present in the database which are not yet given
+        * official names or l10n by the Linter extension.
+        *
+        * @param IDatabase $db
+        * @return string[]
+        */
+       public function getPlaceholderCategories( $db ) {
+               return array_diff(
+                       $this->getDatabaseCategories( $db ),
+                       $this->getVisibleCategories()
+               );
+       }
+
+       /**
+        * All categories, prioritized or not.
+        *
+        * @param IDatabase $db
+        * @return string[]
+        */
+       public function getAllCategories ( $db ) {
+               return array_merge(
+                       $this->getVisibleCategories(),
+                       $this->getPlaceholderCategories( $db )
+               );
+       }
+
+       /**
+        * All categories present in the database.
+        *
+        * @param IDatabase $db
+        * @return string[]
+        */
+       public function getDatabaseCategories( $db ) {
+               $rows = $db->select( 'linter', ['linter_cat'], [], __METHOD__, [
+                       'DISTINCT',
+                       'ORDER BY' => 'linter_cat'
+               ], [] );
+               $cats = [];
+               foreach ( $rows as $row ) {
+                       $cats[] = $this->getCategoryName( $row->linter_cat );
+               }
+               return $cats;
+       }
+
+       /**
+        * Whether this category has a known category id
         *
         * @param string $name
         * @return bool
@@ -135,8 +194,10 @@
        }
 
        /**
+        * Returns the category name, or a special "numeric category" name if
+        * the linter extension does not (yet) know about this category id.
+        *
         * @param int $id
-        * @throws MissingCategoryException if we can't find the name for the id
         * @return string
         */
        public function getCategoryName( $id ) {
@@ -145,7 +206,7 @@
                        return $flip[$id];
                }
 
-               throw new MissingCategoryException( "Could not find name for id 
$id" );
+               return self::NUMERIC_CATID_PREFIX . $id;
        }
 
        /**
@@ -179,6 +240,15 @@
                        return $this->categoryIds[$name];
                }
 
+               // Names in a special "LINT@NNN" form are special; they map 
directly
+               // to category ID <NNN>.  This allows use of the API to query 
for
+               // these lints even before the Linter extension knows a proper
+               // name for them, and they'll show up in the UI under this 
temporary
+               // category name as well.
+               if ( preg_match( self::NUMERIC_CATID_REGEX, $name, $matches ) ) 
{
+                       return (int)$matches[1];
+               }
+
                // Use hint from Parsoid, if available.
                if ( $hint !== null ) {
                        return $hint;
diff --git a/includes/Database.php b/includes/Database.php
index 0febbdd..65b7af6 100644
--- a/includes/Database.php
+++ b/includes/Database.php
@@ -81,15 +81,7 @@
         * @return LintError|bool false on error
         */
        public static function makeLintError( $row ) {
-               try {
-                       $name = ( new CategoryManager() )->getCategoryName( 
$row->linter_cat );
-               } catch ( MissingCategoryException $e ) {
-                       LoggerFactory::getInstance( 'Linter' )->error(
-                               'Could not find name for id: {linter_cat}',
-                               [ 'linter_cat' => $row->linter_cat ]
-                       );
-                       return false;
-               }
+               $name = ( new CategoryManager() )->getCategoryName( 
$row->linter_cat );
                return new LintError(
                        $name,
                        [ (int)$row->linter_start, (int)$row->linter_end ],
@@ -250,11 +242,7 @@
                // Initialize zero values
                $ret = array_fill_keys( 
$this->categoryManager->getVisibleCategories(), 0 );
                foreach ( $rows as $row ) {
-                       try {
-                               $catName = 
$this->categoryManager->getCategoryName( $row->linter_cat );
-                       } catch ( MissingCategoryException $e ) {
-                               continue;
-                       }
+                       $catName = $this->categoryManager->getCategoryName( 
$row->linter_cat );
                        $ret[$catName] = (int)$row->count;
                }
 
diff --git a/includes/SpecialLintErrors.php b/includes/SpecialLintErrors.php
index 2f33fab..951140a 100644
--- a/includes/SpecialLintErrors.php
+++ b/includes/SpecialLintErrors.php
@@ -58,6 +58,8 @@
                $catManager = new CategoryManager();
                if ( in_array( $par, $catManager->getVisibleCategories() ) ) {
                        $this->category = $par;
+               } else if ( preg_match( CategoryManager::NUMERIC_CATID_REGEX, 
$par, $m ) ) {
+                       $this->category = $catManager->getCategoryName( 
(int)$m[1] );
                }
 
                if ( !$this->category ) {
@@ -105,6 +107,13 @@
                $this->displayList( 'high', $totals, 
$catManager->getHighPriority() );
                $this->displayList( 'medium', $totals, 
$catManager->getMediumPriority() );
                $this->displayList( 'low', $totals, 
$catManager->getLowPriority() );
+
+               // Are there any uncategorized issues in the DB?
+               $placeholderCats =
+                       $catManager->getPlaceholderCategories( wfGetDB( 
DB_REPLICA ) );
+               if ( count($placeholderCats) > 0 ) {
+                       $this->displayList( 'placeholder', $totals, 
$placeholderCats );
+               }
        }
 
        /**
@@ -133,7 +142,8 @@
        }
 
        protected function getSubpagesForPrefixSearch() {
-               return ( new CategoryManager() )->getVisibleCategories();
+               $db = wfGetDB( DB_REPLICA );
+               return ( new CategoryManager() )->getAllCategories( $db );
        }
 
 }
diff --git a/includes/TotalsLookup.php b/includes/TotalsLookup.php
index 386b3ee..6bab88f 100644
--- a/includes/TotalsLookup.php
+++ b/includes/TotalsLookup.php
@@ -58,15 +58,16 @@
         * @return array
         */
        public function getTotals() {
-               $cats = $this->catManager->getVisibleCategories();
+               $db = wfGetDB( DB_REPLICA );
+               $cats = $this->catManager->getAllCategories( $db );
                $fetchedTotals = false;
                $totals = [];
                foreach ( $cats as $cat ) {
                        $totals[$cat] = $this->cache->getWithSetCallback(
                                $this->makeKey( $cat ),
                                WANObjectCache::TTL_INDEFINITE,
-                               function ( $oldValue, &$ttl, &$setOpts, 
$oldAsOf ) use ( $cat, &$fetchedTotals ) {
-                                       $setOpts += 
MWDatabase::getCacheSetOptions( wfGetDB( DB_REPLICA ) );
+                               function ( $oldValue, &$ttl, &$setOpts, 
$oldAsOf ) use ( $db, $cat, &$fetchedTotals ) {
+                                       $setOpts += 
MWDatabase::getCacheSetOptions( $db );
                                        if ( $fetchedTotals === false ) {
                                                $fetchedTotals = ( new 
Database( 0 ) )->getTotals();
                                        }

-- 
To view, visit https://gerrit.wikimedia.org/r/403318
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ic917fa3abb61d2f784d839f8f9e5e866640d2d4d
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/Linter
Gerrit-Branch: master
Gerrit-Owner: C. Scott Ananian <canan...@wikimedia.org>

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

Reply via email to