Robert Vogel has uploaded a new change for review. ( 
https://gerrit.wikimedia.org/r/364445 )

Change subject: [WiP] Adding PSR-4 Autoloader and new NamespaceList
......................................................................

[WiP] Adding PSR-4 Autoloader and new NamespaceList

Change-Id: I1931e2b355cacabbcdbe3af29d3e9a513e4a316f
---
A composer.json
M extension.json
M includes/NSFileRepoHooks.php
A src/Hooks/UnitTestsList.php
A src/Hooks/UploadFormInitDescriptor.php
A src/MWNamespace.php
A src/NamespaceList.php
A tests/phpunit/NamespaceListTest.php
8 files changed, 412 insertions(+), 111 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/NSFileRepo 
refs/changes/45/364445/1

diff --git a/composer.json b/composer.json
new file mode 100644
index 0000000..b183c89
--- /dev/null
+++ b/composer.json
@@ -0,0 +1,17 @@
+{
+       "require-dev": {
+               "jakub-onderka/php-parallel-lint": "0.9.2",
+               "jakub-onderka/php-console-highlighter": "0.3.2"
+       },
+       "autoload" : {
+               "psr-4": {
+                       "NSFileRepo\\Tests\\" : "tests/phpunit",
+                       "NSFileRepo\\" : "src"
+               }
+       },
+       "scripts": {
+               "test": [
+                       "parallel-lint . --exclude vendor"
+               ]
+       }
+}
diff --git a/extension.json b/extension.json
index b7e5f46..7d03f64 100644
--- a/extension.json
+++ b/extension.json
@@ -46,10 +46,20 @@
                "@note": "Note, this must be AFTER Extension:Lockdown has been 
included - thus assuming that the user has access to files in general + files 
at this particular namespace.",
                "userCan": "NSFileRepoHooks::onUserCan",
                "BeforePageDisplay": "NSFileRepoHooks::onBeforePageDisplay",
-               "UploadFormInitDescriptor": 
"NSFileRepoHooks::onUploadFormInitDescriptor",
+               "UploadFormInitDescriptor": 
"NSFileRepo\\Hooks\\UploadFormInitDescriptor::handle",
                "ImgAuthBeforeCheckFileExists": 
"NSFileRepoHooks::onImgAuthBeforeCheckFileExists",
                "ImgAuthBeforeStream": "NSFileRepoHooks::onImgAuthBeforeStream",
-               "UploadVerification": "NSFileRepoHooks::onUploadVerification"
+               "UploadVerification": "NSFileRepoHooks::onUploadVerification",
+               "UnitTestsList": "NSFileRepo\\Hooks\\UnitTestsList::handle"
        },
-       "manifest_version": 1
+       "config": {
+               "_prefix": "egNSFileRepo",
+               "@note": "This should probably be 3000 as recommended by 
MediaWiki. But for backwards compatibility we'll stick with this default",
+               "NamespaceThreshold": 100,
+               "@note": "There are some widespread extensions that create 
namespaces. E.g. SemanticMediaWiki, PageForms, Widgets, Scribunto, ...",
+               "NamespaceBlacklist": [ 102, 104, 106, 108, 274, 828 ],
+               "SkipTalk": true
+       },
+       "manifest_version": 1,
+       "load_composer_autoloader": true
 }
\ No newline at end of file
diff --git a/includes/NSFileRepoHooks.php b/includes/NSFileRepoHooks.php
index 116a3bc..37b9b85 100644
--- a/includes/NSFileRepoHooks.php
+++ b/includes/NSFileRepoHooks.php
@@ -98,7 +98,7 @@
         * @param mixed $result
         * @return boolean
         */
