jenkins-bot has submitted this change and it was merged.

Change subject: Add new special page for searching assessments
......................................................................


Add new special page for searching assessments

This adds Special:PageAssessments with a basic search form
and results table. The special page can also be transcluded,
in which case the search form isn't shown (all search and sort
parameters must be provided in the transclusion).

Bug: T120407
Change-Id: I6ee898059ffc62bb5f2788ad83a49b650cdb1335
---
M extension.json
M i18n/en.json
M i18n/qqq.json
A src/NamespaceSelect.php
A src/Pager.php
A src/SpecialPage.php
6 files changed, 319 insertions(+), 3 deletions(-)

Approvals:
  Kaldari: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/extension.json b/extension.json
index 49a9529..bd8ccd7 100644
--- a/extension.json
+++ b/extension.json
@@ -19,7 +19,10 @@
                "PageAssessmentsHooks": "PageAssessments.hooks.php",
                "PageAssessmentsBody": "PageAssessmentsBody.php",
                "ApiQueryPageAssessments": "api/ApiQueryPageAssessments.php",
-               "ApiQueryProjectPages": "api/ApiQueryProjectPages.php"
+               "ApiQueryProjectPages": "api/ApiQueryProjectPages.php",
+               "PageAssessments\\SpecialPage": "src/SpecialPage.php",
+               "PageAssessments\\Pager": "src/Pager.php",
+               "PageAssessments\\NamespaceSelect": "src/NamespaceSelect.php"
        },
        "ExtensionMessagesFiles": {
                "PageAssessmentsMagic": "PageAssessments.i18n.magic.php"
@@ -47,6 +50,9 @@
                "localBasePath": "",
                "remoteExtPath": "examples/PageAssessments"
        },
+       "SpecialPages": {
+               "PageAssessments": "PageAssessments\\SpecialPage"
+       },
        "config": {
                "PageAssessmentsOnTalkPages": true
        },
diff --git a/i18n/en.json b/i18n/en.json
index f5a0313..676a955 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -16,5 +16,14 @@
        "apihelp-query+projectpages-param-limit": "The maximum number of pages 
to return.",
        "apihelp-query+projectpages-example-simple-1": "Get first 10 pages 
associated with any WikiProject.",
        "apihelp-query+projectpages-example-simple-2": "Get first 10 pages 
associated with WikiProject <kbd>Medicine</kbd>, including assessment data.",
-       "apihelp-query+projectpages-example-generator": "Get page info for 
first 10 pages associated with WikiProject <kbd>Textile Arts</kbd>."
+       "apihelp-query+projectpages-example-generator": "Get page info for 
first 10 pages associated with WikiProject <kbd>Textile Arts</kbd>.",
+       "pageassessments-special": "Page assessments",
+       "pageassessments-project": "Project",
+       "pageassessments-page-namespace": "Page namespace",
+       "pageassessments-page-title": "Page title",
+       "pageassessments-search": "Search",
+       "pageassessments-importance": "Importance",
+       "pageassessments-class": "Class",
+       "pageassessments-timestamp": "Timestamp",
+       "pageassessments-total-results": "Total results: $1"
 }
diff --git a/i18n/qqq.json b/i18n/qqq.json
index 6caf8ec..75e10db 100644
--- a/i18n/qqq.json
+++ b/i18n/qqq.json
@@ -16,5 +16,14 @@
        "apihelp-query+projectpages-param-limit": 
"{{doc-apihelp-param|query+projectpages|limit}}",
        "apihelp-query+projectpages-example-simple-1": 
"{{doc-apihelp-example|query+projectpages}}",
        "apihelp-query+projectpages-example-simple-2": 
