r56094 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r56093‎ | r56094 | r56095 >
Date:14:59, 9 September 2009
Author:sergeychernyshev
Status:resolved (Comments)
Tags:
Comment:
Modified paths:
  • /trunk/extensions/PageObjectModel (added) (history)
  • /trunk/extensions/PageObjectModel/Makefile (added) (history)
  • /trunk/extensions/PageObjectModel/POM (added) (history)
  • /trunk/extensions/PageObjectModel/POM.php (added) (history)
  • /trunk/extensions/PageObjectModel/POM/Element.php (added) (history)
  • /trunk/extensions/PageObjectModel/POM/Page.php (added) (history)
  • /trunk/extensions/PageObjectModel/POM/Parser.php (added) (history)
  • /trunk/extensions/PageObjectModel/POM/Template.php (added) (history)
  • /trunk/extensions/PageObjectModel/POM/TemplateCollection.php (added) (history)
  • /trunk/extensions/PageObjectModel/POM/TemplateParameter.php (added) (history)
  • /trunk/extensions/PageObjectModel/POM/TemplateParser.php (added) (history)
  • /trunk/extensions/PageObjectModel/POM/TextNode.php (added) (history)
  • /trunk/extensions/PageObjectModel/POM/Util.php (added) (history)
  • /trunk/extensions/PageObjectModel/PageObjectModel.php (added) (history)
  • /trunk/extensions/PageObjectModel/examples (added) (history)
  • /trunk/extensions/PageObjectModel/examples/POMVersion.php (added) (history)
  • /trunk/extensions/PageObjectModel/tests (added) (history)
  • /trunk/extensions/PageObjectModel/tests/POMPageTest.php (added) (history)
  • /trunk/extensions/PageObjectModel/tests/POMTemplateParserTest.php (added) (history)
  • /trunk/extensions/PageObjectModel/tests/POMTemplateTest.php (added) (history)
  • /trunk/extensions/PageObjectModel/tests/WrongParameterNameExceptionTest.php (added) (history)
  • /trunk/extensions/PageObjectModel/tests/tests.xml (added) (history)

Diff [purge]

Index: trunk/extensions/PageObjectModel/POM.php
@@ -0,0 +1,13 @@
 2+<?
 3+#
 4+# PageObjectModel is a set of classes that allow easy manipulation of MediaWiki page source.
 5+#
 6+
 7+require_once('POM/Element.php');
 8+require_once('POM/Page.php');
 9+require_once('POM/Parser.php');
 10+require_once('POM/TemplateParser.php');
 11+require_once('POM/Template.php');
 12+require_once('POM/TemplateCollection.php');
 13+require_once('POM/TextNode.php');
 14+
Property changes on: trunk/extensions/PageObjectModel/POM.php
___________________________________________________________________
Added: svn:eol-style
115 + native
Index: trunk/extensions/PageObjectModel/tests/tests.xml
@@ -0,0 +1,5 @@
 2+<phpunit>
 3+ <testsuite name="PageObjectModel">
 4+ <directory suffix=".php">tests</directory>
 5+ </testsuite>
 6+</phpunit>
Index: trunk/extensions/PageObjectModel/tests/WrongParameterNameExceptionTest.php
@@ -0,0 +1,15 @@
 2+<?php
 3+require_once 'PHPUnit/Framework.php';
 4+require_once 'POM.php';
 5+
 6+class WrongParameterNameExceptionTest extends PHPUnit_Framework_TestCase
 7+{
 8+ public function testWrongParameterNameExceptionMustContainMessage()
 9+ {
 10+ $e = new WrongParameterNameException("Can't get parameter with no name");
 11+ $this->assertEquals(
 12+ "WrongParameterNameException: [0]: Can't get parameter with no name\n",
 13+ $e->__toString()
 14+ );
 15+ }
 16+}
Property changes on: trunk/extensions/PageObjectModel/tests/WrongParameterNameExceptionTest.php
___________________________________________________________________
Added: svn:eol-style
117 + native
Index: trunk/extensions/PageObjectModel/tests/POMTemplateParserTest.php
@@ -0,0 +1,59 @@
 2+<?php
 3+require_once 'PHPUnit/Framework.php';
 4+require_once 'POM.php';
 5+
 6+class POMTeamplateParserTest extends PHPUnit_Framework_TestCase
 7+{
 8+ public function testTemplateParserMustFindTemplatesInTextNodes()
 9+ {
 10+ $sometext = "sometext\nbefore first with spaces {{sometemplate|var1=var2}}\nbefore second {{someothertemplate}} more text at the end\n";
 11+
 12+ $page = new POMPage($sometext);
 13+ $this->assertTrue(is_a($page->children[0], 'POMTextNode'));
 14+ $this->assertEquals("sometext\nbefore first with spaces ", $page->children[0]->asString());
 15+
 16+ $this->assertTrue(is_a($page->children[1], 'POMTemplate'));
 17+ $this->assertEquals('{{sometemplate|var1=var2}}', $page->children[1]->asString());
 18+
 19+ $this->assertTrue(is_a($page->children[2], 'POMTextNode'));
 20+ $this->assertEquals("\nbefore second ", $page->children[2]->asString());
 21+
 22+ $this->assertTrue(is_a($page->children[3], 'POMTemplate'));
 23+ $this->assertEquals('{{someothertemplate}}', $page->children[3]->asString());
 24+
 25+ $this->assertTrue(is_a($page->children[4], 'POMTextNode'));
 26+ $this->assertEquals(" more text at the end\n", $page->children[4]->asString());
 27+ }
 28+
 29+ public function testTemplateParserMustPopulateTemplatesCollection()
 30+ {
 31+ $sometext = "sometext\nbefore first with spaces {{sometemplate |var1=var2}}\nbefore second {{ someothertemplate|param1 = 0}} plus another {{someothertemplate
 32+|param2 = something
 33+}} more text at the end\n";
 34+
 35+ $page = new POMPage($sometext);
 36+ $this->assertEquals(count($page->c['templates']['sometemplate']), 1);
 37+ $this->assertEquals(count($page->c['templates']['someothertemplate']), 2);
 38+ }
 39+
 40+ public function testTemplateParserMustCorrectlyParseTemplatesWithParameters()
 41+ {
 42+ $sometext = "sometext\nbefore first with spaces {{sometemplate|var1=val1 {{subtemplate|subvar1=subval2}} val1 continue|var2=val2}}\nbefore second {{someothertemplate}} more text at the end\n";
 43+
 44+ $page = new POMPage($sometext);
 45+ $this->assertTrue(is_a($page->children[0], 'POMTextNode'));
 46+ $this->assertEquals("sometext\nbefore first with spaces ", $page->children[0]->asString());
 47+
 48+ $this->assertTrue(is_a($page->children[1], 'POMTemplate'));
 49+ $this->assertEquals('{{sometemplate|var1=val1 {{subtemplate|subvar1=subval2}} val1 continue|var2=val2}}', $page->children[1]->asString());
 50+
 51+ $this->assertTrue(is_a($page->children[2], 'POMTextNode'));
 52+ $this->assertEquals("\nbefore second ", $page->children[2]->asString());
 53+
 54+ $this->assertTrue(is_a($page->children[3], 'POMTemplate'));
 55+ $this->assertEquals('{{someothertemplate}}', $page->children[3]->asString());
 56+
 57+ $this->assertTrue(is_a($page->children[4], 'POMTextNode'));
 58+ $this->assertEquals(" more text at the end\n", $page->children[4]->asString());
 59+ }
 60+}