-       public static function onUserCan( &$title, &$user, $action, &$result) {
+       public static function onUserCan( &$title, &$user, $action, &$result ) {
                global $wgWhitelistRead;
                if ( $wgWhitelistRead !== false && in_array( 
$title->getPrefixedText(), $wgWhitelistRead ) ) {
                        return true;
@@ -119,113 +119,6 @@
 
                $result = null;
                return $ret_val;
-       }
-
-       /**
-        * Add fields to Special:Upload
-        * @param array $descriptor
-        * @return boolean
-        */
-       public static function onUploadFormInitDescriptor( &$descriptor ) {
-               $sSelectedNamespace = '';
-               //wpDestFile is set on query string. e.g after click on redlink 
or on re-upload
-               if( !empty( $descriptor['DestFile']['default'] ) ) {
-                       $oTarget = Title::newFromText( 
$descriptor['DestFile']['default'] );
-                       $descriptor['DestFile']['default'] = 
$oTarget->getText();
-                       $sSelectedNamespace = $oTarget->getNsText();
-               }
-
-               $aNamespaces = self::getPossibleNamespaces();
-               $aOptions = array(
-                       wfMessage('nsfilerepo-nsmain')->plain() => ''
-               );
-               foreach($aNamespaces as $iNsId => $sNsText ) {
-                       if( $iNsId === NS_MAIN ) {
-                               continue;
-                       }
-                       $aOptions[$sNsText] = $sNsText;
-               }
-
-               $aFieldDef = array(
-                       'NSFR_Namespace' => array (
-                               'label'    => wfMessage('namespace')->plain(),
-                               'section'  => 'description',
-                               'class'    => 'HTMLSelectField',
-                               'options'  => $aOptions,
-                               'required' => true,
-                               'default' => str_replace( ' ', '_', 
$sSelectedNamespace )
-                       ),
-                       'NSFR_DestFile' =>
-                               array (
-                                       'type' => 'text',
-                                       'section' => 'description',
-                                       'label-message' => 
'nsfilerepo-upload-target',
-                                       'size' => 60,
-                                       'default' => '',
-                                       'readonly' => true,
-                                       'nodata' => false,
-                       ),
-               );
-
-               $sPostion = array_search(
-                       'UploadDescription',
-                       array_keys( $descriptor )
-               );
-
-               $descriptor =
-                       array_slice($descriptor, 0, $sPostion, true) +
-                       $aFieldDef +
-                       array_slice($descriptor, $sPostion, count($descriptor) 
- 1, true) ;
-
-               return true;
-       }
-
-
-       /**
-        * Returns an Array of Namespaces, that can be used for NSFileRepo
-        * @param Boolean $filterByPermissions
-        * @param User $user
-        * @return Array (NsIdx => NsLocalizedName)
-        */
-       protected static function getPossibleNamespaces( $filterByPermissions = 
true, $user = null ) {
-               $availableNamespaces = RequestContext::getMain()
-                       ->getLanguage()
-                       ->getNamespaces();
-
-               foreach( $availableNamespaces as $nsIdx => $nsText ) {
-                       if( $nsIdx % 2 !== 0 || $nsIdx < 100 ) {
-                               unset( $availableNamespaces[$nsIdx] );
-                       }
-               }
-
-               if( !$filterByPermissions ) {
-                       return $availableNamespaces;
-               }
-
-               return static::filterNamespacesByPermission(
-                       $availableNamespaces,
-                       'read',
-                       $user
-               );
-       }
-
-       /**
-        * Filter array of namespaces based on the user's permission
-        * @param array $namespaces
-        * @param string $permission
-        * @param User $user
-        * @return array
-        */
-       protected static function filterNamespacesByPermission( $namespaces, 
$permission = 'read', $user = null ) {
-               $aReturn = array();
-               foreach($namespaces as $iNsId => $sNsText ) {
-                       $oTitle = Title::makeTitle( $iNsId, 'X' );
-                       if( $oTitle->userCan( $permission, $user ) === false ) {
-                               continue;
-                       }
-                       $aReturn[$iNsId] = $sNsText;
-               }
-               return $aReturn;
        }
 
        /**
diff --git a/src/Hooks/UnitTestsList.php b/src/Hooks/UnitTestsList.php
new file mode 100644
index 0000000..4486935
--- /dev/null
+++ b/src/Hooks/UnitTestsList.php
@@ -0,0 +1,16 @@
+<?php
+
+namespace NSFileRepo\Hooks;
+
+class UnitTestsList {
+
+       /**
+        * Register PHP Unit Tests with MediaWiki framework
+        * @param array $paths
+        * @return boolean
+        */
+       public static function handle( &$paths ) {
+               $paths[] =  dirname( __DIR__ ) . '/tests/phpunit/';
+               return true;
+       }
+}
\ No newline at end of file
diff --git a/src/Hooks/UploadFormInitDescriptor.php 
b/src/Hooks/UploadFormInitDescriptor.php
new file mode 100644
index 0000000..fa73158
--- /dev/null
+++ b/src/Hooks/UploadFormInitDescriptor.php
@@ -0,0 +1,120 @@
+<?php
+
+namespace NSFileRepo\Hooks;
+
+class UploadFormInitDescriptor {
+
+       /**
+        *
+        * @var \Config
+        */
+       protected $config = null;
+
+       /**
+        *
+        * @var \IContextSource
+        */
+       protected $context = null;
+       
+       /**
+        *
+        * @var array
+        */
+       protected $descriptor = [];
+
+       /**
+        *
+        * @param \IContextSource $context
+        * @param \Config $config
+        * @param array $descriptor
+        */
+       public function __construct( \IContextSource $context, \Config $config, 
&$descriptor ) {
+               $this->context = $context;
+               $this->config = $config;
+               $this->descriptor =& $descriptor;
+       }
+
+       /**
+        * Add fields to Special:Upload
+        * @param array $descriptor
+        * @return boolean
+        */
+       public static function handle( &$descriptor ) {
+               $instance = new self(
+                       \RequestContext::getMain(),
+                       new \GlobalVarConfig( 'egNSFileRepo' ),
+                       $descriptor
+               );
+
+               return $instance->process();
+       }
+
+       public function process() {
+               $this->setDefaultNamespace();
+               $this->setNamespaceSelectOptions();
+               $this->setFieldDefinitions();
+               $this->modifyDescriptor();
+
+               return true;
+       }
+
+       protected $selectedNamespace = '';
+
+       protected function setDefaultNamespace() {
+               $this->selectedNamespace = '';
+               //"wpDestFile" is set on query string. e.g after click on 
redlink or on re-upload
+               if( !empty( $this->descriptor['DestFile']['default'] ) ) {
+                       $target = \Title::newFromText( 
$this->descriptor['DestFile']['default'] );
+                       $this->descriptor['DestFile']['default'] = 
$target->getText();
+                       $this->selectedNamespace = str_replace(  ' ', '_', 
$target->getNsText() );
+               }
+       }
+
+       protected $namespaceSelectOptions = [];
+
+       protected function setNamespaceSelectOptions() {
+               $namespaceList = new \NSFileRepo\NamespaceList(
+                       $this->context->getUser(),
+                       $this->config,
+                       $this->context->getLanguage()
+               );
+
+               foreach( $namespaceList->getEditable() as $nsId => $namespace ) 
{
+                       
$this->namespaceSelectOptions[$namespace->getDisplayName()]
+                               = $namespace->getCanonicalName();
+               }
+       }
+
+       protected $fieldDef = [];
+
+       protected function setFieldDefinitions() {
+               $this->fieldDef = [
+                       'NSFR_Namespace' => [
+                               'label'    => wfMessage('namespace')->plain(),
+                               'section'  => 'description',
+                               'class'    => 'HTMLSelectField',
+                               'options'  => $this->namespaceSelectOptions,
+                               'required' => true,
+                               'default' => $this->selectedNamespace
+                       ],
+                       'NSFR_DestFile' => [
+                               'type' => 'text',
+                               'section' => 'description',
+                               'label-message' => 'nsfilerepo-upload-target',
+                               'size' => 60,
+                               'default' => '',
+                               'readonly' => true,
+                               'nodata' => false,
+                       ],
+               ];
+       }
+
+       protected function modifyDescriptor() {
+               $pos = array_search( 'UploadDescription', array_keys( 
$this->descriptor ) );
+
+               $this->descriptor =
+                       array_slice( $this->descriptor, 0, $pos, true ) +
+                       $this->fieldDef +
+                       array_slice( $this->descriptor, $pos, count( 
$this->descriptor ) - 1, true ) ;
+       }
+}
\ No newline at end of file
diff --git a/src/MWNamespace.php b/src/MWNamespace.php
new file mode 100644
index 0000000..31f1293
--- /dev/null
+++ b/src/MWNamespace.php
@@ -0,0 +1,73 @@
+<?php
+
+namespace NSFileRepo;
+
+class MWNamespace implements \JsonSerializable {
+
+       /**
+        *
+        * @var int
+        */
+       protected $id = '';
+
+       /**
+        *
+        * @var string
+        */
+       protected $canonicalName = '';
+
+       /**
+        *
+        * @var string
+        */
+       protected $displayName = '';
+
+       /**
+        *
+        * @param int $id
+        * @param string $canonicalName
+        * @param string $displayName
+        */
+       public function __construct( $id, $canonicalName, $displayName ) {
+               $this->id = (int)$id;
+               $this->canonicalName = $canonicalName;
+               $this->displayName = $displayName;
+       }
+
+       /**
+        *
+        * @return int
+        */
+       public function getId() {
+               return $this->id;
+       }
+
+       /**
+        *
+        * @return string
+        */
+       public function getCanonicalName() {
+               return $this->canonicalName;
+       }
+
+       /**
+        *
+        * @return string
+        */
+       public function getDisplayName() {
+               return $this->displayName;
+       }
+
+       /**
+        *
+        * @return array
+        */
+       public function jsonSerialize() {
+               return [
+                       'id' => $this->getId(),
+                       'canonicalName' => $this->getCanonicalName(),
+                       'displayName' => $this->getDisplayName()
+               ];
+       }
+
+}
\ No newline at end of file
diff --git a/src/NamespaceList.php b/src/NamespaceList.php
new file mode 100644
index 0000000..bc361df
--- /dev/null
+++ b/src/NamespaceList.php
@@ -0,0 +1,106 @@
+<?php
+
+namespace NSFileRepo;
+
+class NamespaceList {
+
+       const CONFIG_SKIP_TALK = 'SkipTalk';
+       const CONFIG_THRESHOLD = 'NamespaceThreshold';
+       const CONFIG_BLACKLIST = 'NamespaceBlacklist';
+
+       /**
+        *
+        * @var \User
+        */
+       protected $user = null;
+
+       /**
+        *
+        * @var \Config
+        */
+       protected $config = null;
+
+       /**
+        *
+        * @var \Language
+        */
+       protected $lang = null;
+
+       /**
+        *
+        * @param \User $user
+        * @param \Config $config
+        * @param \Language $lang
+        */
+       public function __construct( \User $user, \Config $config, \Language 
$lang ) {
+               $this->user = $user;
+               $this->config = new \MultiConfig([
+                       $config,
+                       new \HashConfig( [
+                               self::CONFIG_SKIP_TALK => true,
+                               self::CONFIG_THRESHOLD => 0,
+                               self::CONFIG_BLACKLIST => []
+                       ] )
+               ]);
+               $this->lang = $lang;
+       }
+
+       /**
+        * @return MWNamespace[] With namespace id as an index
+        */
+       public function getReadable() {
+               return $this->getNamespacesByPermission( 'read' );
+       }
+
+       /**
+        * @return MWNamespace[] With namespace id as an index
+        */
+       public function getEditable() {
+               return $this->getNamespacesByPermission( 'edit' );
+       }
+
+       protected function getNamespacesByPermission( $permission ) {
+               $availableNamespaces = $this->lang->getNamespaces();
+
+               $namespaces = [];
+               foreach( $availableNamespaces as $nsId => $nsText ) {
+                       #var_dump( $this->skip( $nsIdx, $permission ) );
+                       if( $this->skip( $nsId, $permission ) ) {
+                               continue;
+                       }
+
+                       if( $nsId === NS_MAIN ) {
+                               $nsText = 
wfMessage('nsfilerepo-nsmain')->plain();
+                       }
+
+                       $canonicalName = \MWNamespace::getCanonicalName( $nsId 
);
+                       $namespaces[$nsId] = new MWNamespace( $nsId, 
$canonicalName , $nsText );
+               }
+
+               return $namespaces;
+       }
+
+       protected function skip( $nsId, $permission = '' ) {
+
+               if( $nsId < $this->config->get( self::CONFIG_THRESHOLD ) && 
$nsId !== NS_MAIN ) {
+                       return true;
+               }
+
+               if( in_array( $nsId, $this->config->get( self::CONFIG_BLACKLIST 
) ) ) {
+                       return true;
+               }
+
+               if( $this->config->get( self::CONFIG_SKIP_TALK )
+                               && \MWNamespace::isTalk( $nsId ) ) {
+                       return true;
+               }
+
+               if( !empty( $permission ) ) {
+                       $title = \Title::makeTitle( $nsId, 'Dummy' );
+                       return !$title->userCan(  $permission, $this->user );
+               }
+
+               return false;
+       }
+
+}
diff --git a/tests/phpunit/NamespaceListTest.php 
b/tests/phpunit/NamespaceListTest.php
new file mode 100644
index 0000000..a19009a
--- /dev/null
+++ b/tests/phpunit/NamespaceListTest.php
@@ -0,0 +1,66 @@
+<?php
+
+namespace NSFileRepo\Tests;
+
+class NamespaceListTest extends \MediaWikiLangTestCase {
+
+       const DUMMY_NS_A_ID = 12412;
+       const DUMMY_NS_B_ID = 12512;
+       const DUMMY_NS_C_ID = 12512;
+
+       protected function setUp() {
+               global $wgExtraNamespaces, $wgNamespaceContentModels, 
$wgContentHandlers, $wgContLang;
+
+               parent::setUp();
+
+               $this->setMwGlobals( [
+                       'wgExtraNamespaces' => $wgExtraNamespaces,
+                       'wgNamespaceContentModels' => $wgNamespaceContentModels,
+                       'wgContentHandlers' => $wgContentHandlers,
+                       'wgContLang' => $wgContLang,
+               ] );
+
+               $wgExtraNamespaces[self::DUMMY_NS_A_ID] = 'NSFRDummyA';
+               $wgExtraNamespaces[self::DUMMY_NS_A_ID + 1] = 'NSFRDummyA_talk';
+
+               $wgExtraNamespaces[self::DUMMY_NS_B_ID] = 'NSFRDummyB';
+               $wgExtraNamespaces[self::DUMMY_NS_B_ID + 1] = 'NSFRDummyB_talk';
+
+               $wgExtraNamespaces[self::DUMMY_NS_C_ID] = 'NSFRDummyC';
+               $wgExtraNamespaces[self::DUMMY_NS_C_ID + 1] = 'NSFRDummyC_talk';
+
+               MWNamespace::getCanonicalNamespaces( true ); # reset namespace 
cache
+               $wgContLang->resetNamespaces(); # reset namespace cache
+
+               /**
+                * Test hook handler that mimics Extension:Lockdown and revokes 
read
+                * permissions on 'NSFRDummyA' and edit permission on 
'NSFRDummyB'
+                */
+               \Hooks::register( 'userCan', function( &$title, &$user, 
$action, &$result ) {
+                       if( $action === 'read'
+                                       && $title instanceof \Title
+                                       && $title->getNamespace() === 
self::DUMMY_NS_A_ID ) {
+                               return false;
+                       }
+                       return true;
+               } );
+       }
+
+       public function textInstance() {
+               $namespacelist = $this->makeInstance();
+               $this->assertInstanceOf( 'NSFileRepo\NamespaceList', 
$namespacelist );
+       }
+
+       public function testGetReadable() {
+               
+       }
+
+       protected function makeInstance( $config = null ) {
+               if( $config === null ) {
+                       $config = new \HashConfig( [] );
+               }
+
+               return new \NSFileRepo\NamespaceList( $user, $config, $lang );
+       }
+
+}
\ No newline at end of file

-- 
To view, visit https://gerrit.wikimedia.org/r/364445
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I1931e2b355cacabbcdbe3af29d3e9a513e4a316f
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/NSFileRepo
Gerrit-Branch: master
Gerrit-Owner: Robert Vogel <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to