"{{doc-apihelp-example|query+projectpages}}",
-       "apihelp-query+projectpages-example-generator": 
"{{doc-apihelp-example|query+projectpages}}"
+       "apihelp-query+projectpages-example-generator": 
"{{doc-apihelp-example|query+projectpages}}",
+       "pageassessments-special": "Name of the Special page",
+       "pageassessments-project": "Form label for the WikiProject search field 
and the results table column header",
+       "pageassessments-page-namespace": "Form label for the page namespace 
dropdown select field",
+       "pageassessments-page-title": "Form label for the page title search 
field and the results table column header",
+       "pageassessments-search": "Search form submit button label",
+       "pageassessments-importance": "Label for the results table column 
header",
+       "pageassessments-class": "Label for the results table column header",
+       "pageassessments-timestamp": "Label for the results table column 
header",
+       "pageassessments-total-results": "Summary shown above the search 
results, with total number found"
 }
diff --git a/src/NamespaceSelect.php b/src/NamespaceSelect.php
new file mode 100644
index 0000000..49a09b4
--- /dev/null
+++ b/src/NamespaceSelect.php
@@ -0,0 +1,37 @@
+<?php
+
+namespace PageAssessments;
+
+use HTMLSelectNamespace;
+use MediaWiki\Widget\NamespaceInputWidget;
+use MWNamespace;
+
+/**
+ * This is an HTML form field for selecting non-talk namespaces. It excludes 
all namespaces with
+ * an even-numbered ID.
+ *
+ * It only overrides the OOUI widget because that's all that the 
PageAssessments special page needs.
+ */
+class NamespaceSelect extends HTMLSelectNamespace {
+
+       /**
+        * Get the widget for selecting one or all non-talkspace namespace(s).
+        * @param string $value The currently selected value.
+        * @return NamespaceInputWidget
+        */
+       public function getInputOOUI( $value ) {
+               $nsIds = array_keys( MWNamespace::getCanonicalNamespaces() );
+               $excludedNsIds = array_filter( $nsIds, function( $ns ) {
+                       return MWNamespace::isTalk( $ns );
+               } );
+               $widget = new NamespaceInputWidget( [
+                       'value' => $value,
+                       'name' => $this->mName,
+                       'id' => $this->mID,
+                       'includeAllValue' => $this->mAllValue,
+                       'exclude' => $excludedNsIds,
+               ] );
+               return $widget;
+       }
+
+}
diff --git a/src/Pager.php b/src/Pager.php
new file mode 100644
index 0000000..5a4eb09
--- /dev/null
+++ b/src/Pager.php
@@ -0,0 +1,148 @@
+<?php
+namespace PageAssessments;
+
+use LikeMatch;
+use MediaWiki\MediaWikiServices;
+use TablePager;
+use Title;
+
+class Pager extends TablePager {
+
+       /** @var boolean Should field sorting be enabled? */
+       protected $sortable;
+
+       /**
+        * All parameters for the main paged query.
+        * @return string[]
+        */
+       public function getQueryInfo() {
+               $info = [
+                       'tables' => [ 'page_assessments', 
'page_assessments_projects', 'page', 'revision' ],
+                       'fields' => [
+                               'project' => 'pap_project_title',
+                               'class' => 'pa_class',
+                               'importance' => 'pa_importance',
+                               'timestamp' => 'rev_timestamp',
+                               'page_title' => 'page_title',
+                               'page_revision' => 'pa_page_revision',
+                               'page_namespace' => 'page_namespace',
+                       ],
+                       'conds' => [],
+                       'options' => [],
+                       'join_conds' => [
+                               'page_assessments_projects' => [ 'JOIN', 
'pa_project_id = pap_project_id' ],
+                               'page' => [ 'JOIN', 'pa_page_id = page_id' ],
+                               'revision' => [ 'JOIN', 'page_id = rev_page AND 
pa_page_revision = rev_id' ],
+                       ],
+               ];
+               // Project.
+               $project = $this->getRequest()->getVal( 'project', false );
+               if ( !empty( $project ) ) {
+                       $info['conds']['pap_project_title'] = $project;
+               }
+               // Namespace (if its set, it's either an integer >= 0, 'all', 
or the empty string).
+               $namespace = $this->getRequest()->getVal( 'namespace', false );
+               if ( $namespace !== 'all' && $namespace !== '' ) {
+                       $info['conds']['page_namespace'] = $namespace;
+               }
+               $pageTitle = $this->getRequest()->getVal( 'page_title', false );
+               if ( !empty( $pageTitle ) ) {
+                       $title = Title::newFromText( $pageTitle )->getDBkey();
+                       $info['conds']['page_title'] = $title;
+               }
+               return $info;
+       }
+
+       /**
+        * Should the table be sortable? It's not when transcluded.
+        * @param boolean $sortable Whether to sort or not.
+        */
+       public function setSortable( $sortable ) {
+               $this->sortable = (bool)$sortable;
+       }
+
+       /**
+        * Return true if the named field should be sortable by the UI, false 
otherwise.
+        * @param string $field The field in question; matches one returned by 
self::getFieldNames().
+        * @return boolean
+        */
+       public function isFieldSortable( $field ) {
+               // Done enable sorting for transcluded pagers, because the 
sorting links will not be to
+               // the current page.
+               if ( $this->sortable === false ) {
+                       // Strict check, to avoid false negative when this 
method is used in parent::__construct
+                       return false;
+               }
+               $sortable = [
+                       'project',
+                       'page',
+                       'timestamp',
+               ];
+               return in_array( $field, $sortable );
+       }
+
+       /**
+        * Format a table cell. The return value should be HTML, but use an 
empty
+        * string not &#160; for empty cells. Do not include the <td> and </td>.
+        *
+        * The current result row is available as $this->mCurrentRow, in case 
you
+        * need more context.
+        *
+        * @param string $name The database field name
+        * @param string $value The value retrieved from the database
+        * @return string
+        */
+       public function formatValue( $name, $value ) {
+               $renderer = MediaWikiServices::getInstance()->getLinkRenderer();
+               $pageTitle = Title::newFromText(
+                       $this->mCurrentRow->page_title,
+                       $this->mCurrentRow->page_namespace
+               );
+
+               // Page title.
+               if ( $name === 'page' ) {
+                       return $renderer->makeKnownLink( $pageTitle );
+               }
+
+               // Timestamp of assessed revision.
+               if ( $name === 'timestamp' ) {
+                       $lang = $this->getLanguage();
+                       $ts = $lang->userTimeAndDate( 
$this->mCurrentRow->timestamp, $this->getUser() );
+                       $linkQuery = [ 'oldid' => 
$this->mCurrentRow->page_revision ];
+                       return $renderer->makeKnownLink( $pageTitle, $ts, [], 
$linkQuery );
+               }
+
+               // All field names from self::getFieldNames() have been taken 
care of above,
+               // so this shouldn't be used.
+               return $value;
+       }
+
+       /**
+        * An array mapping database field names to a textual description of the
+        * field name, for use in the table header. The description should be 
plain
+        * text, it will be HTML-escaped later.
+        *
+        * @return array
+        */
+       public function getFieldNames() {
+               return [
+                       'project' => wfMessage( 'pageassessments-project' 
)->text(),
+                       'page' => wfMessage( 'pageassessments-page-title' 
)->text(),
+                       'importance' => wfMessage( 'pageassessments-importance' 
)->text(),
+                       'class' => wfMessage( 'pageassessments-class' )->text(),
+                       'timestamp' => wfMessage( 'pageassessments-timestamp' 
)->text(),
+               ];
+       }
+
+       /**
+        * The database field name used as a default sort order.
+        *
+        * @protected
+        *
+        * @return string
+        */
+       public function getDefaultSort() {
+               return 'project';
+       }
+
+}
diff --git a/src/SpecialPage.php b/src/SpecialPage.php
new file mode 100644
index 0000000..e31e355
--- /dev/null
+++ b/src/SpecialPage.php
@@ -0,0 +1,107 @@
+<?php
+
+namespace PageAssessments;
+
+use HTMLForm;
+use HTMLTextField;
+use SpecialPage as MediaWikiSpecialPage;
+
+/**
+ * A special page for searching Page Assessments. Can also be transcluded (in 
which case the
+ * search results' sorting links will be disabled).
+ */
+class SpecialPage extends MediaWikiSpecialPage {
+
+       /**
+        * Create this special page, giving it a name and making it 
transcludable.
+        */
+       public function __construct() {
+               parent::__construct();
+               $this->mName = 'PageAssessments';
+               $this->mIncludable = true;
+       }
+
+       /**
+        * Do not include this one in the list of special pages at 
Special:SpecialPages, at least until
+        * it's more functional that it currently is.
+        * @return bool False.
+        */
+       public function isListed() {
+               return false;
+       }
+
+       /**
+        * Returns the name that goes in the \<h1\> in the special page itself, 
and
+        * also the name that will be listed in Special:Specialpages.
+        *
+        * Overridden here because we want proper sentence casing, rather than 
'PageAssessments'.
+        *
+        * @return string
+        */
+       function getDescription() {
+               return $this->msg( 'pageassessments-special' )->text();
+       }
+
+       /**
+        * Output the special page.
+        * @param string $parameters The parameters to the special page.
+        */
+       public function execute( $parameters ) {
+               // Set up.
+               $out = $this->getOutput();
+               $out->setPageTitle( $this->getDescription() );
+               $this->addHelpLink( 'Help:Extension:PageAssessments' );
+
+               // Output form.
+               if ( !$this->including() ) {
+                       $form = $this->getForm();
+                       $form->show();
+               }
+
+               // Output results, if a search has been performed.
+               $queryValues = $this->getRequest()->getQueryValues();
+               // The request has 'title' when this special page is not 
transcluded.
+               unset( $queryValues['title'] );
+               if ( count( $queryValues ) > 0 ) {
+                       $pager = new Pager();
+                       $pager->setSortable( !$this->including() );
+                       // Summary of search resutls.
+                       $total = wfMessage( 'pageassessments-total-results', 
$pager->getNumRows() );
+                       $out->addElement( 'p', ['class'=>'total-results'], 
$total );
+                       // Table pager.
+                       $out->addParserOutput( $pager->getFullOutput() );
+               }
+       }
+
+       /**
+        * Get the search form.
+        * @return HTMLForm
+        */
+       protected function getForm() {
+               $formDescriptor = [
+                       'project' => [
+                               'class' => HTMLTextField::class,
+                               'name' => 'project',
+                               'label-message' => 'pageassessments-project',
+                       ],
+                       'namespace' => [
+                               'class' => NamespaceSelect::class,
+                               'name' => 'namespace',
+                               'label-message' => 
'pageassessments-page-namespace',
+                       ],
+                       'page_title' => [
+                               'class' => HTMLTextField::class,
+                               'name' => 'page_title',
+                               'label-message' => 'pageassessments-page-title',
+                       ],
+               ];
+               $form = HTMLForm::factory( 'ooui', $formDescriptor, 
$this->getContext() );
+               $form->setMethod( 'get' );
+               $form->setSubmitTextMsg( 'pageassessments-search' );
+               $form->setSubmitCallback( function() {
+                       // No callback required, but HTMLForm says we have to 
set one.
+               } );
+               return $form;
+       }
+
+}

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

Gerrit-MessageType: merged
Gerrit-Change-Id: I6ee898059ffc62bb5f2788ad83a49b650cdb1335
Gerrit-PatchSet: 4
Gerrit-Project: mediawiki/extensions/PageAssessments
Gerrit-Branch: master
Gerrit-Owner: Samwilson <s...@samwilson.id.au>
Gerrit-Reviewer: Kaldari <rkald...@wikimedia.org>
Gerrit-Reviewer: Samwilson <s...@samwilson.id.au>
Gerrit-Reviewer: jenkins-bot <>

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

Reply via email to