r55920 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r55919‎ | r55920 | r55921 >
Date:12:44, 7 September 2009
Author:werdna
Status:deferred
Tags:
Comment:
Add LiquidThreads threads API module, for use internally and by other tools
Modified paths:
  • /trunk/extensions/LiquidThreads/LiquidThreads.php (modified) (history)
  • /trunk/extensions/LiquidThreads/api (added) (history)
  • /trunk/extensions/LiquidThreads/api/ApiQueryLQTThreads.php (added) (history)

Diff [purge]

Index: trunk/extensions/LiquidThreads/LiquidThreads.php
@@ -135,6 +135,10 @@
136136 // Preferences
137137 $wgDefaultUserOptions['lqtnotifytalk'] = true;
138138
 139+// API
 140+$wgAutoloadClasses['ApiQueryLQTThreads'] = "$dir/api/ApiQueryLQTThreads.php";
 141+$wgAPIListModules['threads'] = 'ApiQueryLQTThreads';
 142+
139143 /** CONFIGURATION SECTION */
140144
141145 $wgDefaultUserOptions['lqt-watch-threads'] = true;
Index: trunk/extensions/LiquidThreads/api/ApiQueryLQTThreads.php
@@ -0,0 +1,288 @@
 2+<?php
 3+
 4+// LiquidThreads API Query module
 5+
 6+// Data that can be returned:
 7+// - ID
 8+// - Subject
 9+// - "host page"
 10+// - parent
 11+// - ancestor
 12+// - creation time
 13+// - modification time
 14+// - author
 15+// - summary article ID
 16+// - "root" page ID
 17+// - type
 18+
 19+class ApiQueryLQTThreads extends ApiQueryBase {
 20+
 21+ // Property definitions
 22+ static $propRelations = array(
 23+ 'id' => 'thread_id',
 24+ 'subject' => 'thread_subject',
 25+ 'page' => array( 'namespace' => 'thread_article_namespace',
 26+ 'title' => 'thread_article_title' ),
 27+ 'parent' => 'thread_parent',
 28+ 'ancestor' => 'thread_ancestor',
 29+ 'created' => 'thread_created',
 30+ 'modified' => 'thread_modified',
 31+ 'author' => array( 'id' => 'thread_author_id',
 32+ 'name' => 'thread_author_name'),
 33+ 'summaryid' => 'thread_summary_page',
 34+ 'rootid' => 'thread_root',
 35+ 'type' => 'thread_type',
 36+ );
 37+
 38+ public function __construct($query, $moduleName) {
 39+ parent :: __construct($query, $moduleName, 'lqt');
 40+ }
 41+
 42+ public function execute() {
 43+ global $wgUser;
 44+
 45+ $params = $this->extractRequestParams();
 46+ $prop = array_flip($params['prop']);
 47+
 48+ $result = $this->getResult();
 49+
 50+ $this->addTables('thread');
 51+
 52+ $this->addFields('thread_id');
 53+
 54+ foreach( self::$propRelations as $name => $fields ) {
 55+ $addFields = $fields;
 56+
 57+ if ( is_array($addFields) ) $addFields = array_values($addFields);
 58+
 59+ $this->addFieldsIf( $fields, isset($prop[$name]) );
 60+ }
 61+
 62+ // Check for conditions
 63+ $conditionFields = array( 'page', 'root', 'summary', 'author', 'id' );
 64+
 65+ foreach( $conditionFields as $field ) {
 66+ if ( isset($params[$field]) ) {
 67+ $this->handleCondition( $field, $params[$field] );
 68+ }
 69+ }
 70+
 71+ $this->addOption('LIMIT', $params['limit'] + 1);
 72+
 73+ $this->addWhereRange('thread_id', $params['dir'],
 74+ $params['startid'], $params['endid']);
 75+
 76+ if (!is_null($params['show'])) {
 77+ $show = array_flip($params['show']);
 78+ $delType = $this->getDB()->addQuotes( Threads::TYPE_DELETED );
 79+
 80+ $this->addWhereIf( 'thread_type != '.$delType, isset($show['deleted']) );
 81+ }
 82+
 83+ $res = $this->select( __METHOD__ );
 84+
 85+ $count = 0;
 86+ while($row = $res->fetchObject())
 87+ {
 88+ if( ++$count > $params['limit'] ) {
 89+ // We've had enough
 90+ $this->setContinueEnumParameter('startid', $row->thread_id);
 91+ break;
 92+ }
 93+
 94+ $entry = array();
 95+
 96+ foreach( $prop as $name => $nothing ) {
 97+ $fields = self::$propRelations[$name];
 98+ $entry[$name] = self::formatProperty( $name, $fields, $row );
 99+ }
 100+
 101+ if ($entry) {
 102+ $fit = $result->addValue(array( 'query', $this->getModuleName() ), null,
 103+ $entry);
 104+
 105+ if(!$fit) {
 106+ $this->setContinueEnumParameter('startid', $row->thread_id);
 107+ break;
 108+ }
 109+ }
 110+ }
 111+ $result->setIndexedTagName_internal(array('query', $this->getModuleName()), 'thread');
 112+ }
 113+
 114+ static function formatProperty( $name, $fields, $row ) {
 115+ // Common case.
 116+ if ( !is_array($fields) ) {
 117+ return $row->$fields;
 118+ }
 119+
 120+ // Special cases
 121+ if ($name == 'page') {
 122+ $nsField = $fields['namespace'];
 123+ $tField = $fields['title'];
 124+ $title = Title::makeTitleSafe( $row->$nsField, $row->$tField );
 125+ return $title->getPrefixedText();
 126+ }
 127+
 128+ // Complicated case.
 129+ $result = array();
 130+ foreach( $fields as $part => $field ) {
 131+ $result[$part] = $row->$field;
 132+ }
 133+
 134+ return $result;
 135+ }
 136+
 137+ function addPageCond( $prop, $value ) {
 138+
 139+ $value = explode( '|', $value );
 140+
 141+ if ( count($value) === 1 ) {
 142+ $cond = $this->getPageCond($prop, $value[0]);
 143+ $this->addWhere( $cond );
 144+ } else {
 145+ $conds = array();
 146+
 147+ foreach( $value as $page ) {
 148+ $cond = $this->getPageCond( $prop, $page );
 149+ $conds[] = $this->getDB()->makeList( $cond, LIST_AND );
 150+ }
 151+
 152+ $cond = $this->getDB()->makeList( $conds, LIST_OR );
 153+
 154+ $this->addWhere( $cond );
 155+ }
 156+ }
 157+
 158+ function getPageCond( $prop, $value ) {
 159+ $fieldMappings = array( 'page' =>
 160+ array( 'namespace' => 'thread_article_namespace',
 161+ 'title' => 'thread_article_title',
 162+ ),
 163+ 'root' => array( 'id' => 'thread_root' ),
 164+ 'summary' => array( 'id' => 'thread_summary_id' ),
 165+ );
 166+ // Split.
 167+ $t = Title::newFromText( $value );
 168+
 169+ $cond = array();
 170+
 171+ foreach( $fieldMappings[$prop] as $type => $field ) {
 172+ switch($type) {
 173+ case 'namespace':
 174+ $cond[$field] = $t->getNamespace();
 175+ break;
 176+ case 'title':
 177+ $cond[$field] = $t->getDBkey();
 178+ break;
 179+ case 'id':
 180+ $cond[$field] = $t->getArticleID();
 181+ break;
 182+ default:
 183+ throw new MWException( "Unknown condition type $type" );
 184+ }
 185+ }
 186+
 187+ return $cond;
 188+ }
 189+
 190+ function handleCondition( $prop, $value ) {
 191+ // Special cases
 192+ $titleParams = array( 'page', 'root', 'summary' );
 193+
 194+ if ( in_array( $prop, $titleParams ) ) {
 195+ return $this->addPageCond( $prop, $value );
 196+ }
 197+
 198+ $fields = self::$propRelations[$prop];
 199+
 200+ // Some cases where we can pull more than one
 201+ $multiParams = array( 'id', 'author' );
 202+ if ( in_array( $prop, $multiParams ) ) {
 203+ $value = explode( '|', $value );
 204+ }
 205+
 206+ // Common case
 207+ if ( !is_array( $fields ) ) {
 208+ return $this->addWhere( array( $fields => $value ) );
 209+ }
 210+
 211+ // Other special cases.
 212+ if ( $prop == 'author' ) {
 213+ $this->addWhere( array( 'thread_author_name' => $value ) );
 214+ }
 215+ }
 216+
 217+ public function getAllowedParams() {
 218+ return array (
 219+ 'startid' => array(
 220+ ApiBase :: PARAM_TYPE => 'integer'
 221+ ),
 222+ 'endid' => array(
 223+ ApiBase :: PARAM_TYPE => 'integer',
 224+ ),
 225+ 'dir' => array(
 226+ ApiBase :: PARAM_TYPE => array(
 227+ 'older',
 228+ 'newer'
 229+ ),
 230+ ApiBase :: PARAM_DFLT => 'newer'
 231+ ),
 232+ 'show' => array(
 233+ ApiBase :: PARAM_ISMULTI => true,
 234+ ApiBase :: PARAM_TYPE => array (
 235+ 'deleted',
 236+ ),
 237+ ),
 238+ 'limit' => array(
 239+ ApiBase :: PARAM_DFLT => 10,
 240+ ApiBase :: PARAM_TYPE => 'limit',
 241+ ApiBase :: PARAM_MIN => 1,
 242+ ApiBase :: PARAM_MAX => ApiBase :: LIMIT_BIG1,
 243+ ApiBase :: PARAM_MAX2 => ApiBase :: LIMIT_BIG2
 244+ ),
 245+ 'prop' => array(
 246+ ApiBase :: PARAM_DFLT => 'id|subject|page|parent|author',
 247+ ApiBase :: PARAM_TYPE => array_keys(self::$propRelations),
 248+ ApiBase :: PARAM_ISMULTI => true
 249+ ),
 250+
 251+ 'page' => null,
 252+ 'author' => null,
 253+ 'root' => null,
 254+ 'summary' => null,
 255+ 'id' => null,
 256+ );
 257+ }
 258+
 259+ public function getParamDescription() {
 260+ return array (
 261+ 'startid' => 'The thread id to start enumerating from',
 262+ 'endid' => 'The thread id to stop enumerating at',
 263+ 'dir' => 'The direction in which to enumerate',
 264+ 'show' => 'Also show threads which meet these criteria',
 265+ 'limit' => 'The maximum number of threads to list',
 266+ 'prop' => 'Which properties to get',
 267+ 'page' => 'Limit results to threads on a particular page(s)',
 268+ 'author' => 'Limit results to threads by a particular author(s)',
 269+ 'root' => 'Limit results to threads with the given root(s)',
 270+ 'summary' => 'Limit results to threads corresponding to the given summary page(s)',
 271+ 'id' => 'Get threads with the given ID(s)',
 272+ );
 273+ }
 274+
 275+ public function getDescription() {
 276+ return 'Show details of LiquidThreads threads.';
 277+ }
 278+
 279+ protected function getExamples() {
 280+ return array(
 281+ 'api.php?action=query&list=threads&lqtpage=Talk:Main_Page',
 282+ 'api.php?action=query&list=threads&lqtid=1|2|3|4&lqtprop=id|subject|modified'
 283+ );
 284+ }
 285+
 286+ public function getVersion() {
 287+ return __CLASS__;
 288+ }
 289+}

Follow-up revisions

RevisionCommit summaryAuthorDate
r55973LiquidThreads: Clean up API module added in r55920:...catrope14:46, 7 September 2009

Status & tagging log