From 6914257db945a04e7e806a2c1cad7d3b73f90a51 Mon Sep 17 00:00:00 2001 From: marzjan Date: Mon, 4 May 2015 14:43:53 +0000 Subject: [PATCH 1/2] DAT-2760 Initial commit; Streamline files; Add first test --- PortableInfobox.setup.php | 6 ++++ services/Helpers/ImageFilenameSanitizer.php | 24 ++++++++++++++ services/Parser/DummyParser.php | 13 ++++++++ services/Parser/ExternalParser.php | 8 +++++ services/Parser/Nodes/NodeImage.php | 14 +++++--- tests/ImageFilenameSanitizerTest.php | 33 +++++++++++++++++++ tests/ParserNodesTest.php | 6 ++-- ...PortableInfoboxParserTagControllerTest.php | 6 ++-- tests/PortableInfoboxRenderServiceTest.php | 4 +-- tests/XmlParserTest.php | 15 ++------- 10 files changed, 102 insertions(+), 27 deletions(-) create mode 100644 services/Helpers/ImageFilenameSanitizer.php create mode 100644 services/Parser/DummyParser.php create mode 100644 services/Parser/ExternalParser.php create mode 100644 tests/ImageFilenameSanitizerTest.php diff --git a/PortableInfobox.setup.php b/PortableInfobox.setup.php index 47da56e..cc66411 100644 --- a/PortableInfobox.setup.php +++ b/PortableInfobox.setup.php @@ -18,7 +18,9 @@ $wgExtensionCredits[ 'parserhook' ][] = [ $wgAutoloadClasses[ 'PortableInfoboxRenderService' ] = $dir . 'services/PortableInfoboxRenderService.class.php'; // parser +$wgAutoloadClasses[ 'Wikia\\PortableInfobox\\Parser\\ExternalParser'] = $dir . 'services/Parser/ExternalParser.php'; $wgAutoloadClasses[ 'Wikia\\PortableInfobox\\Parser\\XmlParser'] = $dir . 'services/Parser/XmlParser.php'; +$wgAutoloadClasses[ 'Wikia\\PortableInfobox\\Parser\\DummyParser'] = $dir . 'services/Parser/DummyParser.php'; $wgAutoloadClasses[ 'Wikia\\PortableInfobox\\Parser\\MediaWikiParserService'] = $dir . 'services/Parser/MediaWikiParserService.php'; $wgInfoboxParserNodes = [ 'Node', @@ -36,6 +38,9 @@ foreach ( $wgInfoboxParserNodes as $parserNode ) { $wgAutoloadClasses[ 'Wikia\\PortableInfobox\\Parser\\Nodes\\'.$parserNode ] = $dir . 'services/Parser/Nodes/'.$parserNode.'.php'; } +// helpers +$wgAutoloadClasses[ 'Wikia\PortableInfobox\Helpers\ImageFilenameSanitizer' ] = $dir . 'services/Helpers/ImageFilenameSanitizer.php'; + // controller classes $wgAutoloadClasses[ 'PortableInfoboxParserTagController' ] = $dir . 'controllers/PortableInfoboxParserTagController.class.php'; $wgAutoloadClasses[ 'PortableInfoboxHooks' ] = $dir . 'PortableInfoboxHooks.class.php'; @@ -47,3 +52,4 @@ $wgHooks[ 'SkinAfterBottomScripts' ][] = 'PortableInfoboxHooks::onSkinAfterBotto // i18n mapping $wgExtensionMessagesFiles[ 'PortableInfobox' ] = $dir . 'PortableInfobox.i18n.php'; + diff --git a/services/Helpers/ImageFilenameSanitizer.php b/services/Helpers/ImageFilenameSanitizer.php new file mode 100644 index 0000000..ae4db59 --- /dev/null +++ b/services/Helpers/ImageFilenameSanitizer.php @@ -0,0 +1,24 @@ +getInfoboxData( $this->getXmlAttribute($this->xmlNode, self::DATA_SRC_ATTR_NAME ) ); + + $imageName = $this->getValueWithDefault( $this->xmlNode ); $node['value'] = $this->resolveImageUrl( $imageName ); $node['alt'] = $this->getValueWithDefault( $this->xmlNode->{self::ALT_TAG_NAME} ); + return $node; } - protected function resolveImageUrl( $filename ) { - $title = \Title::newFromText( $filename, NS_FILE ); + public function resolveImageUrl( $filename ) { + $title = \Title::newFromText( \Wikia\PortableInfobox\Helpers\ImageFilenameSanitizer::getInstance() + ->sanitizeImageFileName($filename), NS_FILE ); if ( $title && $title->exists() ) { - return \WikiaFileHelper::getFileFromTitle($title)->getUrlGenerator()->url(); + return \WikiaFileHelper::getFileFromTitle( $title )->getUrlGenerator()->url(); + } else { + return ""; } - return ""; } } diff --git a/tests/ImageFilenameSanitizerTest.php b/tests/ImageFilenameSanitizerTest.php new file mode 100644 index 0000000..632e07e --- /dev/null +++ b/tests/ImageFilenameSanitizerTest.php @@ -0,0 +1,33 @@ +setupFile = dirname( __FILE__ ) . '/../PortableInfobox.setup.php'; + parent::setUp(); + + $this->imageFilenameSanitizer = \Wikia\PortableInfobox\Helpers\ImageFilenameSanitizer::getInstance(); + } + + /** + * @param $inputFileName + * @param $expectedOutput + * @param $description + * @dataProvider testSanitizeFilenameDataProvider + */ + public function testSanitizeFilename( $inputFileName, $expectedOutput, $description ) { + $actualOutput = $this->imageFilenameSanitizer->sanitizeImageFileName( $inputFileName ); + + $this->assertEquals( $expectedOutput, $actualOutput, $description ); + } + + public function testSanitizeFilenameDataProvider() { + return [ + [ + 'filename.jpg', + 'filename.jpg' + ] + ]; + } +} diff --git a/tests/ParserNodesTest.php b/tests/ParserNodesTest.php index a9a5420..ad773e4 100644 --- a/tests/ParserNodesTest.php +++ b/tests/ParserNodesTest.php @@ -1,12 +1,10 @@ setupFile = dirname( __FILE__ ) . '/../PortableInfobox.setup.php'; parent::setUp(); - require_once( dirname( __FILE__ ) . '/../PortableInfobox.setup.php' ); - foreach ( $wgAutoloadClasses as $class => $file) { - require_once($file); - } } public function testNodeTitle() { diff --git a/tests/PortableInfoboxParserTagControllerTest.php b/tests/PortableInfoboxParserTagControllerTest.php index 93666c6..5caabca 100644 --- a/tests/PortableInfoboxParserTagControllerTest.php +++ b/tests/PortableInfoboxParserTagControllerTest.php @@ -3,8 +3,8 @@ class PortableInfoboxParserTagControllerTest extends WikiaBaseTest { protected function setUp() { + $this->setupFile = dirname( __FILE__ ) . '/../PortableInfobox.setup.php'; parent::setUp(); - require_once( dirname( __FILE__ ) . '/../PortableInfobox.setup.php' ); } public function testEmptyInfobox() { @@ -24,7 +24,7 @@ class PortableInfoboxParserTagControllerTest extends WikiaBaseTest { public function testNoWrappingParagraphs() { $this->markTestSkipped( 'DAT-2738 - awaiting decision whether this is a behavior to be fixed' ); - $text = PHP_EOL . 'Val' . PHP_EOL; + $text = PHP_EOL . 'Val' . PHP_EOL; $parser = new Parser(); $options = new ParserOptions(); @@ -39,7 +39,7 @@ class PortableInfoboxParserTagControllerTest extends WikiaBaseTest { public function testNoPreTag() { $this->markTestSkipped( 'DAT-2736 - awaiting decision whether this is a behavior to be fixed' ); - $text = 'Val' . PHP_EOL . ' Test'; + $text = 'Val' . PHP_EOL . ' Test'; $parser = new Parser(); $options = new ParserOptions(); diff --git a/tests/PortableInfoboxRenderServiceTest.php b/tests/PortableInfoboxRenderServiceTest.php index 279eff3..c42236a 100644 --- a/tests/PortableInfoboxRenderServiceTest.php +++ b/tests/PortableInfoboxRenderServiceTest.php @@ -3,9 +3,9 @@ class PortableInfoboxRenderServiceTest extends PHPUnit_Framework_TestCase { private $infoboxRenderService; - public function setUp() { + protected function setUp() { + $this->setupFile = dirname( __FILE__ ) . '/../PortableInfobox.setup.php'; parent::setUp(); - require_once( dirname( __FILE__ ) . '/../PortableInfobox.setup.php' ); $this->infoboxRenderService = new PortableInfoboxRenderService(); } diff --git a/tests/XmlParserTest.php b/tests/XmlParserTest.php index 8dc7775..fe6c104 100644 --- a/tests/XmlParserTest.php +++ b/tests/XmlParserTest.php @@ -1,21 +1,10 @@ setupFile = dirname( __FILE__ ) . '/../PortableInfobox.setup.php'; parent::setUp(); - require_once( dirname( __FILE__ ) . '/../PortableInfobox.setup.php' ); } public function testIsEmpty() { @@ -52,7 +41,7 @@ class XmlParserTest extends WikiaBaseTest { 'elem2' => 'ELEM2', 'lado2' => 'LALALA' ]); - $externalParser = new TestParser(); + $externalParser = new \Wikia\PortableInfobox\Parser\DummyParser(); $parser->setExternalParser( $externalParser ); $markup = ' From fe390a9f53cfa9b1d6dbd3aed3c0602729d90d0e Mon Sep 17 00:00:00 2001 From: marzjan Date: Mon, 4 May 2015 15:43:09 +0000 Subject: [PATCH 2/2] DAT-2760 Implement cases for backwards compatibility of infobox markup (image tag) --- PortableInfobox.setup.php | 1 - services/Helpers/ImageFilenameSanitizer.php | 40 ++++++++++++- services/Parser/DummyParser.php | 2 +- services/Parser/Nodes/NodeImage.php | 3 +- tests/ImageFilenameSanitizerTest.php | 58 ++++++++++++++++++- ...PortableInfoboxParserTagControllerTest.php | 4 +- 6 files changed, 98 insertions(+), 10 deletions(-) diff --git a/PortableInfobox.setup.php b/PortableInfobox.setup.php index cc66411..4592c12 100644 --- a/PortableInfobox.setup.php +++ b/PortableInfobox.setup.php @@ -52,4 +52,3 @@ $wgHooks[ 'SkinAfterBottomScripts' ][] = 'PortableInfoboxHooks::onSkinAfterBotto // i18n mapping $wgExtensionMessagesFiles[ 'PortableInfobox' ] = $dir . 'PortableInfobox.i18n.php'; - diff --git a/services/Helpers/ImageFilenameSanitizer.php b/services/Helpers/ImageFilenameSanitizer.php index ae4db59..d2d1465 100644 --- a/services/Helpers/ImageFilenameSanitizer.php +++ b/services/Helpers/ImageFilenameSanitizer.php @@ -4,6 +4,7 @@ namespace Wikia\PortableInfobox\Helpers; class ImageFilenameSanitizer { private static $instance = null; + private $filePrefixRegex = [ ]; private function __construct() { } @@ -18,7 +19,42 @@ class ImageFilenameSanitizer { return self::$instance; } - public function sanitizeImageFileName( $filename ) { + /** + * @param $contLang \Language + * Used as local cache for getting string to remove + */ + private function getFilePrefixRegex( $contLang ) { + $langCode = $contLang->getCode(); + if ( empty( $this->filePrefixRegex[$langCode] ) ) { + $fileNamespaces = [ \MWNamespace::getCanonicalName( NS_FILE ), $contLang->getNamespaces()[NS_FILE] ]; + + $aliases = $contLang->getNamespaceAliases(); + foreach ( $aliases as $alias => $namespaceId ) { + if ( $namespaceId == NS_FILE ) + $fileNamespaces [] = $alias; + } + $this->filePrefixRegex[$langCode] = '^(' . implode( '|', $fileNamespaces ) . '):'; + } + return $this->filePrefixRegex[$langCode]; + } + + /** + * @param $filename string + * @param $contLang \Language + * @return mixed + */ + public function sanitizeImageFileName( $filename, $contLang ) { + // replace the MW square brackets and surrounding whitespace + $trimmedFilename = trim( $filename, "\t\n\r[]" ); + + $filePrefixRegex = $this->getFilePrefixRegex( $contLang ); + $unprefixedFilename = mbereg_replace( $filePrefixRegex, "", $trimmedFilename ); + + // strip + $filenameParts = explode( '|', $unprefixedFilename ); + if ( !empty( $filenameParts[0] ) ) { + $filename = $filenameParts[0]; + } return $filename; } -} \ No newline at end of file +} diff --git a/services/Parser/DummyParser.php b/services/Parser/DummyParser.php index f9ee1ba..4ff1c8c 100644 --- a/services/Parser/DummyParser.php +++ b/services/Parser/DummyParser.php @@ -10,4 +10,4 @@ class DummyParser implements ExternalParser { public function parseRecursive( $text ) { return "parseRecursive($text)"; } -} \ No newline at end of file +} diff --git a/services/Parser/Nodes/NodeImage.php b/services/Parser/Nodes/NodeImage.php index 6c8806e..793d0c6 100644 --- a/services/Parser/Nodes/NodeImage.php +++ b/services/Parser/Nodes/NodeImage.php @@ -15,8 +15,9 @@ class NodeImage extends Node { } public function resolveImageUrl( $filename ) { + global $wgContLang; $title = \Title::newFromText( \Wikia\PortableInfobox\Helpers\ImageFilenameSanitizer::getInstance() - ->sanitizeImageFileName($filename), NS_FILE ); + ->sanitizeImageFileName($filename, $wgContLang), NS_FILE ); if ( $title && $title->exists() ) { return \WikiaFileHelper::getFileFromTitle( $title )->getUrlGenerator()->url(); } else { diff --git a/tests/ImageFilenameSanitizerTest.php b/tests/ImageFilenameSanitizerTest.php index 632e07e..3e6155b 100644 --- a/tests/ImageFilenameSanitizerTest.php +++ b/tests/ImageFilenameSanitizerTest.php @@ -16,8 +16,10 @@ class ImageFilenameSanitizerTest extends WikiaBaseTest { * @param $description * @dataProvider testSanitizeFilenameDataProvider */ - public function testSanitizeFilename( $inputFileName, $expectedOutput, $description ) { - $actualOutput = $this->imageFilenameSanitizer->sanitizeImageFileName( $inputFileName ); + public function testSanitizeFilename( $inputFileName, $contentLanguageCode, $expectedOutput, $description ) { + $language = new \Language(); + $language->setCode( $contentLanguageCode ); + $actualOutput = $this->imageFilenameSanitizer->sanitizeImageFileName( $inputFileName, $language ); $this->assertEquals( $expectedOutput, $actualOutput, $description ); } @@ -26,7 +28,57 @@ class ImageFilenameSanitizerTest extends WikiaBaseTest { return [ [ 'filename.jpg', - 'filename.jpg' + 'en', + 'filename.jpg', + 'Plain filename' + ], + [ + 'File:filename.jpg', + 'en', + 'filename.jpg', + 'Filename with namespace' + ], + [ + 'Plik:filename.jpg', + 'pl', + 'filename.jpg', + 'Filename with localized namespace' + ], + [ + 'Grafika:filename.jpg', + 'pl', + 'filename.jpg', + 'Filename with localized namespace alias' + ], + [ + 'File:filename.jpg|300px', + 'en', + 'filename.jpg', + 'Filename with namespace and width' + ], + [ + '[[File:filename.jpg|300px|lorem ipsum]]', + 'en', + 'filename.jpg', + 'Link to filename with namespace, width and caption' + ], + [ + '[[File:filename.jpg|lorem ipsum]]', + 'en', + 'filename.jpg', + 'Link to filename with namespace and caption' + ], + [ + '{{File:filename.jpg|lorem ipsum}}', + 'en', + '{{File:filename.jpg', + 'Non-file string; sanitized, though useless' + ], + [ + '', + 'en', + '', + 'Empty file name' ] ]; } diff --git a/tests/PortableInfoboxParserTagControllerTest.php b/tests/PortableInfoboxParserTagControllerTest.php index 5caabca..4b160dc 100644 --- a/tests/PortableInfoboxParserTagControllerTest.php +++ b/tests/PortableInfoboxParserTagControllerTest.php @@ -24,7 +24,7 @@ class PortableInfoboxParserTagControllerTest extends WikiaBaseTest { public function testNoWrappingParagraphs() { $this->markTestSkipped( 'DAT-2738 - awaiting decision whether this is a behavior to be fixed' ); - $text = PHP_EOL . 'Val' . PHP_EOL; + $text = PHP_EOL . 'Val' . PHP_EOL; $parser = new Parser(); $options = new ParserOptions(); @@ -39,7 +39,7 @@ class PortableInfoboxParserTagControllerTest extends WikiaBaseTest { public function testNoPreTag() { $this->markTestSkipped( 'DAT-2736 - awaiting decision whether this is a behavior to be fixed' ); - $text = 'Val' . PHP_EOL . ' Test'; + $text = 'Val' . PHP_EOL . ' Test'; $parser = new Parser(); $options = new ParserOptions();