Bene has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/277573

Change subject: [WIP] Special page to create media info entities
......................................................................

[WIP] Special page to create media info entities

This patch creates a new special page Special:NewMediaInfo that allows
users to create new media info entities based on a local file name they
provide.

Change-Id: If2636e75505919e3a65e200c101290abf406fb26
---
M WikibaseMediaInfo.i18n.alias.php
M extension.json
M i18n/en.json
M i18n/qqq.json
A src/Specials/SpecialNewMediaInfo.php
A src/TitleLookup.php
A tests/phpunit/mediawiki/Specials/SpecialNewMediaInfoTest.php
7 files changed, 394 insertions(+), 2 deletions(-)


  git pull 
ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/WikibaseMediaInfo 
refs/changes/73/277573/1

diff --git a/WikibaseMediaInfo.i18n.alias.php b/WikibaseMediaInfo.i18n.alias.php
index 069a42f..cb623a3 100644
--- a/WikibaseMediaInfo.i18n.alias.php
+++ b/WikibaseMediaInfo.i18n.alias.php
@@ -11,4 +11,5 @@
 
 /** English (English) */
 $specialPageAliases['en'] = [
+       'NewMediaInfo' => [ 'NewMediaInfo', 'CreateMediaInfo' ]
 ];
diff --git a/extension.json b/extension.json
index bfa8f11..019149e 100644
--- a/extension.json
+++ b/extension.json
@@ -38,6 +38,7 @@
                "remoteExtPath": "WikibaseMediaInfo"
        },
        "SpecialPages": {
+               "NewMediaInfo": 
"Wikibase\\MediaInfo\\Specials\\SpecialNewMediaInfo"
        },
        "manifest_version": 1
 }
diff --git a/i18n/en.json b/i18n/en.json
index b69d0c4..c84e0e0 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -4,5 +4,11 @@
                        "Bene*"
                ]
        },
-       "wikibasemediainfo-desc": "Wikibase extension to manage structured 
metadata of media files"
+       "wikibasemediainfo-desc": "Wikibase extension to manage structured 
metadata of media files",
+       "special-newmediainfo": "Create a new media info",
+       "wikibase-newmediainfo-legend": "Create a new media info",
+       "wikibase-newmediainfo-filename": "File name:",
+       "wikibase-newmediainfo-filename-placeholder": "enter a file name",
+       "wikibase-newmediainfo-invalid-title": "The given title does not belong 
to a file.",
+       "wikibase-newmediainfo-file-not-found": "The given file name could not 
be found on this wiki."
 }
diff --git a/i18n/qqq.json b/i18n/qqq.json
index aadcffc..db7d388 100644
--- a/i18n/qqq.json
+++ b/i18n/qqq.json
@@ -1,4 +1,10 @@
 {
        "@metadata": [],
-       "wikibasemediainfo-desc": 
"{{desc|name=WikibaseMediaInfo|url=https://www.mediawiki.org/wiki/Extension:WikibaseMediaInfo}}";
+       "wikibasemediainfo-desc": 
"{{desc|name=WikibaseMediaInfo|url=https://www.mediawiki.org/wiki/Extension:WikibaseMediaInfo}}";,
+       "special-newmediainfo": "{{doc-special|NewMediaInfo}}\nThe special page 
is for creating new media info entities.",
+       "wikibase-newmediainfo-legend": "Title for the legend on the 
NewMediaInfo special page for creating new media info entities.",
+       "wikibase-newmediainfo-filename": "Label for the textfield holding the 
name of the file connected to the new media info entity.",
+       "wikibase-newmediainfo-filename-placeholder": "Placeholder for the 
textfield holding the name of the file connected to the new media info entity.",
+       "wikibase-newmediainfo-invalid-title": "Error message shown when an 
invalid title is entered.",
+       "wikibase-newmediainfo-file-not-found": "Error message shown when the 
provided file name could not be found on the local wiki."
 }
