http://www.mediawiki.org/wiki/Special:Code/MediaWiki/88455
Revision: 88455 Author: ashley Date: 2011-05-20 15:34:21 +0000 (Fri, 20 May 2011) Log Message: ----------- EditSimilar: documentation update, coding style tweaks, etc. Modified Paths: -------------- trunk/extensions/EditSimilar/EditSimilar.class.php trunk/extensions/EditSimilar/EditSimilar.php Modified: trunk/extensions/EditSimilar/EditSimilar.class.php =================================================================== --- trunk/extensions/EditSimilar/EditSimilar.class.php 2011-05-20 15:31:36 UTC (rev 88454) +++ trunk/extensions/EditSimilar/EditSimilar.class.php 2011-05-20 15:34:21 UTC (rev 88455) @@ -1,61 +1,109 @@ <?php -/* - How this extension works: - - upon save, the script searches for articles that are similar - right now, I have assumed the following criteria: - * articles that need attention - * articles similar in category to the one we edited - * if no similar articles were found, we're taking results straight from categories that need attention - * number of articles in result is limited +/** + * How this extension works: + * - upon save, the script searches for articles that are similar + * right now, I have assumed the following criteria: + * ** articles that need attention + * ** articles similar in category to the one we edited + * ** if no similar articles were found, we're taking results straight from + * categories that need attention + * ** number of articles in result is limited + * + * IMPORTANT NOTE: This extension REQUIRES the article + * MediaWiki:EditSimilar-Categories to exist on your wiki in order to run. + * If this article is nonexistent, the extension will disable itself. + * + * Format of the article is as follows: + * * Chosen Stub Category 1 + * * Chosen Stub Category 2 + * etc. (separated by stars) + * + * Insert '-' if you want to disable the extension without blanking the + * commanding article. + * + * @file + */ - IMPORTANT NOTE: This extension REQUIRES the article MediaWiki:EditSimilar-Categories to exist on your - wiki in order to run. If this article is nonexistent, the extension will disable itself. - Format of the article is as follows: - * Chosen Stub Category 1 - * Chosen Stub Category 2 - etc. (separated by stars) +class EditSimilar { + var $mBaseArticle; // the article from which we hail in our quest for similiarities, this is its title - insert '-' if you want to disable the extension without blanking the commanding article + /** + * @var String: how do we mark articles that need attention? Currently, by + * category only + */ + var $mMarkerType; -*/ + /** + * @var Array: the marker array (for now it contains categories) + */ + var $mAttentionMarkers; -class EditSimilar { - var $mBaseArticle; // the article from which we hail in our quest for similiarities, this is its title - var $mMarkerType; // how do we mark articles that need attention? currently, by category only - var $mAttentionMarkers; // the marker array (for now it contains categories) - var $mMatchType; // how do we match articles as a secondary - var $mPoolLimit; // limit up the pool of 'stubs' to choose from - var $mBaseCategories; // extracted categories that this saved article is in - var $mSimilarArticles; // to differentiate between really similar results or just needing attention + /** + * @var Integer: limit up the pool of 'stubs' to choose from, controlled + * via the $wgEditSimilarMaxResultsPool global variable + */ + var $mPoolLimit; - // constructor - function __construct( $article, $markertype = 'category' ) { + /** + * @var Array: array of extracted categories that this saved article is in + */ + var $mBaseCategories; + + /** + * @var Boolean: to differentiate between really similar results or just + * needing attention + */ + var $mSimilarArticles; + + /** + * Constructor + * + * @param $article Integer: article ID number + * @param $markerType String: always 'category' + */ + public function __construct( $article, $markerType = 'category' ) { global $wgEditSimilarMaxResultsPool; $this->mBaseArticle = $article; - $this->mMarkerType = $markertype; + $this->mMarkerType = $markerType; $this->mAttentionMarkers = $this->getStubCategories(); $this->mPoolLimit = $wgEditSimilarMaxResultsPool; $this->mBaseCategories = $this->getBaseCategories(); $this->mSimilarArticles = true; } - // fetch categories marked as 'stub categories' + /** + * Fetch categories marked as 'stub categories', controlled via the + * MediaWiki:EditSimilar-Categories interface message. + * + * @return Array|Boolean: array of category names on success, false on + * failure (if MediaWiki:EditSimilar-Categories is + * empty or contains -) + */ function getStubCategories() { - $stub_categories = wfMsgForContent( 'EditSimilar-Categories' ); - if ( ( '<EditSimilar-Categories>' == $stub_categories ) || ( '' == $stub_categories ) || ( '-' == $stub_categories ) ) { + $stubCategories = wfMsgForContent( 'EditSimilar-Categories' ); + if ( + ( '<EditSimilar-Categories>' == $stubCategories ) || + ( '' == $stubCategories ) || ( '-' == $stubCategories ) + ) + { return false; } else { - $lines = preg_split( "/\*/", $stub_categories ); - $normalised_lines = array(); + $lines = preg_split( '/\*/', $stubCategories ); + $normalisedLines = array(); array_shift( $lines ); foreach ( $lines as $line ) { - $normalised_lines[] = str_replace( ' ', '_', trim( $line ) ); + $normalisedLines[] = str_replace( ' ', '_', trim( $line ) ); } - return $normalised_lines; + return $normalisedLines; } } - // this is the main function that returns articles we deem similar or worth showing + /** + * Main function that returns articles we deem similar or worth showing + * + * @return Array|Boolean: array of article names on success, false on + * failure + */ function getSimilarArticles() { global $wgUser, $wgEditSimilarMaxResultsToDisplay; @@ -66,8 +114,15 @@ $articles = array(); $x = 0; - while ( ( count( $articles ) < $wgEditSimilarMaxResultsToDisplay ) && ( $x < count( $this->mAttentionMarkers ) ) ) { - $articles = array_merge( $articles, $this->getResults( $this->mAttentionMarkers[$x] ) ); + while ( + ( count( $articles ) < $wgEditSimilarMaxResultsToDisplay ) && + ( $x < count( $this->mAttentionMarkers ) ) + ) + { + $articles = array_merge( + $articles, + $this->getResults( $this->mAttentionMarkers[$x] ) + ); if ( !empty( $articles ) ) { $articles = array_unique( $articles ); } @@ -84,42 +139,51 @@ $this->mSimilarArticles = false; } - if ( 1 == count( $articles ) ) { // in this case, array_rand returns a single element, not an array + if ( count( $articles ) == 1 ) { // in this case, array_rand returns a single element, not an array $rand_articles = array( 0 ); } else { - $rand_articles = array_rand( $articles, min( $wgEditSimilarMaxResultsToDisplay, count( $articles ) ) ); + $rand_articles = array_rand( + $articles, + min( $wgEditSimilarMaxResultsToDisplay, count( $articles ) ) + ); } + $sk = $wgUser->getSkin(); - $skinname = get_class( $sk ); - $skinname = strtolower( substr( $skinname, 4 ) ); - $real_rand_values = array(); + $realRandValues = array(); + if ( empty( $rand_articles ) ) { return false; } - $translated_titles = array(); + $translatedTitles = array(); foreach ( $rand_articles as $r_key => $rand_article_key ) { - $translated_titles[] = $articles [$rand_article_key]; + $translatedTitles[] = $articles[$rand_article_key]; } - $translated_titles = $this->idsToTitles( $translated_titles ); + $translatedTitles = $this->idsToTitles( $translatedTitles ); - foreach ( $translated_titles as $link_title ) { - $article_link = $sk->makeKnownLinkObj( $link_title ); - $real_rand_values[] = $article_link; + foreach ( $translatedTitles as $linkTitle ) { + $articleLink = $sk->makeKnownLinkObj( $linkTitle ); + $realRandValues[] = $articleLink; } - return $real_rand_values; + return $realRandValues; } - // extract all categories our base article is in + /** + * Extract all categories our base article is in + * + * @return Array|Boolean: array of category names on success, false on + * failure + */ function getBaseCategories() { global $wgEditSimilarMaxResultsToDisplay; + if ( empty( $this->mAttentionMarkers ) || !$this->mAttentionMarkers ) { return false; } $dbr = wfGetDB( DB_SLAVE ); - $result_array = array(); + $resultArray = array(); $res = $dbr->select( array( 'categorylinks' ), array( 'cl_to' ), @@ -130,127 +194,166 @@ 'USE_INDEX' => 'cl_from' ) ); - while ( $x = $dbr->fetchObject( $res ) ) { + + foreach( $res as $x ) { if ( !in_array( $x->cl_to, $this->mAttentionMarkers ) ) { - $result_array[] = $x->cl_to; + $resultArray[] = $x->cl_to; } } - if ( !empty( $result_array ) ) { - return $result_array; + if ( !empty( $resultArray ) ) { + return $resultArray; } else { return false; } } - /* - latest addition: if we got no results at all (indicating that: - A - the article had no categories, - B - the article had no relevant results for its categories) - - this is to ensure we can get always (well, almost - if "marker" categories get no results, it's dead in the water anyway) - some results - */ + /** + * Latest addition: if we got no results at all (indicating that: + * A - the article had no categories, + * B - the article had no relevant results for its categories) + * + * This is to ensure we can get always (well, almost - if "marker" + * categories get no results, it's dead in the water anyway) some results. + * + * @return Array: array of category names + */ function getAdditionalCheck() { $dbr = wfGetDB( DB_SLAVE ); - $fixed_names = array(); + $fixedNames = array(); foreach ( $this->mAttentionMarkers as $category ) { - $fixed_names[] = $dbr->addQuotes( $category ); + $fixedNames[] = $dbr->addQuotes( $category ); } - $stringed_names = implode( ",", $fixed_names ); + $stringedNames = implode( ',', $fixedNames ); $res = $dbr->select( 'categorylinks', array( 'cl_from' ), - array( "cl_to IN ($stringed_names)" ), + array( "cl_to IN ($stringedNames)" ), __METHOD__ ); - $result_array = array(); - while ( $x = $dbr->fetchObject( $res ) ) { + $resultArray = array(); + foreach( $res as $x ) { if ( $this->mBaseArticle != $x->cl_from ) { - $result_array[] = $x->cl_from; + $resultArray[] = $x->cl_from; } } - $dbr->freeResult( $res ); - return $result_array; + return $resultArray; } - // one function to turn result ids into titles in one query rather than multiple ones - function idsToTitles( $id_array ) { + /** + * Turn result IDs into Title objects in one query rather than multiple + * ones. + * + * @param $idArray Array: array of page ID numbers + * @return Array: array of Title objects + */ + function idsToTitles( $idArray ) { global $wgContentNamespaces; + $dbr = wfGetDB( DB_SLAVE ); - $stringed_names = implode( ",", $id_array ); + $stringedNames = implode( ',', $idArray ); $res = $dbr->select( 'page', array( 'page_namespace', 'page_title' ), - array( "page_id IN ($stringed_names)" ), + array( "page_id IN ($stringedNames)" ), __METHOD__ ); - $result_array = array(); + $resultArray = array(); // so for now, to speed things up, just discard results from other namespaces (and subpages) - while ( ( $x = $dbr->fetchObject( $res ) ) - && ( in_array( $x->page_namespace, $wgContentNamespaces ) ) - && false === strpos( $x->page_title, '/' ) ) { - $result_array[] = Title::makeTitle( $x->page_namespace, $x->page_title ); + while ( + ( $x = $dbr->fetchObject( $res ) ) && + ( in_array( $x->page_namespace, $wgContentNamespaces ) ) && + strpos( $x->page_title, '/' ) === false + ) + { + $resultArray[] = Title::makeTitle( + $x->page_namespace, + $x->page_title + ); } $dbr->freeResult( $res ); - return $result_array; + return $resultArray; } - // get categories from the 'stub' or 'attention needed' category - function getResults( $marker_category ) { + /** + * Get categories from the 'stub' or 'attention needed' category + * + * @param $markerCategory String: category name + * @return Array: array of category names + */ + function getResults( $markerCategory ) { $dbr = wfGetDB( DB_SLAVE ); - $title = Title::makeTitle( NS_CATEGORY, $marker_category ); - $result_array = array(); + $title = Title::makeTitle( NS_CATEGORY, $markerCategory ); + $resultArray = array(); if ( empty( $this->mBaseCategories ) ) { - return $result_array; + return $resultArray; } + // @todo CHECKME: is it possible to make this query use MediaWiki's + // Database functions? If so, rewrite it! $query = "SELECT c1.cl_from FROM {$dbr->tableName( 'categorylinks' )} AS c1, {$dbr->tableName( 'categorylinks' )} AS c2 WHERE c1.cl_from = c2.cl_from AND c1.cl_to = " . $dbr->addQuotes( $title->getDBkey() ) . " AND c2.cl_to IN ("; - $fixed_names = array(); + $fixedNames = array(); foreach ( $this->mBaseCategories as $category ) { - $fixed_names[] = $dbr->addQuotes( $category ); + $fixedNames[] = $dbr->addQuotes( $category ); } - $stringed_names = implode( ",", $fixed_names ); - $query .= $stringed_names . ")"; + $stringed_names = implode( ',', $fixedNames ); + $query .= $stringed_names . ')'; $res = $dbr->query( $query, __METHOD__ ); - while ( $x = $dbr->fetchObject( $res ) ) { + foreach( $res as $x ) { if ( $this->mBaseArticle != $x->cl_from ) { - $result_array[] = $x->cl_from; + $resultArray[] = $x->cl_from; } } - $dbr->freeResult( $res ); - return $result_array; + return $resultArray; } - // message box wrapper - static public function showMessage( $text ) { + /** + * Message box wrapper + * + * @param $text String: message to show + */ + public static function showMessage( $text ) { global $wgOut, $wgUser, $wgScript, $wgScriptPath; + $wgOut->addExtensionStyle( $wgScriptPath . '/extensions/EditSimilar/EditSimilar.css' ); + + // If the user is logged in, give them a link to their preferences in + // case if they want to disable EditSimilar suggestions if ( $wgUser->isLoggedIn() ) { - $link = '<div class="editsimilar_dismiss">[<span class="plainlinks"><a href="' . $wgScript . '?title=Special:Preferences#prefsection-4" id="editsimilar_preferences">' . wfMsg( 'editsimilar-link-disable' ) . '</a></span>]</div><div style="display:block"> </div>'; + $link = '<div class="editsimilar_dismiss">[<span class="plainlinks"><a href="' . + $wgScript . '?title=Special:Preferences#prefsection-4" id="editsimilar_preferences">' . + wfMsg( 'editsimilar-link-disable' ) . + '</a></span>]</div><div style="display:block"> </div>'; } else { $link = ''; } - $wgOut->addHTML( '<div id="editsimilar_links" class="usermessage editsimilar"><div>' . $text . '</div>' . $link . '</div>' ); + $wgOut->addHTML( + '<div id="editsimilar_links" class="usermessage editsimilar"><div>' . + $text . '</div>' . $link . '</div>' + ); } - // this is for determining whether to display the message or not - static public function checkCounter() { + /** + * For determining whether to display the message or not + * + * @return Boolean: true to show the message, false to not show it + */ + public static function checkCounter() { global $wgEditSimilarCounterValue; if ( isset( $_SESSION['ES_counter'] ) ) { $_SESSION['ES_counter']--; Modified: trunk/extensions/EditSimilar/EditSimilar.php =================================================================== --- trunk/extensions/EditSimilar/EditSimilar.php 2011-05-20 15:31:36 UTC (rev 88454) +++ trunk/extensions/EditSimilar/EditSimilar.php 2011-05-20 15:34:21 UTC (rev 88455) @@ -8,10 +8,12 @@ * @author Łukasz Garczewski (TOR) <t...@wikia-inc.com> * @copyright Copyright © 2008, Wikia Inc. * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License 2.0 or later + * @link http://www.mediawiki.org/wiki/Extension:EditSimilar Documentation */ -if ( !defined( 'MEDIAWIKI' ) ) +if ( !defined( 'MEDIAWIKI' ) ) { die( "This is not a valid entry point.\n" ); +} // Internationalization file $dir = dirname( __FILE__ ) . '/'; @@ -42,28 +44,46 @@ 'descriptionmsg' => 'editsimilar-desc', ); -// check if we had the extension enabled at all and if this is in a content namespace +/** + * Check if we had the extension enabled at all and if the current page is in a + * content namespace. + * + * @param $article Object: Article object + * @return Boolean: true + */ function wfEditSimilarCheck( $article ) { global $wgUser, $wgContentNamespaces; $namespace = $article->getTitle()->getNamespace(); - if ( ( 1 == $wgUser->getOption( 'edit-similar', 1 ) ) && ( in_array( $namespace, $wgContentNamespaces ) ) ) { + if ( + ( $wgUser->getOption( 'edit-similar', 1 ) == 1 ) && + ( in_array( $namespace, $wgContentNamespaces ) ) + ) + { $_SESSION['ES_saved'] = 'yes'; } return true; } -// view message depending on settings and the relevancy of the results +/** + * Show a message, depending on settings and the relevancy of the results. + * + * @param $out Object: OutputPage instance + * @return Boolean: true + */ function wfEditSimilarViewMesg( &$out ) { global $wgUser, $wgEditSimilarAlwaysShowThanks; - - - if ( !empty( $_SESSION['ES_saved'] ) && ( 1 == $wgUser->getOption( 'edit-similar', 1 ) ) && $out->isArticle() ) { + if ( + !empty( $_SESSION['ES_saved'] ) && + ( $wgUser->getOption( 'edit-similar', 1 ) == 1 ) && + $out->isArticle() + ) + { if ( EditSimilar::checkCounter() ) { $message_text = ''; $title = $out->getTitle(); - $article_title = $title->getText(); + $articleTitle = $title->getText(); // here we'll populate the similar articles and links $instance = new EditSimilar( $title->getArticleId(), 'category' ); $similarities = $instance->getSimilarArticles(); @@ -72,14 +92,14 @@ global $wgLang; if ( $instance->mSimilarArticles ) { - $message_text = wfMsgExt( + $messageText = wfMsgExt( 'editsimilar-thanks', array( 'parsemag' ), $wgLang->listToText( $similarities ), count( $similarities ) ); } else { // the articles we found were rather just articles needing attention - $message_text = wfMsgExt( + $messageText = wfMsgExt( 'editsimilar-thanks-notsimilar', array( 'parsemag' ), $wgLang->listToText( $similarities ), @@ -88,12 +108,12 @@ } } else { if ( $wgUser->isLoggedIn() && !empty( $wgEditSimilarAlwaysShowThanks ) ) { - $message_text = wfMsg( 'editsimilar-thankyou', $wgUser->getName() ); + $messageText = wfMsg( 'editsimilar-thankyou', $wgUser->getName() ); } } - if ( '' != $message_text ) { - EditSimilar::showMessage( $message_text, $article_title ); + if ( $messageText != '' ) { + EditSimilar::showMessage( $messageText, $articleTitle ); } } // display that only once @@ -103,15 +123,14 @@ } /** - * Adds the new toggle to Special:Preferences for enabling EditSimilar extension on a per-user basis + * Adds the new toggle to Special:Preferences for enabling EditSimilar + * extension on a per-user basis. * * @param $user User object * @param $preferences Preferences object - * @return true + * @return Boolean: true */ function wfEditSimilarToggle( $user, &$preferences ) { - - $preferences['edit-similar'] = array( 'type' => 'toggle', 'section' => 'editing', _______________________________________________ MediaWiki-CVS mailing list MediaWiki-CVS@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-cvs