Property changes on: trunk/extensions/PageObjectModel/tests/POMTemplateParserTest.php
___________________________________________________________________
Added: svn:eol-style
161 + native
Index: trunk/extensions/PageObjectModel/tests/POMTemplateTest.php
@@ -0,0 +1,224 @@
 2+<?php
 3+require_once 'PHPUnit/Framework.php';
 4+require_once 'POM.php';
 5+
 6+class POMTemplateTest extends PHPUnit_Framework_TestCase
 7+{
 8+ #
 9+ # Testing template pass-through behavior
 10+ #
 11+
 12+ # TODO add more data
 13+ public static function templateStringsProvider()
 14+ {
 15+ return array(
 16+ array('{{sometemplate|var1=var2}}'),
 17+ array('{{title with spaces|var1=var2}}'),
 18+ array('{{sometemplate| field name with spaces=var2}}'),
 19+ array('{{sometemplate|var1=value with spaces}}'),
 20+ array('{{sometemplate|1234|var1=value with spaces}}'),
 21+ array('{{sometemplate|a=b|b=c|numbered}}')
 22+ );
 23+ }
 24+
 25+ /**
 26+ * @dataProvider templateStringsProvider
 27+ */
 28+ public function testTemplateMustPreserveOrderOfParameters($templatestring)
 29+ {
 30+ $template = new POMTemplate($templatestring);
 31+ $this->assertEquals($template->asString(), $templatestring);
 32+ }
 33+
 34+ # -------------------------------------------------------------------------------------------------------
 35+ #
 36+ # Testing getting parameter values
 37+ #
 38+
 39+ # TODO add more data
 40+ public static function parameterGetNameValueProvider()
 41+ {
 42+ return array(
 43+ array('{{sometemplate|var1=var2}}', 'var1', 'var2'),
 44+ array('{{title with spaces|var1=var2}}', 'var1', 'var2'),
 45+ array('{{sometemplate| field name with spaces=var2}}', 'field name with spaces', 'var2'),
 46+ array('{{sometemplate|var1=value with spaces}}', 'var1', 'value with spaces'),
 47+ array('{{sometemplate|1234|var1=value with spaces}}', 'var1', 'value with spaces'),
 48+ array('{{sometemplate|a=b|b=c|numbered}}', 'a', 'b'),
 49+ array('{{sometemplate|a=b|b=c|numbered}}', 'b', 'c'),
 50+ array('{{sometemplate|a=b|b=c|numbered}}', 1, 'numbered'),
 51+ array('{{sometemplate|var1=var2}}', 'noexistent', null)
 52+ );
 53+ }
 54+
 55+ /**
 56+ * @dataProvider parameterGetNameValueProvider
 57+ */
 58+ public function testTemplateGetParameter($templatestring, $name, $value)
 59+ {
 60+ $template = new POMTemplate($templatestring);
 61+ $this->assertEquals($value, $template->getParameter($name));
 62+ }
 63+
 64+
 65+ # -------------------------------------------------------------------------------------------------------
 66+ #
 67+ # Testing setting parameter values
 68+ #
 69+
 70+ # TODO add more data
 71+ public static function parameterChangeNameValueProvider()
 72+ {
 73+ return array(
 74+ array('{{sometemplate|a=b|b=c|numbered}}',
 75+ 1,
 76+ 'renumbered',
 77+ '{{sometemplate|a=b|b=c|renumbered}}'),
 78+ array('{{sometemplate|a=b|b=c|numbered 1|numbered 2}}',
 79+ 2,
 80+ 'renumbered 2',
 81+ '{{sometemplate|a=b|b=c|numbered 1|renumbered 2}}'),
 82+ array('{{sometemplate|a=b|b=c|numbered 1|numbered 2}}',
 83+ 3,
 84+ 'new numbered',
 85+ '{{sometemplate|a=b|b=c|numbered 1|numbered 2|new numbered}}'),
 86+ array('{{sometemplate|var1=var2}}',
 87+ 'var1',
 88+ 'var3',
 89+ '{{sometemplate|var1=var3}}'),
 90+ array('{{sometemplate|var1= var2}}',
 91+ 'var1',
 92+ 'var3',
 93+ '{{sometemplate|var1= var3}}'),
 94+ array('{{sometemplate|var1 =var2}}',
 95+ 'var1',
 96+ 'var3',
 97+ '{{sometemplate|var1 =var3}}'),
 98+ array('{{title with spaces|var1=var2}}',
 99+ 'var1',
 100+ 'var3',
 101+ '{{title with spaces|var1=var3}}'),
 102+ array('{{sometemplate| field name with spaces=var2}}',
 103+ 'field name with spaces',
 104+ 'var3',
 105+ '{{sometemplate| field name with spaces=var3}}'),
 106+ array('{{sometemplate|var1=value with spaces}}',
 107+ 'var1',
 108+ 'value with spaces 2',
 109+ '{{sometemplate|var1=value with spaces 2}}'),
 110+ array('{{sometemplate|1234|var1=value with spaces}}',
 111+ 'var1',
 112+ 'value with spaces 2',
 113+ '{{sometemplate|1234|var1=value with spaces 2}}'),
 114+ array('{{sometemplate|a=b|b=c|numbered}}',
 115+ 'a',
 116+ 'd',
 117+ '{{sometemplate|a=d|b=c|numbered}}'),
 118+ array('{{sometemplate|a=b|b=c|numbered}}',
 119+ 'x',
 120+ 'y',
 121+ '{{sometemplate|a=b|b=c|numbered|x=y}}')
 122+ );
 123+ }
 124+
 125+ /**
 126+ * @dataProvider parameterChangeNameValueProvider
 127+ */
 128+ public function testTemplateParameterChange($orig, $index, $value, $result)
 129+ {
 130+ $template = new POMTemplate($orig);
 131+ $template->setParameter($index, $value);
 132+ $this->assertEquals($result, $template->asString());
 133+ }
 134+
 135+ # TODO add more data
 136+ public static function parameterChangeSpacedNameValueProvider()
 137+ {
 138+ return array(
 139+ array('{{sometemplate|a=b|b=c|numbered}}',
 140+ ' 1',
 141+ 'renumbered',
 142+ '{{sometemplate|a=b|b=c|renumbered}}'),
 143+ array('{{sometemplate|a=b|b=c|numbered 1|numbered 2}}',
 144+ ' 2 ',
 145+ 'renumbered 2',
 146+ '{{sometemplate|a=b|b=c|numbered 1|renumbered 2}}'),
 147+ array('{{sometemplate|a=b|b=c|numbered 1|numbered 2}}',
 148+ '3 ',
 149+ 'new numbered',
 150+ '{{sometemplate|a=b|b=c|numbered 1|numbered 2|new numbered}}'),
 151+ array('{{sometemplate|var1=var2}}',
 152+ ' var1 ',
 153+ ' var3',
 154+ '{{sometemplate| var1 = var3}}'),
 155+ array('{{sometemplate|var1= var2}}',
 156+ ' var1 ',
 157+ ' var3 ',
 158+ '{{sometemplate| var1 = var3 }}'),
 159+ array('{{sometemplate|var1 =var2}}',
 160+ ' var1 ',
 161+ ' var3 ',
 162+ '{{sometemplate| var1 = var3 }}'),
 163+ array('{{title with spaces|var1=var2}}',
 164+ ' var1 ',
 165+ ' var3 ',
 166+ '{{title with spaces| var1 = var3 }}'),
 167+ array('{{sometemplate| field name with spaces=var2}}',
 168+ 'field name with spaces ',
 169+ 'var3 ',
 170+ '{{sometemplate|field name with spaces =var3 }}'),
 171+ array('{{sometemplate| var1 = value with spaces }}',
 172+ 'var1',
 173+ 'value with spaces 2',
 174+ '{{sometemplate|var1=value with spaces 2}}'),
 175+ array('{{sometemplate|1234|var1= value with spaces}}',
 176+ 'var1',
 177+ 'value with spaces 2',
 178+ '{{sometemplate|1234|var1=value with spaces 2}}'),
 179+ array('{{sometemplate|a =b | b = c|numbered}}',
 180+ 'a',
 181+ 'd',
 182+ '{{sometemplate|a=d| b = c|numbered}}'),
 183+ array('{{sometemplate| a =b|b=c|numbered}}',
 184+ 'x ',
 185+ ' y',
 186+ '{{sometemplate| a =b|b=c|numbered|x = y}}')
 187+ );
 188+ }
 189+ /**
 190+ * @dataProvider parameterChangeSpacedNameValueProvider
 191+ */
 192+ public function testTemplateParameterChangeHonoringSpacing($orig, $index, $value, $result)
 193+ {
 194+ $template = new POMTemplate($orig);
 195+ $template->setParameter($index, $value, false, false, true, true);
 196+ $this->assertEquals($result, $template->asString());
 197+ }
 198+
 199+ public function testParameterWithEmptyNameShouldBeIgnoredButPreserved()
 200+ {
 201+ $somestring = '{{tempname|name=val1|=val2}}';
 202+ $template = new POMTemplate($somestring);
 203+ $this->assertEquals($somestring, $template->asString());
 204+ }
 205+
 206+ /**
 207+ * @expectedException WrongParameterNameException
 208+ */
 209+ public function testThrowExceptionOnGettingParameterByEmptyName()
 210+ {
 211+ $somestring = '{{tempname|name=val1}}';
 212+ $template = new POMTemplate($somestring);
 213+ $res = $template->getParameter(' ');
 214+ }
 215+
 216+ /**
 217+ * @expectedException WrongParameterNameException
 218+ */
 219+ public function testThrowExceptionSettingParameterByEmptyName()
 220+ {
 221+ $somestring = '{{tempname|name=val1}}';
 222+ $template = new POMTemplate($somestring);
 223+ $res = $template->setParameter(' ', 'value');
 224+ }
 225+}
