Add namespace restrictions to Special:Block and API
authorThalia <thalia.e.chan@googlemail.com>
Fri, 14 Dec 2018 21:08:40 +0000 (21:08 +0000)
committerThalia <thalia.e.chan@googlemail.com>
Tue, 22 Jan 2019 12:48:55 +0000 (12:48 +0000)
This adds a UI for blocking namespaces to Special:Block
and a namespacerestrictions parameter to the block API.

The number of namespace restrictions in a single block
is not limited as page restrictions are.

The checkbox allowing the blocker to specify whether
the target can edit their own user page is normally
disabled for a partial block, but is re-enabled if
the block is to the user talk namespace.

If the config $wgBlockAllowsUTEdit is set to false, the
checkbox will not appear, and the target will not be
able to edit their own user talk page if they are
sitewide-blocked, namespace-blocked from the user talk
namespace, or page-blocked from their user talk page.

Bug: T204986
Change-Id: I9e231ad109d7285486ec332b26780339592b8df7

includes/api/ApiBlock.php
includes/api/i18n/en.json
includes/api/i18n/qqq.json
includes/specials/SpecialBlock.php
languages/i18n/en.json
languages/i18n/qqq.json
resources/src/mediawiki.special.block.js
resources/src/mediawiki.special/block.less
tests/phpunit/includes/api/ApiBlockTest.php
tests/phpunit/includes/specials/SpecialBlockTest.php

index ed3d01c..14177ed 100644 (file)
@@ -56,12 +56,14 @@ class ApiBlock extends ApiBase {
 
                $editingRestriction = 'sitewide';
                $pageRestrictions = '';
 
                $editingRestriction = 'sitewide';
                $pageRestrictions = '';
+               $namespaceRestrictions = '';
                if ( $this->getConfig()->get( 'EnablePartialBlocks' ) ) {
                        if ( $params['partial'] ) {
                                $editingRestriction = 'partial';
                        }
 
                        $pageRestrictions = implode( "\n", (array)$params['pagerestrictions'] );
                if ( $this->getConfig()->get( 'EnablePartialBlocks' ) ) {
                        if ( $params['partial'] ) {
                                $editingRestriction = 'partial';
                        }
 
                        $pageRestrictions = implode( "\n", (array)$params['pagerestrictions'] );
+                       $namespaceRestrictions = implode( "\n", (array)$params['namespacerestrictions'] );
                }
 
                if ( $params['userid'] !== null ) {
                }
 
                if ( $params['userid'] !== null ) {
@@ -119,6 +121,7 @@ class ApiBlock extends ApiBase {
                        'Tags' => $params['tags'],
                        'EditingRestriction' => $editingRestriction,
                        'PageRestrictions' => $pageRestrictions,
                        'Tags' => $params['tags'],
                        'EditingRestriction' => $editingRestriction,
                        'PageRestrictions' => $pageRestrictions,
+                       'NamespaceRestrictions' => $namespaceRestrictions,
                ];
 
                $retval = SpecialBlock::processForm( $data, $this->getContext() );
                ];
 
                $retval = SpecialBlock::processForm( $data, $this->getContext() );
@@ -152,6 +155,7 @@ class ApiBlock extends ApiBase {
                if ( $this->getConfig()->get( 'EnablePartialBlocks' ) ) {
                        $res['partial'] = $params['partial'];
                        $res['pagerestrictions'] = $params['pagerestrictions'];
                if ( $this->getConfig()->get( 'EnablePartialBlocks' ) ) {
                        $res['partial'] = $params['partial'];
                        $res['pagerestrictions'] = $params['pagerestrictions'];
+                       $res['namespacerestrictions'] = $params['namespacerestrictions'];
                }
 
                $this->getResult()->addValue( null, $this->getModuleName(), $res );
                }
 
                $this->getResult()->addValue( null, $this->getModuleName(), $res );
@@ -196,6 +200,10 @@ class ApiBlock extends ApiBase {
                                ApiBase::PARAM_ISMULTI_LIMIT1 => 10,
                                ApiBase::PARAM_ISMULTI_LIMIT2 => 10,
                        ];
                                ApiBase::PARAM_ISMULTI_LIMIT1 => 10,
                                ApiBase::PARAM_ISMULTI_LIMIT2 => 10,
                        ];
+                       $params['namespacerestrictions'] = [
+                               ApiBase::PARAM_ISMULTI => true,
+                               ApiBase::PARAM_TYPE => 'namespace',
+                       ];
                }
 
                return $params;
                }
 
                return $params;