diff --git a/src/Specials/SpecialNewMediaInfo.php 
b/src/Specials/SpecialNewMediaInfo.php
new file mode 100644
index 0000000..7aa21e9
--- /dev/null
+++ b/src/Specials/SpecialNewMediaInfo.php
@@ -0,0 +1,182 @@
+<?php
+
+namespace Wikibase\MediaInfo\Specials;
+
+use HTMLForm;
+use Title;
+use Wikibase\CopyrightMessageBuilder;
+use Wikibase\MediaInfo\DataModel\MediaInfo;
+use Wikibase\MediaInfo\DataModel\MediaInfoId;
+use Wikibase\MediaInfo\TitleLookup;
+use Wikibase\Repo\Specials\SpecialPageCopyrightView;
+use Wikibase\Repo\Specials\SpecialWikibaseRepoPage;
+use Wikibase\Repo\WikibaseRepo;
+use Wikibase\Summary;
+
+/**
+ * Special page to create media info entities
+ *
+ * @license GPL-2.0+
+ * @author Bene* < [email protected] >
+ */
+class SpecialNewMediaInfo extends SpecialWikibaseRepoPage {
+
+       /**
+        * @var TitleLookup
+        */
+       private $titleLookup;
+
+       /**
+        * @var string
+        */
+       private $rightsUrl;
+
+       /**
+        * @var string
+        */
+       private $rightsText;
+
+       public function __construct() {
+               parent::__construct( 'NewMediaInfo', 'mediainfo-create' );
+
+               $wikibaseRepo = WikibaseRepo::getDefaultInstance();
+               $settings = $wikibaseRepo->getSettings();
+
+               $this->setSpecialNewMediaInfoServices(
+                       new TitleLookup(),
+                       $settings->getSetting( 'dataRightsUrl' ),
+                       $settings->getSetting( 'dataRightsText' )
+               );
+       }
+
+       /**
+        * @param TitleLookup $titleLookup
+        * @param string $rightsUrl
+        * @param string $rightsText
+        */
+       public function setSpecialNewMediaInfoServices(
+               TitleLookup $titleLookup,
+               $rightsUrl,
+               $rightsText
+       ) {
+               $this->titleLookup = $titleLookup;
+               $this->rightsUrl = $rightsUrl;
+               $this->rightsText = $rightsText;
+       }
+
+       /**
+        * @see SpecialPage::doesWrites
+        *
+        * @return bool
+        */
+       public function doesWrites() {
+               return true;
+       }
+
+       public function execute( $subPage ) {
+               parent::execute( $subPage );
+
+               $this->checkPermissions();
+               $this->checkBlocked();
+               $this->checkReadOnly();
+
+               $request = $this->getRequest();
+               $user = $this->getUser();
+
+               $fileName = $request->getText( 'filename', $subPage );
+               $editToken = $request->getVal( 'wpEditToken' );
+
+               if ( $request->wasPosted() && $user->matchEditToken( $editToken 
) ) {
+                       $this->createMediaInfo( $fileName );
+               }
+
+               $this->showForm( $fileName );
+       }
+
+       private function createMediaInfo( $fileName ) {
+               $title = $this->titleLookup->newFromText( $fileName, NS_FILE );
+
+               if ( $title === null || $title->getNamespace() !== NS_FILE ) {
+                       $this->showErrorHTML( $this->msg( 
'wikibase-newmediainfo-invalid-title' )->escaped() );
+                       return;
+               }
+
+               $pageId = $title->getArticleID();
+
+               if ( $pageId <= 0 ) {
+                       $this->showErrorHTML( $this->msg( 
'wikibase-newmediainfo-file-not-found' )->escaped() );
+                       return;
+               }
+
+               $id = new MediaInfoId( 'M' . $pageId );
+               $mediaInfo = new MediaInfo( $id );
+
+               $summary = new Summary( 'wbeditentity', 'create' );
+               $summary->setLanguage( $this->getLanguage()->getCode() );
+               $summary->addAutoSummaryArgs( $title->getText() );
+
+               $status = $this->saveEntity(
+                       $mediaInfo,
+                       $summary,
+                       $this->getRequest()->getVal( 'wpEditToken' ),
+                       EDIT_NEW
+               );
+
+               if ( $status->isOK() ) {
+                       $entityTitle = $this->getEntityTitle( 
$mediaInfo->getId() );
+                       $this->getOutput()->redirect( 
$entityTitle->getFullURL() );
+               } else {
+                       $this->showErrorHTML( $status->getHTML() );
+               }
+       }
+
+       private function showForm( $fileName ) {
+               $this->addCopyrightText();
+               $this->addAnonWarning();
+
+               HTMLForm::factory( 'ooui', $this->getFormElements( $fileName ), 
$this->getContext() )
+                       ->setSubmitID( 'wb-newmediainfo-submit' )
+                       ->setSubmitName( 'submit' )
+                       ->setSubmitTextMsg( 'wikibase-newentity-submit' )
+                       ->setWrapperLegendMsg( $this->msg( 
'wikibase-newmediainfo-legend' ) )
+                       ->setSubmitCallback( function () {// no-op
+                       } )->show();
+       }
+
+       private function addCopyrightText() {
+               $copyrightView = new SpecialPageCopyrightView(
+                       new CopyrightMessageBuilder(),
+                       $this->rightsUrl,
+                       $this->rightsText
+               );
+
+               $html = $copyrightView->getHtml( $this->getLanguage(), 
'wikibase-newentity-submit' );
+
+               $this->getOutput()->addHTML( $html );
+       }
+
+       private function addAnonWarning() {
+               if ( $this->getUser()->isAnon() ) {
+                       $this->showErrorHTML(
+                               $this->msg( 'wikibase-anonymouseditwarning' 
)->escaped(),
+                               'warning'
+                       );
+               }
+       }
+
+       private function getFormElements( $fileName ) {
+               return [
+                       'filename' => [
+                               'name' => 'filename',
+                               'default' => $fileName,
+                           'type' => 'text',
+                           'id' => 'wb-newmediainfo-fielname',
+                           'placeholder' => $this->msg(
+                                   'wikibase-newmediainfo-filename-placeholder'
+                           )->text(),
+                           'label-message' => 'wikibase-newmediainfo-filename'
+                       ]
+               ];
+       }
+
+}
diff --git a/src/TitleLookup.php b/src/TitleLookup.php
new file mode 100644
index 0000000..5e2b9be
--- /dev/null
+++ b/src/TitleLookup.php
@@ -0,0 +1,27 @@
+<?php
+
+namespace Wikibase\MediaInfo;
+
+use Title;
+
+/**
+ * Provides lookup functionality for MediaWiki titles.
+ *
+ * @license GPL-2.0+
+ * @author Bene* < [email protected] >
+ */
+class TitleLookup {
+
+       /**
+        * @see Title::newFromText
+        *
+        * @param string $text
+        * @param int $defaultNamespace
+        *
+        * @return Title|null
+        */
+       public function newFromText( $text, $defaultNamespace = NS_MAIN ) {
+               return Title::newFromText( $text, $defaultNamespace );
+       }
+
+}
diff --git a/tests/phpunit/mediawiki/Specials/SpecialNewMediaInfoTest.php 
b/tests/phpunit/mediawiki/Specials/SpecialNewMediaInfoTest.php
new file mode 100644
index 0000000..7a138db
--- /dev/null
+++ b/tests/phpunit/mediawiki/Specials/SpecialNewMediaInfoTest.php
@@ -0,0 +1,169 @@
+<?php
+
+namespace Wikibase\MediaInfo\Tests\MediaWiki\Specials;
+
+use FauxRequest;
+use FauxResponse;
+use SpecialPage;
+use SpecialPageTestBase;
+use Status;
+use Title;
+use Wikibase\EditEntityFactory;
+use Wikibase\MediaInfo\DataModel\MediaInfoId;
+use Wikibase\MediaInfo\Specials\SpecialNewMediaInfo;
+use Wikibase\MediaInfo\TitleLookup;
+use Wikibase\Repo\Hooks\EditFilterHookRunner;
+use Wikibase\Repo\Tests\Specials\SpecialWikibaseRepoPageTestBase;
+
+/**
+ * @covers Wikibase\MediaInfo\Specials\SpecialNewMediaInfo
+ *
+ * @license GPL-2.0+
+ * @author Bene* < [email protected] >
+ */
+class SpecialNewMediaInfoTest extends SpecialWikibaseRepoPageTestBase {
+
+       protected function newSpecialPage() {
+               $specialPage = new SpecialNewMediaInfo();
+               $specialPage->setSpecialNewMediaInfoServices(
+                       $this->getTitleLookup(),
+                       'data-rights-url',
+                       'data-rights-text'
+               );
+               $specialPage->setSpecialWikibaseRepoPageServices(
+                       $this->getSummaryFormatter(),
+                       $this->getEntityTitleLookup(),
+                       $this->getSiteStore(),
+                       new EditEntityFactory(
+                               $this->getEntityTitleLookup(),
+                               $this->getEntityRevisionLookup(),
+                               $this->getEntityStore(),
+                               $this->getEntityPermissionChecker(),
+                               $this->getMockEditFitlerHookRunner()
+                       )
+               );
+
+               return $specialPage;
+       }
+
+       /**
+        * @return TitleLookup
+        */
+       private function getTitleLookup() {
+               $titleLookup = $this->getMock( TitleLookup::class );
+               $titleLookup->method( 'newFromText' )
+                       ->willReturnCallback( function( $text, 
$defaultNamespace ) {
+                               $this->assertSame( NS_FILE, $defaultNamespace );
+                               if ( $text === 'invalid' ) {
+                                       return null;
+                               }
+                               if ( $text === 'not-existing' ) {
+                                       $title = $this->getMock( Title::class );
+                                       $title->method( 'getNamespace' 
)->willReturn( NS_FILE );
+                                       $title->method( 'getArticleID' 
)->willReturn( 0 );
+                                       return $title;
+                               }
+                               $title = $this->getMock( Title::class );
+                               $title->method( 'getNamespace' )->willReturn( 
NS_FILE );
+                               $title->method( 'getArticleID' )->willReturn( 1 
);
+                               return $title;
+                       } );
+
+               return $titleLookup;
+       }
+
+       /**
+        * @return EditFilterHookRunner
+        */
+       private function getMockEditFitlerHookRunner() {
+               $runner = $this->getMockBuilder( EditFilterHookRunner::class )
+                       ->setMethods( array( 'run' ) )
+                       ->disableOriginalConstructor()
+                       ->getMock();
+               $runner->expects( $this->any() )
+                       ->method( 'run' )
+                       ->will( $this->returnValue( Status::newGood() ) );
+               return $runner;
+       }
+
+       public function testEmptyForm() {
+               list( $output, ) = $this->executeSpecialPage( '', null, 'qqx' );
+
+               $this->assertRegExp(
+                       "/<input[^>]*name='filename'[^>]*value=''/",
+                       $output
+               );
+       }
+
+       public function testSubpagePrefillsForm() {
+               list( $output, ) = $this->executeSpecialPage( 'Foo', null, 
'qqx' );
+
+               $this->assertRegExp(
+                       "/<input[^>]*name='filename'[^>]*value='Foo'/",
+                       $output
+               );
+       }
+
+       public function testRequestPrefillsForm() {
+               $request = new FauxRequest( [
+                       'filename' => 'Bar'
+               ] );
+
+               list( $output, ) = $this->executeSpecialPage( '', $request, 
'qqx' );
+
+               $this->assertRegExp(
+                       "/<input[^>]*name='filename'[^>]*value='Bar'/",
+                       $output
+               );
+       }
+
+       public function testPrefillHtmlEscaping() {
+               $html = "<b>This is html & 'fun'</b>";
+               list( $output, ) = $this->executeSpecialPage( $html, null, 
'qqx' );
+
+               $this->assertRegExp(
+                       "/<input[^>]*name='filename'[^>]*value='" .
+                       "&lt;b&gt;This is html &amp; 
&#039;fun&#039;&lt;\/b&gt;'/",
+                       $output
+               );
+       }
+
+       public function testInvalidTitle() {
+               $request = new FauxRequest( [
+                       'filename' => 'invalid'
+               ], true );
+
+               list( $output, ) = $this->executeSpecialPage( '', $request, 
'qqx' );
+
+               $this->assertContains(
+                       '<p 
class="error">(wikibase-newmediainfo-invalid-title)</p>',
+                       $output
+               );
+       }
+
+       public function testNotExistingTitle() {
+               $request = new FauxRequest( [
+                       'filename' => 'not-existing'
+               ], true );
+
+               list( $output, ) = $this->executeSpecialPage( '', $request, 
'qqx' );
+
+               $this->assertContains(
+                       '<p 
class="error">(wikibase-newmediainfo-file-not-found)</p>',
+                       $output
+               );
+       }
+
+       public function testValidTitle() {
+               $request = new FauxRequest( [
+                       'filename' => 'cool title'
+               ], true );
+
+               /** @var FauxResponse $response */
+               list( , $response ) = $this->executeSpecialPage( '', $request );
+
+               $this->assertContains( 'M1', $response->getHeader( 'Location' ) 
);
+               $this->assertNotNull( $this->mockRepository->getEntity( new 
MediaInfoId( 'M1' ) ) );
+       }
+
+}

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

Gerrit-MessageType: newchange
Gerrit-Change-Id: If2636e75505919e3a65e200c101290abf406fb26
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/WikibaseMediaInfo
Gerrit-Branch: master
Gerrit-Owner: Bene <[email protected]>

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

Reply via email to