Property changes on: trunk/extensions/PageObjectModel/tests/POMTemplateTest.php
___________________________________________________________________
Added: svn:eol-style
1226 + native
Index: trunk/extensions/PageObjectModel/tests/POMPageTest.php
@@ -0,0 +1,31 @@
 2+<?php
 3+require_once 'PHPUnit/Framework.php';
 4+require_once 'POM.php';
 5+
 6+class POMPageTest extends PHPUnit_Framework_TestCase
 7+{
 8+ # TODO add more data
 9+ public static function pageProvider()
 10+ {
 11+ return array(
 12+ array('{{sometemplate|var1=var2}}'),
 13+ array('{{title with spaces|var1=var2}}'),
 14+ array('{{sometemplate| field name with spaces=var2}}'),
 15+ array('{{sometemplate|var1=value with spaces}}'),
 16+ array('{{sometemplate|1234|var1=value with spaces}}'),
 17+ array('{{sometemplate|a=b|b=c|numbered}}'),
 18+ array("sometext\nbefore first with spaces {{sometemplate |var1=var2}}\nbefore second {{ someothertemplate|param1 = 0}} plus another {{someothertemplate
 19+|param2 = something
 20+}} more text at the end\n")
 21+ );
 22+ }
 23+
 24+ /**
 25+ * @dataProvider pageProvider
 26+ */
 27+ public function testInputIsTheSameAsOutput($pagetext)
 28+ {
 29+ $page = new POMPage($pagetext);
 30+ $this->assertEquals($pagetext, $page->asString());
 31+ }
 32+}