index 8f5ba8d..23bd814 100644 (file)
@@ -41,7 +41,8 @@
        "apihelp-block-param-watchuser": "Watch the user's or IP address's user and talk pages.",
        "apihelp-block-param-tags": "Change tags to apply to the entry in the block log.",
        "apihelp-block-param-partial": "Block user from specific pages or namespaces rather than the entire site.",
        "apihelp-block-param-watchuser": "Watch the user's or IP address's user and talk pages.",
        "apihelp-block-param-tags": "Change tags to apply to the entry in the block log.",
        "apihelp-block-param-partial": "Block user from specific pages or namespaces rather than the entire site.",
-       "apihelp-block-param-pagerestrictions": "List of titles to block the user from editing. Only applies when 'partial' is set to true.",
+       "apihelp-block-param-pagerestrictions": "List of titles to block the user from editing. Only applies when <var>partial</var> is set to true.",
+       "apihelp-block-param-namespacerestrictions": "List of namespace IDs to block the user from editing. Only applies when <var>partial</var> is set to true.",
        "apihelp-block-example-ip-simple": "Block IP address <kbd>192.0.2.5</kbd> for three days with reason <kbd>First strike</kbd>.",
        "apihelp-block-example-user-complex": "Block user <kbd>Vandal</kbd> indefinitely with reason <kbd>Vandalism</kbd>, and prevent new account creation and email sending.",
 
        "apihelp-block-example-ip-simple": "Block IP address <kbd>192.0.2.5</kbd> for three days with reason <kbd>First strike</kbd>.",
        "apihelp-block-example-user-complex": "Block user <kbd>Vandal</kbd> indefinitely with reason <kbd>Vandalism</kbd>, and prevent new account creation and email sending.",
 
index 6437adf..bdd0afb 100644 (file)
@@ -50,6 +50,7 @@
        "apihelp-block-param-tags": "{{doc-apihelp-param|block|tags}}",
        "apihelp-block-param-partial": "{{doc-apihelp-param|block|partial}}",
        "apihelp-block-param-pagerestrictions": "{{doc-apihelp-param|block|pagerestrictions}}",
        "apihelp-block-param-tags": "{{doc-apihelp-param|block|tags}}",
        "apihelp-block-param-partial": "{{doc-apihelp-param|block|partial}}",
        "apihelp-block-param-pagerestrictions": "{{doc-apihelp-param|block|pagerestrictions}}",
+       "apihelp-block-param-namespacerestrictions": "{{doc-apihelp-param|block|namespacerestrictions}}",
        "apihelp-block-example-ip-simple": "{{doc-apihelp-example|block}}",
        "apihelp-block-example-user-complex": "{{doc-apihelp-example|block}}",
        "apihelp-changeauthenticationdata-summary": "{{doc-apihelp-summary|changeauthenticationdata}}",
        "apihelp-block-example-ip-simple": "{{doc-apihelp-example|block}}",
        "apihelp-block-example-user-complex": "{{doc-apihelp-example|block}}",
        "apihelp-changeauthenticationdata-summary": "{{doc-apihelp-summary|changeauthenticationdata}}",
index a482720..4fd263f 100644 (file)
@@ -23,6 +23,7 @@
 
 use MediaWiki\Block\BlockRestriction;
 use MediaWiki\Block\Restriction\PageRestriction;
 
 use MediaWiki\Block\BlockRestriction;
 use MediaWiki\Block\Restriction\PageRestriction;
