Merge "Add parser tests for decoding of entities in IDs and fragments"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Tue, 25 Jul 2017 18:29:52 +0000 (18:29 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Tue, 25 Jul 2017 18:29:52 +0000 (18:29 +0000)
12 files changed:
RELEASE-NOTES-1.30
includes/Title.php
includes/changes/EnhancedChangesList.php
includes/specials/SpecialRecentchanges.php
languages/data/Names.php
languages/messages/MessagesSkr.php [new file with mode: 0644]
languages/messages/MessagesSkr_arab.php [new file with mode: 0644]
resources/src/mediawiki.rcfilters/mw.rcfilters.Controller.js
resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.DateButtonWidget.js
resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.DatePopupWidget.js
tests/phpunit/includes/libs/rdbms/database/DatabaseSQLTest.php
tests/phpunit/includes/specials/SpecialRecentchangesTest.php

index 51f9764..c5ab81a 100644 (file)
@@ -46,6 +46,7 @@ section).
 === Languages updated in 1.30 ===
 
 * Support for kbp (Kabɩyɛ / Kabiyè) was added.
+* Support for skr (Saraiki, سرائیکی) was added.
 
 === External library changes in 1.30 ===
 
index 6538538..edfdaca 100644 (file)
@@ -3172,7 +3172,7 @@ class Title implements LinkTarget {
                if ( $limit > -1 ) {
                        $options['LIMIT'] = $limit;
                }
-               $this->mSubpages = TitleArray::newFromResult(
+               return TitleArray::newFromResult(
                        $dbr->select( 'page',
                                [ 'page_id', 'page_namespace', 'page_title', 'page_is_redirect' ],
                                $conds,
@@ -3180,7 +3180,6 @@ class Title implements LinkTarget {
                                $options
                        )
                );
-               return $this->mSubpages;
        }
 
        /**
index 30c6995..55cb9ed 100644 (file)
@@ -102,15 +102,17 @@ class EnhancedChangesList extends ChangesList {
                        $rc->mAttribs['rc_timestamp'],
                        $this->getUser()
                );
+               if ( $this->lastdate === '' ) {
+                       $this->lastdate = $date;
+               }
 
                $ret = '';
 
-               # If it's a new day, add the headline and flush the cache
-               if ( $date != $this->lastdate ) {
-                       # Process current cache
+               # If it's a new day, flush the cache and update $this->lastdate
+               if ( $date !== $this->lastdate ) {
+                       # Process current cache (uses $this->lastdate to generate a heading)
                        $ret = $this->recentChangesBlock();
                        $this->rc_cache = [];
-                       $ret .= Xml::element( 'h4', null, $date ) . "\n";
                        $this->lastdate = $date;
                }
 
@@ -763,7 +765,11 @@ class EnhancedChangesList extends ChangesList {
                        }
                }
 
-               return '<div>' . $blockOut . '</div>';
+               if ( $blockOut === '' ) {
+                       return '';
+               }
+               // $this->lastdate is kept up to date by recentChangesLine()
+               return Xml::element( 'h4', null, $this->lastdate ) . "\n<div>" . $blockOut . '</div>';
        }
 
        /**
index c9c2475..a05900b 100644 (file)
@@ -315,7 +315,7 @@ class SpecialRecentChanges extends ChangesListSpecialPage {
                $opts = parent::getDefaultOptions();
                $user = $this->getUser();
 
-               $opts->add( 'days', $user->getIntOption( 'rcdays' ) );
+               $opts->add( 'days', $user->getIntOption( 'rcdays' ), FormOptions::FLOAT );
                $opts->add( 'limit', $user->getIntOption( 'rclimit' ) );
                $opts->add( 'from', '' );
 
@@ -359,7 +359,7 @@ class SpecialRecentChanges extends ChangesListSpecialPage {
                        if ( preg_match( '/^limit=(\d+)$/', $bit, $m ) ) {
                                $opts['limit'] = $m[1];
                        }
-                       if ( preg_match( '/^days=(\d+)$/', $bit, $m ) ) {
+                       if ( preg_match( '/^days=(\d+(?:\.\d+)?)$/', $bit, $m ) ) {
                                $opts['days'] = $m[1];
                        }
                        if ( preg_match( '/^namespace=(.*)$/', $bit, $m ) ) {
@@ -388,7 +388,6 @@ class SpecialRecentChanges extends ChangesListSpecialPage {
 
                // Calculate cutoff
                $cutoff_unixtime = time() - ( $opts['days'] * 86400 );
-               $cutoff_unixtime = $cutoff_unixtime - ( $cutoff_unixtime % 86400 );
                $cutoff = $dbr->timestamp( $cutoff_unixtime );
 
                $fromValid = preg_match( '/^[0-9]{14}$/', $opts['from'] );
index 00d91ce..19ff2a4 100644 (file)
@@ -383,6 +383,8 @@ class Names {
                'si' => 'සිංහල', # Sinhalese
                'simple' => 'Simple English', # Simple English
                'sk' => 'slovenčina', # Slovak
+               'skr' => 'سرائیکی', # Saraiki (multiple scripts - defaults to Arabic)
+               'skr-arab' => 'سرائیکی', # Saraiki (Arabic script)
                'sl' => 'slovenščina', # Slovenian
                'sli' => 'Schläsch', # Lower Selisian
                'sm' => 'Gagana Samoa', # Samoan
diff --git a/languages/messages/MessagesSkr.php b/languages/messages/MessagesSkr.php
new file mode 100644 (file)
index 0000000..2072b8d
--- /dev/null
@@ -0,0 +1,11 @@
+<?php
+/** Saraiki (multiple scripts)
+ *
+ * To improve a translation please visit https://translatewiki.net
+ *
+ * @ingroup Language
+ * @file
+ *
+ */
+
+$fallback = 'skr-arab';
diff --git a/languages/messages/MessagesSkr_arab.php b/languages/messages/MessagesSkr_arab.php
new file mode 100644 (file)
index 0000000..901e2aa
--- /dev/null
@@ -0,0 +1,13 @@
+<?php
+/** Saraiki (Arabic script) (سرائیکی)
+ *
+ * To improve a translation please visit https://translatewiki.net
+ *
+ * @ingroup Language
+ * @file
+ *
+ */
+
+$fallback = 'ur, pnb';
+
+$rtl = true;
index cced3d5..5ebec27 100644 (file)
                                        'default': '7',
                                        filters: [
                                                // Hours (1, 2, 6, 12)
-                                               // TEMPORARY: Hide hours temporarily
-                                               // 0.04166, 0.0833, 0.25, 0.5,
+                                               0.04166, 0.0833, 0.25, 0.5,
                                                // Days
                                                1, 3, 7, 14, 30
                                        ].map( function ( num ) {
                                                        uriValue,
                                                        // In this case we don't want to round because it can be arbitrary
                                                        // weird numbers but we want to round to 2 decimal digits
-
-                                                       // HACK: Temporarily remove hours from UI
-                                                       // Number( uriValue ) < 1 ?
-                                                       //      ( Number( uriValue ) * 24 ).toFixed( 2 ) :
-                                                       //      Number( uriValue )
-                                                       Number( uriValue )
+                                                       Number( uriValue ) < 1 ?
+                                                               ( Number( uriValue ) * 24 ).toFixed( 2 ) :
+                                                               Number( uriValue )
                                                ) );
                                        } else {
                                                groupData.filters.push( createFilterDataFromNumber( uriValue, uriValue ) );
index 681b350..1569f38 100644 (file)
                if ( item ) {
                        this.button.setLabel(
                                mw.msg(
-                                       // Number( item.getParamName() ) < 1 ?
-                                       //      'rcfilters-days-show-hours' : 'rcfilters-days-show-days',
-
-                                       // Temporarily hide the functionality for hours, use days only
-                                       'rcfilters-days-show-days',
+                                       Number( item.getParamName() ) < 1 ?
+                                               'rcfilters-days-show-hours' : 'rcfilters-days-show-days',
                                        item.getLabel()
                                )
                        );
index ac841c0..6971df5 100644 (file)
@@ -16,8 +16,6 @@
 
                this.model = model;
 
-               /*
-               // HACK: Temporarily remove hours from UI
                this.hoursValuePicker = new mw.rcfilters.ui.ValuePickerWidget(
                        this.model,
                        {
                                label: mw.msg( 'rcfilters-hours-title' ),
                                itemFilter: function ( itemModel ) { return Number( itemModel.getParamName() ) < 1; }
                        }
-               );*/
+               );
                this.daysValuePicker = new mw.rcfilters.ui.ValuePickerWidget(
                        this.model,
                        {
                                classes: [ 'mw-rcfilters-ui-datePopupWidget-days' ],
-                               label: mw.msg( 'rcfilters-days-title' )
-                               // HACK: Temporarily remove hours from UI
-                               // itemFilter: function ( itemModel ) { return Number( itemModel.getParamName() ) >= 1; }
+                               label: mw.msg( 'rcfilters-days-title' ),
+                               itemFilter: function ( itemModel ) { return Number( itemModel.getParamName() ) >= 1; }
                        }
                );
 
                // Events
-               // HACK: Temporarily remove hours from UI
-               // this.hoursValuePicker.connect( this, { choose: [ 'emit', 'days' ] } );
+               this.hoursValuePicker.connect( this, { choose: [ 'emit', 'days' ] } );
                this.daysValuePicker.connect( this, { choose: [ 'emit', 'days' ] } );
 
                // Initialize
                this.$element
                        .addClass( 'mw-rcfilters-ui-datePopupWidget' )
                        .append(
-                               // HACK: Temporarily remove hours from UI
-                               // this.hoursValuePicker.$element,
+                               this.hoursValuePicker.$element,
                                this.daysValuePicker.$element
                        );
        };
index 57666bd..f519772 100644 (file)
@@ -22,13 +22,18 @@ class DatabaseSQLTest extends PHPUnit_Framework_TestCase {
                );
        }
 