Property changes on: trunk/extensions/PageObjectModel/tests/POMPageTest.php
___________________________________________________________________
Added: svn:eol-style
133 + native
Index: trunk/extensions/PageObjectModel/PageObjectModel.php
@@ -0,0 +1,208 @@
 2+<?php
 3+#
 4+# This will enable POM editing throught MediaWiki API
 5+#
 6+require_once ("$IP/extensions/PageObjectModel/POM.php");
 7+
 8+require_once ("$IP/includes/api/ApiBase.php");
 9+
 10+global $wgAPIModules;
 11+$wgAPIModules['pomsettplparam'] = 'ApiPOMSetTemplateParameter';
 12+$wgAPIModules['pomgettplparam'] = 'ApiPOMGetTemplateParameter';
 13+
 14+/**
 15+ * @addtogroup API
 16+ */
 17+class ApiPOMSetTemplateParameter extends ApiBase {
 18+
 19+ public function __construct($query, $moduleName) {
 20+ parent :: __construct($query, $moduleName);
 21+ }
 22+
 23+ public function execute() {
 24+ global $wgUser;
 25+
 26+ $params = $this->extractRequestParams();
 27+ if (is_null($params['page']))
 28+ $this->dieUsage('Must specify page title', 0);
 29+ if (is_null($params['tpl']))
 30+ $this->dieUsage('Must specify template name', 1);
 31+ if (is_null($params['param']))
 32+ $this->dieUsage('Must specify parameter name', 2);
 33+ if (is_null($params['value']))
 34+ $this->dieUsage('Must specify value', 3);
 35+ if (is_null($params['summary']))
 36+ $this->dieUsage('Must specify edit summary', 4);
 37+
 38+ $page = $params['page'];
 39+ $template = $params['tpl'];
 40+ $instance = $params['tplinstance'];
 41+ $parameter = $params['param'];
 42+ $value = $params['value'];
 43+ $summary = $params['summary'];
 44+
 45+
 46+ $articleTitle = Title::newFromText( $page );
 47+ if (!$articleTitle)
 48+ $this->dieUsage("Can't create title object ($page)", 5);
 49+
 50+ $errors = $articleTitle->getUserPermissionsErrors('edit', $wgUser);
 51+ if(!empty($errors))
 52+ $this->dieUsage(wfMsg($errors[0][0], $errors[0][1]), 8);
 53+
 54+ $article = new Article($articleTitle);
 55+ if (!$article->exists())
 56+ $this->dieUsage("Article doesn't exist ($page)", 6);
 57+
 58+ $pom = new POMPage($article->getContent());
 59+ if (array_key_exists($template, $pom->templates)
 60+ && array_key_exists($instance, $pom->templates[$template])
 61+ )
 62+ {
 63+ $pom->templates[$template][$instance]->setParameter($parameter, $value);
 64+ }
 65+ else
 66+ {
 67+ $this->dieUsage("This template ($template, instance #$instance) with this parameter ($parameter) doesn't exist within this page ($page)", 7);
 68+ }
 69+
 70+ $success = $article->doEdit($pom->asString(), $summary);
 71+
 72+ $result=array();
 73+ if ( $success ) {
 74+ $result['result']='Success';
 75+ } else {
 76+ $result['result']='Failure';
 77+ }
 78+
 79+ $this->getResult()->addValue(null, 'pomsettplparam', $result);
 80+ }
 81+
 82+ protected function getAllowedParams() {
 83+ return array (
 84+ 'page' => null,
 85+ 'tpl' => null,
 86+ 'tplinstance' => array (
 87+ ApiBase :: PARAM_TYPE => 'integer',
 88+ ApiBase :: PARAM_DFLT => 0,
 89+ ApiBase :: PARAM_MIN => 0
 90+ ),
 91+ 'param' => null,
 92+ 'value' => null,
 93+ 'summary' => null
 94+ );
 95+ }
 96+
 97+ protected function getParamDescription() {
 98+ return array (
 99+ 'page' => 'Title of the page to modify',
 100+ 'tpl' => 'Name of the template withing the page',
 101+ 'tplinstance' => 'Instance number of the template - by dafault firt (0) is used',
 102+ 'param' => 'Parameter name',
 103+ 'value' => 'Value to set',
 104+ 'summary' => 'Edit summary'
 105+ );
 106+ }
 107+
 108+ protected function getDescription() {
 109+ return 'Call to set template parameter value using Page Object Model (http://www.mediawiki.org/Extension:Page_Object_Model)';
 110+ }
 111+
 112+ protected function getExamples() {
 113+ return array (
 114+ 'api.php?action=pomsettplparam&page=Somepage&tpl=SomeTempate&param=templateparam&value=It+works!&summary=Editing+template+param+using+Page+Object+Model'
 115+ );
 116+ }
 117+
 118+ public function getVersion() {
 119+ return __CLASS__ . ': $Id$';
 120+ }
 121+}
 122+
 123+/**
 124+ * @addtogroup API
 125+ */
 126+class ApiPOMGetTemplateParameter extends ApiBase {
 127+
 128+ public function __construct($query, $moduleName) {
 129+ parent :: __construct($query, $moduleName);
 130+ }
 131+
 132+ public function execute() {
 133+ global $wgUser;
 134+
 135+ $params = $this->extractRequestParams();
 136+ if (is_null($params['page']))
 137+ $this->dieUsage('Must specify page title', 0);
 138+ if (is_null($params['tpl']))
 139+ $this->dieUsage('Must specify template name', 1);
 140+ if (is_null($params['param']))
 141+ $this->dieUsage('Must specify parameter name', 2);
 142+
 143+ $page = $params['page'];
 144+ $template = $params['tpl'];
 145+ $instance = $params['tplinstance'];
 146+ $parameter = $params['param'];
 147+
 148+ $articleTitle = Title::newFromText( $page );
 149+ if (!$articleTitle)
 150+ $this->dieUsage("Can't create title object ($page)", 5);
 151+
 152+ $errors = $articleTitle->getUserPermissionsErrors('read', $wgUser);
 153+ if(!empty($errors))
 154+ $this->dieUsage(wfMsg($errors[0][0], $errors[0][1]), 8);
 155+
 156+ $article = new Article($articleTitle);
 157+ if (!$article->exists())
 158+ $this->dieUsage("Article doesn't exist ($page)", 6);
 159+
 160+ $pom = new POMPage($article->getContent());
 161+ if (array_key_exists($template, $pom->templates)
 162+ && array_key_exists($instance, $pom->templates[$template])
 163+ )
 164+ {
 165+ $result['value'] = $pom->templates[$template][$instance]->getParameter($parameter);
 166+ $this->getResult()->addValue(null, 'pomgettplparam', $result);
 167+ }
 168+ else
 169+ {
 170+ $this->dieUsage("This template ($template, instance #$instance) with this parameter ($parameter) doesn't exist within this page ($page)", 7);
 171+ }
 172+ }
 173+
 174+ protected function getAllowedParams() {
 175+ return array (
 176+ 'page' => null,
 177+ 'tpl' => null,
 178+ 'tplinstance' => array (
 179+ ApiBase :: PARAM_TYPE => 'integer',
 180+ ApiBase :: PARAM_DFLT => 0,
 181+ ApiBase :: PARAM_MIN => 0
 182+ ),
 183+ 'param' => null
 184+ );
 185+ }
 186+
 187+ protected function getParamDescription() {
 188+ return array (
 189+ 'page' => 'Title of the page to query',
 190+ 'tpl' => 'Name of the template withing the page',
 191+ 'tplinstance' => 'Instance number of the template - by dafault firt (0) is used',
 192+ 'param' => 'Parameter name'
 193+ );
 194+ }
 195+
 196+ protected function getDescription() {
 197+ return 'Call to get template parameter value using Page Object Model (http://www.mediawiki.org/Extension:Page_Object_Model)';
 198+ }
 199+
 200+ protected function getExamples() {
 201+ return array (
 202+ 'api.php?action=pomgettplparam&page=Somepage&tpl=SomeTempate&param=templateparam'
 203+ );
 204+ }
 205+
 206+ public function getVersion() {
 207+ return __CLASS__ . ': $Id$';
 208+ }
 209+}