+use MediaWiki\Block\Restriction\NamespaceRestriction;
 
 /**
  * A special page that allows users with 'block' right to block users from
 
 /**
  * A special page that allows users with 'block' right to block users from
@@ -187,13 +188,23 @@ class SpecialBlock extends FormSpecialPage {
                                'label' => $this->msg( 'ipb-pages-label' )->text(),
                                'exists' => true,
                                'max' => 10,
                                'label' => $this->msg( 'ipb-pages-label' )->text(),
                                'exists' => true,
                                'max' => 10,
-                               'cssclass' => 'mw-block-page-restrictions',
+                               'cssclass' => 'mw-block-restriction',
                                'showMissing' => false,
                                'input' => [
                                        'autocomplete' => false
                                ],
                                'section' => 'actions',
                        ];
                                'showMissing' => false,
                                'input' => [
                                        'autocomplete' => false
                                ],
                                'section' => 'actions',
                        ];
+                       $a['NamespaceRestrictions'] = [
+                               'type' => 'namespacesmultiselect',
+                               'label' => $this->msg( 'ipb-namespaces-label' )->text(),
+                               'exists' => true,
+                               'cssclass' => 'mw-block-restriction',
+                               'input' => [
+                                       'autocomplete' => false
+                               ],
+                               'section' => 'actions',
+                       ];
                }
 
                $a['CreateAccount'] = [
                }
 
                $a['CreateAccount'] = [
@@ -391,21 +402,31 @@ class SpecialBlock extends FormSpecialPage {
 
                        if ( $block instanceof Block ) {
                                $pageRestrictions = [];
 
                        if ( $block instanceof Block ) {
                                $pageRestrictions = [];
+                               $namespaceRestrictions = [];
                                foreach ( $block->getRestrictions() as $restriction ) {
                                foreach ( $block->getRestrictions() as $restriction ) {
-                                       if ( $restriction->getType() !== 'page' ) {
-                                               continue;
+                                       switch ( $restriction->getType() ) {
+                                               case PageRestriction::TYPE:
+                                                       $pageRestrictions[] = $restriction->getTitle()->getPrefixedText();
+                                                       break;
+                                               case NamespaceRestriction::TYPE:
+                                                       $namespaceRestrictions[] = $restriction->getValue();
+                                                       break;
                                        }
                                        }
-
-                                       $pageRestrictions[] = $restriction->getTitle()->getPrefixedText();
                                }
 
                                }
 
-                               if ( !$block->isSitewide() && empty( $pageRestrictions ) ) {
+                               if (
+                                       !$block->isSitewide() &&
+                                       empty( $pageRestrictions ) &&
+                                       empty( $namespaceRestrictions )
+                               ) {
                                        $fields['Editing']['default'] = false;
                                }
 
                                // Sort the restrictions so they are in alphabetical order.
                                sort( $pageRestrictions );
                                $fields['PageRestrictions']['default'] = implode( "\n", $pageRestrictions );
                                        $fields['Editing']['default'] = false;
                                }
 
                                // Sort the restrictions so they are in alphabetical order.
                                sort( $pageRestrictions );
                                $fields['PageRestrictions']['default'] = implode( "\n", $pageRestrictions );
+                               sort( $namespaceRestrictions );
+                               $fields['NamespaceRestrictions']['default'] = implode( "\n", $namespaceRestrictions );
                        }
                }
        }
                        }
                }
        }
@@ -839,10 +860,11 @@ class SpecialBlock extends FormSpecialPage {
                        return $reason;
                }
 
                        return $reason;
                }
 
-               $restrictions = [];
+               $pageRestrictions = [];
+               $namespaceRestrictions = [];
                if ( $enablePartialBlocks ) {
                        if ( $data['PageRestrictions'] !== '' ) {
                if ( $enablePartialBlocks ) {
                        if ( $data['PageRestrictions'] !== '' ) {
-                               $restrictions = array_map( function ( $text ) {
+                               $pageRestrictions = array_map( function ( $text ) {
                                        $title = Title::newFromText( $text );
                                        // Use the link cache since the title has already been loaded when
                                        // the field was validated.
                                        $title = Title::newFromText( $text );
                                        // Use the link cache since the title has already been loaded when
                                        // the field was validated.
@@ -851,7 +873,13 @@ class SpecialBlock extends FormSpecialPage {
                                        return $restriction;
                                }, explode( "\n", $data['PageRestrictions'] ) );
                        }
                                        return $restriction;
                                }, explode( "\n", $data['PageRestrictions'] ) );
                        }
+                       if ( $data['NamespaceRestrictions'] !== '' ) {
+                               $namespaceRestrictions = array_map( function ( $id ) {
+                                       return new NamespaceRestriction( 0, $id );
+                               }, explode( "\n", $data['NamespaceRestrictions'] ) );
+                       }
 
 
+                       $restrictions = ( array_merge( $pageRestrictions, $namespaceRestrictions ) );
                        $block->setRestrictions( $restrictions );
                }
 
                        $block->setRestrictions( $restrictions );
                }
 
@@ -1167,6 +1195,7 @@ class SpecialBlock extends FormSpecialPage {
                if ( isset( $data['Editing'] ) && $data['Editing'] === false ) {
                        $data['EditingRestriction'] = 'partial';
                        $data['PageRestrictions'] = '';
                if ( isset( $data['Editing'] ) && $data['Editing'] === false ) {
                        $data['EditingRestriction'] = 'partial';
                        $data['PageRestrictions'] = '';
+                       $data['NamespaceRestrictions'] = '';
                }
                return self::processForm( $data, $form->getContext() );
        }
                }
                return self::processForm( $data, $form->getContext() );
        }
index 18f41f1..460095a 100644 (file)
        "ipb-sitewide": "Sitewide",
        "ipb-partial": "Partial",
        "ipb-pages-label": "Pages",
        "ipb-sitewide": "Sitewide",
        "ipb-partial": "Partial",
        "ipb-pages-label": "Pages",
+       "ipb-namespaces-label": "Namespaces",
        "badipaddress": "Invalid IP address",
        "blockipsuccesssub": "Block succeeded",
        "blockipsuccesstext": "[[Special:Contributions/$1|$1]] has been blocked.<br />\nSee the [[Special:BlockList|block list]] to review blocks.",
        "badipaddress": "Invalid IP address",
        "blockipsuccesssub": "Block succeeded",
        "blockipsuccesstext": "[[Special:Contributions/$1|$1]] has been blocked.<br />\nSee the [[Special:BlockList|block list]] to review blocks.",
index 1984fd5..6f006c9 100644 (file)
        "ipb-sitewide": "A type of block the user can select from on [[Special:Block]].",
        "ipb-partial": "A type of block the user can select from on [[Special:Block]].",
        "ipb-pages-label": "The label for an autocomplete text field to specify pages to block a user from editing on [[Special:Block]].",
        "ipb-sitewide": "A type of block the user can select from on [[Special:Block]].",
        "ipb-partial": "A type of block the user can select from on [[Special:Block]].",
        "ipb-pages-label": "The label for an autocomplete text field to specify pages to block a user from editing on [[Special:Block]].",
+       "ipb-namespaces-label": "The label for an autocomplete text field to specify namespaces to block a user from editing on [[Special:Block]].",
        "badipaddress": "An error message shown when one entered an invalid IP address in blocking page.",
        "blockipsuccesssub": "Used as page title in [[Special:Block]].\n\nThis message is the subject for the following message:\n* {{msg-mw|Blockipsuccesstext}}",
        "blockipsuccesstext": "Used in [[Special:Block]].\nThe title (subject) for this message is {{msg-mw|Blockipsuccesssub}}.\n\nParameters:\n* $1 - username, can be used for GENDER",
        "badipaddress": "An error message shown when one entered an invalid IP address in blocking page.",
        "blockipsuccesssub": "Used as page title in [[Special:Block]].\n\nThis message is the subject for the following message:\n* {{msg-mw|Blockipsuccesstext}}",
        "blockipsuccesstext": "Used in [[Special:Block]].\nThe title (subject) for this message is {{msg-mw|Blockipsuccesssub}}.\n\nParameters:\n* $1 - username, can be used for GENDER",
index b6d9b48..b777c88 100644 (file)
@@ -22,7 +22,8 @@
                        editingWidget = infuseIfExists( $( '#mw-input-wpEditing' ) ),
                        editingRestrictionWidget = infuseIfExists( $( '#mw-input-wpEditingRestriction' ) ),
                        preventTalkPageEdit = infuseIfExists( $( '#mw-input-wpDisableUTEdit' ) ),
                        editingWidget = infuseIfExists( $( '#mw-input-wpEditing' ) ),
                        editingRestrictionWidget = infuseIfExists( $( '#mw-input-wpEditingRestriction' ) ),
                        preventTalkPageEdit = infuseIfExists( $( '#mw-input-wpDisableUTEdit' ) ),
-                       pageRestrictionsWidget = infuseIfExists( $( '#mw-input-wpPageRestrictions' ) );
+                       pageRestrictionsWidget = infuseIfExists( $( '#mw-input-wpPageRestrictions' ) ),
+                       namespaceRestrictionsWidget = infuseIfExists( $( '#mw-input-wpNamespaceRestrictions' ) );
 
                function updateBlockOptions() {
                        var blocktarget = blockTargetWidget.getValue().trim(),
 
                function updateBlockOptions() {
                        var blocktarget = blockTargetWidget.getValue().trim(),
                        if ( watchUserField ) {
                                watchUserField.toggle( !isIpRange || isEmpty );
                        }
                        if ( watchUserField ) {
                                watchUserField.toggle( !isIpRange || isEmpty );
                        }
-                       if ( pageRestrictionsWidget ) {
+                       if ( editingRestrictionWidget ) {
                                editingRestrictionWidget.setDisabled( !editingIsSelected );
                                editingRestrictionWidget.setDisabled( !editingIsSelected );
+                       }
+                       if ( pageRestrictionsWidget ) {
                                pageRestrictionsWidget.setDisabled( !editingIsSelected || editingRestrictionValue === 'sitewide' );
                        }
                                pageRestrictionsWidget.setDisabled( !editingIsSelected || editingRestrictionValue === 'sitewide' );
                        }
-                       if ( preventTalkPageEdit ) {
-                               // TODO: (T210475) this option is disabled for partial blocks unless
-                               // a namespace restriction for User_talk namespace is in place.
-                               // This needs to be updated once Namespace restrictions is available
-                               preventTalkPageEdit.setDisabled( editingRestrictionValue === 'partial' && editingIsSelected );
+                       if ( namespaceRestrictionsWidget ) {
+                               namespaceRestrictionsWidget.setDisabled( !editingIsSelected || editingRestrictionValue === 'sitewide' );
+                       }
+                       if ( preventTalkPageEdit && namespaceRestrictionsWidget ) {
+                               // This option is disabled for partial blocks unless a namespace restriction
+                               // for the User_talk namespace is in place.
+                               preventTalkPageEdit.setDisabled(
+                                       editingIsSelected &&
+                                       editingRestrictionValue === 'partial' &&
+                                       namespaceRestrictionsWidget.getValue().indexOf(
+                                               String( mw.config.get( 'wgNamespaceIds' ).user_talk )
+                                       ) === -1
+                               );
                        }
 
                }
                        }
 
                }
                        // Bind functions so they're checked whenever stuff changes
                        blockTargetWidget.on( 'change', updateBlockOptions );
                        expiryWidget.on( 'change', updateBlockOptions );
                        // Bind functions so they're checked whenever stuff changes
                        blockTargetWidget.on( 'change', updateBlockOptions );
                        expiryWidget.on( 'change', updateBlockOptions );
+                       if ( editingWidget ) {
+                               editingWidget.on( 'change', updateBlockOptions );
+                       }
                        if ( editingRestrictionWidget ) {
                                editingRestrictionWidget.on( 'change', updateBlockOptions );
                        }
                        if ( editingRestrictionWidget ) {
                                editingRestrictionWidget.on( 'change', updateBlockOptions );
                        }
-                       if ( editingWidget ) {
-                               editingWidget.on( 'change', updateBlockOptions );
+                       if ( namespaceRestrictionsWidget ) {
+                               namespaceRestrictionsWidget.on( 'change', updateBlockOptions );
                        }
 
                        // Call them now to set initial state (ie. Special:Block/Foobar?wpBlockExpiry=2+hours)
                        }
 
                        // Call them now to set initial state (ie. Special:Block/Foobar?wpBlockExpiry=2+hours)
index 30cafe5..d7ee3da 100644 (file)
@@ -11,7 +11,7 @@ body.mw-special-Block {
                margin-left: @ooui-spacing-radio-label;
        }
 
                margin-left: @ooui-spacing-radio-label;
        }
 
-       .mw-block-page-restrictions.oo-ui-fieldLayout {
+       .mw-block-restriction.oo-ui-fieldLayout {
                margin-left: 2 * @ooui-spacing-radio-label;
 
                .oo-ui-widget {
                margin-left: 2 * @ooui-spacing-radio-label;
 
                .oo-ui-widget {
index feafdef..a26f8a8 100644 (file)
@@ -1,5 +1,8 @@
 <?php
 
 <?php
 
+use MediaWiki\Block\Restriction\PageRestriction;
+use MediaWiki\Block\Restriction\NamespaceRestriction;
+
 /**
  * @group API
  * @group Database
 /**
  * @group API
  * @group Database
@@ -235,17 +238,22 @@ class ApiBlockTest extends ApiTestCase {
 
                $title = 'Foo';
                $page = $this->getExistingTestPage( $title );
 
                $title = 'Foo';
                $page = $this->getExistingTestPage( $title );
+               $namespace = NS_TALK;
 
                $this->doBlock( [
                        'partial' => true,
                        'pagerestrictions' => $title,
 
                $this->doBlock( [
                        'partial' => true,
                        'pagerestrictions' => $title,
+                       'namespacerestrictions' => $namespace,
                ] );
 
                $block = Block::newFromTarget( $this->mUser->getName() );
 
                $this->assertFalse( $block->isSitewide() );
                ] );
 
                $block = Block::newFromTarget( $this->mUser->getName() );
 
                $this->assertFalse( $block->isSitewide() );
-               $this->assertCount( 1, $block->getRestrictions() );
+               $this->assertCount( 2, $block->getRestrictions() );
+               $this->assertInstanceOf( PageRestriction::class, $block->getRestrictions()[0] );
                $this->assertEquals( $title, $block->getRestrictions()[0]->getTitle()->getText() );
                $this->assertEquals( $title, $block->getRestrictions()[0]->getTitle()->getText() );
+               $this->assertInstanceOf( NamespaceRestriction::class, $block->getRestrictions()[1] );
+               $this->assertEquals( $namespace, $block->getRestrictions()[1]->getValue() );
        }
 
        /**
        }
 
        /**
@@ -290,7 +298,7 @@ class ApiBlockTest extends ApiTestCase {
         * @expectedExceptionMessage Too many values supplied for parameter "pagerestrictions". The
         * limit is 10.
         */
         * @expectedExceptionMessage Too many values supplied for parameter "pagerestrictions". The
         * limit is 10.
         */
