diff --git a/ProofreadPage.body.php b/ProofreadPage.body.php index b908fb34..6a8af056 100644 --- a/ProofreadPage.body.php +++ b/ProofreadPage.body.php @@ -1,881 +1,881 @@ getPageNamespaceId(); } /** * @deprecated use Context::getIndexNamespaceId * * Returns id of Index namespace. * * @return integer */ public static function getIndexNamespaceId() { return Context::getDefaultContext()->getIndexNamespaceId(); } /** * @deprecated * @return array */ public static function getPageAndIndexNamespace() { static $res; if ( $res === null ) { global $wgExtraNamespaces; $res = [ preg_quote( $wgExtraNamespaces[self::getPageNamespaceId()], '/' ), preg_quote( $wgExtraNamespaces[self::getIndexNamespaceId()], '/' ), ]; } return $res; } /** * @param array $queryPages * @return bool */ public static function onwgQueryPages( &$queryPages ) { $queryPages[] = [ 'ProofreadPages', 'IndexPages' ]; $queryPages[] = [ 'PagesWithoutScans', 'PagesWithoutScans' ]; return true; } /** * Set up content handlers * * @param Title $title the title page * @param string $model the content model for the page * @return boolean if we have to continue the research for a content handler */ public static function onContentHandlerDefaultModelFor( Title $title, &$model ) { if ( $title->inNamespace( self::getPageNamespaceId() ) ) { $model = CONTENT_MODEL_PROOFREAD_PAGE; return false; } else { return true; } } /** * Set up our custom edition system. * * @param Article $article being edited * @param User $user User performing the edit * @return boolean hook return value */ public static function onCustomEditor( Article $article, User $user ) { if ( $article->getTitle()->inNamespace( self::getIndexNamespaceId() ) ) { // TODO ExternalEditor case $editor = new EditProofreadIndexPage( $article ); $editor->edit(); return false; } else { return true; } } /** * Set up our custom parser hooks when initializing parser. * * @param Parser $parser * @return boolean hook return value */ public static function onParserFirstCallInit( Parser $parser ) { $parser->setHook( 'pagelist', [ 'ProofreadPage\Parser\ParserEntryPoint', 'renderPagelistTag' ] ); $parser->setHook( 'pages', [ 'ProofreadPage\Parser\ParserEntryPoint', 'renderPagesTag' ] ); $parser->setHook( 'pagequality', [ 'ProofreadPage\Parser\ParserEntryPoint', 'renderPagequalityTag' ] ); return true; } /** * Query the database to find if the current page is referred in an Index page. * @param Title $title */ public static function loadIndex( $title ) { $title->prpIndexPage = null; $result = ProofreadIndexDbConnector::getRowsFromTitle( $title ); foreach ( $result as $x ) { $refTitle = Title::makeTitle( $x->page_namespace, $x->page_title ); if ( $refTitle !== null && $refTitle->inNamespace( self::getIndexNamespaceId() ) ) { $title->prpIndexPage = ProofreadIndexPage::newFromTitle( $refTitle ); return; } } $m = explode( '/', $title->getText(), 2 ); if ( !isset( $m[1] ) ) { return; } $imageTitle = Title::makeTitleSafe( NS_IMAGE, $m[0] ); if ( $imageTitle === null ) { return; } $image = wfFindFile( $imageTitle ); // if it is multipage, we use the page order of the file if ( $image && $image->exists() && $image->isMultipage() ) { $indexTitle = Title::makeTitle( self::getIndexNamespaceId(), $image->getTitle()->getText() ); if ( $indexTitle !== null ) { $title->prpIndexPage = ProofreadIndexPage::newFromTitle( $indexTitle ); } } } /** * Append javascript variables and code to the page. * @param OutputPage $out * @return bool */ public static function onBeforePageDisplay( OutputPage $out ) { $action = $out->getRequest()->getVal( 'action' ); $isEdit = ( $action === 'submit' || $action === 'edit' ); $title = $out->getTitle(); if ( $title->inNamespace( self::getIndexNamespaceId() ) ) { $out->addModuleStyles( 'ext.proofreadpage.base' ); } elseif ( $title->inNamespace( self::getPageNamespaceId() ) ) { $out->addModules( 'ext.proofreadpage.page.navigation' ); } elseif ( $title->inNamespace( NS_MAIN ) && ( $out->isArticle() || $isEdit ) && !isset( $out->proofreadPageDone ) ) { $out->proofreadPageDone = true; self::prepareArticle( $out ); } return true; } /** * Hook function * @param $page_ids * @param $colours * @return bool */ public static function onGetLinkColours( $page_ids, &$colours ) { global $wgTitle; if ( !isset( $wgTitle ) ) { return true; } self::getLinkColours( $page_ids, $colours ); return true; } /** * Return the quality colour codes to pages linked from an index page * @param array $page_ids * @param array $colours */ private static function getLinkColours( $page_ids, &$colours ) { global $wgTitle; $page_namespace_id = self::getPageNamespaceId(); $in_index_namespace = $wgTitle->inNamespace( self::getIndexNamespaceId() ); $values = []; foreach ( $page_ids as $id => $pdbk ) { $title = Title::newFromText( $pdbk ); // consider only link in page namespace if ( $title->inNamespace( $page_namespace_id ) ) { if ( $in_index_namespace ) { $colours[$pdbk] = 'quality1 prp-pagequality-1'; } else { $colours[$pdbk] = 'prp-pagequality-1'; } $values[] = intval( $id ); } } // Get the names of the quality categories. Replaces earlier code which // called wfMessage()->inContentLanguagE() 5 times for each page. // ISSUE: Should the number of quality levels be adjustable? // ISSUE 2: Should this array be saved as a member variable? // How often is this code called anyway? $qualityCategories = []; for ( $i = 0; $i < 5; $i++ ) { $cat = Title::makeTitleSafe( NS_CATEGORY, wfMessage( "proofreadpage_quality{$i}_category" )->inContentLanguage()->text() ); if ( $cat ) { if ( $in_index_namespace ) { $qualityCategories[$cat->getDBkey()] = 'quality' . $i . ' prp-pagequality-' . $i; } else { $qualityCategories[$cat->getDBkey()] = 'prp-pagequality-' . $i; } } } if ( count( $values ) ) { $res = ProofreadPageDbConnector::getCategoryNamesForPageIds( $values ); foreach ( $res as $x ) { $pdbk = $page_ids[$x->cl_from]; if ( array_key_exists( $x->cl_to, $qualityCategories ) ) { $colours[$pdbk] = $qualityCategories[$x->cl_to]; } } } } /** * @param ImagePage $imgpage * @param OutputPage $out * @return bool */ public static function onImageOpenShowImageInlineBefore( ImagePage &$imgpage, OutputPage &$out ) { $image = $imgpage->getFile(); if ( !$image->isMultipage() ) { return true; } $name = $image->getTitle()->getText(); $title = Title::makeTitle( self::getIndexNamespaceId(), $name ); $link = Linker::link( $title, $out->msg( 'proofreadpage_image_message' )->text(), [], [], 'known' ); $out->addHTML( $link ); return true; } /** * Set is_toc flag (true if page is a table of contents) * @param OutputPage $outputPage * @param ParserOutput $parserOutput * @return bool */ public static function onOutputPageParserOutput( OutputPage $outputPage, ParserOutput $parserOutput ) { if ( isset( $parserOutput->is_toc ) ) { $outputPage->is_toc = $parserOutput->is_toc; } else { $outputPage->is_toc = false; } return true; } /** * Updates index data for an index referencing the specified page. * @param Title $title page title object * @param boolean $deleted indicates whether the page was deleted */ private static function updateIndexOfPage( Title $title, $deleted = false ) { self::loadIndex( $title ); if ( $title->prpIndexPage !== null ) { $indexTitle = $title->prpIndexPage->getTitle(); $indexTitle->invalidateCache(); $index = new Article( $indexTitle ); if ( $index ) { self::updatePrIndex( $index, $deleted ? $title : null ); } } } /** * @param WikiPage $article * @return bool */ public static function onArticleSaveComplete( WikiPage &$article ) { $title = $article->getTitle(); // if it's an index, update pr_index table if ( $title->inNamespace( ProofreadPage::getIndexNamespaceId() ) ) { // Move this part to EditProofreadIndexPage ProofreadPage::updatePrIndex( $article ); return true; } // return if it is not a page if ( !$title->inNamespace( ProofreadPage::getPageNamespaceId() ) ) { return true; } /* check if there is an index */ if ( !isset( $title->prpIndexPage ) ) { ProofreadPage::loadIndex( $title ); } if ( $title->prpIndexPage === null ) { return true; } /** * invalidate the cache of the index page */ $title->prpIndexPage->getTitle()->invalidateCache(); /** * update pr_index iteratively */ $indexId = $title->prpIndexPage->getTitle()->getArticleID(); $indexData = ProofreadIndexDbConnector::getIndexDataFromIndexPageId( $indexId ); if ( $indexData ) { ProofreadIndexDbConnector::replaceIndexById( $indexData, $indexId, $article ); } return true; } /** * if I delete a page, I need to update the index table * if I delete an index page too... * - * @param $article Article object + * @param $article WikiPage object * @return Boolean: true */ - public static function onArticleDelete( Article $article ) { + public static function onArticleDelete( WikiPage $article ) { $title = $article->getTitle(); // Process Index removal. if ( $title->inNamespace( self::getIndexNamespaceId() ) ) { ProofreadIndexDbConnector::removeIndexData( $article->getId() ); // Process Page removal. } elseif ( $title->inNamespace( self::getPageNamespaceId() ) ) { self::updateIndexOfPage( $title, true ); } return true; } /** * @param Title $title Title corresponding to the article restored * @param bool $create If true, the restored page didn't exist before * @param string $comment Comment explaining the undeletion * @param int $oldPageId ID of page previously deleted from archive table * @return bool */ public static function onArticleUndelete( Title $title, $create, $comment, $oldPageId ) { // Process Index restoration. if ( $title->inNamespace( self::getIndexNamespaceId() ) ) { $index = new Article( $title ); if ( $index ) { self::updatePrIndex( $index ); } // Process Page restoration. } elseif ( $title->inNamespace( self::getPageNamespaceId() ) ) { self::updateIndexOfPage( $title ); } return true; } /** * @param MovePageForm $form * @param Title $ot * @param Title $nt * @return bool */ public static function onSpecialMovepageAfterMove( MovePageForm &$form, Title &$ot, Title &$nt ) { if ( $ot->inNamespace( self::getPageNamespaceId() ) ) { self::updateIndexOfPage( $ot ); } elseif ( $ot->inNamespace( self::getIndexNamespaceId() ) && !$nt->inNamespace( self::getIndexNamespaceId() ) ) { // The page is moved out of the Index namespace. // Remove all index data associated with that page. // $nt is used here on purpose, as we need to get the page id. // There is no page under the old title or it is a redirect. $article = new Article( $nt ); if ( $article ) { ProofreadIndexDbConnector::removeIndexData( $article->getId() ); } } if ( $nt->inNamespace( self::getPageNamespaceId() ) ) { self::loadIndex( $nt ); if ( $nt->prpIndexPage !== null && ( !isset( $ot->prpIndexPage ) || ( $nt->prpIndexPage->getTitle()->equals( $ot->prpIndexPage->getTitle() ) ) ) ) { self::updateIndexOfPage( $nt ); } } elseif ( $nt->inNamespace( self::getIndexNamespaceId() ) ) { // Update index data. $article = new Article( $nt ); if ( $article ) { self::updatePrIndex( $article ); } } return true; } /** * When an index page is created or purged, recompute pr_index values - * @param Article $article + * @param WikiPage $article * @return bool */ - public static function onArticlePurge( Article $article ) { + public static function onArticlePurge( WikiPage $article ) { $title = $article->getTitle(); if ( $title->inNamespace( self::getIndexNamespaceId() ) ) { self::updatePrIndex( $article ); return true; } return true; } /** * Update the pr_index entry of an article - * @param Article $index + * @param WikiPage $index * @param Title|null $deletedpage */ - public static function updatePrIndex( Article $index, $deletedPage = null ) { + public static function updatePrIndex( WikiPage $index, $deletedPage = null ) { $indexTitle = $index->getTitle(); $indexId = $index->getId(); // read the list of pages $pages = []; $pagination = Context::getDefaultContext()->getPaginationFactory()->getPaginationForIndexPage( ProofreadIndexPage::newFromTitle( $indexTitle ) ); foreach ( $pagination as $page ) { if ( $deletedPage === null || !$page->getTitle()->equals( $deletedPage ) ) { array_push( $pages, $page->getTitle()->getDBkey() ); } } if ( !count( $pages ) ) { return; } $total = ProofreadPageDbConnector::getNumberOfExistingPagesFromPageTitle( $pages ); if ( $total === null ) { return; } // proofreading status of pages $queryArr = [ 'tables' => [ 'page', 'categorylinks' ], 'fields' => [ 'COUNT(page_id) AS count' ], 'conds' => [ 'cl_to' => '', 'page_namespace' => self::getPageNamespaceId(), 'page_title' => $pages ], 'joins' => [ 'categorylinks' => [ 'LEFT JOIN', 'cl_from=page_id' ] ] ]; $n0 = ProofreadPageDbConnector::queryCount( $queryArr, 'proofreadpage_quality0_category' ); $n2 = ProofreadPageDbConnector::queryCount( $queryArr, 'proofreadpage_quality2_category' ); $n3 = ProofreadPageDbConnector::queryCount( $queryArr, 'proofreadpage_quality3_category' ); $n4 = ProofreadPageDbConnector::queryCount( $queryArr, 'proofreadpage_quality4_category' ); $n1 = $total - $n0 - $n2 - $n3 - $n4; ProofreadIndexDbConnector::setIndexData( $pagination->getNumberOfPages(), $n0, $n1, $n2, $n3, $n4, $indexId ); } /** * In main namespace, display the proofreading status of transcluded pages. * * @param OutputPage $out * @return bool */ private static function prepareArticle( OutputPage $out ) { $id = $out->getTitle()->getArticleID(); if ( $id == -1 ) { return true; } $pageNamespaceId = self::getPageNamespaceId(); $indexNamespaceId = self::getIndexNamespaceId(); if ( $pageNamespaceId == null || $indexNamespaceId == null ) { return true; } // find the index page $indextitle = ProofreadPageDbConnector::getIndexTitleForPageId( $id ); if ( isset( $out->is_toc ) && $out->is_toc ) { $n = 0; if ( $indextitle ) { $row = ProofreadIndexDbConnector::getIndexDataFromIndexTitle( $indextitle ); if ( $row ) { $n0 = $row->pr_q0; $n1 = $row->pr_q1; $n2 = $row->pr_q2; $n3 = $row->pr_q3; $n4 = $row->pr_q4; $n = $row->pr_count; $ne = $n - ( $n0 + $n1 + $n2 + $n3 + $n4 ); } } } else { // count transclusions from page namespace $n = ProofreadPageDbConnector::countTransclusionFromPageId( $id ); if ( $n === null ) { return true; } // find the proofreading status of transclusions $queryArr = [ 'tables' => [ 'templatelinks', 'page', 'categorylinks' ], 'fields' => [ 'COUNT(page_id) AS count' ], 'conds' => [ 'tl_from' => $id, 'tl_namespace' => $pageNamespaceId, 'cl_to' => '' ], 'joins' => [ 'page' => [ 'LEFT JOIN', 'page_title=tl_title AND page_namespace=tl_namespace' ], 'categorylinks' => [ 'LEFT JOIN', 'cl_from=page_id' ], ] ]; $n0 = ProofreadPageDbConnector::queryCount( $queryArr, 'proofreadpage_quality0_category' ); $n2 = ProofreadPageDbConnector::queryCount( $queryArr, 'proofreadpage_quality2_category' ); $n3 = ProofreadPageDbConnector::queryCount( $queryArr, 'proofreadpage_quality3_category' ); $n4 = ProofreadPageDbConnector::queryCount( $queryArr, 'proofreadpage_quality4_category' ); // quality1 is the default value $n1 = $n - $n0 - $n2 - $n3 - $n4; $ne = 0; } if ( $n == 0 ) { return true; } if ( $indextitle ) { $nt = Title::makeTitleSafe( $indexNamespaceId, $indextitle ); $indexlink = Linker::link( $nt, $out->msg( 'proofreadpage_source' )->text(), [ 'title' => $out->msg( 'proofreadpage_source_message' )->text() ] ); $out->addJsConfigVars( 'proofreadpage_source_href', $indexlink ); $out->addModules( 'ext.proofreadpage.article' ); } $q0 = $n0 * 100 / $n; $q1 = $n1 * 100 / $n; $q2 = $n2 * 100 / $n; $q3 = $n3 * 100 / $n; $q4 = $n4 * 100 / $n; $qe = $ne * 100 / $n; $void_cell = $ne ? '
' . $void_cell . ' |