Property changes on: trunk/extensions/PageObjectModel/PageObjectModel.php
___________________________________________________________________
Added: svn:eol-style
1210 + native
Index: trunk/extensions/PageObjectModel/POM/Element.php
@@ -0,0 +1,27 @@
 2+<?php
 3+#
 4+# Element is an abstract class repersents every part distinguished within the page
 5+# All real elements must be a subclass of this class
 6+#
 7+
 8+abstract class POMElement {
 9+
 10+ public $children = array();
 11+
 12+ function asString() {
 13+ $output = '';
 14+
 15+ foreach ($this->children as $child)
 16+ {
 17+ $output.=$child->asString();
 18+ }
 19+
 20+ return $output;
 21+ }
 22+
 23+ function addChild(POMElement $el)
 24+ {
 25+ $this->children[] = $el;
 26+ }
 27+}
 28+
Property changes on: trunk/extensions/PageObjectModel/POM/Element.php
___________________________________________________________________
Added: svn:eol-style
129 + native
Index: trunk/extensions/PageObjectModel/POM/TextNode.php
@@ -0,0 +1,21 @@
 2+<?php
 3+#
 4+# TextNode represents simple text
 5+#
 6+
 7+class POMTextNode extends POMElement {
 8+
 9+ protected $nodeText = '';
 10+
 11+ public function POMTextNode($text)
 12+ {
 13+ $this->nodeText = $text;
 14+ $this->children = null; // forcefully ignore children
 15+ }
 16+
 17+ public function asString()
 18+ {
 19+ return $this->nodeText;
 20+ }
 21+}
 22+