-       public function testBlockingToManyRestrictions() {
+       public function testBlockingToManyPageRestrictions() {
                $this->setMwGlobals( [
                        'wgEnablePartialBlocks' => true,
                ] );
                $this->setMwGlobals( [
                        'wgEnablePartialBlocks' => true,
                ] );
index e2c0084..55a8b66 100644 (file)
@@ -2,6 +2,7 @@
 
 use MediaWiki\Block\BlockRestriction;
 use MediaWiki\Block\Restriction\PageRestriction;
 
 use MediaWiki\Block\BlockRestriction;
 use MediaWiki\Block\Restriction\PageRestriction;
+use MediaWiki\Block\Restriction\NamespaceRestriction;
 use Wikimedia\TestingAccessWrapper;
 
 /**
 use Wikimedia\TestingAccessWrapper;
 
 /**
@@ -45,6 +46,7 @@ class SpecialBlockTest extends SpecialPageTestBase {
 
                $this->assertArrayNotHasKey( 'EditingRestriction', $fields );
                $this->assertArrayNotHasKey( 'PageRestrictions', $fields );
 
                $this->assertArrayNotHasKey( 'EditingRestriction', $fields );
                $this->assertArrayNotHasKey( 'PageRestrictions', $fields );
+               $this->assertArrayNotHasKey( 'NamespaceRestrictions', $fields );
        }
 
        /**
        }
 
        /**
@@ -60,6 +62,7 @@ class SpecialBlockTest extends SpecialPageTestBase {
 
                $this->assertArrayHasKey( 'EditingRestriction', $fields );
                $this->assertArrayHasKey( 'PageRestrictions', $fields );
 
                $this->assertArrayHasKey( 'EditingRestriction', $fields );
                $this->assertArrayHasKey( 'PageRestrictions', $fields );
+               $this->assertArrayHasKey( 'NamespaceRestrictions', $fields );
        }
 
        /**
        }
 
        /**
@@ -115,6 +118,7 @@ class SpecialBlockTest extends SpecialPageTestBase {
                $block->setRestrictions( [
                        new PageRestriction( 0, $pageSaturn->getId() ),
                        new PageRestriction( 0, $pageMars->getId() ),
                $block->setRestrictions( [
                        new PageRestriction( 0, $pageSaturn->getId() ),
                        new PageRestriction( 0, $pageMars->getId() ),
+                       new NamespaceRestriction( 0, NS_TALK ),
                ] );
 
                $block->insert();
                ] );
 
                $block->insert();
@@ -228,7 +232,7 @@ class SpecialBlockTest extends SpecialPageTestBase {
        /**
         * @covers ::processForm()
         */
        /**
         * @covers ::processForm()
         */
-       public function testProcessFormRestictions() {
+       public function testProcessFormRestrictions() {
                $this->setMwGlobals( [
                        'wgEnablePartialBlocks' => true,
                ] );
                $this->setMwGlobals( [
                        'wgEnablePartialBlocks' => true,
                ] );
@@ -262,6 +266,7 @@ class SpecialBlockTest extends SpecialPageTestBase {
                        'Watch' => '0',
                        'EditingRestriction' => 'partial',
                        'PageRestrictions' => implode( "\n", $titles ),
                        'Watch' => '0',
                        'EditingRestriction' => 'partial',
                        'PageRestrictions' => implode( "\n", $titles ),
+                       'NamespaceRestrictions' => '',
                ];
                $result = $page->processForm( $data, $context );
 
                ];
                $result = $page->processForm( $data, $context );
 
@@ -315,6 +320,7 @@ class SpecialBlockTest extends SpecialPageTestBase {
                        'Watch' => '0',
                        'EditingRestriction' => 'partial',
                        'PageRestrictions' => implode( "\n", $titles ),
                        'Watch' => '0',
                        'EditingRestriction' => 'partial',
                        'PageRestrictions' => implode( "\n", $titles ),
+                       'NamespaceRestrictions' => '',
                ];
                $result = $page->processForm( $data, $context );
 
                ];
                $result = $page->processForm( $data, $context );