-       protected function assertLastSqlDb( $sqlText, $db ) {
+       protected function assertLastSqlDb( $sqlText, DatabaseTestHelper $db ) {
                $this->assertEquals( $sqlText, $db->getLastSqls() );
        }
 
        /**
         * @dataProvider provideSelect
         * @covers Wikimedia\Rdbms\Database::select
+        * @covers Wikimedia\Rdbms\Database::selectSQLText
+        * @covers Wikimedia\Rdbms\Database::tableNamesWithIndexClauseOrJOIN
+        * @covers Wikimedia\Rdbms\Database::makeSelectOptions
+        * @covers Wikimedia\Rdbms\Database::makeOrderBy
+        * @covers Wikimedia\Rdbms\Database::makeGroupByWithHaving
         */
        public function testSelect( $sql, $sqlText ) {
                $this->database->select(
@@ -54,6 +59,23 @@ class DatabaseSQLTest extends PHPUnit_Framework_TestCase {
                                        "FROM table " .
                                        "WHERE alias = 'text'"
                        ],
+                       [
+                               [
+                                       // 'tables' with space prepended indicates pre-escaped table name
+                                       'tables' => ' table LEFT JOIN table2',
+                                       'fields' => [ 'field' ],
+                                       'conds' => [ 'field' => 'text' ],
+                               ],
+                               "SELECT field FROM  table LEFT JOIN table2 WHERE field = 'text'"
+                       ],
+                       [
+                               [
+                                       // Empty 'tables' is allowed
+                                       'tables' => '',
+                                       'fields' => [ 'SPECIAL_QUERY()' ],
+                               ],
+                               "SELECT SPECIAL_QUERY()"
+                       ],
                        [
                                [
                                        'tables' => 'table',
@@ -129,12 +151,38 @@ class DatabaseSQLTest extends PHPUnit_Framework_TestCase {
                                        "FROM table " .
                                        "WHERE alias IN ('1','2','3','4')"
                        ],
+                       [
+                               [
+                                       'tables' => 'table',
+                                       'fields' => [ 'field' ],
+                                       'options' => [ 'DISTINCT', 'LOCK IN SHARE MODE' ],
+                               ],
+                               "SELECT DISTINCT field FROM table      LOCK IN SHARE MODE"
+                       ],
+                       [
+                               [
+                                       'tables' => 'table',
+                                       'fields' => [ 'field' ],
+                                       'options' => [ 'EXPLAIN' => true ],
+                               ],
+                               'EXPLAIN SELECT field FROM table'
+                       ],
+                       [
+                               [
+                                       'tables' => 'table',
+                                       'fields' => [ 'field' ],
+                                       'options' => [ 'FOR UPDATE' ],
+                               ],
+                               "SELECT field FROM table      FOR UPDATE"
+                       ],
                ];
        }
 
        /**
         * @dataProvider provideUpdate
         * @covers Wikimedia\Rdbms\Database::update
+        * @covers Wikimedia\Rdbms\Database::makeUpdateOptions
+        * @covers Wikimedia\Rdbms\Database::makeUpdateOptionsArray
         */
        public function testUpdate( $sql, $sqlText ) {
                $this->database->update(
@@ -303,6 +351,7 @@ class DatabaseSQLTest extends PHPUnit_Framework_TestCase {
        /**
         * @dataProvider provideInsert
         * @covers Wikimedia\Rdbms\Database::insert
+        * @covers Wikimedia\Rdbms\Database::makeInsertOptions
         */
        public function testInsert( $sql, $sqlText ) {
                $this->database->insert(
@@ -356,6 +405,7 @@ class DatabaseSQLTest extends PHPUnit_Framework_TestCase {
        /**
         * @dataProvider provideInsertSelect
         * @covers Wikimedia\Rdbms\Database::insertSelect
+        * @covers Wikimedia\Rdbms\Database::nativeInsertSelect
         */
        public function testInsertSelect( $sql, $sqlTextNative, $sqlSelect, $sqlInsert ) {
                $this->database->insertSelect(
@@ -673,6 +723,7 @@ class DatabaseSQLTest extends PHPUnit_Framework_TestCase {
        /**
         * @dataProvider provideBuildLike
         * @covers Wikimedia\Rdbms\Database::buildLike
+        * @covers Wikimedia\Rdbms\Database::escapeLikeInternal
         */
        public function testBuildLike( $array, $sqlText ) {
                $this->assertEquals( trim( $this->database->buildLike(
@@ -921,6 +972,7 @@ class DatabaseSQLTest extends PHPUnit_Framework_TestCase {
 
        /**
         * @covers Wikimedia\Rdbms\Database::commit
+        * @covers Wikimedia\Rdbms\Database::doCommit
         */
        public function testTransactionCommit() {
                $this->database->begin( __METHOD__ );
@@ -930,6 +982,7 @@ class DatabaseSQLTest extends PHPUnit_Framework_TestCase {
 
        /**
         * @covers Wikimedia\Rdbms\Database::rollback
+        * @covers Wikimedia\Rdbms\Database::doRollback
         */
        public function testTransactionRollback() {
                $this->database->begin( __METHOD__ );
@@ -1035,6 +1088,9 @@ class DatabaseSQLTest extends PHPUnit_Framework_TestCase {
                ];
        }
 
+       /**
+        * @covers Wikimedia\Rdbms\Database::registerTempTableOperation
+        */
        public function testSessionTempTables() {
                $temp1 = $this->database->tableName( 'tmp_table_1' );
                $temp2 = $this->database->tableName( 'tmp_table_2' );
index 85becff..a9a612d 100644 (file)
@@ -27,6 +27,8 @@ class SpecialRecentchangesTest extends AbstractChangesListSpecialPageTestCase {
 
                        [ 'days=3', [ 'days' => '3' ] ],
 
+                       [ 'days=0.25', [ 'days' => '0.25'] ],
+
                        [ 'namespace=5', [ 'namespace' => '5' ] ],
 
                        [ 'namespace=5|3', [ 'namespace' => '5|3' ] ],