Property changes on: trunk/extensions/PageObjectModel/POM/TextNode.php
___________________________________________________________________
Added: svn:eol-style
123 + native
Index: trunk/extensions/PageObjectModel/POM/Template.php
@@ -0,0 +1,163 @@
 2+<?php
 3+#
 4+# Template class repersents templates
 5+#
 6+require_once('Util.php');
 7+require_once('TemplateParameter.php');
 8+
 9+class POMTemplate extends POMElement
 10+{
 11+ protected $title_triple;
 12+
 13+ protected $parameters = array();
 14+
 15+ public function POMTemplate($text)
 16+ {
 17+ $this->children = null; // forcefully ignore children
 18+
 19+ # Remove curly braces at the beginning and at the end
 20+ $text = substr($text, 2, strlen($text) - 4);
 21+
 22+ # Split by pipe
 23+ $parts = split('\|', $text);
 24+
 25+ $this->title_triple = new POMUtilTrimTriple(array_shift($parts));
 26+
 27+ foreach ($parts as $part)
 28+ {
 29+ $this->parameters[] = POMTemplateParameter::parse($part);
 30+ }
 31+ }
 32+
 33+ public function getTitle()
 34+ {
 35+ return $this->title_triple->trimmed;
 36+ }
 37+
 38+ public function getParameter($name)
 39+ {
 40+ $trimmed_name = trim($name);
 41+ if (strlen($trimmed_name) == 0)
 42+ {
 43+ throw new WrongParameterNameException('Can\'t get parameter with no name');
 44+ }
 45+
 46+ $number = 1;
 47+ for ($i = 0; $i < count($this->parameters); $i++)
 48+ {
 49+ $parameter = $this->parameters[$i];
 50+
 51+ # checking this in runtime to make sure we cover all post-parsing updates to the list
 52+ if (is_a($parameter, 'POMTemplateNamedParameter'))
 53+ {
 54+ if ($parameter->getName() == $trimmed_name)
 55+ {
 56+ return $parameter->getValue();
 57+ }
 58+ }
 59+ else if (is_a($parameter, 'POMTemplateNumberedParameter'))
 60+ {
 61+ if ($number == $trimmed_name)
 62+ {
 63+ return $parameter->getValue();
 64+ }
 65+ $number++;
 66+ }
 67+ }
 68+
 69+ return null; # none matched
 70+ }
 71+
 72+ public function setParameter($name, $value,
 73+ $ignore_name_spacing = true,
 74+ $ignore_value_spacing = true,
 75+ $override_name_spacing = false, # when original value exists
 76+ $override_value_spacing = false # when original value exists
 77+ )
 78+ {
 79+ $trimmed_name = trim($name);
 80+ if (strlen($trimmed_name) == 0)
 81+ {
 82+ throw new WrongParameterNameException("Can't set parameter with no name");
 83+ }
 84+
 85+ if ($ignore_name_spacing)
 86+ {
 87+ $name = $trimmed_name;
 88+ }
 89+
 90+ if ($ignore_value_spacing)
 91+ {
 92+ $value = trim($value);
 93+ }
 94+
 95+ # first go through named parameters and see if name matches
 96+ for ($i = 0; $i < count($this->parameters); $i++)
 97+ {
 98+ if (is_a($this->parameters[$i], 'POMTemplateNamedParameter') &&
 99+ $this->parameters[$i]->getName() == $trimmed_name)
 100+ {
 101+ $this->parameters[$i]->update($name, $value, $override_name_spacing, $override_value_spacing);
 102+ return;
 103+ }
 104+ }
 105+
 106+ # then go through numbered parameters and see if parameter with this number exists
 107+ $number = 1;
 108+ for ($i = 0; $i < count($this->parameters); $i++)
 109+ {
 110+ if (is_a($this->parameters[$i], 'POMTemplateNumberedParameter'))
 111+ {
 112+ if ($number == $trimmed_name)
 113+ {
 114+ $this->parameters[$i]->update($value, $override_value_spacing);
 115+ return;
 116+ }
 117+ $number++;
 118+ }
 119+ }
 120+
 121+ # now, if passed name is numeric, create numbered parameter, otherwise create named parameter
 122+ # add parameter to parameters array
 123+ if (is_numeric($trimmed_name) && ((int)$trimmed_name) == $trimmed_name)
 124+ {
 125+ $this->parameters[] = new POMTemplateNumberedParameter($value);
 126+ }
 127+ else
 128+ {
 129+ $this->parameters[] = new POMTemplateNamedParameter($name, $value);
 130+ }
 131+ }
 132+
 133+ public function asString()
 134+ {
 135+ $text = '{{'.$this->title_triple->toString();
 136+
 137+ for ($i = 0; $i < count($this->parameters); $i++)
 138+ {
 139+ $text .= '|';
 140+ #echo "\n[$i]: ".var_export($this->parameters)."\n\n-----------------------------------\n";
 141+ $text .= $this->parameters[$i]->toString();
 142+ }
 143+
 144+ $text .= '}}';
 145+
 146+ return $text;
 147+ }
 148+}
 149+
 150+class WrongParameterNameException extends Exception
 151+{
 152+ // Redefine the exception so message isn't optional
 153+ public function __construct($message, $code = 0) {
 154+ // some code
 155+
 156+ // make sure everything is assigned properly
 157+ parent::__construct($message, $code);
 158+ }
 159+
 160+ // custom string representation of object
 161+ public function __toString() {
 162+ return __CLASS__ . ": [{$this->code}]: {$this->message}\n";
 163+ }
 164+}
Property changes on: trunk/extensions/PageObjectModel/POM/Template.php
___________________________________________________________________
Added: svn:eol-style
1165 + native
Index: trunk/extensions/PageObjectModel/POM/Page.php
@@ -0,0 +1,32 @@
 2+<?php
 3+#
 4+# Page class repersents Page - top level element resulting from page parsing.
 5+#
 6+
 7+class POMPage extends POMElement
 8+{
 9+ var $c = array(); # collections array - parsers can elements to it
 10+
 11+ var $templates; # shortcut to $c['templates'], set up if POMTemplateParser was used
 12+
 13+ public function POMPage($text, $parsers = array('POMTemplateParser'))
 14+ {
 15+ $this->addChild(new POMTextNode($text));
 16+
 17+ #
 18+ # Here we'll call parsers
 19+ #
 20+ foreach ($parsers as $parser)
 21+ {
 22+ # workign around no class variables in PHP pre 5.3.0
 23+ call_user_func(array($parser, 'Parse'), $this);
 24+
 25+ # let's try to add $this->templates
 26+ if ($parser == 'POMTemplateParser' && array_key_exists('templates', $this->c))
 27+ {
 28+ $this->templates = $this->c['templates'];
 29+ }
 30+ }
 31+ }
 32+}
 33+
Property changes on: trunk/extensions/PageObjectModel/POM/Page.php
___________________________________________________________________
Added: svn:eol-style
134 + native
Index: trunk/extensions/PageObjectModel/POM/Parser.php
@@ -0,0 +1,15 @@
 2+<?php
 3+#
 4+# Parser is an abstract class for various parsers that will post-process a page.
 5+# All parsers must subclass this class
 6+#
 7+
 8+abstract class POMParser
 9+{
 10+ /**
 11+ This is main method for parsers
 12+ It takes a page as argument and processes it adding elements
 13+ */
 14+ static abstract function Parse(POMPage $page);
 15+}
 16+
