Linter: Display lint errors for a single page

* Added error message when namespace and/or pagename is not
  found or malformed which now displays a bold red message.

Bug: T151362
Change-Id: I70fde2676ded6a112f7f2b07f94f6f4b616f0e39
This commit is contained in:
sbailey 2021-09-30 16:20:01 -07:00
parent af53fbc23a
commit 88aab3cd1e
4 changed files with 108 additions and 14 deletions

View file

@ -44,6 +44,8 @@
"linter-category-wikilink-in-extlink": "Links in links", "linter-category-wikilink-in-extlink": "Links in links",
"linter-category-wikilink-in-extlink-desc": "These pages have wikilinks in external links that could be fixed", "linter-category-wikilink-in-extlink-desc": "These pages have wikilinks in external links that could be fixed",
"linter-desc": "Track lint errors from an external service and show them to users", "linter-desc": "Track lint errors from an external service and show them to users",
"linter-lints-for-single-page-desc": "Show all linter errors for a specific page",
"linter-invalid-title": "Namespace and/or pagename not found or malformed",
"linter-form-namespace": "Namespace:", "linter-form-namespace": "Namespace:",
"linter-heading-high-priority": "High priority", "linter-heading-high-priority": "High priority",
"linter-heading-low-priority": "Low priority", "linter-heading-low-priority": "Low priority",

View file

@ -49,6 +49,8 @@
"linter-category-wikilink-in-extlink": "Name of lint error category. See [[:mw:Help:Lint errors/wikilink-in-extlink]]", "linter-category-wikilink-in-extlink": "Name of lint error category. See [[:mw:Help:Lint errors/wikilink-in-extlink]]",
"linter-category-wikilink-in-extlink-desc": "Description of category\n\nSimilar messages:\n* {{msg-mw|Linter-category-bogus-image-options-desc}}\n* {{msg-mw|Linter-category-deletable-table-tag-desc}}\n* {{msg-mw|Linter-category-fostered-desc}}\netc.", "linter-category-wikilink-in-extlink-desc": "Description of category\n\nSimilar messages:\n* {{msg-mw|Linter-category-bogus-image-options-desc}}\n* {{msg-mw|Linter-category-deletable-table-tag-desc}}\n* {{msg-mw|Linter-category-fostered-desc}}\netc.",
"linter-desc": "{{desc|name=Linter|url=https://www.mediawiki.org/wiki/Extension:Linter}}", "linter-desc": "{{desc|name=Linter|url=https://www.mediawiki.org/wiki/Extension:Linter}}",
"linter-lints-for-single-page-desc": "Heading for form section that allows user to show all linter errors for a specific page",
"linter-invalid-title": "Error message for linter for single page - not found or malformed namespace and-or pagename",
"linter-form-namespace": "Label for select field on Special:LintErrors\n{{Identical|Namespace}}", "linter-form-namespace": "Label for select field on Special:LintErrors\n{{Identical|Namespace}}",
"linter-heading-high-priority": "Heading on [[Special:LintErrors]]", "linter-heading-high-priority": "Heading on [[Special:LintErrors]]",
"linter-heading-low-priority": "Heading on [[Special:LintErrors]]", "linter-heading-low-priority": "Heading on [[Special:LintErrors]]",

View file

