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='" .
+ "<b>This is html &
'fun'<\/b>'/",
+ $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