Property changes on: trunk/extensions/PageObjectModel/POM/Parser.php
___________________________________________________________________
Added: svn:eol-style
117 + native
Index: trunk/extensions/PageObjectModel/POM/TemplateParameter.php
@@ -0,0 +1,158 @@
 2+<?php
 3+#
 4+# Set of classes representing various types of template parameters
 5+#
 6+require_once('Util.php');
 7+
 8+abstract class POMTemplateParameter
 9+{
 10+ abstract function toString();
 11+
 12+ static function parse($text)
 13+ {
 14+
 15+ $pair = split('=', $text, 2);
 16+
 17+ # if it's a name/value pair, create POMTemplateNamedParameter, otherwise, create POMTemplateNumberedParameter
 18+ # if neither can be created, return POMTemplateInvalidParameter
 19+ if (count($pair) > 1)
 20+ {
 21+ $name = $pair[0];
 22+ $value = $pair[1];
 23+
 24+ $name_triple = new POMUtilTrimTriple($name);
 25+
 26+ if (strlen($name_triple->trimmed)<=0)
 27+ {
 28+ # ignore parameters with empty name
 29+ return new POMTemplateInvalidParameter($text);
 30+ }
 31+
 32+ return new POMTemplateNamedParameter($name, $value);
 33+ }
 34+ else
 35+ {
 36+ return new POMTemplateNumberedParameter($text);
 37+ }
 38+ }
 39+}
 40+
 41+class POMTemplateNamedParameter extends POMTemplateParameter
 42+{
 43+ private $name_triple;
 44+ private $value_triple;
 45+
 46+ function __construct($name, $value)
 47+ {
 48+ $this->name_triple = new POMUtilTrimTriple($name);
 49+ $this->value_triple = new POMUtilTrimTriple($value);
 50+ }
 51+
 52+ function update($name, $value, $override_name_spacing = false, $override_value_spacing = false)
 53+ {
 54+ $name_triple = new POMUtilTrimTriple($name);
 55+ $value_triple = new POMUtilTrimTriple($value);
 56+
 57+ if ($override_name_spacing)
 58+ {
 59+ $this->name_triple = $name_triple;
 60+ }
 61+ else
 62+ {
 63+ $this->name_triple->trimmed = $name_triple->trimmed;
 64+ }
 65+
 66+ if ($override_value_spacing)
 67+ {
 68+ $this->value_triple = $value_triple;
 69+ }
 70+ else
 71+ {
 72+ $this->value_triple->trimmed = $value_triple->trimmed;
 73+ }
 74+ }
 75+
 76+ function getName()
 77+ {
 78+ return $this->name_triple->trimmed;
 79+ }
 80+
 81+ function getValue()
 82+ {
 83+ return $this->value_triple->trimmed;
 84+ }
 85+
 86+ function getNameTriple()
 87+ {
 88+ return $this->name_triple;
 89+ }
 90+
 91+ function getValueTriple()
 92+ {
 93+ return $this->value_triple;
 94+ }
 95+
 96+ function toString()
 97+ {
 98+ return $this->name_triple->toString().'='.$this->value_triple->toString();
 99+ }
 100+}
 101+
 102+
 103+class POMTemplateNumberedParameter extends POMTemplateParameter
 104+{
 105+ private $value_triple;
 106+
 107+ function __construct($value)
 108+ {
 109+ $this->value_triple = new POMUtilTrimTriple($value);
 110+ }
 111+
 112+ function update($value, $override_value_spacing = false)
 113+ {
 114+ $value_triple = new POMUtilTrimTriple($value);
 115+
 116+ if ($override_value_spacing)
 117+ {
 118+ $this->value_triple = $value_triple;
 119+ }
 120+ else
 121+ {
 122+ $this->value_triple->trimmed = $value_triple->trimmed;
 123+ }
 124+ }
 125+
 126+ function getValue()
 127+ {
 128+ return $this->value_triple->trimmed;
 129+ }
 130+
 131+ function getValueTriple()
 132+ {
 133+ return $this->value_triple;
 134+ }
 135+
 136+ function toString()
 137+ {
 138+ return $this->value_triple->toString();
 139+ }
 140+
 141+}
 142+
 143+/**
 144+ * Represents parameters that need to be preserved, but not parsed
 145+ */
 146+class POMTemplateInvalidParameter extends POMTemplateParameter
 147+{
 148+ private $text;
 149+
 150+ function __construct($text)
 151+ {
 152+ $this->text = $text;
 153+ }
 154+
 155+ function toString()
 156+ {
 157+ return $this->text;
 158+ }
 159+}
Property changes on: trunk/extensions/PageObjectModel/POM/TemplateParameter.php
___________________________________________________________________
Added: svn:eol-style
1160 + native
Index: trunk/extensions/PageObjectModel/POM/Util.php
@@ -0,0 +1,38 @@
 2+<?php
 3+#
 4+# Set of classes representing various types of template parameters
 5+#
 6+
 7+class POMUtilTrimTriple
 8+{
 9+ public $leading_space;
 10+ public $trimmed;
 11+ public $trailing_space;
 12+
 13+ function POMUtilTrimTriple($text)
 14+ {
 15+ $this->trimmed = trim($text);
 16+ if (strlen($this->trimmed) > 0)
 17+ {
 18+ $this->leading_space = substr($text, 0, strpos($text, $this->trimmed));
 19+ if (strpos($text, $this->trimmed) + strlen($this->trimmed) < strlen($text))
 20+ {
 21+ $this->trailing_space = substr($text, strpos($text, $this->trimmed) + strlen($this->trimmed));
 22+ }
 23+ else
 24+ {
 25+ $this->trailing_space = '';
 26+ }
 27+ }
 28+ else
 29+ {
 30+ $this->leading_space = '';
 31+ $this->trailing_space = $text;
 32+ }
 33+ }
 34+
 35+ function toString()
 36+ {
 37+ return $this->leading_space.$this->trimmed.$this->trailing_space;
 38+ }
 39+}
Property changes on: trunk/extensions/PageObjectModel/POM/Util.php
___________________________________________________________________
Added: svn:eol-style
140 + native
Index: trunk/extensions/PageObjectModel/POM/TemplateCollection.php
@@ -0,0 +1,10 @@
 2+<?php
 3+#
 4+# TemplateCollection class repersents collection of templates with the same name
 5+# Template collections are used in Page::templates shortcut construct
 6+#
 7+
 8+class POMTemplateCollection {
 9+
 10+}
 11+
