Merge "Add ability to filter based on rc_title in API"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Thu, 24 May 2018 10:13:06 +0000 (10:13 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Thu, 24 May 2018 10:13:06 +0000 (10:13 +0000)
1  2 
includes/api/ApiQueryRecentChanges.php
includes/api/i18n/en.json
includes/api/i18n/qqq.json
tests/phpunit/includes/api/ApiQueryRecentChangesIntegrationTest.php

@@@ -181,6 -181,16 +181,16 @@@ class ApiQueryRecentChanges extends Api
                        }
                }
  
+               $title = $params['title'];
+               if ( !is_null( $title ) ) {
+                       $titleObj = Title::newFromText( $title );
+                       if ( is_null( $titleObj ) ) {
+                               $this->dieWithError( [ 'apierror-invalidtitle', wfEscapeWikiText( $title ) ] );
+                       }
+                       $this->addWhereFld( 'rc_namespace', $titleObj->getNamespace() );
+                       $this->addWhereFld( 'rc_title', $titleObj->getDBkey() );
+               }
                if ( !is_null( $params['show'] ) ) {
                        $show = array_flip( $params['show'] );
  
                                || ( isset( $show['patrolled'] ) && isset( $show['!patrolled'] ) )
                                || ( isset( $show['patrolled'] ) && isset( $show['unpatrolled'] ) )
                                || ( isset( $show['!patrolled'] ) && isset( $show['unpatrolled'] ) )
 +                              || ( isset( $show['autopatrolled'] ) && isset( $show['!autopatrolled'] ) )
 +                              || ( isset( $show['autopatrolled'] ) && isset( $show['unpatrolled'] ) )
 +                              || ( isset( $show['autopatrolled'] ) && isset( $show['!patrolled'] ) )
                        ) {
                                $this->dieWithError( 'apierror-show' );
                        }
                        if ( isset( $show['patrolled'] )
                                || isset( $show['!patrolled'] )
                                || isset( $show['unpatrolled'] )
 +                              || isset( $show['autopatrolled'] )
 +                              || isset( $show['!autopatrolled'] )
                        ) {
                                if ( !$user->useRCPatrol() && !$user->useNPPatrol() ) {
                                        $this->dieWithError( 'apierror-permissiondenied-patrolflag', 'permissiondenied' );
                        if ( isset( $show['unpatrolled'] ) ) {
                                // See ChangesList::isUnpatrolled
                                if ( $user->useRCPatrol() ) {
 -                                      $this->addWhere( 'rc_patrolled = 0' );
 +                                      $this->addWhere( 'rc_patrolled = ' . RecentChange::PRC_UNPATROLLED );
                                } elseif ( $user->useNPPatrol() ) {
 -                                      $this->addWhere( 'rc_patrolled = 0' );
 +                                      $this->addWhere( 'rc_patrolled = ' . RecentChange::PRC_UNPATROLLED );
                                        $this->addWhereFld( 'rc_type', RC_NEW );
                                }
                        }
  
 +                      $this->addWhereIf(
 +                              'rc_patrolled != ' . RecentChange::PRC_AUTOPATROLLED,
 +                              isset( $show['!autopatrolled'] )
 +                      );
 +                      $this->addWhereIf(
 +                              'rc_patrolled = ' . RecentChange::PRC_AUTOPATROLLED,
 +                              isset( $show['autopatrolled'] )
 +                      );
 +
                        // Don't throw log entries out the window here
                        $this->addWhereIf(
                                'page_is_redirect = 0 OR page_is_redirect IS NULL',
  
                /* Add the patrolled flag */
                if ( $this->fld_patrolled ) {
 -                      $vals['patrolled'] = $row->rc_patrolled == 1;
 +                      $vals['patrolled'] = $row->rc_patrolled != RecentChange::PRC_UNPATROLLED;
                        $vals['unpatrolled'] = ChangesList::isUnpatrolled( $row, $user );
 +                      $vals['autopatrolled'] = $row->rc_patrolled == RecentChange::PRC_AUTOPATROLLED;
                }
  
                if ( $this->fld_loginfo && $row->rc_type == RC_LOG ) {
                                        '!redirect',
                                        'patrolled',
                                        '!patrolled',
 -                                      'unpatrolled'
 +                                      'unpatrolled',
 +                                      'autopatrolled',
 +                                      '!autopatrolled',
                                ]
                        ],
                        'limit' => [
                                ApiBase::PARAM_TYPE => RecentChange::getChangeTypes()
                        ],
                        'toponly' => false,
+                       'title' => null,
                        'continue' => [
                                ApiBase::PARAM_HELP_MSG => 'api-help-param-continue',
                        ],
@@@ -2,8 -2,7 +2,8 @@@
        "@metadata": {
                "authors": [
                        "Anomie",
 -                      "Siebrand"
 +                      "Siebrand",
 +                      "Zoranzoki21"
                ]
        },
  
        "apihelp-query+exturlusage-param-namespace": "The page namespaces to enumerate.",
        "apihelp-query+exturlusage-param-limit": "How many pages to return.",
        "apihelp-query+exturlusage-param-expandurl": "Expand protocol-relative URLs with the canonical protocol.",
 -      "apihelp-query+exturlusage-example-simple": "Show pages linking to <kbd>http://www.mediawiki.org</kbd>.",
 +      "apihelp-query+exturlusage-example-simple": "Show pages linking to <kbd>https://www.mediawiki.org</kbd>.",
  
        "apihelp-query+filearchive-summary": "Enumerate all deleted files sequentially.",
        "apihelp-query+filearchive-param-from": "The image title to start enumerating from.",
        "apihelp-query+info-paramvalue-prop-readable": "Whether the user can read this page.",
        "apihelp-query+info-paramvalue-prop-preload": "Gives the text returned by EditFormPreloadText.",
        "apihelp-query+info-paramvalue-prop-displaytitle": "Gives the manner in which the page title is actually displayed.",
 +      "apihelp-query+info-paramvalue-prop-varianttitles": "Gives the display title in all variants of the site content language.",
        "apihelp-query+info-param-testactions": "Test whether the current user can perform certain actions on the page.",
        "apihelp-query+info-param-token": "Use [[Special:ApiHelp/query+tokens|action=query&meta=tokens]] instead.",
        "apihelp-query+info-example-simple": "Get information about the page <kbd>Main Page</kbd>.",
        "apihelp-query+recentchanges-paramvalue-prop-sizes": "Adds the new and old page length in bytes.",
        "apihelp-query+recentchanges-paramvalue-prop-redirect": "Tags edit if page is a redirect.",
        "apihelp-query+recentchanges-paramvalue-prop-patrolled": "Tags patrollable edits as being patrolled or unpatrolled.",
 +      "apihelp-query+recentchanges-paramvalue-prop-autopatrolled": "Tags patrollable edits as being autopatrolled or not.",
        "apihelp-query+recentchanges-paramvalue-prop-loginfo": "Adds log information (log ID, log type, etc) to log entries.",
        "apihelp-query+recentchanges-paramvalue-prop-tags": "Lists tags for the entry.",
        "apihelp-query+recentchanges-paramvalue-prop-sha1": "Adds the content checksum for entries associated with a revision.",
        "apihelp-query+recentchanges-param-limit": "How many total changes to return.",
        "apihelp-query+recentchanges-param-type": "Which types of changes to show.",
        "apihelp-query+recentchanges-param-toponly": "Only list changes which are the latest revision.",
+       "apihelp-query+recentchanges-param-title": "Filter entries to those related to a page.",
        "apihelp-query+recentchanges-param-generaterevisions": "When being used as a generator, generate revision IDs rather than titles. Recent change entries without associated revision IDs (e.g. most log entries) will generate nothing.",
        "apihelp-query+recentchanges-example-simple": "List recent changes.",
        "apihelp-query+recentchanges-example-generator": "Get page info about recent unpatrolled changes.",
        "apihelp-query+usercontribs-paramvalue-prop-sizediff": "Adds the size delta of the edit against its parent.",
        "apihelp-query+usercontribs-paramvalue-prop-flags": "Adds flags of the edit.",
        "apihelp-query+usercontribs-paramvalue-prop-patrolled": "Tags patrolled edits.",
 +      "apihelp-query+usercontribs-paramvalue-prop-autopatrolled": "Tags autopatrolled edits.",
        "apihelp-query+usercontribs-paramvalue-prop-tags": "Lists tags for the edit.",
        "apihelp-query+usercontribs-param-show": "Show only items that meet these criteria, e.g. non minor edits only: <kbd>$2show=!minor</kbd>.\n\nIf <kbd>$2show=patrolled</kbd> or <kbd>$2show=!patrolled</kbd> is set, revisions older than <var>[[mw:Special:MyLanguage/Manual:$wgRCMaxAge|$wgRCMaxAge]]</var> ($1 {{PLURAL:$1|second|seconds}}) won't be shown.",
        "apihelp-query+usercontribs-param-tag": "Only list revisions tagged with this tag.",
        "apihelp-query+watchlist-paramvalue-prop-parsedcomment": "Adds parsed comment of the edit.",
        "apihelp-query+watchlist-paramvalue-prop-timestamp": "Adds timestamp of the edit.",
        "apihelp-query+watchlist-paramvalue-prop-patrol": "Tags edits that are patrolled.",
 +      "apihelp-query+watchlist-paramvalue-prop-autopatrol": "Tags edits that are autopatrolled.",
        "apihelp-query+watchlist-paramvalue-prop-sizes": "Adds the old and new lengths of the page.",
        "apihelp-query+watchlist-paramvalue-prop-notificationtimestamp": "Adds timestamp of when the user was last notified about the edit.",
        "apihelp-query+watchlist-paramvalue-prop-loginfo": "Adds log information where appropriate.",
        "api-help-parameters": "{{PLURAL:$1|Parameter|Parameters}}:",
        "api-help-param-deprecated": "Deprecated.",
        "api-help-param-required": "This parameter is required.",
 +      "api-help-param-templated": "This is a [[Special:ApiHelp/main#main/templatedparams|templated parameter]]. When making the request, $2.",
 +      "api-help-param-templated-var-first": "<var>&#x7B;$1&#x7D;</var> in the parameter's name should be replaced with values of <var>$2</var>",
 +      "api-help-param-templated-var": "<var>&#x7B;$1&#x7D;</var> with values of <var>$2</var>",
        "api-help-datatypes-header": "Data types",
        "api-help-datatypes": "Input to MediaWiki should be NFC-normalized UTF-8. MediaWiki may attempt to convert other input, but this may cause some operations (such as [[Special:ApiHelp/edit|edits]] with MD5 checks) to fail.\n\nSome parameter types in API requests need further explanation:\n;boolean\n:Boolean parameters work like HTML checkboxes: if the parameter is specified, regardless of value, it is considered true. For a false value, omit the parameter entirely.\n;timestamp\n:Timestamps may be specified in several formats. ISO 8601 date and time is recommended. All times are in UTC, any included timezone is ignored.\n:* ISO 8601 date and time, <kbd><var>2001</var>-<var>01</var>-<var>15</var>T<var>14</var>:<var>56</var>:<var>00</var>Z</kbd> (punctuation and <kbd>Z</kbd> are optional)\n:* ISO 8601 date and time with (ignored) fractional seconds, <kbd><var>2001</var>-<var>01</var>-<var>15</var>T<var>14</var>:<var>56</var>:<var>00</var>.<var>00001</var>Z</kbd> (dashes, colons, and <kbd>Z</kbd> are optional)\n:* MediaWiki format, <kbd><var>2001</var><var>01</var><var>15</var><var>14</var><var>56</var><var>00</var></kbd>\n:* Generic numeric format, <kbd><var>2001</var>-<var>01</var>-<var>15</var> <var>14</var>:<var>56</var>:<var>00</var></kbd> (optional timezone of <kbd>GMT</kbd>, <kbd>+<var>##</var></kbd>, or <kbd>-<var>##</var></kbd> is ignored)\n:* EXIF format, <kbd><var>2001</var>:<var>01</var>:<var>15</var> <var>14</var>:<var>56</var>:<var>00</var></kbd>\n:*RFC 2822 format (timezone may be omitted), <kbd><var>Mon</var>, <var>15</var> <var>Jan</var> <var>2001</var> <var>14</var>:<var>56</var>:<var>00</var></kbd>\n:* RFC 850 format (timezone may be omitted), <kbd><var>Monday</var>, <var>15</var>-<var>Jan</var>-<var>2001</var> <var>14</var>:<var>56</var>:<var>00</var></kbd>\n:* C ctime format, <kbd><var>Mon</var> <var>Jan</var> <var>15</var> <var>14</var>:<var>56</var>:<var>00</var> <var>2001</var></kbd>\n:* Seconds since 1970-01-01T00:00:00Z as a 1 to 13 digit integer (excluding <kbd>0</kbd>)\n:* The string <kbd>now</kbd>\n;alternative multiple-value separator\n:Parameters that take multiple values are normally submitted with the values separated using the pipe character, e.g. <kbd>param=value1|value2</kbd> or <kbd>param=value1%7Cvalue2</kbd>. If a value must contain the pipe character, use U+001F (Unit Separator) as the separator ''and'' prefix the value with U+001F, e.g. <kbd>param=%1Fvalue1%1Fvalue2</kbd>.",
 +      "api-help-templatedparams-header": "Templated parameters",
 +      "api-help-templatedparams": "Templated parameters support cases where an API module needs a value for each value of some other parameter. For example, if there were an API module to request fruit, it might have a parameter <var>fruits</var> to specify which fruits are being requested and a templated parameter <var>{fruit}-quantity</var> to specify how many of each fruit to request. An API client that wants 1 apple, 5 bananas, and 20 strawberries could then make a request like <kbd>fruits=apples|bananas|strawberries&apples-quantity=1&bananas-quantity=5&strawberries-quantity=20</kbd>.",
        "api-help-param-type-limit": "Type: integer or <kbd>max</kbd>",
        "api-help-param-type-integer": "Type: {{PLURAL:$1|1=integer|2=list of integers}}",
        "api-help-param-type-boolean": "Type: boolean ([[Special:ApiHelp/main#main/datatypes|details]])",
        "apierror-missingtitle-byname": "The page $1 doesn't exist.",
        "apierror-moduledisabled": "The <kbd>$1</kbd> module has been disabled.",
        "apierror-multival-only-one-of": "{{PLURAL:$3|Only|Only one of}} $2 is allowed for parameter <var>$1</var>.",
 -      "apierror-multival-only-one": "Only one value is allowed for parameter <var>$1</var>.",
        "apierror-multpages": "<var>$1</var> may only be used with a single page.",
        "apierror-mustbeloggedin-changeauth": "You must be logged in to change authentication data.",
        "apierror-mustbeloggedin-generic": "You must be logged in.",
        "apierror-templateexpansion-notwikitext": "Template expansion is only supported for wikitext content. $1 uses content model $2.",
        "apierror-timeout": "The server did not respond within the expected time.",
        "apierror-toofewexpiries": "$1 expiry {{PLURAL:$1|timestamp was|timestamps were}} provided where $2 {{PLURAL:$2|was|were}} needed.",
 +      "apierror-toomanyvalues": "Too many values supplied for parameter <var>$1</var>. The limit is $2.",
        "apierror-unknownaction": "The action specified, <kbd>$1</kbd>, is not recognized.",
        "apierror-unknownerror-editpage": "Unknown EditPage error: $1.",
        "apierror-unknownerror-nocode": "Unknown error.",
        "apiwarn-difftohidden": "Couldn't diff to r$1: content is hidden.",
        "apiwarn-errorprinterfailed": "Error printer failed. Will retry without params.",
        "apiwarn-errorprinterfailed-ex": "Error printer failed (will retry without params): $1",
 +      "apiwarn-ignoring-invalid-templated-value": "Ignoring value <kbd>$2</kbd> in <var>$1</var> when processing templated parameters.",
        "apiwarn-invalidcategory": "\"$1\" is not a category.",
        "apiwarn-invalidtitle": "\"$1\" is not a valid title.",
        "apiwarn-invalidxmlstylesheetext": "Stylesheet should have <code>.xsl</code> extension.",
        "apiwarn-redirectsandrevids": "Redirect resolution cannot be used together with the <var>revids</var> parameter. Any redirects the <var>revids</var> point to have not been resolved.",
        "apiwarn-tokennotallowed": "Action \"$1\" is not allowed for the current user.",
        "apiwarn-tokens-origin": "Tokens may not be obtained when the same-origin policy is not applied.",
 -      "apiwarn-toomanyvalues": "Too many values supplied for parameter <var>$1</var>. The limit is $2.",
        "apiwarn-truncatedresult": "This result was truncated because it would otherwise be larger than the limit of $1 bytes.",
        "apiwarn-unclearnowtimestamp": "Passing \"$2\" for timestamp parameter <var>$1</var> has been deprecated. If for some reason you need to explicitly specify the current time without calculating it client-side, use <kbd>now</kbd>.",
        "apiwarn-unrecognizedvalues": "Unrecognized {{PLURAL:$3|value|values}} for parameter <var>$1</var>: $2.",
        "apihelp-query+info-paramvalue-prop-readable": "{{doc-apihelp-paramvalue|query+info|prop|readable}}",
        "apihelp-query+info-paramvalue-prop-preload": "{{doc-apihelp-paramvalue|query+info|prop|preload}}",
        "apihelp-query+info-paramvalue-prop-displaytitle": "{{doc-apihelp-paramvalue|query+info|prop|displaytitle}}",
 +      "apihelp-query+info-paramvalue-prop-varianttitles": "{{doc-apihelp-paramvalue|query+info|prop|varianttitles}}",
        "apihelp-query+info-param-testactions": "{{doc-apihelp-param|query+info|testactions}}",
        "apihelp-query+info-param-token": "{{doc-apihelp-param|query+info|token}}",
        "apihelp-query+info-example-simple": "{{doc-apihelp-example|query+info}}",
        "apihelp-query+recentchanges-paramvalue-prop-sizes": "{{doc-apihelp-paramvalue|query+recentchanges|prop|sizes}}",
        "apihelp-query+recentchanges-paramvalue-prop-redirect": "{{doc-apihelp-paramvalue|query+recentchanges|prop|redirect}}",
        "apihelp-query+recentchanges-paramvalue-prop-patrolled": "{{doc-apihelp-paramvalue|query+recentchanges|prop|patrolled}}",
 +      "apihelp-query+recentchanges-paramvalue-prop-autopatrolled": "{{doc-apihelp-paramvalue|query+recentchanges|prop|autopatrolled}}",
        "apihelp-query+recentchanges-paramvalue-prop-loginfo": "{{doc-apihelp-paramvalue|query+recentchanges|prop|loginfo}}",
        "apihelp-query+recentchanges-paramvalue-prop-tags": "{{doc-apihelp-paramvalue|query+recentchanges|prop|tags}}",
        "apihelp-query+recentchanges-paramvalue-prop-sha1": "{{doc-apihelp-paramvalue|query+recentchanges|prop|sha1}}",
        "apihelp-query+recentchanges-param-limit": "{{doc-apihelp-param|query+recentchanges|limit}}",
        "apihelp-query+recentchanges-param-type": "{{doc-apihelp-param|query+recentchanges|type}}",
        "apihelp-query+recentchanges-param-toponly": "{{doc-apihelp-param|query+recentchanges|toponly}}",
+       "apihelp-query+recentchanges-param-title": "{{doc-apihelp-param|query+recentchanges|title}}",
        "apihelp-query+recentchanges-param-generaterevisions": "{{doc-apihelp-param|query+recentchanges|generaterevisions}}",
        "apihelp-query+recentchanges-example-simple": "{{doc-apihelp-example|query+recentchanges}}",
        "apihelp-query+recentchanges-example-generator": "{{doc-apihelp-example|query+recentchanges}}",
        "apihelp-query+usercontribs-paramvalue-prop-sizediff": "{{doc-apihelp-paramvalue|query+usercontribs|prop|sizediff}}",
        "apihelp-query+usercontribs-paramvalue-prop-flags": "{{doc-apihelp-paramvalue|query+usercontribs|prop|flags}}",
        "apihelp-query+usercontribs-paramvalue-prop-patrolled": "{{doc-apihelp-paramvalue|query+usercontribs|prop|patrolled}}",
 +      "apihelp-query+usercontribs-paramvalue-prop-autopatrolled": "{{doc-apihelp-paramvalue|query+usercontribs|prop|autopatrolled}}",
        "apihelp-query+usercontribs-paramvalue-prop-tags": "{{doc-apihelp-paramvalue|query+usercontribs|prop|tags}}",
        "apihelp-query+usercontribs-param-show": "{{doc-apihelp-param|query+usercontribs|show|params=* $1 - Value of [[mw:Manual:$RCMaxAge|$RCMaxAge]]|paramstart=2}}",
        "apihelp-query+usercontribs-param-tag": "{{doc-apihelp-param|query+usercontribs|tag}}",
        "apihelp-query+watchlist-paramvalue-prop-parsedcomment": "{{doc-apihelp-paramvalue|query+watchlist|prop|parsedcomment}}",
        "apihelp-query+watchlist-paramvalue-prop-timestamp": "{{doc-apihelp-paramvalue|query+watchlist|prop|timestamp}}",
        "apihelp-query+watchlist-paramvalue-prop-patrol": "{{doc-apihelp-paramvalue|query+watchlist|prop|patrol}}",
 +      "apihelp-query+watchlist-paramvalue-prop-autopatrol": "{{doc-apihelp-paramvalue|query+watchlist|prop|autopatrol}}",
        "apihelp-query+watchlist-paramvalue-prop-sizes": "{{doc-apihelp-paramvalue|query+watchlist|prop|sizes}}",
        "apihelp-query+watchlist-paramvalue-prop-notificationtimestamp": "{{doc-apihelp-paramvalue|query+watchlist|prop|notificationtimestamp}}",
        "apihelp-query+watchlist-paramvalue-prop-loginfo": "{{doc-apihelp-paramvalue|query+watchlist|prop|loginfo}}",
        "api-help-parameters": "Label for the API help parameters section\n\nParameters:\n* $1 - Number of parameters to be displayed\n{{Identical|Parameter}}",
        "api-help-param-deprecated": "Displayed in the API help for any deprecated parameter\n{{Identical|Deprecated}}",
        "api-help-param-required": "Displayed in the API help for any required parameter",
 +      "api-help-param-templated": "Displayed in the API help for any templated parameter.\n\nParameters:\n* $1 - Count of template variables in the parameter name.\n* $2 - A list, composed using {{msg-mw|comma-separator}} and {{msg-mw|and}}, of the template variables in the parameter name. The first is formatted using {{msg-mw|api-help-param-templated-var-first|notext=1}} and the rest use {{msg-mw|api-help-param-templated-var|notext=1}}.\n\nSee also:\n* {{msg-mw|api-help-param-templated-var-first}}\n* {{msg-mw|api-help-param-templated-var}}",
 +      "api-help-param-templated-var-first": "Used with {{msg-mw|api-help-param-templated|notext=1}} to display templated parameter replacement variables. See that message for context.\n\nParameters:\n* $1 - Variable.\n* $2 - Parameter from which values are taken.\n\nSee also:\n* {{msg-mw|api-help-param-templated}}\n* {{msg-mw|api-help-param-templated-var}}",
 +      "api-help-param-templated-var": "Used with {{msg-mw|api-help-param-templated|notext=1}} to display templated parameter replacement variables. See that message for context.\n\nParameters:\n* $1 - Variable.\n* $2 - Parameter from which values are taken.\n\nSee also:\n* {{msg-mw|api-help-param-templated}}\n* {{msg-mw|api-help-param-templated-var-first}}",
        "api-help-datatypes-header": "Header for the data type section in the API help output",
        "api-help-datatypes": "{{technical}} {{doc-important|Do not translate or reformat dates inside <nowiki><kbd></kbd></nowiki> or <nowiki><var></var></nowiki> tags}} Documentation of certain API data types\nSee also:\n* [[Special:PrefixIndex/MediaWiki:api-help-param-type]]",
 +      "api-help-templatedparams-header": "Header for the \"templated parameters\" section in the API help output.",
 +      "api-help-templatedparams": "{{technical}} {{doc-important|Unlike in other API messages, feel free to localize the words \"fruit\", \"fruits\", \"quantity\", \"apples\", \"bananas\", and \"strawberries\" in this message even when inside <nowiki><kbd></kbd></nowiki> or <nowiki><var></var></nowiki> tags. Do not change the punctuation, only the words.}} Documentation for the \"templated parameters\" feature.",
        "api-help-param-type-limit": "{{technical}} {{doc-important|Do not translate text inside &lt;kbd&gt; tags}} Used to indicate that a parameter is a \"limit\" type. Parameters:\n* $1 - Always 1.\nSee also:\n* {{msg-mw|api-help-datatypes}}\n* [[Special:PrefixIndex/MediaWiki:api-help-param-type]]",
        "api-help-param-type-integer": "{{technical}} Used to indicate that a parameter is an integer or list of integers. Parameters:\n* $1 - 1 if the parameter takes one value, 2 if the parameter takes a list of values.\nSee also:\n* {{msg-mw|api-help-datatypes}}\n* [[Special:PrefixIndex/MediaWiki:api-help-param-type]]",
        "api-help-param-type-boolean": "{{technical}} {{doc-important|Do not translate <code>Special:ApiHelp</code> in this message.}} Used to indicate that a parameter is a boolean. Parameters:\n* $1 - Always 1.\nSee also:\n* {{msg-mw|api-help-datatypes}}\n* [[Special:PrefixIndex/MediaWiki:api-help-param-type]]",
        "apierror-missingtitle-byname": "{{doc-apierror}}",
        "apierror-moduledisabled": "{{doc-apierror}}\n\nParameters:\n* $1 - Name of the module.",
        "apierror-multival-only-one-of": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name.\n* $2 - Possible values for the parameter.\n* $3 - Number of values.",
 -      "apierror-multival-only-one": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name.",
        "apierror-multpages": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name",
        "apierror-mustbeloggedin-changeauth": "{{doc-apierror}}",
        "apierror-mustbeloggedin-generic": "{{doc-apierror}}",
        "apierror-templateexpansion-notwikitext": "{{doc-apierror}}\n\nParameters:\n* $1 - Page title.\n* $2 - Content model.",
        "apierror-timeout": "{{doc-apierror}}\nAPI error message that can be used for client side localisation of API errors.",
        "apierror-toofewexpiries": "{{doc-apierror}}\n\nParameters:\n* $1 - Number provided.\n* $2 - Number needed.",
 +      "apierror-toomanyvalues": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name.\n* $2 - Maximum number of values allowed.",
        "apierror-unknownaction": "{{doc-apierror}}\n\nParameters:\n* $1 - Action provided.",
        "apierror-unknownerror-editpage": "{{doc-apierror}}\n\nParameters:\n* $1 - Error code (an integer).",
        "apierror-unknownerror-nocode": "{{doc-apierror}}",
        "apiwarn-difftohidden": "{{doc-apierror}}\n\nParameters:\n* $1 - Revision ID number.\n\n\"r\" is short for \"revision\". You may translate it.",
        "apiwarn-errorprinterfailed": "{{doc-apierror}}",
        "apiwarn-errorprinterfailed-ex": "{{doc-apierror}}\n\nParameters:\n* $1 - Exception message, which may already end in punctuation. Probably in English.",
 +      "apiwarn-ignoring-invalid-templated-value": "{{doc-apierror}}\n\nParameters:\n* $1 - Target parameter having a bad value.\n* $2 - The bad value being ignored.",
        "apiwarn-invalidcategory": "{{doc-apierror}}\n\nParameters:\n* $1 - Supplied category name.",
        "apiwarn-invalidtitle": "{{doc-apierror}}\n\nParameters:\n* $1 - Supplied title.",
        "apiwarn-invalidxmlstylesheetext": "{{doc-apierror}}",
        "apiwarn-redirectsandrevids": "{{doc-apierror}}",
        "apiwarn-tokennotallowed": "{{doc-apierror}}\n\nParameters:\n* $1 - Token type being requested, typically named after the action requiring the token.",
        "apiwarn-tokens-origin": "{{doc-apierror}}",
 -      "apiwarn-toomanyvalues": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name.\n* $2 - Maximum number of values allowed.",
        "apiwarn-truncatedresult": "{{doc-apierror}}\n\nParameters:\n* $1 - Size limit in bytes.",
        "apiwarn-unclearnowtimestamp": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name.\n* $2 - Supplied value.",
        "apiwarn-unrecognizedvalues": "{{doc-apierror}}\n\nParameters:\n* $1 - Parameter name.\n* $2 - List of unknown values supplied.\n* $3 - Number of unknown values.",
@@@ -23,6 -23,7 +23,6 @@@ class ApiQueryRecentChangesIntegrationT
                parent::setUp();
  
                self::$users['ApiQueryRecentChangesIntegrationTestUser'] = $this->getMutableTestUser();
 -              $this->doLogin( 'ApiQueryRecentChangesIntegrationTestUser' );
                wfGetDB( DB_MASTER )->delete( 'recentchanges', '*', __METHOD__ );
        }
  
                                $params
                        ),
                        null,
 -                      false
 +                      false,
 +                      $this->getLoggedInTestUser()
                );
        }
  
                        array_merge(
                                [ 'action' => 'query', 'generator' => 'recentchanges' ],
                                $params
 -                      )
 +                      ),
 +                      null,
 +                      false,
 +                      $this->getLoggedInTestUser()
                );
        }
  
                );
        }
  