@ -68,20 +68,32 @@ class LintErrorsPager extends TablePager {
*/ */
private $invertnamespace; private $invertnamespace;
/**
* @var int|null
*/
private $pageId;
/** /**
* @param IContextSource $context * @param IContextSource $context
* @param string $category * @param string|null $category
* @param LinkRenderer $linkRenderer * @param LinkRenderer $linkRenderer
* @param CategoryManager $catManager * @param CategoryManager $catManager
* @param int|null $namespace * @param int|null $namespace
* @param bool $invertnamespace * @param bool $invertnamespace
* @param int|null $pageId
*/ */
public function __construct( IContextSource $context, $category, LinkRenderer $linkRenderer, public function __construct( IContextSource $context, $category, LinkRenderer $linkRenderer,
CategoryManager $catManager, $namespace, $invertnamespace CategoryManager $catManager, $namespace, $invertnamespace, $pageId = null
) { ) {
$this->category = $category; $this->category = $category;
$this->categoryManager = $catManager; $this->categoryManager = $catManager;
$this->categoryId = $catManager->getCategoryId( $this->category ); if ( $category !== null ) {
$this->categoryId = $catManager->getCategoryId( $this->category );
$this->pageId = null;
} else {
$this->categoryId = null;
$this->pageId = $pageId;
}
$this->linkRenderer = $linkRenderer; $this->linkRenderer = $linkRenderer;
$this->namespace = $namespace; $this->namespace = $namespace;
$this->invertnamespace = $invertnamespace; $this->invertnamespace = $invertnamespace;
@ -91,7 +103,11 @@ class LintErrorsPager extends TablePager {
/** @inheritDoc */ /** @inheritDoc */
public function getQueryInfo() { public function getQueryInfo() {
$conds = [ 'linter_cat' => $this->categoryId ]; if ( $this->categoryId !== null ) {
$conds = [ 'linter_cat' => $this->categoryId ];
} else {
$conds = [ 'linter_page' => $this->pageId ];
}
if ( $this->namespace !== null ) { if ( $this->namespace !== null ) {
$eq_op = $this->invertnamespace ? '!=' : '='; $eq_op = $this->invertnamespace ? '!=' : '=';
$conds[] = "page_namespace $eq_op " . $this->mDb->addQuotes( $this->namespace ); $conds[] = "page_namespace $eq_op " . $this->mDb->addQuotes( $this->namespace );
@ -104,6 +120,7 @@ class LintErrorsPager extends TablePager {
'page_namespace', 'page_title', 'page_namespace', 'page_title',
'linter_id', 'linter_params', 'linter_id', 'linter_params',
'linter_start', 'linter_end', 'linter_start', 'linter_end',
'linter_cat'
] ]
), ),
'conds' => $conds, 'conds' => $conds,
@ -132,13 +149,23 @@ class LintErrorsPager extends TablePager {
*/ */
public function formatValue( $name, $value ) { public function formatValue( $name, $value ) {
$row = $this->mCurrentRow; $row = $this->mCurrentRow;
$row->linter_cat = $this->categoryId;
// To support multiple lint errors of varying types for a single page, the
// category is set each time based on the category set in the lint error $row
// not by the class when lints are being reported by type for many pages
if ( $this->category === null && $row->linter_cat !== null ) {
$category = $this->categoryManager->getCategoryName( $row->linter_cat );
} else {
$category = $this->category;
$row->linter_cat = $this->categoryId;
}
$lintError = Database::makeLintError( $row ); $lintError = Database::makeLintError( $row );
if ( !$lintError ) { if ( !$lintError ) {
return ''; return '';
} }
if ( $this->haveParserMigrationExt && if ( $this->haveParserMigrationExt &&
$this->categoryManager->needsParserMigrationEdit( $this->category ) $this->categoryManager->needsParserMigrationEdit( $category )
) { ) {
$editAction = 'parsermigration-edit'; $editAction = 'parsermigration-edit';
} else { } else {
@ -170,32 +197,32 @@ class LintErrorsPager extends TablePager {
->rawParams( $viewLink, $editHistLinks ) ->rawParams( $viewLink, $editHistLinks )
->escaped(); ->escaped();
case 'details': case 'details':
if ( $this->categoryManager->hasNameParam( $this->category ) && if ( $this->categoryManager->hasNameParam( $category ) &&
isset( $lintError->params['name'] ) ) { isset( $lintError->params['name'] ) ) {
return Html::element( 'code', [], $lintError->params['name'] ); return Html::element( 'code', [], $lintError->params['name'] );
} elseif ( $this->category === 'bogus-image-options' && isset( $lintError->params['items'] ) ) { } elseif ( $category === 'bogus-image-options' && isset( $lintError->params['items'] ) ) {
$list = array_map( static function ( $in ) { $list = array_map( static function ( $in ) {
return Html::element( 'code', [], $in ); return Html::element( 'code', [], $in );
}, $lintError->params['items'] ); }, $lintError->params['items'] );
return $this->getLanguage()->commaList( $list ); return $this->getLanguage()->commaList( $list );
} elseif ( $this->category === 'pwrap-bug-workaround' && } elseif ( $category === 'pwrap-bug-workaround' &&
isset( $lintError->params['root'] ) && isset( $lintError->params['root'] ) &&
isset( $lintError->params['child'] ) ) { isset( $lintError->params['child'] ) ) {
return Html::element( 'code', [], return Html::element( 'code', [],
$lintError->params['root'] . " > " . $lintError->params['child'] ); $lintError->params['root'] . " > " . $lintError->params['child'] );
} elseif ( $this->category === 'tidy-whitespace-bug' && } elseif ( $category === 'tidy-whitespace-bug' &&
isset( $lintError->params['node'] ) && isset( $lintError->params['node'] ) &&
isset( $lintError->params['sibling'] ) ) { isset( $lintError->params['sibling'] ) ) {
return Html::element( 'code', [], return Html::element( 'code', [],
$lintError->params['node'] . " + " . $lintError->params['sibling'] ); $lintError->params['node'] . " + " . $lintError->params['sibling'] );
} elseif ( $this->category === 'multi-colon-escape' && } elseif ( $category === 'multi-colon-escape' &&
isset( $lintError->params['href'] ) ) { isset( $lintError->params['href'] ) ) {
return Html::element( 'code', [], $lintError->params['href'] ); return Html::element( 'code', [], $lintError->params['href'] );
} elseif ( $this->category === 'multiline-html-table-in-list' ) { } elseif ( $category === 'multiline-html-table-in-list' ) {
/* ancestor and name will be set */ /* ancestor and name will be set */
return Html::element( 'code', [], return Html::element( 'code', [],
$lintError->params['ancestorName'] . " > " . $lintError->params['name'] ); $lintError->params['ancestorName'] . " > " . $lintError->params['name'] );
} elseif ( $this->category === 'misc-tidy-replacement-issues' ) { } elseif ( $category === 'misc-tidy-replacement-issues' ) {
/* There will be a 'subtype' param to disambiguate */ /* There will be a 'subtype' param to disambiguate */
return Html::element( 'code', [], $lintError->params['subtype'] ); return Html::element( 'code', [], $lintError->params['subtype'] );
} }
@ -222,6 +249,8 @@ class LintErrorsPager extends TablePager {
return $this->linkRenderer->makeLink( return $this->linkRenderer->makeLink(
$templateTitle $templateTitle
); );
case 'category':
return Html::element( 'code', [], $category );
default: default:
throw new InvalidArgumentException( "Unexpected name: $name" ); throw new InvalidArgumentException( "Unexpected name: $name" );
} }
@ -239,6 +268,9 @@ class LintErrorsPager extends TablePager {
$names = [ $names = [
'title' => $this->msg( 'linter-pager-title' )->text(), 'title' => $this->msg( 'linter-pager-title' )->text(),
]; ];
if ( isset( $this->pageId ) ) {
$names['category'] = 'Category';
}
if ( !$this->categoryManager->hasNoParams( $this->category ) ) { if ( !$this->categoryManager->hasNoParams( $this->category ) ) {
$names['details'] = $this->msg( "linter-pager-{$this->category}-details" )->text(); $names['details'] = $this->msg( "linter-pager-{$this->category}-details" )->text();
} }

View file

@ -24,11 +24,12 @@ use Html;
use HTMLForm; use HTMLForm;
use MediaWiki\MediaWikiServices; use MediaWiki\MediaWikiServices;
use SpecialPage; use SpecialPage;
use Title;
class SpecialLintErrors extends SpecialPage { class SpecialLintErrors extends SpecialPage {
/** /**
* @var string * @var string|null
*/ */
private $category; private $category;
@ -66,10 +67,56 @@ class SpecialLintErrors extends SpecialPage {
$form->prepareForm()->displayForm( false ); $form->prepareForm()->displayForm( false );
} }
/**
*/
protected function showPageNameFilterForm() {
$fields = [
'pagename' => [
'type' => 'text',
'name' => 'pagename',
'label-message' => 'linter-pager-title',
'default' => '',
'id' => 'pagename',
'size' => 255,
]
];
$form = HTMLForm::factory( 'ooui', $fields, $this->getContext() );
$form->setWrapperLegend( true );
$form->setMethod( 'get' );
$form->prepareForm()->displayForm( false );
}
/** /**
* @param string|null $par * @param string|null $par
*/ */
public function execute( $par ) { public function execute( $par ) {
// if the request contains a pagename parameter, then the user entered a pagename
// and pressed the Submit button to display of all lints for a single page.
$params = $this->mContext->getRequest()->getQueryValues();
$pageName = $params['pagename'] ?? null;
if ( $par === null && $pageName !== null ) {
$out = $this->getOutput();
$title = Title::newFromText( $pageName );
if ( $title !== null ) {
$pageArticleID = $title->getArticleID();
if ( $pageArticleID !== 0 ) {
$ns = $title->getNamespace();
$catManager = new CategoryManager();
$pager = new LintErrorsPager(
$this->getContext(), null, $this->getLinkRenderer(),
$catManager, $ns, false, $pageArticleID
);
$out->addParserOutput( $pager->getFullOutput() );
return;
}
}
$out->addHTML( Html::element( 'span class="error"', [],
$this->msg( "linter-invalid-title" )->text() ) );
return;
}
$this->setHeaders(); $this->setHeaders();
$this->outputHeader(); $this->outputHeader();
$catManager = new CategoryManager(); $catManager = new CategoryManager();
@ -112,6 +159,15 @@ class SpecialLintErrors extends SpecialPage {
$out->addHTML( $this->buildCategoryList( $categories, $totals ) ); $out->addHTML( $this->buildCategoryList( $categories, $totals ) );
} }
/**
*/
private function displaySearchPage() {
$out = $this->getOutput();
$out->addHTML( Html::element( 'h2', [],
$this->msg( "linter-lints-for-single-page-desc" )->text() ) );
$this->showPageNameFilterForm();
}
/** /**
* @param CategoryManager $catManager * @param CategoryManager $catManager
*/ */
@ -126,6 +182,8 @@ class SpecialLintErrors extends SpecialPage {
$this->displayList( 'high', $totals, $catManager->getHighPriority() ); $this->displayList( 'high', $totals, $catManager->getHighPriority() );
$this->displayList( 'medium', $totals, $catManager->getMediumPriority() ); $this->displayList( 'medium', $totals, $catManager->getMediumPriority() );
$this->displayList( 'low', $totals, $catManager->getLowPriority() ); $this->displayList( 'low', $totals, $catManager->getLowPriority() );
$this->displaySearchPage();
} }
/** /**