Property changes on: trunk/extensions/PageObjectModel/POM/TemplateCollection.php
___________________________________________________________________
Added: svn:eol-style
112 + native
Index: trunk/extensions/PageObjectModel/POM/TemplateParser.php
@@ -0,0 +1,104 @@
 2+<?php
 3+#
 4+# Template class repersents templates
 5+#
 6+
 7+define("MAX_TEMPLATE_NESTING_LEVEL", 50);
 8+
 9+class POMTemplateParser extends POMParser
 10+{
 11+ #
 12+ # This function will parse all POMTextNodes in the page and add POMTemplate nodes if templates are found
 13+ #
 14+ static function Parse(POMPage $page)
 15+ {
 16+ // this array holds shortcuts to templates
 17+ $page->c['templates'] = array();
 18+
 19+ // this array will hold updated version of the tree end will replace original one if it was updated
 20+ $newchildren = array();
 21+
 22+ // we'll set it to true if tree was updated
 23+ $replaceoldchildrenwithnew = false;
 24+
 25+ for ($n = 0; $n < sizeof($page->children); $n++)
 26+ {
 27+ if (is_a($page->children[$n], 'POMTextNode'))
 28+ {
 29+ $nodetext = $page->children[$n]->asString();
 30+
 31+ while(($firstopen = strpos($nodetext, '{{')) !== FALSE)
 32+ {
 33+ $position = $firstopen;
 34+
 35+ $balance = 1; // we just found first open, balance moved up
 36+
 37+ // by the end of this loop, $position should hold end of template
 38+ do
 39+ {
 40+ $nextopen = strpos($nodetext, '{{', $position+2);
 41+ $nextclose = strpos($nodetext, '}}', $position+2);
 42+
 43+ // we didn't find end of template but still in this loop - skipping to next chunk
 44+ if ($nextclose === FALSE)
 45+ {
 46+ $brokenchunk = TRUE;
 47+ continue 3; // get to next item in for loop
 48+ }
 49+
 50+ // next open tag is first, balance goes up
 51+ // position is updated to closest marker
 52+ if ($nextopen !== FALSE && $nextopen < $nextclose)
 53+ {
 54+ $balance += 1;
 55+ $position = $nextopen;
 56+ }
 57+ else
 58+ {
 59+ $balance -= 1;
 60+ $position = $nextclose;
 61+ }
 62+
 63+ // In case something is wrong and we recursed too deep, die.
 64+ if ($balance > MAX_TEMPLATE_NESTING_LEVEL)
 65+ {
 66+ die('[ERROR] Reached maximum template nesting level of '.MAX_TEMPLATE_NESTING_LEVEL.". Something is probably wrong with POM, please report this problem to developers.\n");
 67+ }
 68+ } while ($balance > 0); // we'll be done with the loop only when found matching chunk
 69+
 70+ // part before the template becomes text node
 71+ $newchildren[] = new POMTextNode(substr($nodetext, 0, $firstopen));
 72+
 73+ // part between opening {{ and closing }} becomes template
 74+ $template = new POMTemplate(substr($nodetext, $firstopen, $position+2-$firstopen));
 75+ $newchildren[] = $template;
 76+ $page->c['templates'][$template->getTitle()][] = $template;
 77+
 78+ // the rest of it should be processed for more templates
 79+ $nodetext = substr($nodetext, $position+2);
 80+
 81+ $replaceoldchildrenwithnew = true;
 82+ }
 83+
 84+ if (strlen($nodetext) > 0)
 85+ {
 86+ $newchildren[] = new POMTextNode($nodetext);
 87+
 88+ $replaceoldchildrenwithnew = true;
 89+ }
 90+ }
 91+ else
 92+ {
 93+ // preserve non-text nodes in the tree
 94+ $newchildren[] = $page->children[$n];
 95+ }
 96+ }
 97+
 98+ // if tree was updated, let's replace it in the page
 99+ if ($replaceoldchildrenwithnew)
 100+ {
 101+ $page->children = $newchildren;
 102+ }
 103+ }
 104+}
 105+
Property changes on: trunk/extensions/PageObjectModel/POM/TemplateParser.php
___________________________________________________________________
Added: svn:eol-style
1106 + native
Index: trunk/extensions/PageObjectModel/Makefile
@@ -0,0 +1,16 @@
 2+# Simple make file to run PHPUnit tests
 3+
 4+all: testcoverage
 5+
 6+test:
 7+ phpunit --configuration tests/tests.xml
 8+
 9+testcoverage:
 10+ phpunit --configuration tests/tests.xml --coverage-html code_coverage
 11+
 12+clean:
 13+ rm -rf code_coverage
 14+ rm PageObjectModel*.tgz
 15+
 16+tardist:
 17+ tar -c POM.php POM/ --exclude .svn| gzip >PageObjectModel.tgz
Property changes on: trunk/extensions/PageObjectModel/Makefile
___________________________________________________________________
Added: svn:eol-style
118 + native
Index: trunk/extensions/PageObjectModel/examples/POMVersion.php
@@ -0,0 +1,15 @@
 2+<?
 3+require_once('POM.php');
 4+
 5+# Get document from MediaWiki server
 6+$pom = new POMPage(join(file('http://www.mediawiki.org/w/index.php?title=Extension:Page_Object_Model&action=raw')));
 7+
 8+# Check current version
 9+$ver = $pom->templates['Extension'][0]->getParameter('version');
 10+echo "Current version: $ver\n";
 11+
 12+# Increase version number by fraction
 13+$pom->templates['Extension'][0]->setParameter('version', $ver + 0.1);
 14+
 15+# Do whatever you want with result (we'll just display it)
 16+echo "Document with increased version:\n".$pom->asString();
Property changes on: trunk/extensions/PageObjectModel/examples/POMVersion.php
___________________________________________________________________
Added: svn:eol-style
117 + native

Follow-up revisions

RevisionCommit summaryAuthorDate
r92074Resolve fixme on r56094: Cannot have abstract static functions in a class. Tu...demon18:26, 13 July 2011

Comments

#Comment by Simetrical (talk | contribs)   16:02, 9 September 2009

You should add license info somewhere.

#Comment by Sergey Chernyshev (talk | contribs)   16:24, 9 September 2009

Hmm. Yes, I forgot that I didn't decide on a license - what's best for code that can be used as library for people's bots and at the same time being MW Extension? BSD?

#Comment by Sergey Chernyshev (talk | contribs)   16:25, 9 September 2009

Actually, it's already licensed as LGPL on Google Code so it's LGPL then, I'll update the page and code.

#Comment by Platonides (talk | contribs)   15:17, 5 December 2010

PHP Strict Standards: Static function POMParser::Parse() should not be abstract in extensions/PageObjectModel/POM/Parser.php on line 13

#Comment by Sergey Chernyshev (talk | contribs)   06:45, 18 December 2010

So, how should abstract class define static methods that should be implemented in subclasses?

I don't have a particularly good plan for class structure here and not maintaining this extension actively, but just curious what is the guideline here.

#Comment by Nikerabbit (talk | contribs)   10:43, 18 December 2010

It doesn't. You must use an interface. It's still dubious whether it makes any sense to have static functions in an interface, since they are awkward to use with class inheritance. See http://php.net/manual/en/language.oop5.late-static-bindings.php, which is only PHP 5.3 stuff.

Status & tagging log