Index: trunk/extensions/WikiObjectModel/includes/parsers/WOMTemplateParser.php |
— | — | @@ -15,7 +15,7 @@ |
16 | 16 | |
17 | 17 | public function parseNext( $text, WikiObjectModelCollection $parentObj, $offset = 0 ) { |
18 | 18 | $text = substr( $text, $offset ); |
19 | | - $r = preg_match( '/^(\{\{([^|}]+))([|}])/', $text, $m ); |
| 19 | + $r = preg_match( '/^(\{\{([^{|}]+))([|}])/', $text, $m ); |
20 | 20 | |
21 | 21 | if ( $r ) { |
22 | 22 | if ( !preg_match( '/[^' . Title::legalChars() . ']/', trim( $m[2] ) ) ) |
Index: trunk/extensions/WikiObjectModel/includes/parsers/WOMParamValueParser.php |
— | — | @@ -14,7 +14,8 @@ |
15 | 15 | } |
16 | 16 | |
17 | 17 | public function parseNext( $text, WikiObjectModelCollection $parentObj, $offset = 0 ) { |
18 | | - if ( !( $parentObj instanceof WOMParameterModel ) ) |
| 18 | + if ( !( ( $parentObj instanceof WOMParameterModel ) |
| 19 | + || ( $parentObj instanceof WOMTemplateFieldHolderModel ) ) ) |
19 | 20 | return null; |
20 | 21 | |
21 | 22 | return array( 'len' => 0, 'obj' => new WOMParamValueModel() ); |
Index: trunk/extensions/WikiObjectModel/includes/parsers/WOMTemplateFieldHolderParser.php |
— | — | @@ -0,0 +1,44 @@ |
| 2 | +<?php
|
| 3 | +/**
|
| 4 | + * @author Ning
|
| 5 | + *
|
| 6 | + * @file
|
| 7 | + * @ingroup WikiObjectModels
|
| 8 | + */
|
| 9 | +
|
| 10 | +class WOMTemplateFieldHolderParser extends WikiObjectModelParser {
|
| 11 | +
|
| 12 | + public function __construct() {
|
| 13 | + parent::__construct();
|
| 14 | + $this->m_parserId = WOM_PARSER_ID_TEMPLATE_FIELD_HOLDER;
|
| 15 | + }
|
| 16 | +
|
| 17 | + public function parseNext( $text, WikiObjectModelCollection $parentObj, $offset = 0 ) {
|
| 18 | + $text = substr( $text, $offset );
|
| 19 | + $r = preg_match( '/^(\{\{\{([^{|}]+))([|}])/', $text, $m );
|
| 20 | +
|
| 21 | + if ( $r ) {
|
| 22 | + if ( !preg_match( '/[^' . Title::legalChars() . ']/', trim( $m[2] ) ) )
|
| 23 | +// if(!preg_match(Title::getTitleInvalidRegex(), trim($m[2])))
|
| 24 | + return array( 'len' => ( $m[3] == '|' ) ? strlen( $m[0] ) : strlen( $m[1] ), 'obj' => new WOMTemplateFieldHolderModel( trim( $m[2] ) ) );
|
| 25 | + }
|
| 26 | + return null;
|
| 27 | + }
|
| 28 | +
|
| 29 | + public function getSubParserID() {
|
| 30 | + return WOM_PARSER_ID_PARAM_VALUE;
|
| 31 | + }
|
| 32 | +
|
| 33 | + public function isObjectClosed( $obj, $text, $offset ) {
|
| 34 | + if ( !$obj instanceof WOMTemplateFieldHolderModel ) return false;
|
| 35 | +
|
| 36 | + if ( ( strlen( $text ) >= $offset + 3 )
|
| 37 | + && $text { $offset } == '}'
|
| 38 | + && $text { $offset + 1 } == '}'
|
| 39 | + && $text { $offset + 2 } == '}' ) {
|
| 40 | + return 3;
|
| 41 | + }
|
| 42 | +
|
| 43 | + return false;
|
| 44 | + }
|
| 45 | +}
|
Index: trunk/extensions/WikiObjectModel/includes/parsers/WOMPropertyParser.php |
— | — | @@ -24,7 +24,9 @@ |
25 | 25 | // copied from SemanticMediaWiki, includes/SMW_ParserExtensions.php |
26 | 26 | // not deal with <nowiki>, could be bug here. SMW has the same bug |
27 | 27 | // E.g., [[text::this <nowiki> is ]] </nowiki> not good]] |
28 | | - $semanticLinkPattern = '/^\[\[ # Beginning of the link |
| 28 | +// global $smwgLinksInValues; |
| 29 | +// if ( $smwgLinksInValues ) { // More complex regexp -- lib PCRE may cause segfaults if text is long :-( |
| 30 | + $semanticLinkPattern = '/^\[\[ # Beginning of the link |
29 | 31 | (?:([^:][^]]*):[=:])+ # Property name (or a list of those) |
30 | 32 | ( # After that: |
31 | 33 | (?:[^|\[\]] # either normal text (without |, [ or ]) |
— | — | @@ -34,7 +36,13 @@ |
35 | 37 | (?:\|([^]]*))? # Display text (like "text" in [[link|text]]), optional |
36 | 38 | \]\] # End of link |
37 | 39 | /xu'; |
38 | | - |
| 40 | +// } else { // Simpler regexps -- no segfaults found for those, but no links in values. |
| 41 | +// $semanticLinkPattern = '/\[\[ # Beginning of the link |
| 42 | +// (?:([^:][^]]*):[=:])+ # Property name (or a list of those) |
| 43 | +// ([^\[\]]*) # content: anything but [, |, ] |
| 44 | +// \]\] # End of link |
| 45 | +// /xu'; |
| 46 | +// } |
39 | 47 | $r = preg_match( $semanticLinkPattern, $text, $m ); |
40 | 48 | if ( $r ) { |
41 | 49 | return array( 'len' => strlen( $m[0] ), 'obj' => new WOMPropertyModel( $m[1], $m[2], isset( $m[3] ) ? $m[3] : '' ) ); |
Index: trunk/extensions/WikiObjectModel/includes/models/WOM_OM_Category.php |
— | — | @@ -38,6 +38,6 @@ |
39 | 39 | } |
40 | 40 | |
41 | 41 | protected function getXMLContent() { |
42 | | - return $this->m_name; |
| 42 | + return self::xml_entities( $this->m_name ); |
43 | 43 | } |
44 | 44 | } |
Index: trunk/extensions/WikiObjectModel/includes/models/WOM_OM_TmplFieldHolder.php |
— | — | @@ -0,0 +1,44 @@ |
| 2 | +<?php
|
| 3 | +/**
|
| 4 | + * This model implements Template Field Holder models.
|
| 5 | + *
|
| 6 | + * @author Ning
|
| 7 | + * @file
|
| 8 | + * @ingroup WikiObjectModels
|
| 9 | + *
|
| 10 | + */
|
| 11 | +
|
| 12 | +class WOMTemplateFieldHolderModel extends WikiObjectModelCollection {
|
| 13 | + protected $m_key;
|
| 14 | +
|
| 15 | + public function __construct( $key ) {
|
| 16 | + parent::__construct( WOM_TYPE_TMPL_FIELD_HOLDER );
|
| 17 | + $this->m_key = $key;
|
| 18 | + }
|
| 19 | +
|
| 20 | + public function getKey() {
|
| 21 | + return $this->m_key;
|
| 22 | + }
|
| 23 | +
|
| 24 | + public function getWikiText() {
|
| 25 | + return "{{{{$this->m_key}|{$this->getValueText()}}}}";
|
| 26 | + }
|
| 27 | +
|
| 28 | + public function getValueText() {
|
| 29 | + return parent::getWikiText();
|
| 30 | + }
|
| 31 | +
|
| 32 | + public function setXMLAttribute( $key, $value ) {
|
| 33 | + if ( $value == '' ) throw new MWException( __METHOD__ . ": value cannot be empty" );
|
| 34 | +
|
| 35 | + if ( $key == 'name' ) {
|
| 36 | + $this->m_key = $value;
|
| 37 | + } else {
|
| 38 | + throw new MWException( __METHOD__ . ": invalid key/value pair: name|value_if_blank" );
|
| 39 | + }
|
| 40 | + }
|
| 41 | +
|
| 42 | + protected function getXMLAttributes() {
|
| 43 | + return 'name="' . self::xml_entities( $this->m_key ) . '"';
|
| 44 | + }
|
| 45 | +}
|
Index: trunk/extensions/WikiObjectModel/includes/models/WOM_OM_Parameter.php |
— | — | @@ -41,6 +41,6 @@ |
42 | 42 | } |
43 | 43 | |
44 | 44 | protected function getXMLAttributes() { |
45 | | - return "key=\"{$this->m_key}\""; |
| 45 | + return 'key="' . self::xml_entities( $this->m_key ) . '"'; |
46 | 46 | } |
47 | 47 | } |
Index: trunk/extensions/WikiObjectModel/includes/models/WOM_OM_TblCell.php |
— | — | @@ -33,7 +33,7 @@ |
34 | 34 | public function setXMLAttribute( $key, $value ) { |
35 | 35 | if ( $value == '' ) throw new MWException( __METHOD__ . ": value cannot be empty" ); |
36 | 36 | |
37 | | - $value = str_replace( '\n', "\n", $value ); |
| 37 | +// $value = str_replace( '\n', "\n", $value ); |
38 | 38 | if ( $key == 'prefix' ) { |
39 | 39 | $this->m_prefix = $value; |
40 | 40 | return; |
— | — | @@ -42,8 +42,8 @@ |
43 | 43 | } |
44 | 44 | |
45 | 45 | protected function getXMLAttributes() { |
46 | | - $prefix = str_replace( "\n", '\n', $this->m_prefix ); |
| 46 | +// $prefix = str_replace( "\n", '\n', $this->m_prefix ); |
47 | 47 | $prefix = str_replace( '"', "'", $prefix ); |
48 | | - return "prefix=\"{$prefix}\""; |
| 48 | + return 'prefix="' . self::xml_entities( $prefix ) . '"'; |
49 | 49 | } |
50 | 50 | } |
Index: trunk/extensions/WikiObjectModel/includes/models/WOM_OM_Property.php |
— | — | @@ -11,6 +11,8 @@ |
12 | 12 | class WOMPropertyModel extends WikiObjectModel { |
13 | 13 | protected $m_property; // name |
14 | 14 | protected $m_smwdatavalue; // value, caption, type |
| 15 | + protected $m_value; |
| 16 | + protected $m_caption; |
15 | 17 | protected $m_visible; |
16 | 18 | |
17 | 19 | public function __construct( $property, $value, $caption = '' ) { |
— | — | @@ -22,10 +24,20 @@ |
23 | 25 | } |
24 | 26 | |
25 | 27 | $property = SMWPropertyValue::makeUserProperty( $property ); |
26 | | - $smwdatavalue = SMWDataValueFactory::newPropertyObjectValue( $property, $value, $caption ); |
| 28 | + $smwdatavalue = null; |
| 29 | + // FIXME: property should be collection object according to templates |
| 30 | + // if template/field used |
| 31 | + if ( preg_match( '/\{\{.+\}\}/s', $value . $caption ) ) { |
| 32 | + $value = "{$value}|{$caption}"; |
| 33 | + $caption = ''; |
| 34 | + } else { |
| 35 | + $smwdatavalue = SMWDataValueFactory::newPropertyObjectValue( $property, $value, $caption ); |
| 36 | + } |
27 | 37 | |
28 | 38 | $this->m_property = $property; |
29 | 39 | $this->m_smwdatavalue = $smwdatavalue; |
| 40 | + $this->m_value = $value; |
| 41 | + $this->m_caption = $caption; |
30 | 42 | $this->m_visible = !preg_match( '/\s+/', $caption ); |
31 | 43 | } |
32 | 44 | |
— | — | @@ -63,11 +75,11 @@ |
64 | 76 | } |
65 | 77 | |
66 | 78 | public function getPropertyValue() { |
67 | | - return $this->m_smwdatavalue->getWikiValue(); |
| 79 | + return $this->m_smwdatavalue == null ? $this->m_value : $this->m_smwdatavalue->getWikiValue(); |
68 | 80 | } |
69 | 81 | |
70 | 82 | public function getCaption() { |
71 | | - $caption = $this->m_smwdatavalue->getShortWikiText(); |
| 83 | + $caption = $this->m_smwdatavalue == null ? $this->m_caption : $this->m_smwdatavalue->getShortWikiText(); |
72 | 84 | return ( $caption == $this->getPropertyValue() ) ? '' : $caption; |
73 | 85 | } |
74 | 86 | |
— | — | @@ -81,12 +93,12 @@ |
82 | 94 | } |
83 | 95 | } |
84 | 96 | protected function getXMLAttributes() { |
85 | | - return "name=\"{$this->getPropertyName()}\""; |
| 97 | + return 'name="' . self::xml_entities( $this->getPropertyName() ) . '"'; |
86 | 98 | } |
87 | 99 | protected function getXMLContent() { |
88 | 100 | return " |
89 | | -<value>{$this->getPropertyValue()}</value> |
90 | | -<caption>{$this->getCaption()}</caption> |
| 101 | +<value><![CDATA[{$this->getPropertyValue()}]]></value> |
| 102 | +<caption><![CDATA[{$this->getCaption()}]]></caption> |
91 | 103 | "; |
92 | 104 | } |
93 | 105 | } |
Index: trunk/extensions/WikiObjectModel/includes/models/WOM_OM_Table.php |
— | — | @@ -26,7 +26,8 @@ |
27 | 27 | } |
28 | 28 | |
29 | 29 | public function getWikiText() { |
30 | | - return "{| {$this->m_style}" . parent::getWikiText() . "\n|}"; |
| 30 | + return ( $this->isLastLF() ? '' : "\n" ) . |
| 31 | + "{| {$this->m_style}" . parent::getWikiText() . "\n|}"; |
31 | 32 | } |
32 | 33 | |
33 | 34 | public function setXMLAttribute( $key, $value ) { |
— | — | @@ -38,7 +39,6 @@ |
39 | 40 | } |
40 | 41 | |
41 | 42 | protected function getXMLAttributes() { |
42 | | - $style = str_replace( '"', "'", $this->m_style ); |
43 | | - return "style=\"{$style}\""; |
| 43 | + return 'style="' . self::xml_entities( str_replace( '"', "'", $this->m_style ) ) . '"'; |
44 | 44 | } |
45 | 45 | } |
Index: trunk/extensions/WikiObjectModel/includes/models/WOM_OM_ListItem.php |
— | — | @@ -22,7 +22,8 @@ |
23 | 23 | } |
24 | 24 | |
25 | 25 | public function getWikiText() { |
26 | | - return $this->m_header . parent::getWikiText(); |
| 26 | + return ( $this->isLastLF() ? '' : "\n" ) . |
| 27 | + $this->m_header . parent::getWikiText(); |
27 | 28 | } |
28 | 29 | |
29 | 30 | public function setXMLAttribute( $key, $value ) { |
Index: trunk/extensions/WikiObjectModel/includes/models/WOM_OM_ParamValue.php |
— | — | @@ -17,8 +17,4 @@ |
18 | 18 | public function setXMLAttribute( $key, $value ) { |
19 | 19 | throw new MWException( __METHOD__ . ": no key/value pair required" ); |
20 | 20 | } |
21 | | - |
22 | | - protected function getXMLAttributes() { |
23 | | - return ''; |
24 | | - } |
25 | 21 | } |
Index: trunk/extensions/WikiObjectModel/includes/models/WikiObjectModel.php |
— | — | @@ -66,6 +66,30 @@ |
67 | 67 | return $this->m_typeid; |
68 | 68 | } |
69 | 69 | |
| 70 | + public function getPreviousObject() { |
| 71 | + $p = $this->getParent(); |
| 72 | + if ( $p == null ) return $p; |
| 73 | + |
| 74 | + $previous = null; |
| 75 | + foreach ( $p->getObjects() as $v ) { |
| 76 | + if ( $this->getObjectID() == $v->getObjectID() ) { |
| 77 | + return $previous; |
| 78 | + } |
| 79 | + $previous = $v; |
| 80 | + } |
| 81 | + return null; |
| 82 | + } |
| 83 | + |
| 84 | + protected function isLastLF() { |
| 85 | + $pre = $this->getPreviousObject(); |
| 86 | + if ( $pre != null ) { |
| 87 | + $wiki = $pre->getWikiText(); |
| 88 | + $len = strlen( $wiki ); |
| 89 | + return ( $len == 0 || $wiki { $len - 1 } == "\n" ); |
| 90 | + } |
| 91 | + return true; |
| 92 | + } |
| 93 | + |
70 | 94 | /** |
71 | 95 | * Return TRUE if a value was defined and understood by the given type, |
72 | 96 | * and false if parsing errors occured or no value was given. |
— | — | @@ -107,4 +131,39 @@ |
108 | 132 | } |
109 | 133 | |
110 | 134 | public function objectUpdate( WikiObjectModel $obj ) { } |
| 135 | + |
| 136 | + static function xml_entity_decode( $text, $charset = 'Windows-1252' ) { |
| 137 | + // Double decode, so if the value was &trade; it will become Trademark |
| 138 | + $text = html_entity_decode( $text, ENT_COMPAT, $charset ); |
| 139 | + $text = html_entity_decode( $text, ENT_COMPAT, $charset ); |
| 140 | + |
| 141 | + return $text; |
| 142 | + } |
| 143 | + |
| 144 | + static function xml_entities( $text, $charset = 'Windows-1252' ) { |
| 145 | + // First we encode html characters that are also invalid in xml |
| 146 | + $text = htmlentities( $text, ENT_COMPAT, $charset, false ); |
| 147 | + // XML character entity array from Wiki |
| 148 | + // Note: ' is useless in UTF-8 or in UTF-16 |
| 149 | + $arr_xml_special_char = array( """, "&", "'", "<", ">" ); |
| 150 | + // Building the regex string to exclude all strings with xml special char |
| 151 | + $arr_xml_special_char_regex = "(?"; |
| 152 | + |
| 153 | + foreach ( $arr_xml_special_char as $key => $value ) { |
| 154 | + $arr_xml_special_char_regex .= "(?!$value)"; |
| 155 | + } |
| 156 | + $arr_xml_special_char_regex .= ")"; |
| 157 | + |
| 158 | + // Scan the array for &something_not_xml; syntax |
| 159 | + $pattern = "/$arr_xml_special_char_regex&([a-zA-Z0-9]+;)/"; |
| 160 | + |
| 161 | + // Replace the &something_not_xml; with &something_not_xml; |
| 162 | + $replacement = '&${1}'; |
| 163 | + |
| 164 | + return preg_replace( $pattern, $replacement, $text ); |
| 165 | + } |
| 166 | + static function xml_attribute_entities( $text, $charset = 'Windows-1252' ) { |
| 167 | + $ret = self::xml_entities( $text, $charset ); |
| 168 | + return str_replace( "\n", ' ', $ret ); |
| 169 | + } |
111 | 170 | } |
Index: trunk/extensions/WikiObjectModel/includes/models/WOM_OM_HTMLTag.php |
— | — | @@ -27,17 +27,34 @@ |
28 | 28 | } |
29 | 29 | |
30 | 30 | public function getAttributes() { |
31 | | - return $this->m_attributes; |
| 31 | + return $this->m_attrs; |
32 | 32 | } |
33 | 33 | |
| 34 | + public function getAttribute( $attr ) { |
| 35 | + $attr = strtolower( $attr ); |
| 36 | + foreach ( $this->m_attrs as $a => $v ) { |
| 37 | + $a = strtolower( $a ); |
| 38 | + $v = preg_replace( '/^[\'"](.*)[\'"]$/', '$1', $v ); |
| 39 | + if ( $attr == $a ) return $v; |
| 40 | + } |
| 41 | + } |
| 42 | + |
34 | 43 | public function setAttributes( $attrs ) { |
35 | | - $this->m_attributes = $attrs; |
| 44 | + $this->m_attrs = $attrs; |
36 | 45 | } |
37 | 46 | |
38 | 47 | public function getWikiText() { |
39 | | - return "<{$this->m_name}>" . parent::getWikiText() . "</{$this->m_name}>"; |
| 48 | + $attr = ''; |
| 49 | + foreach ( $this->m_attrs as $a => $v ) { |
| 50 | + $attr .= " {$a}={$v}"; |
| 51 | + } |
| 52 | + return "<{$this->m_name}{$attr}>" . parent::getWikiText() . "</{$this->m_name}>"; |
40 | 53 | } |
41 | 54 | |
| 55 | + public function getInnerWikiText() { |
| 56 | + return parent::getWikiText(); |
| 57 | + } |
| 58 | + |
42 | 59 | public function updateOnNodeClosed() { |
43 | 60 | // use SemanticForms to bind properties to fields |
44 | 61 | } |
— | — | @@ -52,6 +69,13 @@ |
53 | 70 | } |
54 | 71 | } |
55 | 72 | protected function getXMLAttributes() { |
56 | | - return "name=\"{$this->m_name}\""; |
| 73 | + $ret = 'name="' . self::xml_entities( $this->m_name ) . '"'; |
| 74 | + foreach ( $this->m_attrs as $a => $v ) { |
| 75 | + $v = preg_replace( '/^"(.*)"$/', '$1', $v ); |
| 76 | + if ( $a == 'id' ) $a = 'tag_id'; |
| 77 | + $v = self::xml_entities( $v ); |
| 78 | + $ret .= " {$a}=\"{$v}\""; |
| 79 | + } |
| 80 | + return $ret; |
57 | 81 | } |
58 | 82 | } |
Index: trunk/extensions/WikiObjectModel/includes/models/WOM_OM_ParserFunction.php |
— | — | @@ -36,6 +36,6 @@ |
37 | 37 | } |
38 | 38 | |
39 | 39 | protected function getXMLAttributes() { |
40 | | - return "key=\"{$this->m_function_key}\""; |
| 40 | + return 'key="' . self::xml_entities( $this->m_function_key ) . '"'; |
41 | 41 | } |
42 | 42 | } |
Index: trunk/extensions/WikiObjectModel/includes/models/WOM_OM_Section.php |
— | — | @@ -37,8 +37,8 @@ |
38 | 38 | } |
39 | 39 | |
40 | 40 | public function getHeaderText() { |
41 | | -// return "\n" . |
42 | | - return substr( WOMSectionModel::$heading, 0, $this->m_level ) . |
| 41 | + return ( $this->isLastLF() ? '' : "\n" ) . |
| 42 | + substr( WOMSectionModel::$heading, 0, $this->m_level ) . |
43 | 43 | $this->m_name . |
44 | 44 | substr( WOMSectionModel::$heading, 0, $this->m_level ) . |
45 | 45 | "\n"; |
— | — | @@ -69,6 +69,6 @@ |
70 | 70 | } |
71 | 71 | |
72 | 72 | protected function getXMLAttributes() { |
73 | | - return "name=\"{$this->m_name}\" level=\"{$this->m_level}\""; |
| 73 | + return 'name="' . self::xml_entities( $this->m_name ) . '" level="' . $this->m_level . '"'; |
74 | 74 | } |
75 | 75 | } |
Index: trunk/extensions/WikiObjectModel/includes/models/WOM_OM_Paragraph.php |
— | — | @@ -0,0 +1,25 @@ |
| 2 | +<?php
|
| 3 | +/**
|
| 4 | + * This model implements Paragraph models.
|
| 5 | + *
|
| 6 | + * @author Ning
|
| 7 | + * @file
|
| 8 | + * @ingroup WikiObjectModels
|
| 9 | + *
|
| 10 | + */
|
| 11 | +
|
| 12 | +class WOMParagraphModel extends WikiObjectModelCollection {
|
| 13 | +
|
| 14 | + public function __construct() {
|
| 15 | + parent::__construct( WOM_TYPE_PARAGRAPH );
|
| 16 | + }
|
| 17 | +
|
| 18 | + public function getWikiText() {
|
| 19 | + $pre = $this->getPreviousObject();
|
| 20 | + return ( ( $pre != null && ( $pre->getTypeID() == WOM_TYPE_PARAGRAPH ) ) ? "\n\n" : '' ) . $this->getValueText();
|
| 21 | + }
|
| 22 | +
|
| 23 | + public function getValueText() {
|
| 24 | + return parent::getWikiText();
|
| 25 | + }
|
| 26 | +}
|
Index: trunk/extensions/WikiObjectModel/includes/models/WOM_OM_Template.php |
— | — | @@ -57,6 +57,6 @@ |
58 | 58 | } |
59 | 59 | } |
60 | 60 | protected function getXMLAttributes() { |
61 | | - return "name=\"{$this->m_name}\""; |
| 61 | + return 'name="' . self::xml_entities( $this->m_name ) . '"'; |
62 | 62 | } |
63 | 63 | } |
Index: trunk/extensions/WikiObjectModel/includes/WOM_Processor.php |
— | — | @@ -16,36 +16,36 @@ |
17 | 17 | private static $base_parser; |
18 | 18 | |
19 | 19 | private static function setupParsers() { |
20 | | - if ( WOMProcessor::$isParsersRegistered ) return; |
| 20 | + if ( self::$isParsersRegistered ) return; |
21 | 21 | |
22 | 22 | global $wgOMParsers; |
23 | 23 | foreach ( $wgOMParsers as $p ) { |
24 | 24 | $parser = new $p(); |
25 | | - WOMProcessor::$parsers[$parser->getParserID()] = $parser; |
| 25 | + self::$parsers[$parser->getParserID()] = $parser; |
26 | 26 | } |
27 | | - WOMProcessor::$base_parser = WOMProcessor::$parsers[WOM_PARSER_ID_TEXT]; |
| 27 | + self::$base_parser = self::$parsers[WOM_PARSER_ID_TEXT]; |
28 | 28 | |
29 | | - WOMProcessor::$isParsersRegistered = true; |
| 29 | + self::$isParsersRegistered = true; |
30 | 30 | } |
31 | 31 | |
32 | 32 | public static function getObjectParser( WikiObjectModel $obj ) { |
33 | 33 | $fname = 'WikiObjectModel::getObjectParser (WOM)'; |
34 | 34 | wfProfileIn( $fname ); |
35 | 35 | |
36 | | - if ( !WOMProcessor::$isParsersRegistered ) { |
37 | | - WOMProcessor::setupParsers(); |
| 36 | + if ( !self::$isParsersRegistered ) { |
| 37 | + self::setupParsers(); |
38 | 38 | } |
39 | 39 | global $wgOMModelParserMapping; |
40 | 40 | if ( isset( $wgOMModelParserMapping[$obj->getTypeID()] ) ) { |
41 | 41 | $id = $wgOMModelParserMapping[$obj->getTypeID()]; |
42 | | - if ( isset( WOMProcessor::$parsers[$id] ) ) { |
| 42 | + if ( isset( self::$parsers[$id] ) ) { |
43 | 43 | wfProfileOut( $fname ); |
44 | | - return WOMProcessor::$parsers[$id]; |
| 44 | + return self::$parsers[$id]; |
45 | 45 | } |
46 | 46 | } |
47 | 47 | wfProfileOut( $fname ); |
48 | 48 | |
49 | | - return WOMProcessor::$base_parser; |
| 49 | + return self::$base_parser; |
50 | 50 | } |
51 | 51 | |
52 | 52 | private static function applyObjID( WikiObjectModel $wom, WOMPageModel $root ) { |
— | — | @@ -53,7 +53,7 @@ |
54 | 54 | $root->addToPageObjectSet( $wom ); |
55 | 55 | if ( $wom instanceof WikiObjectModelCollection ) { |
56 | 56 | foreach ( $wom->getObjects() as $obj ) { |
57 | | - WOMProcessor::applyObjID( $obj, $root ); |
| 57 | + self::applyObjID( $obj, $root ); |
58 | 58 | } |
59 | 59 | } |
60 | 60 | } |
— | — | @@ -62,23 +62,76 @@ |
63 | 63 | $fname = 'WikiObjectModel::parseToWOM (WOM)'; |
64 | 64 | wfProfileIn( $fname ); |
65 | 65 | |
66 | | - if ( !WOMProcessor::$isParsersRegistered ) { |
67 | | - WOMProcessor::setupParsers(); |
| 66 | + if ( !self::$isParsersRegistered ) { |
| 67 | + self::setupParsers(); |
68 | 68 | } |
69 | 69 | |
70 | 70 | $root = new WOMPageModel(); |
71 | | - WOMProcessor::parseNext( $text, $root, $root ); |
72 | | - WOMProcessor::parseSentences( $root ); |
73 | | - WOMProcessor::applyObjID( $root, $root ); |
| 71 | + self::parseNext( $text, $root, $root ); |
| 72 | + self::parseParagraphs( $root ); |
| 73 | + self::parseSentences( $root ); |
| 74 | + self::applyObjID( $root, $root ); |
74 | 75 | wfProfileOut( $fname ); |
75 | 76 | return $root; |
76 | 77 | } |
77 | 78 | |
78 | 79 | /** |
79 | | - * Special case, sentence is not standard wiki object |
| 80 | + * Special case, paragraphs and sentences are not standard wiki object |
80 | 81 | * |
81 | 82 | * @param WOMPageModel $rootObj |
82 | 83 | */ |
| 84 | + private static function parseParagraphs( WikiObjectModelCollection $wom ) { |
| 85 | + global $wgOMParagraphObjectTypes; |
| 86 | + $in_paragraph = false; |
| 87 | + $new_objs = array(); |
| 88 | + $paragraphObj = null; |
| 89 | + foreach ( $wom->getObjects() as $id => $obj ) { |
| 90 | + if ( in_array( $obj->getTypeID(), $wgOMParagraphObjectTypes ) ) { |
| 91 | + if ( !$in_paragraph ) { |
| 92 | + $paragraphObj = new WOMParagraphModel(); |
| 93 | + $new_objs[] = $paragraphObj; |
| 94 | + $in_paragraph = true; |
| 95 | + } |
| 96 | + $paragraphObj->insertObject( $obj ); |
| 97 | + // parse paragraph break |
| 98 | + if ( $obj->getTypeID() == WOM_TYPE_TEXT ) { |
| 99 | + $text = $obj->getWikiText(); |
| 100 | + $offset = 0; |
| 101 | + $len = strlen( $text ); |
| 102 | + // HTML tag <p> is not valid 'paragraph' syntax in WOM |
| 103 | + $r = preg_match_all( '/\n[ \t]*\n/', $text, $ms, PREG_SET_ORDER | PREG_OFFSET_CAPTURE ); |
| 104 | + if ( $r ) { |
| 105 | + foreach ( $ms as $m ) { |
| 106 | + $end = $m[0][1] + strlen( $m[0][0] ); |
| 107 | + $obj->setText( substr( $text, $offset, $m[0][1] - $offset ) ); |
| 108 | + $offset = $end; |
| 109 | + $paragraphObj = new WOMParagraphModel(); |
| 110 | + $new_objs[] = $paragraphObj; |
| 111 | + $obj = new WOMTextModel( substr( $text, $end ) ); |
| 112 | + $paragraphObj->insertObject( $obj ); |
| 113 | + } |
| 114 | + } |
| 115 | + } |
| 116 | + } else { |
| 117 | + $in_paragraph = false; |
| 118 | + $paragraphObj = null; |
| 119 | + |
| 120 | + if ( $obj->getTypeID() == WOM_TYPE_HTMLTAG ) { |
| 121 | + // special case, html tag |
| 122 | + } else if ( $obj instanceof WikiObjectModelCollection ) { |
| 123 | + self::parseParagraphs( $obj ); |
| 124 | + } |
| 125 | + $new_objs[] = $obj; |
| 126 | + } |
| 127 | + } |
| 128 | + |
| 129 | + $wom->reset(); |
| 130 | + |
| 131 | + foreach ( $new_objs as $obj ) { |
| 132 | + $wom->insertObject( $obj ); |
| 133 | + } |
| 134 | + } |
| 135 | + |
83 | 136 | private static function parseSentences( WikiObjectModelCollection $wom ) { |
84 | 137 | global $wgOMSentenceObjectTypes; |
85 | 138 | $in_sentence = false; |
— | — | @@ -127,7 +180,7 @@ |
128 | 181 | if ( $obj->getTypeID() == WOM_TYPE_HTMLTAG ) { |
129 | 182 | // special case, html tag |
130 | 183 | } elseif ( $obj instanceof WikiObjectModelCollection ) { |
131 | | - WOMProcessor::parseSentences( $obj ); |
| 184 | + self::parseSentences( $obj ); |
132 | 185 | } |
133 | 186 | $new_objs[] = $obj; |
134 | 187 | } |
— | — | @@ -160,8 +213,8 @@ |
161 | 214 | $len = strlen( $text ); |
162 | 215 | |
163 | 216 | while ( $offset < $len ) { |
164 | | - if ( WOMProcessor::getObjectParser( $parentObj ) != null ) { |
165 | | - $objectClosed = WOMProcessor::getObjectParser( $parentObj ) |
| 217 | + if ( self::getObjectParser( $parentObj ) != null ) { |
| 218 | + $objectClosed = self::getObjectParser( $parentObj ) |
166 | 219 | ->isObjectClosed( $parentObj, $text, $offset ); |
167 | 220 | if ( $objectClosed !== false ) { |
168 | 221 | $offset += $objectClosed; |
— | — | @@ -173,7 +226,7 @@ |
174 | 227 | $result = null; |
175 | 228 | if ( $parserInstance == null ) { |
176 | 229 | $parserInstance2 = null; |
177 | | - foreach ( WOMProcessor::$parsers as $parser ) { |
| 230 | + foreach ( self::$parsers as $parser ) { |
178 | 231 | $parser_res = $parser->parseNext( $text, $parentObj, $offset ); |
179 | 232 | if ( $parser_res == null ) continue; |
180 | 233 | if ( $parserInstance2 == null || $parser->subclassOf( $parserInstance2 ) ) { |
— | — | @@ -182,7 +235,7 @@ |
183 | 236 | } |
184 | 237 | } |
185 | 238 | if ( $parserInstance2 == null ) { |
186 | | - $parserInstance2 = WOMProcessor::$base_parser; |
| 239 | + $parserInstance2 = self::$base_parser; |
187 | 240 | $result = $parserInstance2->parseNext( $text, $parentObj, $offset ); |
188 | 241 | } |
189 | 242 | } else { |
— | — | @@ -208,27 +261,27 @@ |
209 | 262 | $next_obj->setParent( $parentObj ); |
210 | 263 | } |
211 | 264 | |
212 | | - WOMProcessor::assemble( $next_obj ); |
| 265 | + self::assemble( $next_obj ); |
213 | 266 | |
214 | 267 | if ( $next_obj->isCollection() && !( isset( $result['closed'] ) && $result['closed'] ) ) { |
215 | 268 | $collection_start = $offset; |
216 | | - $d = WOMProcessor::parseNext( $text, $next_obj, $rootObj, $offset, |
217 | | - ( ( $parserInstance2 != null && isset( WOMProcessor::$parsers[$parserInstance2->getSubParserID()] ) ) ? |
218 | | - WOMProcessor::$parsers[$parserInstance2->getSubParserID()] : |
| 269 | + $d = self::parseNext( $text, $next_obj, $rootObj, $offset, |
| 270 | + ( ( $parserInstance2 != null && isset( self::$parsers[$parserInstance2->getSubParserID()] ) ) ? |
| 271 | + self::$parsers[$parserInstance2->getSubParserID()] : |
219 | 272 | null ) ); |
220 | 273 | if ( $d == 100 && $parserInstance2->isObjectClosed( $next_obj, $text, $offset ) === false ) { |
221 | 274 | // rollback |
222 | | - $p = WOMProcessor::getObjectParser( $parentObj ); |
| 275 | + $p = self::getObjectParser( $parentObj ); |
223 | 276 | if ( $p != null && $p->isObjectClosed( $parentObj, $text, $offset ) === false ) { |
224 | 277 | return $d; |
225 | 278 | } |
226 | 279 | $parentObj->rollback(); |
227 | 280 | $offset = $collection_start - $result['len']; |
228 | | - $result = WOMProcessor::$base_parser->parseNext( $text, $parentObj, $offset ); |
| 281 | + $result = self::$base_parser->parseNext( $text, $parentObj, $offset ); |
229 | 282 | $offset += $result['len']; |
230 | 283 | $next_obj = $result['obj']; |
231 | 284 | $next_obj->setParent( $parentObj ); |
232 | | - WOMProcessor::assemble( $next_obj ); |
| 285 | + self::assemble( $next_obj ); |
233 | 286 | } else { |
234 | 287 | $next_obj->updateOnNodeClosed(); |
235 | 288 | } |
— | — | @@ -281,9 +334,9 @@ |
282 | 335 | $possible_values[] = html_entity_decode( $value->getWikiValue() ); |
283 | 336 | } |
284 | 337 | if ( count( $possible_values ) > 0 ) { |
285 | | - $result = WOMProcessor::getSemanticEditor( 'enumeration' ); |
| 338 | + $result = self::getSemanticEditor( 'enumeration' ); |
286 | 339 | } else { |
287 | | - $result = WOMProcessor::getSemanticEditor( $property->getPropertyTypeID() ); |
| 340 | + $result = self::getSemanticEditor( $property->getPropertyTypeID() ); |
288 | 341 | } |
289 | 342 | |
290 | 343 | wfProfileOut( $fname ); |
— | — | @@ -332,7 +385,7 @@ |
333 | 386 | } |
334 | 387 | $content = $revision->getText(); |
335 | 388 | |
336 | | - $wom = WOMProcessor::parseToWOM( $content ); |
| 389 | + $wom = self::parseToWOM( $content ); |
337 | 390 | $wom->setTitle( $title ); |
338 | 391 | $wom->setRevisionID( $revision->getId() ); |
339 | 392 | |
— | — | @@ -341,12 +394,22 @@ |
342 | 395 | return $wom; |
343 | 396 | } |
344 | 397 | |
345 | | - public static function getObjIdByXPath( $title, $xpath, $rid = 0 ) { |
| 398 | + public static function getPageDom( $title, $rid = 0 ) { |
346 | 399 | $fname = 'WikiObjectModel::getObjIdByXPath (WOM)'; |
347 | 400 | wfProfileIn( $fname ); |
348 | 401 | |
349 | | - $xml = WOMProcessor::getPageObject( $title, $rid )->toXML(); |
| 402 | + $xml = self::getPageObject( $title, $rid )->toXML(); |
350 | 403 | $xObj = simplexml_load_string( $xml ); |
| 404 | + |
| 405 | + wfProfileOut( $fname ); |
| 406 | + return $xObj; |
| 407 | + } |
| 408 | + public static function getObjIdByXPath2( WOMPageModel $wom_obj, $xpath ) { |
| 409 | + $fname = 'WikiObjectModel::getObjIdByXPath2 (WOM)'; |
| 410 | + wfProfileIn( $fname ); |
| 411 | + |
| 412 | + $xml = $wom_obj->toXML(); |
| 413 | + $xObj = simplexml_load_string( $xml ); |
351 | 414 | try { |
352 | 415 | $objs = $xObj->xpath( $xpath ); |
353 | 416 | } catch ( Exception $e ) { |
— | — | @@ -364,12 +427,21 @@ |
365 | 428 | wfProfileOut( $fname ); |
366 | 429 | return $ret; |
367 | 430 | } |
| 431 | + public static function getObjIdByXPath( $title, $xpath, $rid = 0 ) { |
| 432 | + $fname = 'WikiObjectModel::getObjIdByXPath (WOM)'; |
| 433 | + wfProfileIn( $fname ); |
368 | 434 | |
| 435 | + $ret = self::getObjIdByXPath2( self::getPageObject( $title, $rid ), $xpath ); |
| 436 | + |
| 437 | + wfProfileOut( $fname ); |
| 438 | + return $ret; |
| 439 | + } |
| 440 | + |
369 | 441 | public static function getSubObjectsByParentId( $title, $obj_id, $rid = 0 ) { |
370 | 442 | $fname = 'WikiObjectModel::getSubPageObjectsByParentId (WOM)'; |
371 | 443 | wfProfileIn( $fname ); |
372 | 444 | |
373 | | - $wom = WOMProcessor::getPageObject( $title, $rid ); |
| 445 | + $wom = self::getPageObject( $title, $rid ); |
374 | 446 | |
375 | 447 | $obj = $wom->getObject( $obj_id ); |
376 | 448 | |
— | — | @@ -384,7 +456,7 @@ |
385 | 457 | $fname = 'WikiObjectModel::getPageObjectsByTypeID (WOM)'; |
386 | 458 | wfProfileIn( $fname ); |
387 | 459 | |
388 | | - $wom = WOMProcessor::getPageObject( $title, $rid ); |
| 460 | + $wom = self::getPageObject( $title, $rid ); |
389 | 461 | |
390 | 462 | $result = $wom->getObjectsByTypeID( $type_id ); |
391 | 463 | |
— | — | @@ -397,7 +469,7 @@ |
398 | 470 | $fname = 'WikiObjectModel::getPageTemplates (WOM)'; |
399 | 471 | wfProfileIn( $fname ); |
400 | 472 | |
401 | | - $result = WOMProcessor::getPageObjectsByTypeID( |
| 473 | + $result = self::getPageObjectsByTypeID( |
402 | 474 | WOM_TYPE_TEMPLATE, $title, $rid ); |
403 | 475 | |
404 | 476 | if ( $name == '' ) { |
— | — | @@ -420,7 +492,7 @@ |
421 | 493 | $fname = 'WikiObjectModel::getPageCategories (WOM)'; |
422 | 494 | wfProfileIn( $fname ); |
423 | 495 | |
424 | | - $result = WOMProcessor::getPageObjectsByTypeID( |
| 496 | + $result = self::getPageObjectsByTypeID( |
425 | 497 | WOM_TYPE_CATEGORY, $title, $rid ); |
426 | 498 | |
427 | 499 | wfProfileOut( $fname ); |
— | — | @@ -432,7 +504,7 @@ |
433 | 505 | $fname = 'WikiObjectModel::getPageLinks (WOM)'; |
434 | 506 | wfProfileIn( $fname ); |
435 | 507 | |
436 | | - $result = WOMProcessor::getPageObjectsByTypeID( |
| 508 | + $result = self::getPageObjectsByTypeID( |
437 | 509 | WOM_TYPE_LINK, $title, $rid ); |
438 | 510 | |
439 | 511 | wfProfileOut( $fname ); |
— | — | @@ -445,7 +517,7 @@ |
446 | 518 | wfProfileIn( $fname ); |
447 | 519 | |
448 | 520 | // do not return properties which are binding template fields, in current version |
449 | | - $result = WOMProcessor::getPageObjectsByTypeID( |
| 521 | + $result = self::getPageObjectsByTypeID( |
450 | 522 | WOM_TYPE_PROPERTY, $title, $rid ); |
451 | 523 | |
452 | 524 | wfProfileOut( $fname ); |
— | — | @@ -457,7 +529,7 @@ |
458 | 530 | $fname = 'WikiObjectModel::getParserFunctions (WOM)'; |
459 | 531 | wfProfileIn( $fname ); |
460 | 532 | |
461 | | - $result = WOMProcessor::getPageObjectsByTypeID( |
| 533 | + $result = self::getPageObjectsByTypeID( |
462 | 534 | WOM_TYPE_PARSERFUNCTION, $title, $rid ); |
463 | 535 | |
464 | 536 | if ( $function_key == '' ) { |
— | — | @@ -489,7 +561,7 @@ |
490 | 562 | return; |
491 | 563 | } |
492 | 564 | } |
493 | | - $wom = WOMProcessor::getPageObject( $title, $revision_id ); |
| 565 | + $wom = self::getPageObject( $title, $revision_id ); |
494 | 566 | $wom->insertPageObject( $object, $obj_id ); |
495 | 567 | |
496 | 568 | // save to wiki |
— | — | @@ -513,7 +585,7 @@ |
514 | 586 | return; |
515 | 587 | } |
516 | 588 | } |
517 | | - $wom = WOMProcessor::getPageObject( $title, $revision_id ); |
| 589 | + $wom = self::getPageObject( $title, $revision_id ); |
518 | 590 | $parent = $wom->getObject( $obj_id ); |
519 | 591 | if ( !( $parent instanceof WikiObjectModelCollection ) ) { |
520 | 592 | throw new MWException( __METHOD__ . ": Object is not a collection object '{$title} ({$revision_id}) - {$obj_id}'" ); |
— | — | @@ -543,7 +615,7 @@ |
544 | 616 | return; |
545 | 617 | } |
546 | 618 | } |
547 | | - $wom = WOMProcessor::getPageObject( $title, $revision_id ); |
| 619 | + $wom = self::getPageObject( $title, $revision_id ); |
548 | 620 | $wom->updatePageObject( $object, $obj_id ); |
549 | 621 | |
550 | 622 | // save to wiki |
— | — | @@ -567,7 +639,7 @@ |
568 | 640 | return; |
569 | 641 | } |
570 | 642 | } |
571 | | - $wom = WOMProcessor::getPageObject( $title, $revision_id ); |
| 643 | + $wom = self::getPageObject( $title, $revision_id ); |
572 | 644 | $wom->removePageObject( $obj_id ); |
573 | 645 | |
574 | 646 | // save to wiki |
— | — | @@ -591,8 +663,8 @@ |
592 | 664 | return; |
593 | 665 | } |
594 | 666 | } |
595 | | - $wom = WOMProcessor::getPageObject( $title, $revision_id ); |
596 | | - $text = WOMProcessor::getValidText( $text, $wom->getObject( $obj_id )->getParent(), $wom ); |
| 667 | + $wom = self::getPageObject( $title, $revision_id ); |
| 668 | + $text = self::getValidText( $text, $wom->getObject( $obj_id )->getParent(), $wom ); |
597 | 669 | // no need to parse or merge object model but use text |
598 | 670 | $wom->insertPageObject( new WOMTextModel( $text ), $obj_id ); |
599 | 671 | |
— | — | @@ -617,14 +689,14 @@ |
618 | 690 | return; |
619 | 691 | } |
620 | 692 | } |
621 | | - $wom = WOMProcessor::getPageObject( $title, $revision_id ); |
| 693 | + $wom = self::getPageObject( $title, $revision_id ); |
622 | 694 | $parent = $wom->getObject( $obj_id ); |
623 | 695 | if ( !( $parent instanceof WikiObjectModelCollection ) ) { |
624 | 696 | throw new MWException( __METHOD__ . ": Object is not a collection object '{$title} ({$revision_id}) - {$obj_id}'" ); |
625 | 697 | wfProfileOut( $fname ); |
626 | 698 | return; |
627 | 699 | } |
628 | | - $text = WOMProcessor::getValidText( $text, $parent, $wom ); |
| 700 | + $text = self::getValidText( $text, $parent, $wom ); |
629 | 701 | // no need to parse or merge object model but use text |
630 | 702 | $wom->appendChildObject( new WOMTextModel( $text ), $obj_id ); |
631 | 703 | |
— | — | @@ -649,8 +721,8 @@ |
650 | 722 | return; |
651 | 723 | } |
652 | 724 | } |
653 | | - $wom = WOMProcessor::getPageObject( $title, $revision_id ); |
654 | | - $text = WOMProcessor::getValidText( $text, $wom->getObject( $obj_id )->getParent(), $wom ); |
| 725 | + $wom = self::getPageObject( $title, $revision_id ); |
| 726 | + $text = self::getValidText( $text, $wom->getObject( $obj_id )->getParent(), $wom ); |
655 | 727 | // no need to parse or merge object model but use text |
656 | 728 | $wom->updatePageObject( new WOMTextModel( $text ), $obj_id ); |
657 | 729 | |
— | — | @@ -664,13 +736,13 @@ |
665 | 737 | |
666 | 738 | private static function getValidText( $text, $parent, $wom ) { |
667 | 739 | if ( $parent != null ) { |
668 | | - $parserId = WOMProcessor::getObjectParser( $parent )->getSubParserID(); |
| 740 | + $parserId = self::getObjectParser( $parent )->getSubParserID(); |
669 | 741 | if ( $parserId != '' ) { |
670 | | - $parser = WOMProcessor::$parsers[$parserId]; |
| 742 | + $parser = self::$parsers[$parserId]; |
671 | 743 | $offset = 0; |
672 | 744 | $p2 = clone ( $parent ); |
673 | 745 | $p2->reset(); |
674 | | - WOMProcessor::parseNext( $text, $p2, $wom, $offset, $parser ); |
| 746 | + self::parseNext( $text, $p2, $wom, $offset, $parser ); |
675 | 747 | $text = ''; |
676 | 748 | foreach ( $p2->getObjects() as $obj ) { |
677 | 749 | $text .= $obj->getWikiText(); |
— | — | @@ -684,10 +756,10 @@ |
685 | 757 | $fname = 'WikiObjectModel::getToc (WOM)'; |
686 | 758 | wfProfileIn( $fname ); |
687 | 759 | |
688 | | - $wom = WOMProcessor::getPageObject( $title, $revision_id ); |
| 760 | + $wom = self::getPageObject( $title, $revision_id ); |
689 | 761 | |
690 | 762 | $arr = array(); |
691 | | - WOMProcessor::saveToToc( $wom, $arr ); |
| 763 | + self::saveToToc( $wom, $arr ); |
692 | 764 | |
693 | 765 | wfProfileOut( $fname ); |
694 | 766 | |
— | — | @@ -698,7 +770,7 @@ |
699 | 771 | foreach ( $wom->getObjects() as $obj ) { |
700 | 772 | if ( $obj->getTypeID() == WOM_TYPE_SECTION ) { |
701 | 773 | $sec = array( 'section' => $obj->getName(), 'sub' => array() ); |
702 | | - WOMProcessor::saveToToc( $obj, $sec['sub'] ); |
| 774 | + self::saveToToc( $obj, $sec['sub'] ); |
703 | 775 | $arr[] = $sec; |
704 | 776 | } |
705 | 777 | } |
— | — | @@ -726,7 +798,7 @@ |
727 | 799 | $fname = 'WikiObjectModel::objectToWikiText (WOM)'; |
728 | 800 | wfProfileIn( $fname ); |
729 | 801 | |
730 | | - $wom = WOMProcessor::getPageObject( $title, $revision_id ); |
| 802 | + $wom = self::getPageObject( $title, $revision_id ); |
731 | 803 | |
732 | 804 | $obj = $wom->getObject( $obj_id ); |
733 | 805 | |
Index: trunk/extensions/WikiObjectModel/includes/WOM_Setup.php |
— | — | @@ -21,11 +21,13 @@ |
22 | 22 | $wgAutoloadClasses['WOMLinkModel'] = $wgOMIP . '/includes/models/WOM_OM_Link.php'; |
23 | 23 | $wgAutoloadClasses['WOMSectionModel'] = $wgOMIP . '/includes/models/WOM_OM_Section.php'; |
24 | 24 | $wgAutoloadClasses['WOMSentenceModel'] = $wgOMIP . '/includes/models/WOM_OM_Sentence.php'; |
| 25 | +$wgAutoloadClasses['WOMParagraphModel'] = $wgOMIP . '/includes/models/WOM_OM_Paragraph.php'; |
25 | 26 | $wgAutoloadClasses['WOMListItemModel'] = $wgOMIP . '/includes/models/WOM_OM_ListItem.php'; |
26 | 27 | $wgAutoloadClasses['WOMTableModel'] = $wgOMIP . '/includes/models/WOM_OM_Table.php'; |
27 | 28 | $wgAutoloadClasses['WOMTableCellModel'] = $wgOMIP . '/includes/models/WOM_OM_TblCell.php'; |
28 | 29 | $wgAutoloadClasses['WOMMagicWordModel'] = $wgOMIP . '/includes/models/WOM_OM_MagicWord.php'; |
29 | 30 | $wgAutoloadClasses['WOMHTMLTagModel'] = $wgOMIP . '/includes/models/WOM_OM_HTMLTag.php'; |
| 31 | +$wgAutoloadClasses['WOMTemplateFieldHolderModel'] = $wgOMIP . '/includes/models/WOM_OM_TmplFieldHolder.php'; |
30 | 32 | |
31 | 33 | // Definitions |
32 | 34 | define( 'WOM_TYPE_PAGE' , 'page' ); |
— | — | @@ -40,11 +42,13 @@ |
41 | 43 | define( 'WOM_TYPE_PARAM_VALUE' , 'value' ); |
42 | 44 | define( 'WOM_TYPE_TMPL_FIELD' , 'template_field' ); |
43 | 45 | define( 'WOM_TYPE_SENTENCE' , 'sentence' ); |
| 46 | +define( 'WOM_TYPE_PARAGRAPH' , 'paragraph' ); |
44 | 47 | define( 'WOM_TYPE_LISTITEM' , 'list_item' ); |
45 | 48 | define( 'WOM_TYPE_TABLE' , 'table' ); |
46 | 49 | define( 'WOM_TYPE_TBL_CELL' , 'table_cell' ); |
47 | 50 | define( 'WOM_TYPE_MAGICWORD' , 'magicword' ); |
48 | 51 | define( 'WOM_TYPE_HTMLTAG' , 'html' ); |
| 52 | +define( 'WOM_TYPE_TMPL_FIELD_HOLDER', 'template_field_holder' ); |
49 | 53 | |
50 | 54 | // POM Parser |
51 | 55 | $wgAutoloadClasses['WikiObjectModelParser'] = $wgOMIP . '/includes/parsers/WikiObjectModelParser.php'; |
— | — | @@ -62,6 +66,7 @@ |
63 | 67 | $wgAutoloadClasses['WOMTableCellParser'] = $wgOMIP . '/includes/parsers/WOMTblCellParser.php'; |
64 | 68 | $wgAutoloadClasses['WOMMagicWordParser'] = $wgOMIP . '/includes/parsers/WOMMagicWordParser.php'; |
65 | 69 | $wgAutoloadClasses['WOMHTMLTagParser'] = $wgOMIP . '/includes/parsers/WOMHTMLTagParser.php'; |
| 70 | +$wgAutoloadClasses['WOMTemplateFieldHolderParser'] = $wgOMIP . '/includes/parsers/WOMTemplateFieldHolderParser.php'; |
66 | 71 | |
67 | 72 | // Definitions |
68 | 73 | define( 'WOM_PARSER_ID_CATEGORY' , 'category' ); |
— | — | @@ -78,6 +83,7 @@ |
79 | 84 | define( 'WOM_PARSER_ID_TABLECELL' , 'tbl_cell' ); |
80 | 85 | define( 'WOM_PARSER_ID_MAGICWORD' , 'magicword' ); |
81 | 86 | define( 'WOM_PARSER_ID_HTMLTAG' , 'html' ); |
| 87 | +define( 'WOM_PARSER_ID_TEMPLATE_FIELD_HOLDER', 'template_field_holder' ); |
82 | 88 | |
83 | 89 | global $wgOMParsers, $wgOMModelParserMapping; |
84 | 90 | $wgOMParsers = array( |
— | — | @@ -95,6 +101,7 @@ |
96 | 102 | 'WOMTableCellParser', |
97 | 103 | 'WOMMagicWordParser', |
98 | 104 | 'WOMHTMLTagParser', |
| 105 | + 'WOMTemplateFieldHolderParser', |
99 | 106 | ); |
100 | 107 | |
101 | 108 | $wgOMModelParserMapping = array( |
— | — | @@ -113,6 +120,7 @@ |
114 | 121 | WOM_TYPE_TBL_CELL => WOM_PARSER_ID_TABLECELL, |
115 | 122 | WOM_TYPE_MAGICWORD => WOM_PARSER_ID_MAGICWORD, |
116 | 123 | WOM_TYPE_HTMLTAG => WOM_PARSER_ID_HTMLTAG, |
| 124 | + WOM_TYPE_TMPL_FIELD_HOLDER => WOM_PARSER_ID_TEMPLATE_FIELD_HOLDER, |
117 | 125 | ); |
118 | 126 | |
119 | 127 | global $wgOMSentenceObjectTypes; |
— | — | @@ -122,13 +130,23 @@ |
123 | 131 | WOM_TYPE_LINK, |
124 | 132 | WOM_TYPE_CATEGORY, |
125 | 133 | WOM_TYPE_MAGICWORD, |
| 134 | + WOM_TYPE_TMPL_FIELD_HOLDER, |
126 | 135 | ); |
127 | 136 | |
| 137 | +global $wgOMParagraphObjectTypes; |
| 138 | +$wgOMParagraphObjectTypes = $wgOMSentenceObjectTypes; |
| 139 | +$wgOMParagraphObjectTypes[] = WOM_TYPE_LISTITEM; |
| 140 | +$wgOMParagraphObjectTypes[] = WOM_TYPE_PARSERFUNCTION; |
| 141 | +$wgOMParagraphObjectTypes[] = WOM_TYPE_TEMPLATE; |
| 142 | + |
128 | 143 | // APIs |
129 | 144 | global $wgAPIModules; |
130 | 145 | $wgAPIModules['womset'] = 'ApiWOMSetObjectModel'; |
131 | 146 | $wgAutoloadClasses['ApiWOMSetObjectModel'] = $wgOMIP . '/includes/apis/WOM_SetObjectModel.php'; |
132 | 147 | $wgAPIModules['womget'] = 'ApiWOMGetObjectModel'; |
133 | 148 | $wgAutoloadClasses['ApiWOMGetObjectModel'] = $wgOMIP . '/includes/apis/WOM_GetObjectModel.php'; |
| 149 | +$wgAPIModules['womquery'] = 'ApiWOMQuery'; |
| 150 | +$wgAutoloadClasses['ApiWOMQuery'] = $wgOMIP . '/includes/apis/WOM_Query.php'; |
| 151 | +$wgAPIModules['womoutput'] = 'ApiWOMOutputObjectModel'; |
| 152 | +$wgAutoloadClasses['ApiWOMOutputObjectModel'] = $wgOMIP . '/includes/apis/WOM_OutputObjectModel.php'; |
134 | 153 | |
135 | | - |
Index: trunk/extensions/WikiObjectModel/includes/apis/WOM_OutputObjectModel.php |
— | — | @@ -0,0 +1,139 @@ |
| 2 | +<?php
|
| 3 | +
|
| 4 | +global $wgOMIP;
|
| 5 | +require_once( $wgOMIP . '/includes/apis/WOM_OutputProcessor.php' );
|
| 6 | +
|
| 7 | +/**
|
| 8 | + * @addtogroup API
|
| 9 | + */
|
| 10 | +class ApiWOMOutputObjectModel extends ApiBase {
|
| 11 | +
|
| 12 | + public function __construct( $main, $action ) {
|
| 13 | + parent :: __construct( $main, $action );
|
| 14 | + }
|
| 15 | +
|
| 16 | + public function execute() {
|
| 17 | + global $wgUser;
|
| 18 | +
|
| 19 | + $params = $this->extractRequestParams();
|
| 20 | + if ( is_null( $params['page'] ) )
|
| 21 | + $this->dieUsage( 'Must specify page title', 0 );
|
| 22 | + if ( is_null( $params['xpath'] ) )
|
| 23 | + $this->dieUsage( 'Must specify xpath', 1 );
|
| 24 | +
|
| 25 | + $page = $params['page'];
|
| 26 | + $xpath = $params['xpath'];
|
| 27 | + $type = $params['type'];
|
| 28 | + $rid = $params['rid'];
|
| 29 | +
|
| 30 | +
|
| 31 | + $articleTitle = Title::newFromText( $page );
|
| 32 | + if ( !$articleTitle )
|
| 33 | + $this->dieUsage( "Can't create title object ($page)", 2 );
|
| 34 | +
|
| 35 | + $article = new Article( $articleTitle );
|
| 36 | + if ( !$article->exists() )
|
| 37 | + $this->dieUsage( "Article doesn't exist ($page)", 3 );
|
| 38 | +
|
| 39 | + $page_obj = WOMOutputProcessor::getOutputData( $articleTitle, $rid );
|
| 40 | + try {
|
| 41 | + $objs = WOMProcessor::getObjIdByXPath2( $page_obj, $xpath );
|
| 42 | + } catch ( Exception $e ) {
|
| 43 | + $err = $e->getMessage();
|
| 44 | + }
|
| 45 | +
|
| 46 | + $result = array();
|
| 47 | +
|
| 48 | + if ( isset( $err ) ) {
|
| 49 | + $result = array(
|
| 50 | + 'result' => 'Failure',
|
| 51 | + 'message' => array(),
|
| 52 | + );
|
| 53 | + $this->getResult()->setContent( $result['message'], $err );
|
| 54 | + } else {
|
| 55 | + $result['result'] = 'Success';
|
| 56 | +
|
| 57 | + // pay attention to special xml tag, e.g., <property><value>...</value></property>
|
| 58 | + $result['return'] = array();
|
| 59 | + if ( $type == 'count' ) {
|
| 60 | + $count = 0;
|
| 61 | + foreach ( $objs as $id ) {
|
| 62 | + if ( $id == '' ) continue;
|
| 63 | + ++ $count;
|
| 64 | + }
|
| 65 | + $this->getResult()->setContent( $result['return'], $count );
|
| 66 | + } else {
|
| 67 | + $xml = '';
|
| 68 | + foreach ( $objs as $id ) {
|
| 69 | + if ( $id == '' ) continue;
|
| 70 | + $wobj = $page_obj->getObject( $id );
|
| 71 | + $result['return'][$id] = array();
|
| 72 | + if ( $type == 'xml' ) {
|
| 73 | + $xml .= "<{$id} xml:space=\"preserve\">{$wobj->toXML()}</{$id}>";
|
| 74 | + } else {
|
| 75 | + $this->getResult()->setContent( $result['return'][$id], $wobj->getWikiText() );
|
| 76 | + }
|
| 77 | + }
|
| 78 | + if ( $type == 'xml' ) {
|
| 79 | + header ( "Content-Type: application/rdf+xml" );
|
| 80 | + echo <<<OUTPUT
|
| 81 | +<?xml version="1.0" encoding="UTF-8" ?>
|
| 82 | +<api><womget result="Success"><return>
|
| 83 | +{$xml}
|
| 84 | +</return></womget></api>
|
| 85 | +OUTPUT;
|
| 86 | + exit( 1 );
|
| 87 | + }
|
| 88 | + }
|
| 89 | + }
|
| 90 | + $this->getResult()->addValue( null, $this->getModuleName(), $result );
|
| 91 | + }
|
| 92 | +
|
| 93 | + protected function getAllowedParams() {
|
| 94 | + return array (
|
| 95 | + 'page' => null,
|
| 96 | + 'xpath' => null,
|
| 97 | + 'type' => array(
|
| 98 | + ApiBase :: PARAM_DFLT => 'wiki',
|
| 99 | + ApiBase :: PARAM_TYPE => array(
|
| 100 | + 'wiki',
|
| 101 | + 'count',
|
| 102 | + 'xml',
|
| 103 | + ),
|
| 104 | + ),
|
| 105 | + 'rid' => array (
|
| 106 | + ApiBase :: PARAM_TYPE => 'integer',
|
| 107 | + ApiBase :: PARAM_DFLT => 0,
|
| 108 | + ApiBase :: PARAM_MIN => 0
|
| 109 | + ),
|
| 110 | + );
|
| 111 | + }
|
| 112 | +
|
| 113 | + protected function getParamDescription() {
|
| 114 | + return array (
|
| 115 | + 'page' => 'Title of the page to modify',
|
| 116 | + 'xpath' => 'DOM-like xpath to locate WOM object instances (http://www.w3schools.com/xpath/xpath_syntax.asp)',
|
| 117 | + 'type' => array (
|
| 118 | + 'Type to fetch useful wiki object data',
|
| 119 | + 'type = wiki, get wiki text of specified object',
|
| 120 | + 'type = count, get objects count with specified xpath',
|
| 121 | + 'type = xml, view "encoded objects\' xml" with specified xpath, usually use with format=xml',
|
| 122 | + ),
|
| 123 | + 'rid' => 'Revision id of specified page - by dafault latest updated revision (0) is used',
|
| 124 | + );
|
| 125 | + }
|
| 126 | +
|
| 127 | + protected function getDescription() {
|
| 128 | + return 'Call to get object values to Wiki Object Model';
|
| 129 | + }
|
| 130 | +
|
| 131 | + protected function getExamples() {
|
| 132 | + return array (
|
| 133 | + 'api.php?action=womget&page=Somepage&xpath=//template[@name=SomeTempate]/template_field[@key=templateparam]'
|
| 134 | + );
|
| 135 | + }
|
| 136 | +
|
| 137 | + public function getVersion() {
|
| 138 | + return __CLASS__ . ': $Id$';
|
| 139 | + }
|
| 140 | +}
|
Index: trunk/extensions/WikiObjectModel/includes/apis/WOM_OM_QueryResult.php |
— | — | @@ -0,0 +1,16 @@ |
| 2 | +<?php
|
| 3 | +/**
|
| 4 | + * This model implements Query result models.
|
| 5 | + *
|
| 6 | + * @author Ning
|
| 7 | + * @file
|
| 8 | + * @ingroup WikiObjectModels
|
| 9 | + *
|
| 10 | + */
|
| 11 | +
|
| 12 | +class WOMQueryResult extends WikiObjectModelCollection {
|
| 13 | +
|
| 14 | + public function __construct() {
|
| 15 | + parent::__construct( 'q_result' );
|
| 16 | + }
|
| 17 | +}
|
Index: trunk/extensions/WikiObjectModel/includes/apis/WOM_OutputProcessor.php |
— | — | @@ -0,0 +1,296 @@ |
| 2 | +<?php
|
| 3 | +if ( !defined( 'MEDIAWIKI' ) ) die;
|
| 4 | +
|
| 5 | +global $wgHooks, $wgParser;
|
| 6 | +if ( defined( 'MW_SUPPORTS_PARSERFIRSTCALLINIT' ) ) {
|
| 7 | + $wgHooks['ParserFirstCallInit'][] = 'WOMOutputProcessor::smwgWTregisterParserFunctions';
|
| 8 | +} else {
|
| 9 | + if ( class_exists( 'StubObject' ) && !StubObject::isRealObject( $wgParser ) ) {
|
| 10 | + $wgParser->_unstub();
|
| 11 | + }
|
| 12 | + WOMOutputProcessor::smwgWTregisterParserFunctions( $wgParser );
|
| 13 | +}
|
| 14 | +
|
| 15 | +global $wgOMOutputHookedParserFunctions;
|
| 16 | +$wgOMOutputHookedParserFunctions = array(
|
| 17 | + 'ask',
|
| 18 | + 'sparql',
|
| 19 | +);
|
| 20 | +
|
| 21 | +global $wgOMIP;
|
| 22 | +require_once( $wgOMIP . '/includes/apis/WOM_OM_QueryResult.php' );
|
| 23 | +
|
| 24 | +class WOMOutputProcessor {
|
| 25 | + static function smwfProcessSPARQLQueryParserFunctionGTP( &$parser ) {
|
| 26 | + global $smwgWebserviceEndpoint;
|
| 27 | + if ( !isset( $smwgWebserviceEndpoint ) ) return '';
|
| 28 | +
|
| 29 | + global $smwgIQRunningNumber;
|
| 30 | + $smwgIQRunningNumber++;
|
| 31 | + $params = func_get_args();
|
| 32 | + array_shift( $params ); // we already know the $parser ...
|
| 33 | +
|
| 34 | + SMWSPARQLQueryProcessor::processFunctionParams( $params, $querystring, $params, $printouts );
|
| 35 | + $query = SMWSPARQLQueryProcessor::createQuery( $querystring, $params, SMWQueryProcessor::INLINE_QUERY, '', $printouts );
|
| 36 | +
|
| 37 | + if ( !( ( $query->querymode == SMWQuery::MODE_INSTANCES ) || ( $query->querymode == SMWQuery::MODE_NONE ) ) ) {
|
| 38 | + return '';
|
| 39 | + }
|
| 40 | + self::prequery( $params, $printouts, $label, $wom_id );
|
| 41 | +
|
| 42 | + // source from SMWHalo, SMW_SPARQLQueryProcessor.php
|
| 43 | +
|
| 44 | + // Query routing allows extensions to provide alternative stores as data sources
|
| 45 | + // The while feature is experimental and is not properly integrated with most of SMW's architecture. For instance, some query printers just fetch their own store.
|
| 46 | + /// TODO: case-insensitive
|
| 47 | + global $smwgQuerySources;
|
| 48 | +
|
| 49 | + $query->params = $params; // this is a hack
|
| 50 | +
|
| 51 | + if ( array_key_exists( "source", $params ) && array_key_exists( $params["source"], $smwgQuerySources ) ) {
|
| 52 | + $store = new $smwgQuerySources[$params["source"]]();
|
| 53 | + } else {
|
| 54 | + $store = smwfGetStore(); // default store
|
| 55 | + }
|
| 56 | +
|
| 57 | + $res = $store->getQueryResult( $query );
|
| 58 | +
|
| 59 | + if ( !is_array( $res ) ) {
|
| 60 | + $qResults['tsc'] = $res;
|
| 61 | + } else {
|
| 62 | + $qResults = $res;
|
| 63 | + }
|
| 64 | +
|
| 65 | + foreach ( $qResults as $source => $res ) {
|
| 66 | + while ( $row = $res->getNext() ) {
|
| 67 | + $firstcol = true;
|
| 68 | + foreach ( $row as $field ) {
|
| 69 | + $object = $field->getNextObject();
|
| 70 | + $text = $object->getWikiValue();
|
| 71 | + self::$queryProps[$wom_id][$label][] = $text;
|
| 72 | +
|
| 73 | + // get the first column only
|
| 74 | + break;
|
| 75 | + }
|
| 76 | + }
|
| 77 | + }
|
| 78 | +
|
| 79 | + return '';
|
| 80 | + }
|
| 81 | + private static function prequery( &$params, $printouts, &$label, &$wom_id ) {
|
| 82 | + if ( isset( $params['mainlabel'] ) ) {
|
| 83 | + $label = $params['mainlabel'];
|
| 84 | + if ( $label == '-' ) {
|
| 85 | + $pr = $printouts[0];
|
| 86 | + $label = $pr->getLabel();
|
| 87 | + }
|
| 88 | + } else {
|
| 89 | + $label = '{Query #' . self::$queryId . '}';
|
| 90 | + self::$queryId ++;
|
| 91 | + }
|
| 92 | +
|
| 93 | + if ( !isset( $params['limit'] ) ) {
|
| 94 | + $params['limit'] = 20; // limit to 20 result by default
|
| 95 | + }
|
| 96 | + $wom_id = '';
|
| 97 | + if ( isset( $params['wom_id'] ) ) {
|
| 98 | + $wom_id = $params['wom_id'];
|
| 99 | + }
|
| 100 | + }
|
| 101 | + static function smwfProcessInlineQueryParserFunctionGTP( &$parser ) {
|
| 102 | + global $smwgQEnabled, $smwgIQRunningNumber;
|
| 103 | + if ( $smwgQEnabled ) {
|
| 104 | + $smwgIQRunningNumber++;
|
| 105 | + $rawparams = func_get_args();
|
| 106 | + array_shift( $rawparams ); // we already know the $parser ...
|
| 107 | +
|
| 108 | + SMWQueryProcessor::processFunctionParams( $rawparams, &$querystring, &$params, &$printouts );
|
| 109 | + self::prequery( $params, $printouts, $label, $wom_id );
|
| 110 | +
|
| 111 | + $query = SMWQueryProcessor::createQuery(
|
| 112 | + $querystring,
|
| 113 | + $params,
|
| 114 | + SMWQueryProcessor::INLINE_QUERY,
|
| 115 | + SMW_OUTPUT_WIKI,
|
| 116 | + $printouts
|
| 117 | + );
|
| 118 | + $res = smwfGetStore()->getQueryResult( $query );
|
| 119 | +
|
| 120 | + while ( $row = $res->getNext() ) {
|
| 121 | + $firstcol = true;
|
| 122 | + foreach ( $row as $field ) {
|
| 123 | + $object = $field->getNextObject();
|
| 124 | + $text = $object->getWikiValue();
|
| 125 | + self::$queryProps[$wom_id][$label][] = $text;
|
| 126 | +
|
| 127 | + // get the first column only
|
| 128 | + break;
|
| 129 | + }
|
| 130 | + }
|
| 131 | + }
|
| 132 | + return '';
|
| 133 | + }
|
| 134 | +
|
| 135 | + static function smwgWTregisterParserFunctions( &$parser ) {
|
| 136 | + global $wgWOMOutputHooked;
|
| 137 | + if ( $wgWOMOutputHooked === true ) {
|
| 138 | + if ( defined( SMW_VERSION ) ) {
|
| 139 | + $parser->setFunctionHook( 'ask', 'WOMOutputProcessor::smwfProcessInlineQueryParserFunctionGTP' );
|
| 140 | + }
|
| 141 | + if ( defined( SMW_HALO_VERSION ) ) {
|
| 142 | + $parser->setFunctionHook( 'sparql', 'WOMOutputProcessor::smwfProcessSPARQLQueryParserFunctionGTP' );
|
| 143 | + }
|
| 144 | + }
|
| 145 | + return true; // always return true, in order not to stop MW's hook processing!
|
| 146 | + }
|
| 147 | +
|
| 148 | + private static function removeSubWOMIds( WikiObjectModelCollection $parent ) {
|
| 149 | + foreach ( $parent->getObjects() as $wobj ) {
|
| 150 | + $wobj->setObjectID( '' );
|
| 151 | + if ( $wobj instanceof WikiObjectModelCollection ) {
|
| 152 | + self::removeSubWOMIds( $wobj );
|
| 153 | + }
|
| 154 | + }
|
| 155 | + }
|
| 156 | +
|
| 157 | + static $queryProps = null;
|
| 158 | + static $queryId = 0;
|
| 159 | + static function getOutputData( $title, $rid = 0 ) {
|
| 160 | + // normal page
|
| 161 | + global $wgTitle, $wgUser;
|
| 162 | + $wgTitle = $title;
|
| 163 | + $revision = Revision::newFromTitle( $title, $rid );
|
| 164 | + if ( $revision === NULL ) {
|
| 165 | + throw new MWException( __METHOD__ . ": Page not exist '{$page_name} ({$rid})'" );
|
| 166 | + }
|
| 167 | + $text = $revision->getText();
|
| 168 | + $wom = WOMProcessor::parseToWOM( $text );
|
| 169 | +
|
| 170 | + global $wgOMOutputHookedParserFunctions;
|
| 171 | + $pfs = $wom->getObjectsByTypeID( WOM_TYPE_PARSERFUNCTION );
|
| 172 | + foreach ( $pfs as $id => $obj ) {
|
| 173 | + self::removeSubWOMIds( $obj );
|
| 174 | + foreach ( $wgOMOutputHookedParserFunctions as $function_key ) {
|
| 175 | + if ( $obj->getFunctionKey() == $function_key ) {
|
| 176 | + // add wom id to parser function, with specified parameter 'wom_id'
|
| 177 | + $param = new WOMParameterModel( 'wom_id' );
|
| 178 | + $pv = new WOMParamValueModel();
|
| 179 | + $param->insertObject( $pv );
|
| 180 | + $pv->insertObject( new WOMTextModel( $id ) );
|
| 181 | + $obj->insertObject( $param );
|
| 182 | + }
|
| 183 | + }
|
| 184 | + }
|
| 185 | + // FIXME: template values may have object ids
|
| 186 | + $tmpls = $wom->getObjectsByTypeID( WOM_TYPE_TEMPLATE );
|
| 187 | + foreach ( $tmpls as $id => $obj ) {
|
| 188 | + self::removeSubWOMIds( $obj );
|
| 189 | + }
|
| 190 | +
|
| 191 | + global $wgParser, $wgOut, $wgWOMOutputHooked;
|
| 192 | + $wgWOMOutputHooked = true;
|
| 193 | + $options = ParserOptions::newFromUser( $wgUser );
|
| 194 | +
|
| 195 | + self::$queryProps = array();
|
| 196 | + self::$queryId = 1;
|
| 197 | + $wgParser->parse( $wom->getWikiText(), $title, $options );
|
| 198 | +
|
| 199 | + $output = SMWParseData::getSMWdata( $wgParser );
|
| 200 | +
|
| 201 | + if ( !isset( $output ) ) {
|
| 202 | + $semdata = smwfGetStore()->getSemanticData( $title );
|
| 203 | + } else {
|
| 204 | + $semdata = $output;
|
| 205 | + }
|
| 206 | +
|
| 207 | + $tmp_id = 0;
|
| 208 | + // fill in semantic properties
|
| 209 | + $properties = array();
|
| 210 | + foreach ( $semdata->getProperties() as $property ) {
|
| 211 | + if ( !$property->isShown() ) { // showing this is not desired, hide
|
| 212 | + continue;
|
| 213 | + } elseif ( $property->isUserDefined() ) { // user defined property
|
| 214 | + $property->setCaption( preg_replace( '/[ ]/u', ' ', $property->getWikiValue(), 2 ) );
|
| 215 | + // / NOTE: the preg_replace is a slight hack to ensure that the left column does not get too narrow
|
| 216 | + $properties[$property->getWikiValue()] = array();
|
| 217 | + } elseif ( $property->isVisible() ) { // predefined property
|
| 218 | + $properties[$property->getWikiValue()] = array();
|
| 219 | + } else { // predefined, internal property
|
| 220 | + continue;
|
| 221 | + }
|
| 222 | +
|
| 223 | + $propvalues = $semdata->getPropertyValues( $property );
|
| 224 | + foreach ( $propvalues as $propvalue ) {
|
| 225 | + $properties[$property->getWikiValue()][$propvalue->getWikiValue()] = false;
|
| 226 | + }
|
| 227 | + }
|
| 228 | + $props = $wom->getObjectsByTypeID( WOM_TYPE_PROPERTY );
|
| 229 | + foreach ( $props as $prop ) {
|
| 230 | + $id = $prop->getObjectID();
|
| 231 | + if ( $id == '' ) continue;
|
| 232 | + $name = $prop->getPropertyName();
|
| 233 | + $value = $prop->getPropertyValue();
|
| 234 | + if ( !isset( $properties[$name][$value] ) ) {
|
| 235 | + // remove category not match to output
|
| 236 | + $wom->removePageObject( $id );
|
| 237 | + } else {
|
| 238 | + $properties[$name][$value] = true;
|
| 239 | + }
|
| 240 | + }
|
| 241 | + foreach ( $properties as $name => $values ) {
|
| 242 | + foreach ( $values as $val => $flag ) {
|
| 243 | + if ( $flag !== true ) {
|
| 244 | + $p = new WOMPropertyModel( $name, $val );
|
| 245 | + $p->setObjectID( 'output' . ( $tmp_id ++ ) );
|
| 246 | + $wom->insertObject( $p );
|
| 247 | + $wom->addToPageObjectSet( $p );
|
| 248 | + }
|
| 249 | + }
|
| 250 | + }
|
| 251 | +
|
| 252 | + // fill in ask query results
|
| 253 | + foreach ( self::$queryProps as $wom_id => $queries ) {
|
| 254 | + $query_res = new WOMQueryResult();
|
| 255 | + if ( $wom_id != '' ) {
|
| 256 | + $parent = $wom->getObject( $wom_id );
|
| 257 | + } else {
|
| 258 | + $parent = new WOMParserFunctionModel( 'ask' );
|
| 259 | + $parent->setObjectID( 'output' . ( $tmp_id ++ ) );
|
| 260 | + $wom->insertObject( $parent );
|
| 261 | + $wom->addToPageObjectSet( $parent );
|
| 262 | + }
|
| 263 | + $parent->insertObject( $query_res );
|
| 264 | + foreach ( $queries as $label => $vals ) {
|
| 265 | + $vals = array_unique( $vals );
|
| 266 | + foreach ( $vals as $val ) {
|
| 267 | + $query_res->insertObject( new WOMPropertyModel( $label, $val ) );
|
| 268 | + }
|
| 269 | + }
|
| 270 | + }
|
| 271 | +
|
| 272 | + // fill in categories
|
| 273 | + $categories = $title->getParentCategories();
|
| 274 | + $cates = $wom->getObjectsByTypeID( WOM_TYPE_CATEGORY );
|
| 275 | + foreach ( $cates as $cate ) {
|
| 276 | + $id = $cate->getObjectID();
|
| 277 | + if ( $id == '' ) continue;
|
| 278 | + $name = Title::newFromText( $cate->getName(), NS_CATEGORY )->getFullText();
|
| 279 | + if ( !isset( $categories[$name] ) ) {
|
| 280 | + // remove category not match to output
|
| 281 | + $wom->removePageObject( $id );
|
| 282 | + } else {
|
| 283 | + $categories[$name] = true;
|
| 284 | + }
|
| 285 | + }
|
| 286 | + foreach ( $categories as $cate => $flag ) {
|
| 287 | + if ( $flag !== true ) {
|
| 288 | + $c = new WOMCategoryModel( Title::newFromText( $cate )->getText() );
|
| 289 | + $c->setObjectID( 'output' . ( $tmp_id ++ ) );
|
| 290 | + $wom->insertObject( $c );
|
| 291 | + $wom->addToPageObjectSet( $c );
|
| 292 | + }
|
| 293 | + }
|
| 294 | +
|
| 295 | + return $wom;
|
| 296 | + }
|
| 297 | +}
|
Index: trunk/extensions/WikiObjectModel/includes/apis/WOM_SetObjectModel.php |
— | — | @@ -38,6 +38,15 @@ |
39 | 39 | if ( !$article->exists() ) |
40 | 40 | $this->dieUsage( "Article doesn't exist ($page)", 4 ); |
41 | 41 | |
| 42 | +// $ep = new EditPage( $article ); |
| 43 | +// // EditPage wants to parse its stuff from a WebRequest |
| 44 | +// // That interface kind of sucks, but it's workable |
| 45 | +// $reqArr = array( 'wpTextbox1' => $params['text'], |
| 46 | +// 'wpEditToken' => $params['token'], |
| 47 | +// 'wpIgnoreBlankSummary' => '' |
| 48 | +// ); |
| 49 | +// if ( !is_null( $summary ) ) |
| 50 | +// $reqArr['wpSummary'] = $summary; |
42 | 51 | |
43 | 52 | try { |
44 | 53 | $objs = WOMProcessor::getObjIdByXPath( $articleTitle, $xpath, $rid ); |
— | — | @@ -119,6 +128,7 @@ |
120 | 129 | protected function getAllowedParams() { |
121 | 130 | return array ( |
122 | 131 | 'page' => null, |
| 132 | +// 'token' => null, |
123 | 133 | 'verb' => array( |
124 | 134 | ApiBase :: PARAM_DFLT => 'update', |
125 | 135 | ApiBase :: PARAM_TYPE => array( |
— | — | @@ -153,6 +163,7 @@ |
154 | 164 | protected function getParamDescription() { |
155 | 165 | return array ( |
156 | 166 | 'page' => 'Title of the page to modify', |
| 167 | +// 'token' => 'Edit token. You can get one of these through prop=info', |
157 | 168 | 'verb' => 'Action verb to set to change wiki object instances', |
158 | 169 | 'xpath' => array( |
159 | 170 | 'DOM-like xpath to locate WOM object instances (http://www.w3schools.com/xpath/xpath_syntax.asp)', |
— | — | @@ -183,7 +194,7 @@ |
184 | 195 | |
185 | 196 | protected function getExamples() { |
186 | 197 | return array ( |
187 | | - 'api.php?action=womset&page=Somepage&xpath=//template[@name=SomeTempate]/template_field[@key=templateparam]&value=It+works!&summary=Editing+template+param+using+Wiki+Object+Model' |
| 198 | + 'api.php?action=womset&page=Somepage&token=ABC123&xpath=//template[@name=SomeTempate]/template_field[@key=templateparam]&value=It+works!&summary=Editing+template+param+using+Wiki+Object+Model' |
188 | 199 | ); |
189 | 200 | } |
190 | 201 | |
Index: trunk/extensions/WikiObjectModel/includes/apis/WOM_Query.php |
— | — | @@ -0,0 +1,154 @@ |
| 2 | +<?php
|
| 3 | +
|
| 4 | +/**
|
| 5 | + * @addtogroup API
|
| 6 | + */
|
| 7 | +class ApiWOMQuery extends ApiBase {
|
| 8 | +
|
| 9 | + public function __construct( $main, $action ) {
|
| 10 | + parent :: __construct( $main, $action );
|
| 11 | + }
|
| 12 | +
|
| 13 | + // given the 'key', return the result set of 'xpath' or wiki object id set
|
| 14 | + // e.g., key=hello, world&action=womquery,
|
| 15 | + // returns <match><id>1</id><type>text</type><start>20</start><end>30</end></match>
|
| 16 | + // in wiki object id="1", the text part of WOM node, char index start at 20 and end at 30
|
| 17 | + // for the paragraph instance, it will return id1, id2, id 3
|
| 18 | + // given the 'key', specify the returning object type, same result set to the previous api
|
| 19 | + // e.g., key=hello, world&action=womquery&return=sentence/paragraph/property value/template value/section...
|
| 20 | + // for the paragraph instance,
|
| 21 | + // return=sentence, it will return id3
|
| 22 | + // return=paragraph, it will return id1, id2
|
| 23 | + // given the 'key' and returning type, specify the context of required object, same return
|
| 24 | + // e.g., key=hello, world&action=womquery&return=sentence&xpath=/page/section[3]
|
| 25 | + // for the paragraph instance,
|
| 26 | + // return=paragraph, xpath=sentence/.., it will return id2
|
| 27 | +
|
| 28 | + public function execute() {
|
| 29 | + global $wgUser;
|
| 30 | +
|
| 31 | + $params = $this->extractRequestParams();
|
| 32 | + if ( is_null( $params['page'] ) )
|
| 33 | + $this->dieUsage( 'Must specify page title', 0 );
|
| 34 | + if ( is_null( $params['key'] ) )
|
| 35 | + $this->dieUsage( 'Must specify key', 1 );
|
| 36 | +
|
| 37 | + $page = $params['page'];
|
| 38 | + $key = $params['key'];
|
| 39 | + $rid = $params['rid'];
|
| 40 | + $type = $params['type'];
|
| 41 | + $xpath = $params['xpath'];
|
| 42 | +
|
| 43 | + $articleTitle = Title::newFromText( $page );
|
| 44 | + if ( !$articleTitle )
|
| 45 | + $this->dieUsage( "Can't create title object ($page)", 2 );
|
| 46 | +
|
| 47 | + $article = new Article( $articleTitle );
|
| 48 | + if ( !$article->exists() )
|
| 49 | + $this->dieUsage( "Article doesn't exist ($page)", 3 );
|
| 50 | +
|
| 51 | + if ( !$xpath ) {
|
| 52 | + $xpath = '/';
|
| 53 | + }
|
| 54 | + try {
|
| 55 | + $objs = WOMProcessor::getObjIdByXPath( $articleTitle, $xpath, $rid );
|
| 56 | + } catch ( Exception $e ) {
|
| 57 | + $err = $e->getMessage();
|
| 58 | + }
|
| 59 | +
|
| 60 | + $result = array();
|
| 61 | +
|
| 62 | + if ( isset( $err ) ) {
|
| 63 | + $result = array(
|
| 64 | + 'result' => 'Failure',
|
| 65 | + 'message' => array(),
|
| 66 | + );
|
| 67 | + $this->getResult()->setContent( $result['message'], $err );
|
| 68 | + } else {
|
| 69 | + $result['result'] = 'Success';
|
| 70 | +
|
| 71 | + // pay attention to special xml tag, e.g., <property><value>...</value></property>
|
| 72 | + $result['return'] = array();
|
| 73 | + if ( $type == 'count' ) {
|
| 74 | + $count = 0;
|
| 75 | + foreach ( $objs as $id ) {
|
| 76 | + if ( $id == '' ) continue;
|
| 77 | + ++ $count;
|
| 78 | + }
|
| 79 | + $this->getResult()->setContent( $result['return'], $count );
|
| 80 | + } else {
|
| 81 | + $xml = '';
|
| 82 | + $page_obj = WOMProcessor::getPageObject( $articleTitle, $rid );
|
| 83 | + foreach ( $objs as $id ) {
|
| 84 | + if ( $id == '' ) continue;
|
| 85 | + $wobj = $page_obj->getObject( $id );
|
| 86 | + $result['return'][$id] = array();
|
| 87 | + if ( $type == 'xml' ) {
|
| 88 | + $xml .= "<{$id} xml:space=\"preserve\">{$wobj->toXML()}</{$id}>";
|
| 89 | +// $this->getResult()->setContent( $result['return'][$id], $wobj->toXML() );
|
| 90 | + } else {
|
| 91 | + $this->getResult()->setContent( $result['return'][$id], $wobj->getWikiText() );
|
| 92 | + }
|
| 93 | + }
|
| 94 | + if ( $type == 'xml' ) {
|
| 95 | + header ( "Content-Type: application/rdf+xml" );
|
| 96 | + echo <<<OUTPUT
|
| 97 | +<?xml version="1.0" encoding="UTF-8" ?>
|
| 98 | +<api><womget result="Success"><return>
|
| 99 | +{$xml}
|
| 100 | +</return></womget></api>
|
| 101 | +OUTPUT;
|
| 102 | + exit( 1 );
|
| 103 | + }
|
| 104 | + }
|
| 105 | + }
|
| 106 | + $this->getResult()->addValue( null, $this->getModuleName(), $result );
|
| 107 | + }
|
| 108 | +
|
| 109 | + protected function getAllowedParams() {
|
| 110 | + return array (
|
| 111 | + 'page' => null,
|
| 112 | + 'key' => null,
|
| 113 | + 'xpath' => null,
|
| 114 | + 'type' => array(
|
| 115 | + ApiBase :: PARAM_DFLT => WOM_TYPE_SENTENCE,
|
| 116 | + ApiBase :: PARAM_TYPE => array(
|
| 117 | + WOM_TYPE_SECTION,
|
| 118 | + WOM_TYPE_PARAGRAPH,
|
| 119 | + WOM_TYPE_SENTENCE,
|
| 120 | + ),
|
| 121 | + ),
|
| 122 | + 'rid' => array (
|
| 123 | + ApiBase :: PARAM_TYPE => 'integer',
|
| 124 | + ApiBase :: PARAM_DFLT => 0,
|
| 125 | + ApiBase :: PARAM_MIN => 0
|
| 126 | + ),
|
| 127 | + );
|
| 128 | + }
|
| 129 | +
|
| 130 | + protected function getParamDescription() {
|
| 131 | + return array (
|
| 132 | + 'page' => 'Title of the page to modify',
|
| 133 | + 'key' => 'query key',
|
| 134 | + 'xpath' => 'DOM-like xpath to locate WOM object instances (http://www.w3schools.com/xpath/xpath_syntax.asp)',
|
| 135 | + 'type' => array (
|
| 136 | + 'Object type to fetch useful wiki object data',
|
| 137 | + ),
|
| 138 | + 'rid' => 'Revision id of specified page - by dafault latest updated revision (0) is used',
|
| 139 | + );
|
| 140 | + }
|
| 141 | +
|
| 142 | + protected function getDescription() {
|
| 143 | + return 'Call to get objects to Wiki Object Model';
|
| 144 | + }
|
| 145 | +
|
| 146 | + protected function getExamples() {
|
| 147 | + return array (
|
| 148 | + 'api.php?action=womquery&page=Somepage&key=hello,world'
|
| 149 | + );
|
| 150 | + }
|
| 151 | +
|
| 152 | + public function getVersion() {
|
| 153 | + return __CLASS__ . ': $Id$';
|
| 154 | + }
|
| 155 | +}
|