+       public function testTitleParams() {
+               $page1 = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPage' );
+               $page2 = new TitleValue( 1, 'ApiQueryRecentChangesIntegrationTestPage2' );
+               $page3 = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPage3' );
+               $this->doPageEdits(
+                       $this->getLoggedInTestUser(),
+                       [
+                               [
+                                       'target' => $page1,
+                                       'summary' => 'Create the page',
+                               ],
+                               [
+                                       'target' => $page2,
+                                       'summary' => 'Create the page',
+                               ],
+                               [
+                                       'target' => $page3,
+                                       'summary' => 'Create the page',
+                               ],
+                       ]
+               );
+               $result = $this->doListRecentChangesRequest(
+                       [
+                               'rctitle' => 'ApiQueryRecentChangesIntegrationTestPage',
+                               'rcprop' => 'title'
+                       ]
+               );
+               $result2 = $this->doListRecentChangesRequest(
+                       [
+                               'rctitle' => 'Talk:ApiQueryRecentChangesIntegrationTestPage2',
+                               'rcprop' => 'title'
+                       ]
+               );
+               $this->assertEquals(
+                       [
+                               [
+                                       'type' => 'new',
+                                       'ns' => $page1->getNamespace(),
+                                       'title' => $this->getPrefixedText( $page1 )
+                               ],
+                       ],
+                       $this->getItemsFromApiResponse( $result )
+               );
+               $this->assertEquals(
+                       [
+                               [
+                                       'type' => 'new',
+                                       'ns' => $page2->getNamespace(),
+                                       'title' => $this->getPrefixedText( $page2 )
+                               ],
+                       ],
+                       $this->getItemsFromApiResponse( $result2 )
+               );
+       }
        public function testStartEndParams() {
                $target = new TitleValue( 0, 'ApiQueryRecentChangesIntegrationTestPage' );
                $this->doPageEdit( $this->getLoggedInTestUser(), $target, 'Create the page' );