r72987 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r72986‎ | r72987 | r72988 >
Date:16:16, 14 September 2010
Author:jeroendedauw
Status:deferred
Tags:
Comment:
Changes for 1.5.3 - moved the datavalues to their own directory as discussed with Markus a few months back

Will fix the includes in the light setup file soonish
Modified paths:
  • /trunk/extensions/SemanticMediaWiki/includes/SMW_DV_Bool.php (deleted) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/SMW_DV_Concept.php (deleted) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/SMW_DV_Container.php (deleted) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/SMW_DV_Error.php (deleted) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/SMW_DV_Import.php (deleted) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/SMW_DV_Linear.php (deleted) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/SMW_DV_Number.php (deleted) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/SMW_DV_Property.php (deleted) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/SMW_DV_Record.php (deleted) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/SMW_DV_SimpleWikiPage.php (deleted) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/SMW_DV_String.php (deleted) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/SMW_DV_Temperature.php (deleted) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/SMW_DV_Time.php (deleted) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/SMW_DV_TypeList.php (deleted) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/SMW_DV_Types.php (deleted) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/SMW_DV_URI.php (deleted) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/SMW_DV_WikiPage.php (deleted) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/SMW_Setup.php (modified) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/datavalues (added) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_Bool.php (added) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_Concept.php (added) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_Container.php (added) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_Error.php (added) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_Import.php (added) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_Linear.php (added) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_Number.php (added) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_Property.php (added) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_Record.php (added) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_SimpleWikiPage.php (added) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_String.php (added) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_Temperature.php (added) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_Time.php (added) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_TypeList.php (added) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_Types.php (added) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_URI.php (added) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_WikiPage.php (added) (history)

Diff [purge]

Index: trunk/extensions/SemanticMediaWiki/includes/SMW_DV_Error.php
@@ -1,76 +0,0 @@
2 -<?php
3 -/**
4 - * @file
5 - * @ingroup SMWDataValues
6 - */
7 -
8 -/**
9 - * This datavalue implements Error-Datavalues.
10 - *
11 - * @author Nikolas Iwan
12 - * @ingroup SMWDataValues
13 - */
14 -class SMWErrorValue extends SMWDataValue {
15 -
16 - private $m_value;
17 -
18 - public function SMWErrorValue( $errormsg = '', $uservalue = '', $caption = false ) {
19 - $this->setUserValue( $uservalue, $caption );
20 - if ( $errormsg != '' ) $this->addError( $errormsg );
21 - }
22 -
23 - protected function parseUserValue( $value ) {
24 - if ( $this->m_caption === false ) {
25 - $this->m_caption = $value;
26 - }
27 - $this->m_value = $value;
28 - return true;
29 - }
30 -
31 - protected function parseDBkeys( $args ) {
32 - $this->setUserValue( strval( $args[0] ) ); // compatible syntax
33 - // Note that errors are never a proper result of reading data from the
34 - // store, so it is quite unlikely that the data we get here fits this
35 - // datatype. Normally, it will not be displayed either since this value
36 - // is not valid by default. So keeping the DB key here is rather
37 - // irrelevant.
38 - }
39 -
40 - public function setOutputFormat( $formatstring ) {
41 - // no output formats
42 - }
43 -
44 - public function getShortWikiText( $linked = null ) {
45 - $this->unstub();
46 - // TODO: support linking?
47 - return $this->m_caption;
48 - }
49 -
50 - public function getShortHTMLText( $linker = null ) {
51 - return htmlspecialchars( $this->getShortWikiText( $linker ) );
52 - }
53 -
54 - public function getLongWikiText( $linked = null ) {
55 - // TODO: support linking?
56 - $this->unstub();
57 - return $this->getErrorText();
58 - }
59 -
60 - public function getLongHTMLText( $linker = null ) {
61 - $this->unstub();
62 - return $this->getErrorText();
63 - }
64 -
65 - public function getDBkeys() {
66 - return array( $this->getShortWikiText() ); ///TODO: really? (errors are not meant to be saved, or are they?)
67 - }
68 -
69 - public function getWikiValue() {
70 - return $this->getShortWikiText(); /// FIXME: wikivalue must not be influenced by the caption
71 - }
72 -
73 - public function isValid() {
74 - return false;
75 - }
76 -
77 -}
Index: trunk/extensions/SemanticMediaWiki/includes/SMW_DV_Temperature.php
@@ -1,160 +0,0 @@
2 -<?php
3 -/**
4 - * @file
5 - * @ingroup SMWDataValues
6 - */
7 -
8 -/**
9 - * This datavalue implements unit support for measuring temperatures. This is
10 - * mostly an example implementation of how to realise custom unit types easily.
11 - *
12 - * @author Markus Krötzsch
13 - * @ingroup SMWDataValues
14 - */
15 -class SMWTemperatureValue extends SMWNumberValue {
16 -
17 - /**
18 - * Converts the current m_value and m_unit to the main unit, if possible.
19 - * This means, it changes the fileds m_value and m_unit accordingly, and
20 - * that it stores the ID of the originally given unit in $this->m_unitin.
21 - * This should obviously not be done more than once, so it is advisable to
22 - * first check if m_unitin is non-false. Also, it should be checked if the
23 - * value is valid before trying to calculate with its contents.
24 - */
25 - protected function convertToMainUnit() {
26 - if ( $this->m_unitin !== false ) return;
27 - if ( !$this->isValid() ) { // give up, avoid calculations with non-numbers
28 - $this->m_unitin = $this->m_unit;
29 - return;
30 - }
31 -
32 - // Find current ID and covert main values to Kelvin, if possible
33 - // Note: there is no error when unknown units are used.
34 - $this->m_unitin = $this->getUnitID( $this->m_unit );
35 - switch ( $this->m_unitin ) {
36 - case 'K':
37 - $this->m_unit = 'K';
38 - break;
39 - case '°C':
40 - $this->m_unit = 'K';
41 - $this->m_value = $this->m_value + 273.15;
42 - break;
43 - case '°F':
44 - $this->m_unit = 'K';
45 - $this->m_value = ( $this->m_value - 32 ) / 1.8 + 273.15;
46 - break;
47 - case '°R':
48 - $this->m_unit = 'K';
49 - $this->m_value = ( $this->m_value ) / 1.8;
50 - break;
51 - default: // unsupported unit
52 - // create error here, assuming that our temperature units should not be augmented by unknown units
53 - smwfLoadExtensionMessages( 'SemanticMediaWiki' );
54 - $this->addError( wfMsgForContent( 'smw_unsupportedunit', $this->m_unit ) );
55 - $this->m_unit = $this->m_unitin;
56 - break;
57 - }
58 - }
59 -
60 - /**
61 - * This method creates an array of unit-value-pairs that should be
62 - * printed. Units are the keys and should be canonical unit IDs.
63 - * The result is stored in $this->m_unitvalues. Again, any class that
64 - * requires effort for doing this should first check whether the array
65 - * is already set (i.e. not false) before doing any work.
66 - * Note that the values should be plain numbers. Output formatting is done
67 - * later when needed. Also, it should be checked if the value is valid
68 - * before trying to calculate with its contents.
69 - * This method also must call or implement convertToMainUnit().
70 - */
71 - protected function makeConversionValues() {
72 - if ( $this->m_unitvalues !== false ) return;
73 - $this->convertToMainUnit();
74 - $this->m_unitvalues = array( $this->m_unit => $this->m_value );
75 - if ( $this->isValid() && ( $this->m_unit == 'K' ) ) {
76 - $this->m_unitvalues['°C'] = $this->m_value - 273.15;
77 - $this->m_unitvalues['°F'] = ( $this->m_value - 273.15 ) * 1.8 + 32;
78 - $this->m_unitvalues['°R'] = ( $this->m_value ) * 1.8;
79 - }
80 - }
81 -
82 - /**
83 - * This method is used when no user input was given to find the best
84 - * values for m_wikivalue, m_unitin, and m_caption. After conversion,
85 - * these fields will look as if they were generated from user input,
86 - * and convertToMainUnit() will have been called (if not, it would be
87 - * blocked by the presence of m_unitin).
88 - */
89 - protected function makeUserValue() {
90 - $this->convertToMainUnit();
91 -
92 - $value = false;
93 - if ( ( $this->m_unit === 'K' ) && $this->m_outformat && ( $this->m_outformat != '-' ) ) { // try given output unit (only if conversion worked)
94 - $unit = $this->getUnitID( $this->normalizeUnit( $this->m_outformat ) );
95 - $printunit = $this->m_outformat;
96 - switch ( $unit ) {
97 - case 'K':
98 - $value = $this->m_value;
99 - break; // nothing to do
100 - case '°C':
101 - $value = $this->m_value - 273.15;
102 - break;
103 - case '°F':
104 - $value = ( $this->m_value - 273.15 ) * 1.8 + 32;
105 - break;
106 - case '°R':
107 - $value = ( $this->m_value ) * 1.8;
108 - break;
109 - // default: unit not supported
110 - }
111 - }
112 - if ( $value === false ) { // finally fallback to current value
113 - $value = $this->m_value;
114 - $unit = $this->m_unit;
115 - $printunit = $unit;
116 - }
117 -
118 - $this->m_caption = smwfNumberFormat( $value );
119 - if ( $printunit != '' ) {
120 - $this->m_caption .= '&#160;' . $printunit;
121 - }
122 - $this->m_wikivalue = $this->m_caption;
123 - $this->m_unitin = $unit;
124 - }
125 -
126 -
127 -
128 - /**
129 - * Helper method to find the main representation of a certain unit.
130 - */
131 - protected function getUnitID( $unit ) {
132 - /// TODO possibly localise some of those strings
133 - switch ( $unit ) {
134 - case '': case 'K': case 'Kelvin': case 'kelvin': case 'kelvins':
135 - return 'K';
136 - // There's a dedicated Unicode character (℃, U+2103) for degrees C.
137 - // Your font may or may not display it; do not be alarmed.
138 - case '°C': case '℃': case 'Celsius': case 'centigrade':
139 - return '°C';
140 - break;
141 - case '°F': case 'Fahrenheit':
142 - return '°F';
143 - break;
144 - case '°R': case 'Rankine':
145 - return '°R';
146 - break;
147 - default: // unsupported unit
148 - return $unit;
149 - break;
150 - }
151 - }
152 -
153 - /**
154 - * Return an array of major unit strings (ids only recommended) supported by
155 - * this datavalue.
156 - */
157 - public function getUnitList() {
158 - return array( 'K', '°C', '°F', '°R' );
159 - }
160 -
161 -}
Index: trunk/extensions/SemanticMediaWiki/includes/SMW_DV_URI.php
@@ -1,283 +0,0 @@
2 -<?php
3 -/**
4 - * @file
5 - * @ingroup SMWDataValues
6 - */
7 -
8 -define( 'SMW_URI_MODE_EMAIL', 1 );
9 -define( 'SMW_URI_MODE_URI', 3 );
10 -define( 'SMW_URI_MODE_ANNOURI', 4 );
11 -define( 'SMW_URI_MODE_TEL', 5 );
12 -
13 -/**
14 - * This datavalue implements URL/URI/ANNURI/PHONE/EMAIL-Datavalues suitable for defining
15 - * the respective types of properties.
16 - *
17 - * @author Nikolas Iwan
18 - * @author Markus Krötzsch
19 - * @ingroup SMWDataValues
20 - * @bug Correctly create safe HTML and Wiki text.
21 - */
22 -class SMWURIValue extends SMWDataValue {
23 -
24 - /// Value; usually a human readable version of the URI (esp. "mailto:" might be ommitted)
25 - private $m_value = '';
26 - /// Only set if a link should be created in the wiki.
27 - private $m_url = '';
28 - /// Canonical URI for identifying the object
29 - private $m_uri = '';
30 - /// Distinguish different modes (emails, URL, ...)
31 - private $m_mode = '';
32 -
33 - public function SMWURIValue( $typeid ) {
34 - SMWDataValue::__construct( $typeid );
35 - switch ( $typeid ) {
36 - case '_ema':
37 - $this->m_mode = SMW_URI_MODE_EMAIL;
38 - break;
39 - case '_anu':
40 - $this->m_mode = SMW_URI_MODE_ANNOURI;
41 - break;
42 - case '_tel':
43 - $this->m_mode = SMW_URI_MODE_TEL;
44 - break;
45 - case '_uri': case '_url': case '__spu': default:
46 - $this->m_mode = SMW_URI_MODE_URI;
47 - break;
48 - }
49 - }
50 -
51 - protected function parseUserValue( $value ) {
52 - smwfLoadExtensionMessages( 'SemanticMediaWiki' );
53 - $value = trim( $value );
54 - $this->m_url = '';
55 - $this->m_uri = '';
56 - $this->m_value = $value;
57 - if ( $this->m_caption === false ) {
58 - $this->m_caption = $this->m_value;
59 - }
60 - if ( $value != '' ) { // do not accept empty strings
61 - switch ( $this->m_mode ) {
62 - case SMW_URI_MODE_URI: case SMW_URI_MODE_ANNOURI:
63 - $parts = explode( ':', $value, 2 ); // try to split "schema:rest"
64 - if ( count( $parts ) == 1 ) { // take "http" as default
65 - $value = 'http://' . $value;
66 - $parts[1] = $parts[0];
67 - $parts[0] = 'http';
68 - } elseif ( ( count( $parts ) < 1 ) || ( $parts[0] == '' ) || ( $parts[1] == '' ) || ( preg_match( '/[^a-zA-Z]/u', $parts[0] ) ) ) {
69 - $this->addError( wfMsgForContent( 'smw_baduri', $value ) );
70 - return true;
71 - }
72 -
73 - // check against blacklist
74 - $uri_blacklist = explode( "\n", wfMsgForContent( 'smw_uri_blacklist' ) );
75 - foreach ( $uri_blacklist as $uri ) {
76 - $uri = trim( $uri );
77 - if ( $uri == mb_substr( $value, 0, mb_strlen( $uri ) ) ) { // disallowed URI!
78 - $this->addError( wfMsgForContent( 'smw_baduri', $uri ) );
79 - return true;
80 - }
81 - }
82 - // simple check for invalid characters: ' ', '{', '}'
83 -// $check1 = "@(\}|\{| )+@u";
84 -// if (preg_match($check1, $value, $matches)) {
85 -// $this->addError(wfMsgForContent('smw_baduri', $value));
86 -// break;
87 -// }
88 -/// TODO: the remaining checks need improvement
89 -// // validate last part of URI (after #) if provided
90 -// $uri_ex = explode('#',$value);
91 -// $check2 = "@^[a-zA-Z0-9-_\%]+$@u"; ///FIXME: why only ascii symbols?
92 -// if(sizeof($uri_ex)>2 ){ // URI should only contain at most one '#'
93 -// $this->addError(wfMsgForContent('smw_baduri', $value) . 'Debug3');
94 -// break;
95 -// } elseif ( (sizeof($uri_ex) == 2) && !(preg_match($check2, $uri_ex[1])) ) {
96 -// $this->addError(wfMsgForContent('smw_baduri', $value) . 'Debug4');
97 -// break;
98 -// }
99 -// // validate protocol + domain part of URI
100 -//// $check3 = "@^([a-zA-Z]{0,6}:)[a-zA-Z0-9\.\/%]+$@"; //simple regexp for protocol+domain part of URI
101 -// $check3 = "@^([a-zA-Z]:)[a-zA-Z0-9\.\/%]+$@"; //simple regexp for protocol+domain part of URI
102 -// /// FIXME: why {0,6}?
103 -// if (!preg_match($check3, $uri_ex[0],$matches)){
104 -// $this->addError(wfMsgForContent('smw_baduri', $value) . 'Debug5');
105 -// break;
106 -// }
107 -
108 - // encode most characters, but leave special symbols as given by user:
109 - $this->m_uri = str_replace( array( '%3A', '%2F', '%23', '%40', '%3F', '%3D', '%26', '%25' ), array( ':', '/', '#', '@', '?', '=', '&', '%' ), rawurlencode( $value ) );
110 - /// NOTE: we do not support raw [ (%5D) and ] (%5E), although they are needed for ldap:// (but rarely in a wiki)
111 - /// NOTE: we do not check the validity of the use of the raw symbols -- does RFC 3986 as such care?
112 - /// NOTE: "+" gets encoded, as it is interpreted as space by most browsers when part of a URL;
113 - /// this prevents tel: from working directly, but we should have a datatype for this anyway.
114 - global $wgUrlProtocols;
115 - foreach ( $wgUrlProtocols as $prot ) { // only set URL if wiki-enabled protocol
116 - if ( ( $prot == $parts[0] . ':' ) || ( $prot == $parts[0] . '://' ) ) {
117 - $this->m_url = $this->m_uri;
118 - break;
119 - }
120 - }
121 - break;
122 - case SMW_URI_MODE_TEL:
123 - if ( substr( $value, 0, 4 ) === 'tel:' ) {
124 - $value = substr( $value, 4 );
125 - $this->m_value = $value;
126 - }
127 - $value = preg_replace( '/(?<=[0-9]) (?=[0-9])/', '\1-\2', $value );
128 - $value = str_replace( ' ', '', $value );
129 - if ( substr( $value, 0, 2 ) == '00' ) {
130 - $value = '+' . substr( $value, 2 );
131 - }
132 - $value = 'tel:' . $value;
133 - if ( ( strlen( preg_replace( '/[^0-9]/', '', $value ) ) < 6 ) ||
134 - ( preg_match( '<[-+./][-./]>', $value ) ) ||
135 - ( !SMWURIValue::isValidTelURI( $value ) ) ) { ///TODO: introduce error-message for "bad" phone number
136 - $this->addError( wfMsgForContent( 'smw_baduri', $this->m_value ) );
137 - }
138 - $this->m_uri = $value;
139 - break;
140 - case SMW_URI_MODE_EMAIL:
141 - if ( strpos( $value, 'mailto:' ) === 0 ) { // accept optional "mailto"
142 - $value = substr( $value, 7 );
143 - $this->m_value = $value;
144 - }
145 - $check = "#^([_a-zA-Z0-9-]+)((\.[_a-zA-Z0-9-]+)*)@([_a-zA-Z0-9-]+(\.[_a-zA-Z0-9-]+)*)\.([a-zA-Z]{2,6})$#u";
146 - if ( !preg_match( $check, $value ) ) {
147 - ///TODO: introduce error-message for "bad" email
148 - $this->addError( wfMsgForContent( 'smw_baduri', $value ) );
149 - break;
150 - }
151 - $this->m_url = 'mailto:' . str_replace( array( '%3A', '%2F', '%23', '%40', '%3F', '%3D', '%26', '%25' ), array( ':', '/', '#', '@', '?', '=', '&', '%' ), rawurlencode( $value ) );
152 - $this->m_uri = $this->m_url;
153 - }
154 - } else {
155 - $this->addError( wfMsgForContent( 'smw_emptystring' ) );
156 - }
157 -
158 - return true;
159 - }
160 -
161 - /**
162 - * Returns true if the argument is a valid RFC 3966 phone number.
163 - * Only global phone numbers are supported, and no full validation
164 - * of parameters (appended via ;param=value) is performed.
165 - */
166 - protected static function isValidTelURI( $s ) {
167 - $tel_uri_regex = '<^tel:\+[0-9./-]*[0-9][0-9./-]*(;[0-9a-zA-Z-]+=(%[0-9a-zA-Z][0-9a-zA-Z]|[0-9a-zA-Z._~:/?#[\]@!$&\'()*+,;=-])*)*$>';
168 - return (bool) preg_match( $tel_uri_regex, $s );
169 - }
170 -
171 -
172 - protected function parseDBkeys( $args ) {
173 - $this->m_uri = $args[0];
174 - $this->m_value = $this->m_uri;
175 - $this->m_caption = $this->m_value;
176 - if ( $this->m_mode == SMW_URI_MODE_EMAIL ) {
177 - $this->m_url = $this->m_value;
178 - if ( strpos( $this->m_uri, 'mailto:' ) === 0 ) { // catch inconsistencies in DB, should usually be the case
179 - $this->m_caption = substr( $this->m_value, 7 );
180 - $this->m_value = $this->m_caption;
181 - } else { // this case is only for backwards compatibility/repair; may vanish at some point
182 - $this->m_uri = 'mailto:' . $this->m_value;
183 - $this->m_url = $this->m_uri;
184 - }
185 - } elseif ( $this->m_mode == SMW_URI_MODE_TEL ) {
186 - $this->m_url = '';
187 - if ( strpos( $this->m_uri, 'tel:' ) === 0 ) { // catch inconsistencies in DB, should usually be the case
188 - $this->m_caption = substr( $this->m_value, 4 );
189 - $this->m_value = $this->m_caption;
190 - }
191 - } else {
192 - $parts = explode( ':', $this->m_uri, 2 ); // try to split "schema:rest"
193 - global $wgUrlProtocols;
194 - $this->m_url = '';
195 - foreach ( $wgUrlProtocols as $prot ) { // only set URL if wiki-enabled protocol
196 - if ( ( $prot == $parts[0] . ':' ) || ( $prot == $parts[0] . '://' ) ) {
197 - $this->m_url = $this->m_uri;
198 - break;
199 - }
200 - }
201 - }
202 - }
203 -
204 - public function getShortWikiText( $linked = null ) {
205 - $this->unstub();
206 - if ( ( $linked === null ) || ( $linked === false ) || ( $this->m_outformat == '-' ) || ( $this->m_url == '' ) || ( $this->m_caption == '' ) ) {
207 - return $this->m_caption;
208 - } else {
209 - return '[' . $this->m_url . ' ' . $this->m_caption . ']';
210 - }
211 - }
212 -
213 - public function getShortHTMLText( $linker = null ) {
214 - $this->unstub();
215 - if ( ( $linker === null ) || ( !$this->isValid() ) || ( $this->m_outformat == '-' ) || ( $this->m_url == '' ) || ( $this->m_caption == '' ) ) {
216 - return $this->m_caption;
217 - } else {
218 - return $linker->makeExternalLink( $this->m_url, $this->m_caption );
219 - }
220 - }
221 -
222 - public function getLongWikiText( $linked = null ) {
223 - if ( !$this->isValid() ) {
224 - return $this->getErrorText();
225 - }
226 - if ( ( $linked === null ) || ( $linked === false ) || ( $this->m_outformat == '-' ) || ( $this->m_url == '' ) ) {
227 - return $this->m_value;
228 - } else {
229 - return '[' . $this->m_url . ' ' . $this->m_value . ']';
230 - }
231 - }
232 -
233 - public function getLongHTMLText( $linker = null ) {
234 - if ( !$this->isValid() ) {
235 - return $this->getErrorText();
236 - }
237 - if ( ( $linker === null ) || ( $this->m_outformat == '-' ) || ( $this->m_url == '' ) ) {
238 - return htmlspecialchars( $this->m_value );
239 - } else {
240 - return $linker->makeExternalLink( $this->m_url, $this->m_value );
241 - }
242 - }
243 -
244 - public function getDBkeys() {
245 - $this->unstub();
246 - return array( $this->m_uri );
247 - }
248 -
249 - public function getSignature() {
250 - return 't';
251 - }
252 -
253 - public function getValueIndex() {
254 - return 0;
255 - }
256 -
257 - public function getLabelIndex() {
258 - return 0;
259 - }
260 -
261 - public function getWikiValue() {
262 - $this->unstub();
263 - return $this->m_value;
264 - }
265 -
266 - protected function getServiceLinkParams() {
267 - $this->unstub();
268 - // Create links to mapping services based on a wiki-editable message. The parameters
269 - // available to the message are:
270 - // $1: urlencoded version of URI/URL value (includes mailto: for emails)
271 - return array( rawurlencode( $this->m_uri ) );
272 - }
273 -
274 - public function getExportData() {
275 - if ( $this->isValid() ) {
276 - $res = new SMWExpResource( str_replace( '&', '&amp;', $this->m_uri ), $this );
277 - return new SMWExpData( $res );
278 - } else {
279 - return null;
280 - }
281 - }
282 -
283 -}
284 -
Index: trunk/extensions/SemanticMediaWiki/includes/SMW_DV_String.php
@@ -1,162 +0,0 @@
2 -<?php
3 -/**
4 - * @file
5 - * @ingroup SMWDataValues
6 - */
7 -
8 -/**
9 - * This datavalue implements String-Datavalues suitable for defining
10 - * String-types of properties.
11 - *
12 - * @author Nikolas Iwan
13 - * @author Markus Krötzsch
14 - * @ingroup SMWDataValues
15 - */
16 -class SMWStringValue extends SMWDataValue {
17 -
18 - /// Wiki-compatible value representation, possibly unsafe for plain HTML.
19 - protected $m_value = '';
20 -
21 - protected function parseUserValue( $value ) {
22 - smwfLoadExtensionMessages( 'SemanticMediaWiki' );
23 - if ( $value != '' ) {
24 - $this->m_value = $value;
25 - if ( ( $this->m_typeid != '_txt' ) && ( $this->m_typeid != '_cod' ) && ( strlen( $this->m_value ) > 255 ) ) { // limit size (for DB indexing)
26 - $this->addError( wfMsgForContent( 'smw_maxstring', mb_substr( $value, 0, 42 ) . ' <span class="smwwarning">[…]</span> ' . mb_substr( $value, mb_strlen( $this->m_value ) - 42 ) ) );
27 - }
28 - } else {
29 - $this->addError( wfMsgForContent( 'smw_emptystring' ) );
30 - }
31 - if ( $this->m_caption === false ) {
32 - $this->m_caption = ( $this->m_typeid == '_cod' ) ? $this->getCodeDisplay( $value ):$value;
33 - }
34 - return true;
35 - }
36 -
37 - protected function parseDBkeys( $args ) {
38 - $this->parseUserValue( $args[0] );
39 - $this->m_caption = $this->m_value; // this is our output text
40 - }
41 -
42 - public function getShortWikiText( $linked = null ) {
43 - $this->unstub();
44 - // TODO: Support linking?
45 - return $this->m_caption;
46 - }
47 -
48 - /**
49 - * @todo Rather parse input to obtain properly formatted HTML.
50 - */
51 - public function getShortHTMLText( $linker = null ) {
52 - return smwfXMLContentEncode( $this->getShortWikiText( $linker ) );
53 - }
54 -
55 - public function getLongWikiText( $linked = null ) {
56 - return $this->isValid() ? $this->getAbbValue( $linked, $this->m_value ):$this->getErrorText();
57 - }
58 -
59 - /**
60 - * @todo Rather parse input to obtain properly formatted HTML.
61 - */
62 - public function getLongHTMLText( $linker = null ) {
63 - return $this->isValid() ? $this->getAbbValue( $linker, smwfXMLContentEncode( $this->m_value ) ):$this->getErrorText();
64 - }
65 -
66 - public function getDBkeys() {
67 - $this->unstub();
68 - return array( $this->m_value );
69 - }
70 -
71 - public function getSignature() {
72 - return ( ( $this->m_typeid == '_txt' ) || ( $this->m_typeid == '_cod' ) ) ? 'l':'t';
73 - }
74 -
75 - /**
76 - * For perfomance reasons, long text data like _txt and _cod does not
77 - * support sorting. This class can be subclassed to change this.
78 - */
79 - public function getValueIndex() {
80 - return ( $this->m_typeid == '_txt' || $this->m_typeid == '_cod' ) ? - 1 : 0;
81 - }
82 -
83 - /**
84 - * For perfomance reasons, long text data like _txt and _cod does not
85 - * support string matching. This class can be subclassed to change this.
86 - */
87 - public function getLabelIndex() {
88 - return ( $this->m_typeid == '_txt' || $this->m_typeid == '_cod' ) ? - 1 : 0;
89 - }
90 -
91 - public function getWikiValue() {
92 - $this->unstub();
93 - return $this->m_value;
94 - }
95 -
96 - public function getInfolinks() {
97 - $this->unstub();
98 - if ( ( $this->m_typeid != '_txt' ) && ( $this->m_typeid != '_cod' ) ) {
99 - return SMWDataValue::getInfolinks();
100 - } else {
101 - return $this->m_infolinks;
102 - }
103 - }
104 -
105 - protected function getServiceLinkParams() {
106 - $this->unstub();
107 - // Create links to mapping services based on a wiki-editable message. The parameters
108 - // available to the message are:
109 - // $1: urlencoded string
110 - if ( ( $this->m_typeid != '_txt' ) && ( $this->m_typeid != '_cod' ) ) {
111 - return array( rawurlencode( $this->m_value ) );
112 - } else {
113 - return false; // no services for Type:Text and Type:Code
114 - }
115 - }
116 -
117 - public function getExportData() {
118 - if ( $this->isValid() ) {
119 - $lit = new SMWExpLiteral( smwfHTMLtoUTF8( $this->m_value ), $this, 'http://www.w3.org/2001/XMLSchema#string' );
120 - return new SMWExpData( $lit );
121 - } else {
122 - return null;
123 - }
124 - }
125 -
126 - /**
127 - * Make a possibly shortened printout string for displaying the value.
128 - * The value must be specified as an input since necessary HTML escaping
129 - * must be applied to it first, if desired. The result of getAbbValue()
130 - * may contain wiki-compatible HTML mark-up that should not be escaped.
131 - * @todo The method abbreviates very long strings for display by simply
132 - * taking substrings. This is not in all cases a good idea, since it may
133 - * break XML entities and mark-up.
134 - */
135 - protected function getAbbValue( $linked, $value ) {
136 - $len = mb_strlen( $value );
137 - if ( ( $len > 255 ) && ( $this->m_typeid != '_cod' ) ) {
138 - if ( ( $linked === null ) || ( $linked === false ) ) {
139 - return mb_substr( $value, 0, 42 ) . ' <span class="smwwarning">…</span> ' . mb_substr( $value, $len - 42 );
140 - } else {
141 - SMWOutputs::requireHeadItem( SMW_HEADER_TOOLTIP );
142 - return mb_substr( $value, 0, 42 ) . ' <span class="smwttpersist"> … <span class="smwttcontent">' . $value . '</span></span> ' . mb_substr( $value, $len - 42 );
143 - }
144 - } elseif ( $this->m_typeid == '_cod' ) {
145 - return $this->getCodeDisplay( $value, true );
146 - } else {
147 - return $value;
148 - }
149 - }
150 -
151 - /**
152 - * Special features for Type:Code formatting.
153 - */
154 - protected function getCodeDisplay( $value, $scroll = false ) {
155 - SMWOutputs::requireHeadItem( SMW_HEADER_STYLE );
156 - $result = str_replace( array( '<', '>', ' ', '=', "'", ':', "\n" ), array( '&lt;', '&gt;', '&#160;', '&#x003D;', '&#x0027;', '&#58;', "<br />" ), $value );
157 - if ( $scroll ) {
158 - $result = "<div style=\"height:5em; overflow:auto;\">$result</div>";
159 - }
160 - return "<div class=\"smwpre\">$result</div>";
161 - }
162 -
163 -}
Index: trunk/extensions/SemanticMediaWiki/includes/SMW_DV_SimpleWikiPage.php
@@ -1,51 +0,0 @@
2 -<?php
3 -/**
4 - * @file
5 - * @ingroup SMWDataValues
6 - */
7 -
8 -/**
9 - * This datavalue is similiar to SMWWikiPageValue in that it represents pages
10 - * in the wiki. However, it is tailored for uses where it is enough to store
11 - * the title string of the page without namespace, interwiki prefix, or
12 - * sortkey. This is useful for "special" properties like "Has type" where the
13 - * namespace is fixed, and which do not need any of the other settings. The
14 - * advantage of the reduction of data is that these important values can be
15 - * stored in smaller tables that allow for faster direct access than general
16 - * page type values.
17 - *
18 - * @author Markus Krötzsch
19 - * @ingroup SMWDataValues
20 - */
21 -class SMWSimpleWikiPageValue extends SMWWikiPageValue {
22 -
23 - protected function parseDBkeys( $args ) {
24 - $this->m_dbkeyform = $args[0];
25 - $this->m_namespace = $this->m_fixNamespace;
26 - $this->m_interwiki = '';
27 - $this->m_sortkey = $this->m_dbkeyform;
28 - $this->m_textform = str_replace( '_', ' ', $this->m_dbkeyform );
29 - $this->m_id = false;
30 - $this->m_title = null;
31 - $this->m_prefixedtext = false;
32 - $this->m_caption = false;
33 - }
34 -
35 - public function getDBkeys() {
36 - $this->unstub();
37 - return array( $this->m_dbkeyform );
38 - }
39 -
40 - public function getSignature() {
41 - return 't';
42 - }
43 -
44 - public function getValueIndex() {
45 - return 1;
46 - }
47 -
48 - public function getLabelIndex() {
49 - return 1;
50 - }
51 -
52 -}
\ No newline at end of file
Index: trunk/extensions/SemanticMediaWiki/includes/SMW_DV_Import.php
@@ -1,191 +0,0 @@
2 -<?php
3 -/**
4 - * @file
5 - * @ingroup SMWDataValues
6 - */
7 -
8 -/**
9 - * This datavalue implements datavalues used by special property '_IMPO' used for assigning
10 - * imported vocabulary to some page of the wiki.
11 - * It looks up a MediaWiki message to find out whether a user-supplied vocabulary name
12 - * can be imported in the wiki, and whether its declaration is correct (to the extend
13 - * that this can be checked).
14 - *
15 - * @author Fabian Howahl
16 - * @author Markus Krötzsch
17 - * @ingroup SMWDataValues
18 - */
19 -class SMWImportValue extends SMWDataValue {
20 -
21 - protected $m_value = ''; // stores string provided by user which is used to look up data on Mediawiki:*-Page
22 - protected $m_uri = ''; // URI of namespace (without local name)
23 - protected $m_namespace = ''; // namespace id (e.g. "foaf")
24 - protected $m_section = ''; // stores local name (e.g. "knows")
25 - protected $m_name = ''; // stores wiki name of the vocab (e.g. "Friend of a Friend")
26 - protected $m_wikilink = ''; // store string to be displayed in factbox
27 -
28 - protected function parseUserValue( $value ) {
29 - global $wgContLang;
30 -
31 - $this->m_value = $value;
32 - list( $onto_ns, $onto_section ) = explode( ':', $value, 2 );
33 -
34 - $msglines = preg_split( "([\n][\s]?)", wfMsgForContent( "smw_import_$onto_ns" ) ); // get the definition for "$namespace:$section"
35 -
36 - if ( count( $msglines ) < 2 ) { // error: no elements for this namespace
37 - $this->addError( wfMsgForContent( 'smw_unknown_importns', $onto_ns ) );
38 - return true;
39 - }
40 -
41 - // browse list in smw_import_* for section
42 - list( $onto_uri, $onto_name ) = explode( '|', array_shift( $msglines ), 2 );
43 -
44 - if ( $onto_uri[0] == ' ' ) $onto_uri = mb_substr( $onto_uri, 1 ); // tolerate initial space
45 -
46 - $this->m_uri = $onto_uri;
47 - $this->m_namespace = $onto_ns;
48 - $this->m_section = $onto_section;
49 - $this->m_name = $onto_name;
50 -
51 - $elemtype = - 1;
52 - foreach ( $msglines as $msgline ) {
53 - list( $secname, $typestring ) = explode( '|', $msgline, 2 );
54 - if ( $secname === $onto_section ) {
55 - list( $namespace, ) = explode( ':', $typestring, 2 );
56 - // check whether type matches
57 - switch ( $namespace ) {
58 - case $wgContLang->getNsText( SMW_NS_TYPE ):
59 - $elemtype = SMW_NS_PROPERTY;
60 - break;
61 - case $wgContLang->getNsText( SMW_NS_PROPERTY ):
62 - $elemtype = SMW_NS_PROPERTY;
63 - break;
64 - case $wgContLang->getNsText( NS_CATEGORY ):
65 - $elemtype = NS_CATEGORY;
66 - break;
67 - case $wgContLang->getNsText( SMW_NS_CONCEPT ):
68 - $elemtype = NS_CATEGORY;
69 - break;
70 - default: // match all other namespaces
71 - $elemtype = NS_MAIN;
72 - }
73 - break;
74 - }
75 - }
76 -
77 - // check whether element of correct type was found (extracts data from factbox)
78 - ///TODO: parser needed to do that
79 -// if(SMWParseData::getSMWData($parser) instanceof SMWSemanticData) {
80 -// $this_ns = SMWParseData::getSMWData($parser)->getSubject()->getNamespace();
81 -// $error = null;
82 -// switch ($elemtype) {
83 -// case SMW_NS_PROPERTY: case NS_CATEGORY:
84 -// if ($this_ns != $elemtype) {
85 -// $error = wfMsgForContent('smw_nonright_importtype',$value, $wgContLang->getNsText($elemtype));
86 -// }
87 -// break;
88 -// case NS_MAIN:
89 -// if ( (SMW_NS_PROPERTY == $this_ns) || (NS_CATEGORY == $this_ns)) {
90 -// $error = wfMsgForContent('smw_wrong_importtype',$value, $wgContLang->getNsText($this_ns));
91 -// }
92 -// break;
93 -// case -1:
94 -// $error = wfMsgForContent('smw_no_importelement',$value);
95 -// }
96 -//
97 -// if (null != $error) {
98 -// $this->addError($error);
99 -// return true;
100 -// }
101 -// }
102 -
103 - // create String to be returned by getShort/LongWikiText
104 - $this->m_wikilink = "[" . $this->m_uri . " " . $this->m_value . "] (" . $this->m_name . ")";
105 -
106 - // check whether caption is set, otherwise assign link statement to caption
107 - if ( $this->m_caption === false ) {
108 - $this->m_caption = $this->m_wikilink;
109 - }
110 -
111 - return true;
112 - }
113 -
114 - protected function parseDBkeys( $args ) {
115 - $parts = explode( ' ', $args[0], 3 );
116 - if ( array_key_exists( 0, $parts ) ) {
117 - $this->m_namespace = $parts[0];
118 - }
119 - if ( array_key_exists( 1, $parts ) ) {
120 - $this->m_section = $parts[1];
121 - }
122 - if ( array_key_exists( 2, $parts ) ) {
123 - $this->m_uri = $parts[2];
124 - }
125 - $this->m_value = $this->m_namespace . ':' . $this->m_section;
126 - $this->m_caption = $this->m_value; // not as pretty as on input, don't care
127 - $this->m_wikilink = $this->m_value; // not as pretty as on input, don't care
128 - }
129 -
130 - public function getShortWikiText( $linked = null ) {
131 - $this->unstub();
132 - return $this->m_caption;
133 - }
134 -
135 - public function getShortHTMLText( $linker = null ) {
136 - $this->unstub();
137 - return htmlspecialchars( $this->m_value );
138 - }
139 -
140 - public function getLongWikiText( $linked = null ) {
141 - if ( !$this->isValid() ) {
142 - return $this->getErrorText();
143 - } else {
144 - return $this->m_wikilink;
145 - }
146 - }
147 -
148 - public function getLongHTMLText( $linker = null ) {
149 - if ( !$this->isValid() ) {
150 - return $this->getErrorText();
151 - } else {
152 - return htmlspecialchars( $this->m_value );
153 - }
154 - }
155 -
156 - public function getDBkeys() {
157 - $this->unstub();
158 - return array( $this->m_namespace . ' ' . $this->m_section . ' ' . $this->m_uri );
159 - }
160 -
161 - public function getSignature() {
162 - return 't';
163 - }
164 -
165 - public function getValueIndex() {
166 - return 0;
167 - }
168 -
169 - public function getLabelIndex() {
170 - return 0;
171 - }
172 -
173 - public function getWikiValue() {
174 - $this->unstub();
175 - return $this->m_value;
176 - }
177 -
178 - public function getNS() {
179 - $this->unstub();
180 - return $this->m_uri;
181 - }
182 -
183 - public function getNSID() {
184 - $this->unstub();
185 - return $this->m_namespace;
186 - }
187 -
188 - public function getLocalName() {
189 - $this->unstub();
190 - return $this->m_section;
191 - }
192 -}
Index: trunk/extensions/SemanticMediaWiki/includes/SMW_DV_TypeList.php
@@ -1,119 +0,0 @@
2 -<?php
3 -/**
4 - * @file
5 - * @ingroup SMWDataValues
6 - */
7 -
8 -/**
9 - * This datavalue implements special processing suitable for defining the list
10 - * of types that is required for SMWRecordValue objects. The input is a plain
11 - * semicolon-separated list of type labels.
12 - *
13 - * @author Markus Krötzsch
14 - * @ingroup SMWDataValues
15 - */
16 -class SMWTypeListValue extends SMWDataValue {
17 -
18 - private $m_typevalues = false;
19 -
20 - protected function parseUserValue( $value ) {
21 - $this->m_typevalues = array();
22 - $types = explode( ';', $value );
23 - foreach ( $types as $type ) {
24 - $tval = SMWDataValueFactory::newTypeIDValue( '__typ', $type );
25 - $this->m_typevalues[] = $tval;
26 - }
27 - }
28 -
29 - protected function parseDBkeys( $args ) {
30 - $this->m_typevalues = array();
31 - $ids = explode( ';', $args[0] );
32 - foreach ( $ids as $id ) {
33 - $this->m_typevalues[] = SMWDataValueFactory::newTypeIDValue( '__typ', SMWDataValueFactory::findTypeLabel( $id ) );
34 - }
35 - }
36 -
37 - /**
38 - * The special feature of this implementation of getDBkeys is that it uses
39 - * internal type ids to obtain a short internal value for the type. Note
40 - * that this also given language independence but that this is of little
41 - * use: if the value is given in another language in the wiki, then either
42 - * the value is still understood, or the language-independent database
43 - * entry is only of temporary use until someine edits the respective page.
44 - */
45 - public function getDBkeys() {
46 - if ( $this->isvalid() ) {
47 - $result = '';
48 - foreach ( $this->m_typevalues as $tv ) {
49 - if ( $result != '' ) $result .= ';';
50 - $result .= $tv->getDBkey();
51 - }
52 - return array( $result );
53 - } else {
54 - return array( false );
55 - }
56 - }
57 -
58 - public function getSignature() {
59 - return 't';
60 - }
61 -
62 - public function getValueIndex() {
63 - return 0;
64 - }
65 -
66 - public function getLabelIndex() {
67 - return 0;
68 - }
69 -
70 - public function getShortWikiText( $linked = null ) {
71 - return ( $this->m_caption !== false ) ? $this->m_caption : $this->makeOutputText( 0, $linked );
72 - }
73 -
74 - public function getShortHTMLText( $linker = null ) {
75 - return ( $this->m_caption !== false ) ? $this->m_caption : $this->makeOutputText( 1, $linker );
76 - }
77 -
78 - public function getLongWikiText( $linked = null ) {
79 - return $this->makeOutputText( 2, $linked );
80 - }
81 -
82 - public function getLongHTMLText( $linker = null ) {
83 - return $this->makeOutputText( 3, $linker );
84 - }
85 -
86 - public function getWikiValue() {
87 - return $this->makeOutputText( 4 );
88 - }
89 -
90 - public function getTypeValues() {
91 - $this->unstub();
92 - return $this->m_typevalues;
93 - }
94 -
95 -////// Internal helper functions
96 -
97 - private function makeOutputText( $type = 0, $linker = null ) {
98 - if ( !$this->isValid() ) {
99 - return ( ( $type == 0 ) || ( $type == 1 ) ) ? '' : $this->getErrorText();
100 - }
101 - $result = '';
102 - $sep = ( $type == 4 ) ? '; ' : ', ';
103 - foreach ( $this->m_typevalues as $tv ) {
104 - if ( $result != '' ) $result .= $sep;
105 - $result .= $this->makeValueOutputText( $type, $tv, $linker );
106 - }
107 - return $result;
108 - }
109 -
110 - private function makeValueOutputText( $type, $datavalue, $linker ) {
111 - switch ( $type ) {
112 - case 0: return $datavalue->getShortWikiText( $linker );
113 - case 1: return $datavalue->getShortHTMLText( $linker );
114 - case 2: return $datavalue->getLongWikiText( $linker );
115 - case 3: return $datavalue->getLongHTMLText( $linker );
116 - case 4: return $datavalue->getWikiValue();
117 - }
118 - }
119 -
120 -}
\ No newline at end of file
Index: trunk/extensions/SemanticMediaWiki/includes/SMW_DV_Container.php
@@ -1,105 +0,0 @@
2 -<?php
3 -/**
4 - * @file
5 - * @ingroup SMWDataValues
6 - */
7 -
8 -/**
9 - * Abstract datavalue class to implement a generic container for
10 - * complex values (internal objects) that do not have a single
11 - * value but a set of nested property-value pairs.
12 - *
13 - * @author Markus Krötzsch
14 - * @ingroup SMWDataValues
15 - */
16 -abstract class SMWContainerValue extends SMWDataValue {
17 -
18 - protected $m_data;
19 -
20 - public function __construct( $typeid ) {
21 - parent::__construct( $typeid );
22 - $this->m_data = new SMWSemanticData( null );
23 - }
24 -
25 - /**
26 - * We use the internal SMWSemanticData object to store some of this objects
27 - * data. Clone it to make sure that data can be modified independelty from
28 - * the original object's content.
29 - */
30 - public function __clone() {
31 - $this->m_data = clone $this->m_data; // note that this is always set
32 - }
33 -
34 - /**
35 - * Containers have one DB key, so the value of this function should be an array with one
36 - * element. This one DB key should consist of an array of arbitrary length where each
37 - * entry encodes one property-value pair. The pairs are encoded as arrays of size two
38 - * that correspond to the input arguments of SMWSemanticData::addPropertyStubValue():
39 - * a property DB key (string), and a value DB key array (array).
40 - */
41 - protected function parseDBkeys( $args ) {
42 - $this->m_data->clear();
43 - if ( count( $args ) > 0 ) {
44 - foreach ( reset( $args ) as $value ) {
45 - if ( is_array( $value ) && ( count( $value ) == 2 ) ) {
46 - $this->m_data->addPropertyStubValue( reset( $value ), end( $value ) );
47 - }
48 - }
49 - }
50 - }
51 -
52 - /**
53 - * Serialize data in the format described for parseDBkeys(). However, it is usually
54 - * expected that callers are aware of containers (this is the main purpose of this
55 - * abstract class) so they can use specific methods for accessing the data in a more
56 - * convenient form that contains the (probably available) information about property
57 - * and data *objects* (not just their plain strings).
58 - */
59 - public function getDBkeys() {
60 - $data = array();
61 - foreach ( $this->m_data->getProperties() as $property ) {
62 - foreach ( $this->m_data->getPropertyValues( $property ) as $dv ) {
63 - $data[] = array( $property->getDBkey(), $dv->getDBkeys() );
64 - }
65 - }
66 - return array( $data );
67 - }
68 -
69 - public function getSignature() {
70 - return 'c';
71 - }
72 -
73 - public function getValueIndex() {
74 - return -1;
75 - }
76 -
77 - public function getLabelIndex() {
78 - return -1;
79 - }
80 -
81 - public function getHash() {
82 - if ( $this->isValid() ) {
83 - return $this->m_data->getHash();
84 - } else {
85 - return implode( "\t", $this->getErrors() );
86 - }
87 - }
88 -
89 - // Methods for parsing, serialisation, and display are not defined in this abstract class:
90 - // public function getShortWikiText($linked = null);
91 - // public function getShortHTMLText($linker = null);
92 - // public function getLongWikiText($linked = null);
93 - // public function getLongHTMLText($linker = null);
94 - // protected function parseUserValue($value);
95 - // public function getWikiValue();
96 -
97 - /**
98 - * Return the stored data as a SMWSemanticData object. This is more conveniently to access than
99 - * what getDBkeys() gives, but intended only for reading. It may not be safe to write to the returned
100 - * object.
101 - */
102 - public function getData() {
103 - return $this->m_data;
104 - }
105 -
106 -}
Index: trunk/extensions/SemanticMediaWiki/includes/SMW_DV_Property.php
@@ -1,471 +0,0 @@
2 -<?php
3 -/**
4 - * File holding class SMWPropertyValue.
5 - *
6 - * @author Markus Krötzsch
7 - *
8 - * @file
9 - * @ingroup SMWDataValues
10 - */
11 -
12 -/**
13 - * Objects of this class represent properties in SMW.
14 - *
15 - * This class represents both normal (user-defined) properties and
16 - * predefined ("special") properties. Predefined properties may still
17 - * have a standard label (and associated wiki article) and they will
18 - * behave just like user-defined properties in most cases (e.g. when
19 - * asking for a printout text, a link to the according page is produced).
20 - * It is possible that predefined properties have no visible label at all,
21 - * if they are used only internally and never specified by or shown to
22 - * the user. Those will use their internal ID as DB key, and
23 - * empty texts for most printouts. All other proeprties use their
24 - * canonical DB key (even if they are predefined and have an id).
25 - * Functions are provided to check whether a property is visible or
26 - * user-defined, and to get the internal ID, if any.
27 - *
28 - * @note This datavalue is used only for representing properties and,
29 - * possibly objects/values, but never for subjects (pages as such). Hence
30 - * it does not provide a complete Title-like interface, or support for
31 - * things like sortkey.
32 - *
33 - * @author Markus Krötzsch
34 - * @ingroup SMWDataValues
35 - */
36 -class SMWPropertyValue extends SMWDataValue {
37 -
38 - /** Array for assigning types to predefined properties. Each
39 - * property is associated with an array with the following
40 - * elements:
41 - *
42 - * * ID of datatype to be used for this property
43 - *
44 - * * Boolean, stating if this property is shown in Factbox, Browse, and similar interfaces;
45 - * (note that this is only relevant if the property can be displayed at all, i.e. has an
46 - * translated label in the given language; we still set invisible properties to false here)
47 - */
48 - static private $mPropertyTypes;
49 - static private $mPropertyLabels;
50 - static private $mPropertyAliases;
51 -
52 - /// If the property is predefined, its internal key is stored here. Otherwise FALSE.
53 - protected $m_propertyid;
54 - /// If the property is associated with a wikipage, it is stored here. Otherwise NULL.
55 - protected $m_wikipage = null;
56 - /// Store if this property is an inverse
57 - protected $m_inv = false;
58 -
59 - /**
60 - * Remember the type value of this property once it has been calculated.
61 - * @var unknown_type
62 - */
63 - private $mPropTypeValue;
64 -
65 - /**
66 - * Remember the type id of this property once it has been calculated.
67 - * @var unknown_type
68 - */
69 - private $mPropTypeId;
70 -
71 - /**
72 - * Static function for creating a new property object from a
73 - * propertyname (string) as a user might enter it.
74 - * @note The resulting property object might be invalid if
75 - * the provided name is not allowed. An object is returned
76 - * in any case.
77 - *
78 - * @param string $propertyName
79 - *
80 - * @return SMWPropertyValue
81 - */
82 - static public function makeUserProperty( $propertyName ) {
83 - $property = new SMWPropertyValue( '__pro' );
84 - $property->setUserValue( $propertyName );
85 - return $property;
86 - }
87 -
88 - /**
89 - * Static function for creating a new property object from a
90 - * property identifier (string) as it might be used internally.
91 - * This might be the DB-key version of some property title
92 - * text or the id of a predefined property (such as '_TYPE').
93 - * @note The resulting property object might be invalid if
94 - * the provided name is not allowed. An object is returned
95 - * in any case.
96 - */
97 - static public function makeProperty( $propertyid ) {
98 - $property = new SMWPropertyValue( '__pro' );
99 - $property->setDBkeys( array( $propertyid ) );
100 - return $property;
101 - }
102 -
103 - /**
104 - * We use the internal wikipage object to store some of this objects data.
105 - * Clone it to make sure that data can be modified independelty from the
106 - * original object's content.
107 - */
108 - public function __clone() {
109 - if ( $this->m_wikipage !== null ) $this->m_wikipage = clone $this->m_wikipage;
110 - }
111 -
112 - /**
113 - * Extended parsing function to first check whether value refers to pre-defined
114 - * property, resolve aliases, and set internal property id accordingly.
115 - * @todo Accept/enforce property namespace.
116 - */
117 - protected function parseUserValue( $value ) {
118 - $this->mPropTypeValue = null;
119 - $this->mPropTypeId = null;
120 - $this->m_inv = false;
121 - if ( $this->m_caption === false ) { // always use this as caption
122 - $this->m_caption = $value;
123 - }
124 - $value = smwfNormalTitleText( ltrim( rtrim( $value, ' ]' ), ' [' ) ); // slightly normalise label
125 - if ( ( $value !== '' ) && ( $value { 0 } == '-' ) ) { // check if this property refers to an inverse
126 - $value = substr( $value, 1 );
127 - $this->m_inv = true;
128 - }
129 - $this->m_propertyid = SMWPropertyValue::findPropertyID( $value );
130 - if ( $this->m_propertyid !== false ) {
131 - $value = SMWPropertyValue::findPropertyLabel( $this->m_propertyid );
132 - }
133 - if ( $value !== false ) {
134 - $this->m_wikipage = SMWDataValueFactory::newTypeIDValue( '_wpp' );
135 - $this->m_wikipage->setUserValue( $value, $this->m_caption );
136 - $this->addError( $this->m_wikipage->getErrors() );
137 - } else { // should rarely happen ($value is only changed if the input $value really was a label for a predefined prop)
138 - $this->m_wikipage = null;
139 - }
140 - }
141 -
142 - /**
143 - * Extended parsing function to first check whether value is the id of a
144 - * pre-defined property, to resolve property names and aliases, and to set
145 - * internal property id accordingly.
146 - */
147 - protected function parseDBkeys( $args ) {
148 - $this->mPropTypeValue = null;
149 - $this->mPropTypeId = null;
150 - $this->m_inv = false;
151 - if ( $args[0] { 0 } == '-' ) { // check if this property refers to an inverse
152 - $args[0] = substr( $args[0], 1 );
153 - $this->m_inv = true;
154 - }
155 - SMWPropertyValue::initProperties();
156 - if ( $args[0] { 0 } == '_' ) { // internal id, use as is (and hope it is still known)
157 - $this->m_propertyid = $args[0];
158 - } else { // possibly name of special property
159 - $this->m_propertyid = SMWPropertyValue::findPropertyID( str_replace( '_', ' ', $args[0] ) );
160 - }
161 - $label = ( $this->m_propertyid !== false ) ? SMWPropertyValue::findPropertyLabel( $this->m_propertyid ):$args[0];
162 - if ( $label != '' ) {
163 - $this->m_wikipage = SMWDataValueFactory::newTypeIDValue( '_wpp' );
164 - $this->m_wikipage->setDBkeys( array( str_replace( ' ', '_', $label ), SMW_NS_PROPERTY, '', '' ) );
165 - $this->m_wikipage->setOutputFormat( $this->m_outformat );
166 - $this->m_caption = $label;
167 - $this->addError( $this->m_wikipage->getErrors() ); // NOTE: this unstubs the wikipage, should we rather ignore errors here to prevent this?
168 - } else { // predefined property without label
169 - $this->m_wikipage = null;
170 - $this->m_caption = $this->m_propertyid;
171 - }
172 - }
173 -
174 - public function setCaption( $caption ) {
175 - parent::setCaption( $caption );
176 - if ( $this->m_wikipage instanceof SMWDataValue ) { // pass caption to embedded datavalue (used for printout)
177 - $this->m_wikipage->setCaption( $caption );
178 - }
179 - }
180 -
181 -
182 - public function setInverse( $isinverse ) {
183 - $this->unstub(); // make sure later unstubbing does not overwrite this
184 - return $this->m_inv = ( $isinverse == true );
185 - }
186 -
187 - /**
188 - * Return TRUE if this is a usual wiki property that is defined by a wiki page, as
189 - * opposed to a property that is pre-defined in the wiki.
190 - */
191 - public function isUserDefined() {
192 - $this->unstub();
193 - return ( $this->m_propertyid == '' );
194 - }
195 -
196 - /**
197 - * Return TRUE if this is a property that can be displayed, and not a pre-defined
198 - * property that is used only internally and does not even have a user-readable name.
199 - * @note Every user defined property is necessarily visible.
200 - */
201 - public function isVisible() {
202 - $this->unstub();
203 - return ( $this->m_wikipage !== null );
204 - }
205 -
206 - /**
207 - * Specifies whether values of this property should be shown in typical
208 - * browsing interfaces. A property may wish to prevent this if either
209 - * (1) its information is really dull, e.g. being a mere copy of
210 - * information that is obvious from other things that are shown, or (2) the
211 - * property is set in a hook after parsing, so that it is not reliably
212 - * available when Factboxes are displayed. If a property is internal so it
213 - * should never be observed by users, then it is better to just not
214 - * associate any translated label with it, so it never appears anywhere.
215 - */
216 - public function isShown() {
217 - $this->unstub();
218 - return ( ( $this->m_propertyid == '' ) ||
219 - ( array_key_exists( $this->m_propertyid, SMWPropertyvalue::$mPropertyTypes ) &&
220 - SMWPropertyvalue::$mPropertyTypes[$this->m_propertyid][1] ) );
221 - }
222 -
223 - /**
224 - * Return TRUE if this property is an inverse.
225 - */
226 - public function isInverse() {
227 - $this->unstub();
228 - return $this->m_inv;
229 - }
230 -
231 - public function setOutputFormat( $formatstring ) {
232 - $this->m_outformat = $formatstring;
233 - if ( $this->m_wikipage !== null ) { // do not unstub if not needed
234 - $this->m_wikipage->setOutputFormat( $formatstring );
235 - }
236 - }
237 -
238 - public function getShortWikiText( $linked = null ) {
239 - return $this->isVisible() ? $this->highlightText( $this->m_wikipage->getShortWikiText( $linked ) ):'';
240 - }
241 -
242 - public function getShortHTMLText( $linker = null ) {
243 - return $this->isVisible() ? $this->highlightText( $this->m_wikipage->getShortHTMLText( $linker ) ):'';
244 - }
245 -
246 - public function getLongWikiText( $linked = null ) {
247 - return $this->isVisible() ? $this->highlightText( $this->m_wikipage->getLongWikiText( $linked ) ):'';
248 - }
249 -
250 - public function getLongHTMLText( $linker = null ) {
251 - return $this->isVisible() ? $this->highlightText( $this->m_wikipage->getLongHTMLText( $linker ) ):'';
252 - }
253 -
254 - /**
255 - * Return internal property id or page DBkey, either of which is sufficient for storing property references.
256 - */
257 - public function getDBkeys() {
258 - $this->unstub();
259 - return $this->isVisible() ? array( $this->m_wikipage->getDBkey() ):array( $this->m_propertyid );
260 - }
261 -
262 - public function getSignature() {
263 - return 't';
264 - }
265 -
266 - public function getValueIndex() {
267 - return 0;
268 - }
269 -
270 - public function getLabelIndex() {
271 - return 0;
272 - }
273 -
274 - public function getWikiValue() {
275 - return $this->isVisible() ? ( ( $this->isInverse() ? '-':'' ) . $this->m_wikipage->getWikiValue() ):'';
276 - }
277 -
278 - /**
279 - * If this property is associated with a wiki page, return an SMWWikiPageValue for
280 - * that page. Otherwise return NULL.
281 - */
282 - public function getWikiPageValue() {
283 - $this->unstub();
284 - return $this->m_wikipage;
285 - }
286 -
287 - /**
288 - * If this property was not user defined, return the internal ID string referring to
289 - * that property. Otherwise return FALSE;
290 - */
291 - public function getPropertyID() {
292 - $this->unstub();
293 - return $this->m_propertyid;
294 - }
295 -
296 - /**
297 - * Return an SMWTypesValue object representing the datatype of this property.
298 - */
299 - public function getTypesValue() {
300 - global $smwgPDefaultType;
301 - if ( $this->mPropTypeValue !== null ) return $this->mPropTypeValue;
302 - if ( !$this->isValid() ) { // errors in property, return invalid types value with same errors
303 - $result = SMWDataValueFactory::newTypeIDValue( '__typ' );
304 - $result->setDBkeys( array( '__err' ) );
305 - $result->addError( $this->getErrors() );
306 - } elseif ( $this->isUserDefined() ) { // normal property
307 - $typearray = smwfGetStore()->getPropertyValues( $this->getWikiPageValue(), SMWPropertyValue::makeProperty( '_TYPE' ) );
308 - if ( count( $typearray ) == 1 ) { // unique type given
309 - $result = current( $typearray );
310 - } elseif ( count( $typearray ) == 0 ) { // no type given
311 - $result = SMWDataValueFactory::newTypeIDValue( '__typ' );
312 - $result->setDBkeys( array( $smwgPDefaultType ) );
313 - } else { // many types given, error
314 - smwfLoadExtensionMessages( 'SemanticMediaWiki' );
315 - $result = SMWDataValueFactory::newTypeIDValue( '__typ' );
316 - $result->setDBkeys( array( '__err' ) );
317 - $result->addError( wfMsgForContent( 'smw_manytypes' ) );
318 - }
319 - } else { // pre-defined property
320 - $result = SMWDataValueFactory::newTypeIDValue( '__typ' );
321 - if ( array_key_exists( $this->m_propertyid, SMWPropertyValue::$mPropertyTypes ) ) {
322 - $result->setDBkeys( array( SMWPropertyValue::$mPropertyTypes[$this->m_propertyid][0] ) );
323 - } else { // unknown type; it may still be that the property is "type-polymorphic" (like _1, _2, ... for Records)
324 - $result->setDBkeys( array( '__err' ) ); // use "__err" to make sure that it gets noticed if this information is really used to create values
325 - }
326 - }
327 - $this->mPropTypeValue = $result;
328 - return $result;
329 - }
330 -
331 - /**
332 - * Quickly get the type id of some property without necessarily making
333 - * another datavalue. Note that this is not the same as getTypeID(), which
334 - * returns the id of this property datavalue.
335 - */
336 - public function getPropertyTypeID() {
337 - if ( $this->mPropTypeId === null ) {
338 - $type = $this->getTypesValue();
339 - if ( $type instanceof SMWTypesValue ) {
340 - $this->mPropTypeId = $type->getDBkey();
341 - } else {
342 - $this->mPropTypeId = '__err';
343 - }
344 - }
345 - return $this->mPropTypeId;
346 - }
347 -
348 - /**
349 - * Return a DB-key-like string: for visible properties, it is the actual DB key,
350 - * for internal (invisible) properties, it is the property ID. The value agrees
351 - * with the first component of getDBkeys() and it can be used in its place.
352 - */
353 - public function getDBkey() {
354 - return $this->isVisible() ? $this->m_wikipage->getDBkey():$this->m_propertyid;
355 - }
356 -
357 - public function getText() {
358 - return $this->isVisible() ? $this->m_wikipage->getWikiValue():'';
359 - }
360 -
361 - /**
362 - * Create special highlighting for hinting at special properties.
363 - */
364 - protected function highlightText( $text ) {
365 - if ( $this->isUserDefined() ) {
366 - return $text;
367 - } else {
368 - SMWOutputs::requireHeadItem( SMW_HEADER_TOOLTIP );
369 - smwfLoadExtensionMessages( 'SemanticMediaWiki' );
370 - return '<span class="smwttinline"><span class="smwbuiltin">' . $text .
371 - '</span><span class="smwttcontent">' . wfMsgForContent( 'smw_isspecprop' ) . '</span></span>';
372 - }
373 - }
374 -
375 - /**
376 - * Find and return the id for the pre-defined property of the given local label.
377 - * If the label does not belong to a pre-defined property, return false.
378 - * The given label should be slightly normalised, i.e. as returned by Title
379 - * or smwfNormalTitleText().
380 - *
381 - * This function is protected. The public way of getting this data is to simply
382 - * create a new property object and to retrieve its ID (if any).
383 - */
384 - static protected function findPropertyID( $label, $useAlias = true ) {
385 - SMWPropertyValue::initProperties();
386 - $id = array_search( $label, SMWPropertyValue::$mPropertyLabels );
387 - if ( $id !== false ) {
388 - return $id;
389 - } elseif ( ( $useAlias ) && ( array_key_exists( $label, SMWPropertyValue::$mPropertyAliases ) ) ) {
390 - return SMWPropertyValue::$mPropertyAliases[$label];
391 - } else {
392 - return false;
393 - }
394 - }
395 -
396 - /**
397 - * Get the translated user label for a given internal property ID.
398 - * Returns false for properties without a translation (these are usually the
399 - * internal ones generated by SMW but not shown to the user).
400 - */
401 - static protected function findPropertyLabel( $id ) {
402 - SMWPropertyValue::initProperties();
403 - if ( array_key_exists( $id, SMWPropertyValue::$mPropertyLabels ) ) {
404 - return SMWPropertyValue::$mPropertyLabels[$id];
405 - } else { // incomplete translation (language bug) or deliberately invisible property
406 - return false;
407 - }
408 - }
409 -
410 - /**
411 - * Set up predefined properties, including their label, aliases, and typing information.
412 - */
413 - static protected function initProperties() {
414 - if ( is_array( SMWPropertyValue::$mPropertyTypes ) ) {
415 - return; // init happened before
416 - }
417 -
418 - global $smwgContLang, $smwgUseCategoryHierarchy;
419 - SMWPropertyValue::$mPropertyLabels = $smwgContLang->getPropertyLabels();
420 - SMWPropertyValue::$mPropertyAliases = $smwgContLang->getPropertyAliases();
421 - // Setup built-in predefined properties.
422 - // NOTE: all ids must start with underscores, where two underscores informally indicate
423 - // truly internal (non user-accessible properties). All others should also get a
424 - // translation in the language files, or they won't be available for users.
425 - SMWPropertyValue::$mPropertyTypes = array(
426 - '_TYPE' => array( '__typ', true ),
427 - '_URI' => array( '__spu', true ),
428 - '_INST' => array( '__sin', false ),
429 - '_UNIT' => array( '__sps', true ),
430 - '_IMPO' => array( '__imp', true ),
431 - '_CONV' => array( '__sps', true ),
432 - '_SERV' => array( '__sps', true ),
433 - '_PVAL' => array( '__sps', true ),
434 - '_REDI' => array( '__red', true ),
435 - '_SUBP' => array( '__sup', true ),
436 - '_SUBC' => array( '__suc', !$smwgUseCategoryHierarchy ),
437 - '_CONC' => array( '__con', false ),
438 - '_MDAT' => array( '_dat', false ),
439 - '_ERRP' => array( '_wpp', false ),
440 - '_LIST' => array( '__tls', true ),
441 - // "virtual" properties for encoding lists in n-ary datatypes (their type must never be used, hence use __err)
442 -// '_1' => array('__err',false),
443 -// '_2' => array('__err',false),
444 -// '_3' => array('__err',false),
445 -// '_4' => array('__err',false),
446 -// '_5' => array('__err',false),
447 - );
448 - wfRunHooks( 'smwInitProperties' );
449 - }
450 -
451 - /**
452 - * A function for registering/overwriting predefined properties for SMW. Should be called from
453 - * within the hook 'smwInitProperties'. Ids should start with three underscores "___" to avoid
454 - * current and future confusion with SMW built-ins.
455 - */
456 - static public function registerProperty( $id, $typeid, $label = false, $show = false ) {
457 - SMWPropertyValue::$mPropertyTypes[$id] = array( $typeid, $show );
458 - if ( $label != false ) {
459 - SMWPropertyValue::$mPropertyLabels[$id] = $label;
460 - }
461 - }
462 -
463 - /**
464 - * Add a new alias label to an existing datatype id. Note that every ID should have a primary
465 - * label, either provided by SMW or registered with registerDatatype. This function should be
466 - * called from within the hook 'smwInitDatatypes'.
467 - */
468 - static public function registerPropertyAlias( $id, $label ) {
469 - SMWPropertyValue::$mPropertyAliases[$label] = $id;
470 - }
471 -
472 -}
Index: trunk/extensions/SemanticMediaWiki/includes/SMW_DV_Number.php
@@ -1,300 +0,0 @@
2 -<?php
3 -/**
4 - * @file
5 - * @ingroup SMWDataValues
6 - */
7 -
8 -/**
9 - * This datavalue implements numerical datavalues, and supports optional
10 - * unit conversions. It parses and manages unit strings, since even plain
11 - * numbers may have (not further specified) units that are stored. However,
12 - * only subclasses implement full unit conversion by extending the methods
13 - * convertToMainUnit() and makeConversionValues().
14 - *
15 - * Units work as follows: a unit is a string, but many such strings might
16 - * refer to the same unit of measurement. There is always one string, that
17 - * canonically represents the unit, and we will call this version of writing
18 - * the unit the /unit id/. IDs for units are needed for tasks like duplicate
19 - * avoidance. If no conversion information is given, any unit is its own ID.
20 - * In any case, units are /normalised/, i.e. given a more standardised meaning
21 - * before being processed. All units, IDs or otherwise, should be suitable for
22 - * printout in wikitext, and main IDs should moreover be suitable for printout
23 - * in HTML.
24 - *
25 - * @author Markus Krötzsch
26 - * @ingroup SMWDataValues
27 - *
28 - * @todo Wiki-HTML-conversion for unit strings must be revisited, as the current
29 - * solution might be unsafe.
30 - * @todo Respect desired output unit (relevant for queries).
31 - */
32 -class SMWNumberValue extends SMWDataValue {
33 -
34 - protected $m_wikivalue = ''; // local language value, user input if given
35 - protected $m_value = ''; // numerical value, in $m_unit
36 - protected $m_unit = ''; // HTML-safe unit string, if any
37 - protected $m_unitin; // if set, specifies the originally given input unit in a standard writing
38 - protected $m_unitvalues; // array with entries unit=>value
39 -
40 - protected function parseUserValue( $value ) {
41 - $this->m_wikivalue = $value;
42 - $this->m_unitin = false;
43 - $this->m_unitvalues = false;
44 -
45 - smwfLoadExtensionMessages( 'SemanticMediaWiki' );
46 -
47 - // Parse to find value and unit
48 - $decseparator = wfMsgForContent( 'smw_decseparator' );
49 - $kiloseparator = wfMsgForContent( 'smw_kiloseparator' );
50 -
51 - $parts = preg_split( '/([-+]?\s*\d+(?:\\' . $kiloseparator . '\d\d\d)*' .
52 - '(?:\\' . $decseparator . '\d+)?\s*(?:[eE][-+]?\d+)?)/u',
53 - trim( str_replace( array( '&nbsp;', '&#160;', '&thinsp;', ' ' ), '', $value ) ),
54 - 2, PREG_SPLIT_DELIM_CAPTURE );
55 -
56 - if ( count( $parts ) >= 2 ) {
57 - $numstring = str_replace( $kiloseparator, '', preg_replace( '/\s*/u', '', $parts[1] ) ); // simplify
58 - if ( $decseparator != '.' ) {
59 - $numstring = str_replace( $decseparator, '.', $numstring );
60 - }
61 - list( $this->m_value ) = sscanf( $numstring, "%f" );
62 - }
63 - if ( count( $parts ) >= 3 ) $this->m_unit = $this->normalizeUnit( $parts[2] );
64 -
65 - if ( ( count( $parts ) == 1 ) || ( $numstring == '' ) ) { // no number found
66 - $this->addError( wfMsgForContent( 'smw_nofloat', $value ) );
67 - } elseif ( is_infinite( $this->m_value ) ) {
68 - wfMsgForContent( 'smw_infinite', $value );
69 - }
70 -
71 - // Set caption
72 - if ( $this->m_caption === false ) {
73 - $this->m_caption = $value;
74 - }
75 - return true;
76 - }
77 -
78 - protected function parseDBkeys( $args ) {
79 - $this->m_value = $args[0];
80 - $this->m_unit = array_key_exists( 2, $args ) ? $args[2]:'';
81 - $this->m_caption = false;
82 - $this->m_unitin = false;
83 - $this->makeUserValue();
84 - $this->m_unitvalues = false;
85 - }
86 -
87 - public function setOutputFormat( $formatstring ) {
88 - $oldformat = $this->m_outformat;
89 - $this->m_outformat = $formatstring;
90 - if ( ( $formatstring != $oldformat ) && $this->isValid() ) {
91 - // recompute conversion if outputformat is changed after initialisation
92 - $this->m_stubvalues = array( $this->m_value, $this->m_value, $this->m_unit );
93 - }
94 - }
95 -
96 - public function getShortWikiText( $linked = null ) {
97 - $this->unstub();
98 - if ( ( $linked === null ) || ( $linked === false ) || ( $this->m_outformat == '-' ) || ( $this->m_outformat == '-u' ) || ( $this->m_outformat == '-n' ) ) {
99 - return $this->m_caption;
100 - }
101 - $this->makeConversionValues();
102 - $tooltip = '';
103 - $i = 0;
104 - $sep = '';
105 - foreach ( $this->m_unitvalues as $unit => $value ) {
106 - if ( $unit != $this->m_unitin ) {
107 - $tooltip .= $sep . smwfNumberFormat( $value );
108 - if ( $unit != '' ) {
109 - $tooltip .= '&#160;' . $unit;
110 - }
111 - $sep = ' <br />';
112 - $i++;
113 - if ( $i >= 5 ) { // limit number of printouts in tooltip
114 - break;
115 - }
116 - }
117 - }
118 - if ( $tooltip != '' ) {
119 - SMWOutputs::requireHeadItem( SMW_HEADER_TOOLTIP );
120 - return '<span class="smwttinline">' . $this->m_caption . '<span class="smwttcontent">' . $tooltip . '</span></span>';
121 - } else {
122 - return $this->m_caption;
123 - }
124 - }
125 -
126 - public function getShortHTMLText( $linker = null ) {
127 - return $this->getShortWikiText( $linker );
128 - }
129 -
130 - public function getLongWikiText( $linked = null ) {
131 - $this->unstub();
132 - if ( !$this->isValid() ) {
133 - return $this->getErrorText();
134 - } else {
135 - $this->makeConversionValues();
136 - $result = '';
137 - $i = 0;
138 - foreach ( $this->m_unitvalues as $unit => $value ) {
139 - if ( $i == 1 ) {
140 - $result .= ' (';
141 - } elseif ( $i > 1 ) {
142 - $result .= ', ';
143 - }
144 - $result .= ( $this->m_outformat != '-' ? smwfNumberFormat( $value ):$value );
145 - if ( $unit != '' ) {
146 - $result .= '&#160;' . $unit;
147 - }
148 - $i++;
149 - if ( $this->m_outformat == '-' ) { // no further conversions for plain output format
150 - break;
151 - }
152 - }
153 - if ( $i > 1 ) {
154 - $result .= ')';
155 - }
156 - return $result;
157 - }
158 - }
159 -
160 - public function getLongHTMLText( $linker = null ) {
161 - return $this->getLongWikiText( $linker );
162 - }
163 -
164 - public function getDBkeys() {
165 - $this->unstub();
166 - $this->convertToMainUnit();
167 - return array( $this->m_value, floatval( $this->m_value ), $this->m_unit );
168 - }
169 -
170 - public function getSignature() {
171 - return 'tfu';
172 - }
173 -
174 - public function getValueIndex() {
175 - return 1;
176 - }
177 -
178 - public function getLabelIndex() {
179 - return 0;
180 - }
181 -
182 - public function getWikiValue() {
183 - $this->unstub();
184 - return $this->m_wikivalue;
185 - }
186 -
187 - public function getUnit() {
188 - $values = $this->getDBkeys();
189 - return $values[2];
190 - }
191 -
192 - public function getHash() {
193 - $this->unstub();
194 - if ( $this->isValid() ) {
195 - $this->convertToMainUnit();
196 - return $this->m_value . $this->m_unit;
197 - } else {
198 - return implode( "\t", $this->getErrors() );
199 - }
200 - }
201 -
202 - protected function getServiceLinkParams() {
203 - $this->unstub();
204 - // Create links to mapping services based on a wiki-editable message. The parameters
205 - // available to the message are:
206 - // $1: string of numerical value in English punctuation
207 - // $2: string of integer version of value, in English punctuation
208 - // $3: string of unit (if any)
209 - return array( (string)$this->m_value, (string)round( $this->m_value ), $this->m_unit );
210 - }
211 -
212 - public function getExportData() {
213 - $this->unstub();
214 - if ( $this->isValid() ) {
215 - $lit = new SMWExpLiteral( $this->m_value, $this, 'http://www.w3.org/2001/XMLSchema#double' );
216 - return new SMWExpData( $lit );
217 - } else {
218 - return null;
219 - }
220 - }
221 -
222 - /**
223 - * Transform a (typically unit-) string into a normalised form,
224 - * so that, e.g., "km²" and "km<sup>2</sup>" do not need to be
225 - * distinguished.
226 - */
227 - protected function normalizeUnit( $unit ) {
228 - $unit = str_replace( array( '[[', ']]' ), '', trim( $unit ) ); // allow simple links to be used inside annotations
229 - $unit = str_replace( array( '²', '<sup>2</sup>' ), '&sup2;', $unit );
230 - $unit = str_replace( array( '³', '<sup>3</sup>' ), '&sup3;', $unit );
231 - return smwfXMLContentEncode( $unit );
232 - }
233 -
234 - /**
235 - * Converts the current m_value and m_unit to the main unit, if possible.
236 - * This means, it changes the fileds m_value and m_unit accordingly, and
237 - * that it stores the ID of the originally given unit in $this->m_unitin.
238 - * This should obviously not be done more than once, so it is advisable to
239 - * first check if m_unitin is non-false. Also, it should be checked if the
240 - * value is valid before trying to calculate with its contents.
241 - *
242 - * Overwritten by subclasses that support units.
243 - */
244 - protected function convertToMainUnit() {
245 - $this->m_unitin = $this->m_unit; // just use unit as ID (no check needed, we can do this as often as desired)
246 - }
247 -
248 - /**
249 - * This method creates an array of unit-value-pairs that should be
250 - * printed. Units are the keys and should be canonical unit IDs.
251 - * The result is stored in $this->m_unitvalues. Again, any class that
252 - * requires effort for doing this should first check whether the array
253 - * is already set (i.e. not false) before doing any work.
254 - * Note that the values should be plain numbers. Output formatting is done
255 - * later when needed. Also, it should be checked if the value is valid
256 - * before trying to calculate with its contents.
257 - * This method also must call or implement convertToMainUnit().
258 - *
259 - * Overwritten by subclasses that support units.
260 - */
261 - protected function makeConversionValues() {
262 - $this->convertToMainUnit();
263 - $this->m_unitvalues = array( $this->m_unit => $this->m_value );
264 - }
265 -
266 - /**
267 - * This method is used when no user input was given to find the best
268 - * values for m_wikivalue, m_unitin, and m_caption. After conversion,
269 - * these fields will look as if they were generated from user input,
270 - * and convertToMainUnit() will have been called (if not, it would be
271 - * blocked by the presence of m_unitin).
272 - *
273 - * Overwritten by subclasses that support units.
274 - */
275 - protected function makeUserValue() {
276 - $this->convertToMainUnit();
277 - $this->m_caption = '';
278 - if ( $this->m_outformat != '-u' ) { // -u is the format for displaying the unit only
279 - $this->m_caption .= ( ( $this->m_outformat != '-' ) && ( $this->m_outformat != '-n' ) ? smwfNumberFormat( $this->m_value ) : $this->m_value );
280 - }
281 - if ( ( $this->m_unit != '' ) && ( $this->m_outformat != '-n' ) ) { // -n is the format for displaying the number only
282 - if ( $this->m_outformat != '-u' ) {
283 - $this->m_caption .= ( $this->m_outformat != '-' ? '&#160;' : ' ' );
284 - }
285 - $this->m_caption .= $this->m_unit;
286 - }
287 - $this->m_wikivalue = $this->m_caption;
288 - $this->m_unitin = $this->m_unit;
289 - }
290 -
291 - /**
292 - * Return an array of major unit strings (ids only recommended) supported by
293 - * this datavalue.
294 - *
295 - * Overwritten by subclasses that support units.
296 - */
297 - public function getUnitList() {
298 - return array();
299 - }
300 -
301 -}
Index: trunk/extensions/SemanticMediaWiki/includes/SMW_DV_Bool.php
@@ -1,134 +0,0 @@
2 -<?php
3 -/**
4 - * @file
5 - * @ingroup SMWDataValues
6 - */
7 -
8 -/**
9 - * This datavalue implements Boolean datavalues.
10 - *
11 - * @author Markus Krötzsch
12 - * @ingroup SMWDataValues
13 - */
14 -class SMWBoolValue extends SMWDataValue {
15 -
16 - protected $m_value = null; // true, false, or NULL (unset)
17 - protected $m_stdcaption = ''; // a localised standard label for that value (if value is not NULL)
18 - protected $m_truecaption = null; // a desired label for "true" if given
19 - protected $m_falsecaption = null; // a desired label for "false" if given
20 -
21 - protected function parseUserValue( $value ) {
22 - smwfLoadExtensionMessages( 'SemanticMediaWiki' );
23 - $value = trim( $value );
24 - $lcv = strtolower( $value );
25 - $this->m_value = null;
26 - if ( $lcv === '1' ) { // note: if English "true" should be possible, specify in smw_true_words
27 - $this->m_value = true;
28 - } elseif ( $lcv === '0' ) { // note: English "false" may be added to smw_true_words
29 - $this->m_value = false;
30 - } elseif ( in_array( $lcv, explode( ',', wfMsgForContent( 'smw_true_words' ) ), TRUE ) ) {
31 - $this->m_value = true;
32 - } elseif ( in_array( $lcv, explode( ',', wfMsgForContent( 'smw_false_words' ) ), TRUE ) ) {
33 - $this->m_value = false;
34 - } else {
35 - $this->addError( wfMsgForContent( 'smw_noboolean', $value ) );
36 - }
37 -
38 - if ( $this->m_caption === false ) {
39 - $this->m_caption = $value;
40 - }
41 - if ( $this->m_value === true ) {
42 - if ( $this->m_truecaption !== null ) {
43 - $this->m_stdcaption = $this->m_truecaption;
44 - } else {
45 - $vals = explode( ',', wfMsgForContent( 'smw_true_words' ) );
46 - $this->m_stdcaption = $vals[0];
47 - }
48 - } elseif ( $this->m_value === false ) {
49 - if ( $this->m_falsecaption !== null ) {
50 - $this->m_stdcaption = $this->m_falsecaption;
51 - } else {
52 - $vals = explode( ',', wfMsgForContent( 'smw_false_words' ) );
53 - $this->m_stdcaption = $vals[0];
54 - }
55 - } else {
56 - $this->m_stdcaption = '';
57 - }
58 - return true;
59 - }
60 -
61 - protected function parseDBkeys( $args ) {
62 - $this->parseUserValue( $args[0] );
63 - $this->m_caption = $this->m_stdcaption; // use default for this language
64 - }
65 -
66 - public function setOutputFormat( $formatstring ) {
67 - if ( $formatstring == '' ) {
68 - // ignore
69 - } elseif ( strtolower( $formatstring ) == 'x' ) {
70 - $this->m_truecaption = '<span style="font-family: sans-serif; ">X</span>';
71 - $this->m_falsecaption = '';
72 - } else { // try format "truelabel, falselabel"
73 - $captions = explode( ',', $formatstring, 2 );
74 - if ( count( $captions ) == 2 ) { // note: escaping needed to be safe; MW-sanitising would be an alternative
75 - $this->m_truecaption = htmlspecialchars( trim( $captions[0] ) );
76 - $this->m_falsecaption = htmlspecialchars( trim( $captions[1] ) );
77 - } // else ignore
78 - }
79 - if ( ( $formatstring != $this->m_outformat ) && $this->isValid() && ( $this->m_truecaption !== null ) ) { // also adjust display
80 - $this->m_caption = $this->m_stdcaption = ( $this->m_value ? $this->m_truecaption:$this->m_falsecaption );
81 - }
82 - $this->m_outformat = $formatstring;
83 - }
84 -
85 - public function getShortWikiText( $linked = null ) {
86 - $this->unstub();
87 - return $this->m_caption;
88 - }
89 -
90 - public function getShortHTMLText( $linker = null ) {
91 - $this->unstub();
92 - return $this->m_caption;
93 - }
94 -
95 - public function getLongWikiText( $linked = null ) {
96 - return $this->isValid() ? $this->m_stdcaption:$this->getErrorText();
97 - }
98 -
99 - public function getLongHTMLText( $linker = null ) {
100 - return $this->isValid() ? $this->m_stdcaption:$this->getErrorText();
101 - }
102 -
103 - public function getDBkeys() {
104 - $this->unstub();
105 - return $this->m_value ? array( '1', 1 ):array( '0', 0 );
106 - }
107 -
108 - public function getSignature() {
109 - return 'tn';
110 - }
111 -
112 - public function getValueIndex() {
113 - return 1;
114 - }
115 -
116 - public function getLabelIndex() {
117 - return 0;
118 - }
119 -
120 - public function getWikiValue() {
121 - $this->unstub();
122 - return $this->m_stdcaption;
123 - }
124 -
125 - public function getExportData() {
126 - if ( $this->isValid() ) {
127 - $xsdvalue = $this->m_value ? 'true':'false';
128 - $lit = new SMWExpLiteral( $xsdvalue, $this, 'http://www.w3.org/2001/XMLSchema#boolean' );
129 - return new SMWExpData( $lit );
130 - } else {
131 - return null;
132 - }
133 - }
134 -
135 -}
Index: trunk/extensions/SemanticMediaWiki/includes/SMW_DV_Concept.php
@@ -1,224 +0,0 @@
2 -<?php
3 -/**
4 - * @file
5 - * @ingroup SMWDataValues
6 - */
7 -
8 -/**
9 - * This datavalue is used as a container for concept descriptions as used
10 - * on Concept pages with the #concept parserfunction. It has a somewhat
11 - * non-standard interface as compared to other datavalues, but this is not
12 - * an issue.
13 - *
14 - * @author Markus Krötzsch
15 - * @ingroup SMWDataValues
16 - */
17 -class SMWConceptValue extends SMWDataValue {
18 -
19 - protected $m_concept = ''; // XML-safe, HTML-safe, Wiki-compatible concept expression (query string)
20 - protected $m_docu = ''; // text description of concept, can only be set by special function "setvalues"
21 -
22 - protected function parseUserValue( $value ) {
23 - $this->clear();
24 - // this function is normally not used for this class, not created from user input directly
25 - $this->m_concept = smwfXMLContentEncode( $value );
26 - if ( $this->m_caption === false ) {
27 - $this->m_caption = $value;
28 - }
29 - return true;
30 - }
31 -
32 - protected function parseDBkeys( $args ) {
33 - $this->m_concept = $args[0];
34 - $this->m_caption = $args[0]; // is this useful?
35 - $this->m_docu = $args[1] ? smwfXMLContentEncode( $args[1] ):'';
36 - $this->m_queryfeatures = $args[2];
37 - $this->m_size = $args[3];
38 - $this->m_depth = $args[4];
39 - }
40 -
41 - protected function clear() {
42 - $this->m_concept = '';
43 - $this->m_docu = '';
44 - $this->m_queryfeatures = 0;
45 - $this->m_size = - 1;
46 - $this->m_depth = - 1;
47 - }
48 -
49 - public function getShortWikiText( $linked = null ) {
50 - $this->unstub();
51 - return $this->m_caption;
52 - }
53 -
54 - public function getShortHTMLText( $linker = null ) {
55 - return $this->getShortWikiText( $linker ); // should be save (based on xsdvalue)
56 - }
57 -
58 - public function getLongWikiText( $linked = null ) {
59 - if ( !$this->isValid() ) {
60 - return $this->getErrorText();
61 - } else {
62 - return $this->m_caption;
63 - }
64 - }
65 -
66 - public function getLongHTMLText( $linker = null ) {
67 - if ( !$this->isValid() ) {
68 - return $this->getErrorText();
69 - } else {
70 - return $this->m_caption; // should be save (based on xsdvalue)
71 - }
72 - }
73 -
74 - public function getDBkeys() {
75 - $this->unstub();
76 - return array( $this->m_concept, $this->m_docu, $this->m_queryfeatures, $this->m_size, $this->m_depth );
77 - }
78 -
79 - public function getSignature() {
80 - return 'tllnnn';
81 - }
82 -
83 - public function getValueIndex() {
84 - return 0;
85 - }
86 -
87 - public function getLabelIndex() {
88 - return 0;
89 - }
90 -
91 - public function getWikiValue() {
92 - $this->unstub();
93 - return str_replace( array( '&lt;', '&gt;', '&amp;' ), array( '<', '>', '&' ), $this->m_concept );
94 - }
95 -
96 - public function getExportData() {
97 - if ( $this->isValid() ) {
98 - $qp = new SMWQueryParser();
99 - $desc = $qp->getQueryDescription( $this->getWikiValue() );
100 - $exact = true;
101 - $owldesc = $this->descriptionToExpData( $desc, $exact );
102 - if ( $owldesc === false ) {
103 - $element = new SMWExpData( SMWExporter::getSpecialElement( 'owl', 'Thing' ) );
104 - }
105 - if ( !$exact ) {
106 - $result = new SMWExpData( new SMWExpElement( '' ) );
107 - $result->addPropertyObjectValue( SMWExporter::getSpecialElement( 'rdf', 'type' ),
108 - new SMWExpData( SMWExporter::getSpecialElement( 'owl', 'Class' ) ) );
109 - $result->addPropertyObjectValue( SMWExporter::getSpecialElement( 'rdfs', 'subClassOf' ), $owldesc );
110 - return $result;
111 - } else {
112 - return $owldesc;
113 - }
114 - } else {
115 - return null;
116 - }
117 - }
118 -
119 - public function descriptionToExpData( $desc, &$exact ) {
120 - if ( ( $desc instanceof SMWConjunction ) || ( $desc instanceof SMWDisjunction ) ) {
121 - $result = new SMWExpData( new SMWExpElement( '' ) );
122 - $result->addPropertyObjectValue( SMWExporter::getSpecialElement( 'rdf', 'type' ),
123 - new SMWExpData( SMWExporter::getSpecialElement( 'owl', 'Class' ) ) );
124 - $elements = array();
125 - foreach ( $desc->getDescriptions() as $subdesc ) {
126 - $element = $this->descriptionToExpData( $subdesc, $exact );
127 - if ( $element === false ) {
128 - $element = new SMWExpData( SMWExporter::getSpecialElement( 'owl', 'Thing' ) );
129 - }
130 - $elements[] = $element;
131 - }
132 - $prop = ( $desc instanceof SMWConjunction ) ? 'intersectionOf':'unionOf';
133 - $result->addPropertyObjectValue( SMWExporter::getSpecialElement( 'owl', $prop ),
134 - SMWExpData::makeCollection( $elements ) );
135 - } elseif ( $desc instanceof SMWClassDescription ) {
136 - if ( count( $desc->getCategories() ) == 1 ) { // single category
137 - $result = new SMWExpData( SMWExporter::getResourceElement( end( $desc->getCategories() ) ) );
138 - } else { // disjunction of categories
139 - $result = new SMWExpData( new SMWExpElement( '' ) );
140 - $elements = array();
141 - foreach ( $desc->getCategories() as $cat ) {
142 - $elements[] = new SMWExpData( SMWExporter::getResourceElement( $cat ) ); ;
143 - }
144 - $result->addPropertyObjectValue( SMWExporter::getSpecialElement( 'owl', 'unionOf' ),
145 - SMWExpData::makeCollection( $elements ) );
146 - }
147 - $result->addPropertyObjectValue( SMWExporter::getSpecialElement( 'rdf', 'type' ),
148 - new SMWExpData( SMWExporter::getSpecialElement( 'owl', 'Class' ) ) );
149 - } elseif ( $desc instanceof SMWConceptDescription ) {
150 - $result = new SMWExpData( SMWExporter::getResourceElement( $desc->getConcept() ) );
151 - } elseif ( $desc instanceof SMWSomeProperty ) {
152 - $result = new SMWExpData( new SMWExpElement( '' ) );
153 - $result->addPropertyObjectValue( SMWExporter::getSpecialElement( 'rdf', 'type' ),
154 - new SMWExpData( SMWExporter::getSpecialElement( 'owl', 'Restriction' ) ) );
155 - $result->addPropertyObjectValue( SMWExporter::getSpecialElement( 'owl', 'onProperty' ),
156 - new SMWExpData( SMWExporter::getResourceElement( $desc->getProperty() ) ) );
157 - $subdata = $this->descriptionToExpData( $desc->getDescription(), $exact );
158 - if ( ( $desc->getDescription() instanceof SMWValueDescription ) &&
159 - ( $desc->getDescription()->getComparator() == SMW_CMP_EQ ) ) {
160 - $result->addPropertyObjectValue( SMWExporter::getSpecialElement( 'owl', 'hasValue' ), $subdata );
161 - } else {
162 - if ( $subdata === false ) {
163 - $owltype = SMWExporter::getOWLPropertyType( $desc->getProperty()->getPropertyTypeID() );
164 - if ( $owltype == 'ObjectProperty' ) {
165 - $subdata = new SMWExpData( SMWExporter::getSpecialElement( 'owl', 'Thing' ) );
166 - } elseif ( $owltype == 'DatatypeProperty' ) {
167 - $subdata = new SMWExpData( SMWExporter::getSpecialElement( 'rdfs', 'Literal' ) );
168 - } else { // no restrictions at all with annotation properties ...
169 - return new SMWExpData( SMWExporter::getSpecialElement( 'owl', 'Thing' ) );
170 - }
171 - }
172 - $result->addPropertyObjectValue( SMWExporter::getSpecialElement( 'owl', 'someValuesFrom' ), $subdata );
173 - }
174 - } elseif ( $desc instanceof SMWValueDescription ) {
175 - if ( $desc->getComparator() == SMW_CMP_EQ ) {
176 - $result = $desc->getDataValue()->getExportData();
177 - } else { // alas, OWL cannot represent <= and >= ...
178 - $exact = false;
179 - $result = false;
180 - }
181 - } elseif ( $desc instanceof SMWThingDescription ) {
182 - $result = false;
183 - } else {
184 - $result = false;
185 - $exact = false;
186 - }
187 - return $result;
188 - }
189 -
190 - /// Return the concept's defining text (in SMW query syntax)
191 - public function getConceptText() {
192 - $this->unstub();
193 - return $this->m_concept;
194 - }
195 -
196 - /// Return the optional concept documentation.
197 - public function getDocu() {
198 - $this->unstub();
199 - return $this->m_docu;
200 - }
201 -
202 - /// Return the concept's size (a metric used to estimate computation complexity).
203 - public function getSize() {
204 - $this->unstub();
205 - return $this->m_size;
206 - }
207 -
208 - /// Return the concept's depth (a metric used to estimate computation complexity).
209 - public function getDepth() {
210 - $this->unstub();
211 - return $this->m_depth;
212 - }
213 -
214 - /// Return the concept's query feature bit field (a metric used to estimate computation complexity).
215 - public function getQueryFeatures() {
216 - $this->unstub();
217 - return $this->m_queryfeatures;
218 - }
219 -
220 - /// @deprecated Use setDBkeys(). This method will vanish before SMW 1.6
221 - public function setValues( $concept, $docu, $queryfeatures, $size, $depth ) {
222 - $this->setDBkeys( array( $concept, $docu, $queryfeatures, $size, $depth ) );
223 - }
224 -
225 -}
Index: trunk/extensions/SemanticMediaWiki/includes/SMW_DV_Time.php
@@ -1,856 +0,0 @@
2 -<?php
3 -/**
4 - * @file
5 - * @ingroup SMWDataValues
6 - */
7 -
8 -/**
9 - * This datavalue captures values of dates and times. All dates and times refer to
10 - * Coordinated Universal Time (UTC), or the local time of the wiki server.
11 - * A wiki may define what timezone this refers to by common conventions.
12 - * For export, times are given without timezone information. However, time offsets to
13 - * that local time, or to UTC, are supported (see below). The difference is arbitrary.
14 - *
15 - * Dates can be given in many formats, using numbers, month names, and abbreviated
16 - * month names. The preferred interpretation of ambiguous dates ("1 2 2008" or even
17 - * "1 2 3 BC") is controlled by the language file, as is the local naming of months.
18 - * English month names are always supported.
19 - *
20 - * Currently, the twelve-hour clock annotations "am" and "pm", and the calendar
21 - * symbols "BC", "AD", "Gr", "Jl", "JD", "MJD", and "OS" are supported,
22 - * and localised to most SMW-supported languages. Civilian and military time-zone monikers
23 - * are also supported; these do not require internationalization, except perhaps into
24 - * Cyrillic. Cyrillic support will be added when deemed necessary.
25 - *
26 - * The standard calendar model is the Gregorian calendar, inaugurated October 15, 1582.
27 - * Tooltip outputs in the Gregorian or proleptic Gregorian calendar (for dates earlier
28 - * than the proclamation date) always appear. However, the printout for browsing or
29 - * queries will be governed by the expressed preference, so that annotation in certain
30 - * calendar models will be preserved at query or browse. All annotated dates will *sort*
31 - * by a common key, regardless of model. (See below for details.)
32 - *
33 - * By default, a date annotated without preference is always treated as a Gregorian
34 - * calendar date (if later than October 4, 1582), or a Julian calendar date (if October
35 - * 4, 1582 or earlier). But users may override the default interpretation by specifying
36 - * the symbols "Gr" or "Jl", as appropriate, for any date falling within the Common Era
37 - * (aka Anno Domini). The annotation of a proleptic Gregorian date *before* the common
38 - * era is not supported; all BC(E) dates are treated as Julian. However, the proleptic
39 - * Gregorian date will appear in the tooltip.
40 - *
41 - * The "OS" (Old Style) symbol is supported in English, and dates annotated with this
42 - * symbol are processed accordingly: the year is incremented by one if the date falls
43 - * between 1 January and 24 March inclusive, and the resultant day is converted
44 - * according to Julian rules. The printout will be Julian or Gregorian, according to the
45 - * epoch. As before, the tooltip dialog will show a Gregorian or proleptic Gregorian date.
46 - *
47 - * The primary sort key for this datatype is the Julian Day, developed by J. J. Scaliger.
48 - * All dates are converted to JD and back-converted to the supported models for purposes
49 - * of output and captioning. In addition, this datatype supports the direct annotation of
50 - * a JD or a Modified Julian Day (MJD), which might be given in an astronomical table or
51 - * the flight schedule of a spacecraft, satellite, or rocket probe. For dates falling
52 - * earlier than midnight 1 January 4713 BC(E) (Julian), the program stores a negative
53 - * value consisting of the year (as a negative integer) and a fraction of a year. For
54 - * all other dates, the type stores the conventional JD, normalized to noon UTC.
55 - *
56 - * As such, this type can handle dates across history with full precision for storing,
57 - * and substantial precision for sorting and querying. The range of supported past
58 - * dates should encompass the Beginning of Time according to most of today's theories.
59 - * The range of supported future dates is limited more strictly, but it does also allow
60 - * year numbers in the order of 10^9.
61 - *
62 - * Years before common era (aka BC) can be denoted using "BC" in a date. The internal
63 - * numeric date model supports the year 0, and considers it to be the same as "1 BC"
64 - * in the Julian calendar. (The proleptic Gregorian calendar accepts a year of 0, but
65 - * this usage is not permitted here). All outputs follow ISO6801 and the remarks in
66 - * XML Schema Datatypes 2nd Edition (the latter uses a different convention that
67 - * disallows year 0, but it explicitly endorses the ISO convention and announces the
68 - * future use of this in XML). Note that the implementation currently does not support
69 - * the specification of negative year numbers as input; negative numbers are only used
70 - * internally. Likewise, "proleptic" negative He and AM inputs are not allowed.
71 - *
72 - * The implementation notices and stores whether parts of a date/time have been
73 - * omitted (as in "2008" or "May 2007"). For all exporting and sorting purposes,
74 - * incomplete dates are completed with defaults (usually using the earliest possible
75 - * time, i.e. interpreting "2008" as "Jan 1 2008 00:00:00"). The information
76 - * on what was unspecified is kept internally for improving behaviour e.g. for
77 - * outputs (defaults are not printed when querying for a value). Functions are
78 - * provided to access the individual time components (getYear, getMonth, getDay,
79 - * getTimeString), and those can also be used to find out what was unspecified.
80 - *
81 - * Time offsets are supported (e.g. "1 1 2008 12:00-2:00"). A time offset is the number
82 - * of hours:minutes to be added to UTC (GMT) to obtain the local-clock reading. Time zone
83 - * monikers (EST, CST, CET, MEZ, etc.) and military time (e.g. 1240Z, equivalent to 12:40
84 - * UTC) are also supported.
85 - *
86 - * Time offsets take leap years into account, e.g. the date
87 - * "Feb 28 2004 23:00+2:00" is equivalent to "29 February 2004 01:00:00", while
88 - * "Feb 28 1900 23:00+2:00" is equivalent to "1 March 1900 01:00:00".
89 - *
90 - * @todo Add support for additional calendar models (mainly requires conversion algorithms and
91 - * internationalization support).
92 - * @todo Try to reuse more of MediaWiki's records, e.g. to obtain month names or to
93 - * format dates. The problem is that MW is based on SIO timestamps that don't extend to
94 - * very ancient or future dates, and that MW uses PHP functions that are bound to UNIX time.
95 - *
96 - * @author Fabian Howahl
97 - * @author Terry A. Hurlbut
98 - * @author Markus Krötzsch
99 - * @ingroup SMWDataValues
100 - */
101 -class SMWTimeValue extends SMWDataValue {
102 -
103 - protected $m_wikivalue; // a suitable wiki input value
104 - protected $m_xsdvalue = false; // cache for DB key
105 - protected $m_gregvalue = false; // cache for (proleptic) Gregorian value
106 - protected $m_julvalue = false; // cache for (proleptic) Julian value
107 - protected $m_pref = false; // holds a symbol for the calendar model
108 - protected $m_day = false; // Gregorian day, remains false if unspecified
109 - protected $m_month = false; // Gregorian month, remains false if unspecified
110 - protected $m_year = false; // Gregorian year, remains false if unspecified
111 - protected $m_time = false; // time, remains false if unspecified
112 - protected $m_jd = 0; // numerical time representation similiar to Julian Day; for ancient times, a more compressed number is used (preserving ordering of time points)
113 - protected $m_format = false; // number of parts of the date that were specified
114 - protected $m_outformat = false; // A special code governing printout formats.
115 - protected $m_timeoffset; // contains offset (e.g. timezone)
116 - protected $m_timeannotation; // contains am or pm
117 - protected $m_dayj = false; // Julian day, remains false if unspecified
118 - protected $m_monthj = false; // Julian month, remains false if unspecified
119 - protected $m_yearj = false; // Julian year, remains false if unspecified
120 - // The following are constant (array-valued constants are not supported, hence the declaration as private static variable):
121 - private static $m_months = array( "January", "February", "March", "April" , "May" , "June" , "July" , "August" , "September" , "October" , "November" , "December" );
122 - private static $m_monthsshort = array( "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" );
123 - private static $m_formats = array( SMW_Y => array( 'year' ), SMW_YM => array( 'year', 'month' ), SMW_MY => array( 'month', 'year' ), SMW_YDM => array( 'year', 'day', 'month' ), SMW_YMD => array( 'year', 'month', 'day' ), SMW_DMY => array( 'day', 'month', 'year' ), SMW_MDY => array( 'month', 'day', 'year' ) );
124 - private static $m_daysofmonths = array ( 1 => 31, 2 => 29, 3 => 31, 4 => 30, 5 => 31, 6 => 30, 7 => 31, 8 => 31, 9 => 30, 10 => 31, 11 => 30, 12 => 31 );
125 - private static $m_daysofmonthsam = array ( 1 => 30, 2 => 30, 3 => 30, 4 => 30, 5 => 30, 6 => 30, 7 => 30, 8 => 30, 9 => 30, 10 => 30, 11 => 30, 12 => 60 );
126 - // Time zone monikers and their associated offsets in hours and fractions of hours
127 - private static $m_tz = array( "A" => 1, "ACDT" => 10.5, "ACST" => 9.5, "ADT" => - 3, "AEDT" => 11,
128 - "AEST" => 10, "AKDT" => - 8, "AKST" => - 9, "AST" => - 4, "AWDT" => 9, "AWST" => 8,
129 - "B" => 2, "BST" => 1, "C" => 3, "CDT" => - 5, "CEDT" => 2, "CEST" => 2,
130 - "CET" => 1, "CST" => - 6, "CXT" => 7, "D" => 4, "E" => 5, "EDT" => - 4,
131 - "EEDT" => 3, "EEST" => 3, "EET" => 2, "EST" => - 5, "F" => 6, "G" => 7,
132 - "GMT" => 0, "H" => 8, "HAA" => - 3, "HAC" => - 5, "HADT" => - 9, "HAE" => - 4,
133 - "HAP" => - 7, "HAR" => - 6, "HAST" => - 10, "HAT" => - 2.5, "HAY" => - 8,
134 - "HNA" => - 4, "HNC" => - 6, "HNE" => - 5, "HNP" => - 8, "HNR" => - 7, "HNT" => - 3.5,
135 - "HNY" => - 9, "I" => 9, "IST" => 1, "K" => 10, "L" => 11, "M" => 12,
136 - "MDT" => - 6, "MESZ" => 2, "MEZ" => 1, "MSD" => 4, "MSK" => 3, "MST" => - 7,
137 - "N" => - 1, "NDT" => - 2.5, "NFT" => 11.5, "NST" => - 3.5, "O" => - 2, "P" => - 3,
138 - "PDT" => - 7, "PST" => - 8, "Q" => - 4, "R" => - 5, "S" => - 6, "T" => - 7,
139 - "U" => - 8, "UTC" => 0, "V" => - 9, "W" => - 10, "WDT" => 9, "WEDT" => 1,
140 - "WEST" => 1, "WET" => 0, "WST" => 8, "X" => - 11, "Y" => - 12, "Z" => 0 );
141 -
142 -// constant epochal values
143 - const J1582 = 2299160.5; // Date of switchover to Gregorian calendar
144 - const MJD_EPOCH = 2400000.5; // Normalizes the Modified JD to midnight 17 Nov 1858 Gregorian.
145 -
146 - protected function parseUserValue( $value ) {
147 - global $smwgContLang;
148 -
149 - $band = false; // group of bits storing information about the possible meaning of each digit of the entered date
150 - $this->m_pref = false;
151 - $this->m_day = false;
152 - $this->m_month = false;
153 - $this->m_year = false;
154 - $this->m_jd = false;
155 - $this->m_time = false;
156 - $this->m_timeoffset = 0;
157 - $this->m_timeannotation = false;
158 - $this->m_format = false;
159 - $this->m_dayj = false;
160 - $this->m_monthj = false;
161 - $this->m_yearj = false;
162 -
163 - $value = trim( $value ); // ignore whitespace
164 - if ( $this->m_caption === false ) { // Store the caption now.
165 - $this->m_caption = $value;
166 - }
167 -
168 - // if the value is a number, and it has at least six places left of decimal, we know
169 - // it's not a year, so treat it as a Julian day, but leave it as the caption and wikivalue.
170 - if ( is_numeric( $value ) && $value >= 100000 ) {
171 - $this->m_jd = $value;
172 - $this->m_format = 3;
173 - $this->JD2Date();
174 - $this->fracToTime();
175 - $this->m_wikivalue = $value;
176 - return true;
177 - }
178 -
179 - $this->m_wikivalue = $value;
180 - $filteredvalue = $value; // value without time definition and further abbreviations like PM or BC
181 -
182 - // browse string for special abbreviations referring to time like am, pm
183 - if ( preg_match( "/([Aa]|[Pp])[Mm]/u", $filteredvalue, $match ) ) {
184 - $this->m_timeannotation = strtolower( trim( $match[0] ) );
185 - $regexp = "/(\040|T){0,1}" . str_replace( "+", "\+", $match[0] ) . "(\040){0,1}/u"; // delete pm/am, preceding and following chars
186 - $filteredvalue = preg_replace( $regexp, '', $filteredvalue ); // value without am/pm
187 - }
188 -
189 - // browse string in advance for timezone monikers ("EST", "WET", "MESZ", etc.)
190 - $regexptz = "/A[CEKW]?[DS]T|BST|CXT|[CEW]([DES]|E[DS])T|" .
191 - "GMT|H(A[DS]T|[AN][ACEPRTY])|IST|M(DT|E(S)?Z|S[DKT])|N[DFS]T|P[DS]T|UTC/u";
192 - if ( preg_match( $regexptz, $filteredvalue, $match ) ) {
193 - // Retrieve the offset and store it as the initial time offset value.
194 - $this->m_timeoffset = $this->m_timeoffset + self::$m_tz[$match[0]] / 24;
195 - $regexp = "/(\040|T){0,1}" . str_replace( "+", "\+", $match[0] ) . "(\040){0,1}/u"; // delete tz moniker and preceding and following chars
196 - $filteredvalue = preg_replace( $regexp, '', $filteredvalue ); // value without the tz moniker
197 - }
198 -
199 - // browse string for special abbreviations referring to year like AD, BC, and OS
200 - $is_yearbc = false;
201 - if ( preg_match( "/(A[DM]|BC(E)?|CE|Gr|He|Jl|(M)?JD|OS)/u", $filteredvalue, $match ) ) {
202 - $this->m_pref = trim( $match[0] );
203 - if ( ( $this->m_pref == 'BC' ) || ( $this->m_pref == 'BCE' ) ) {
204 - $is_yearbc = true;
205 - }
206 - $regexp = "/(\040|T){0,1}" . str_replace( "+", "\+", $match[0] ) . "(\040){0,1}/u"; // delete ad/bc value and preceding and following chars
207 - $filteredvalue = preg_replace( $regexp, '', $filteredvalue ); // value without ad/bc
208 - }
209 -
210 - // handle direct entry of Julian or Modified Julian days here; don't bother browsing for times.
211 - if ( ( $this->m_pref == 'JD' ) || ( $this->m_pref == 'MJD' ) ) {
212 - if ( !( is_numeric( $filteredvalue ) ) ) {// Immediate error check
213 - smwfLoadExtensionMessages( 'SemanticMediaWiki' );
214 - $this->addError( wfMsgForContent( 'smw_nodatetime', $value ) );
215 - return true;
216 - }
217 - $this->m_jd = ( $this->m_pref == 'JD' ) ? $filteredvalue : ( $filteredvalue + self::MJD_EPOCH );
218 - $this->m_pref = "Gr";
219 - $this->m_format = 3; // Specify all three parts of the date (see below)
220 - $this->JD2Date();
221 - $this->fracToTime();
222 - return true;
223 - }
224 -
225 - // browse string for civilian time value
226 - if ( preg_match( "/[0-2]?[0-9]:[0-5][0-9](:[0-5][0-9])?([+\-][0-2]?[0-9](:(30|00))?)?/u", $filteredvalue, $match ) ) {
227 - $time = $match[0];
228 -
229 - // timezone direct offset handling
230 - if ( preg_match( "/([+\-][0-2]?[0-9](:(30|00))?)/u", $time, $match2 ) ) { // get timezone definition
231 - $offset = SMWTimeValue::normalizeTimeValue( $match2[0] );
232 - $sign = 1;
233 - if ( $offset[0] == '-' ) $sign = - 1;
234 - $offset = substr( $offset, 1 );
235 - list ( $offhours, $offminutes, $offseconds ) = explode( ':', $offset, 3 );
236 - $offset = $sign * ( ( $offhours / 24 ) + ( $offminutes / ( 60 * 24 ) ) + ( $offseconds / ( 3600 * 24 ) ) );
237 - $this->m_timeoffset = $this->m_timeoffset + $offset;
238 - $time = str_replace( $match2[0], '', $time );
239 - }
240 -
241 - list( $hours, $minutes, $seconds ) = explode( ':', SMWTimeValue::normalizeTimeValue( $time ), 3 );
242 -
243 - // am/pm handling
244 - if ( $this->m_timeannotation != false ) {
245 - if ( !strcmp( $this->m_timeannotation, 'am' ) && $hours == 12 ) $hours = 0;
246 - if ( !strcmp( $this->m_timeannotation, 'pm' ) && $hours <= 11 ) {
247 - $this->m_timeoffset = $this->m_timeoffset - 0.5;
248 - }
249 - }
250 -
251 - $this->m_time = SMWTimeValue::normalizeValue( $hours ) . ":" . SMWTimeValue::normalizeValue( $minutes ) . ":" . SMWTimeValue::normalizeValue( $seconds );
252 - $regexp = "/(\040|T){0,1}" . str_replace( "+", "\+", $match[0] ) . "(\040){0,1}/u"; // delete time value and preceding and following chars
253 - $filteredvalue = preg_replace( $regexp, '', $filteredvalue ); // value without time
254 - }
255 -
256 - // browse string for military time value
257 - if ( preg_match( "/([0-1][0-9]|2[0-3])[0-5][0-9]([0-5][0-9])?[A-IK-Z]/u", $filteredvalue, $match ) ) {
258 - $time = $match[0];
259 - // timezone handling (Zulu, Romeo, Sierra, etc.)
260 - if ( preg_match( "/[A-IK-Z]/u", $time, $match2 ) ) {// get military timezone offset
261 - $this->m_timeoffset = $this->m_timeoffset + self::$m_tz[$match2[0]] / 24;
262 - $time = str_replace( $match2[0], '', $time );// strip away the one-letter moniker
263 - }
264 - $hours = substr( $time, 0, 2 );
265 - $minutes = substr( $time, 2, 2 );
266 - $seconds = ( strlen( $time ) > 4 ) ? substr( $time, 4, 2 ) : '00';
267 - $this->m_time = SMWTimeValue::normalizeValue( $hours ) . ":" . SMWTimeValue::normalizeValue( $minutes ) . ":" . SMWTimeValue::normalizeValue( $seconds );
268 - $regexp = "/(\040|T){0,1}" . str_replace( "+", "\+", $match[0] ) . "(\040){0,1}/u"; // delete time value and preceding and following chars
269 - $filteredvalue = preg_replace( $regexp, '', $filteredvalue ); // value without time
270 - }
271 -
272 - // split array in order to separate the date digits
273 - $array = preg_split( "/[\040|.|,|\-|\/]+/u", $filteredvalue, 3 ); // TODO: support &nbsp and - again;
274 -
275 - // The following code segment creates a band by finding out which role each digit of the entered date can take
276 - // (date, year, month). The band starts with 1 and for each digit of the entered date a binary code with three
277 - // bits is attached. Examples:
278 - // 111 states that the digit can be interpreted as a month, a day or a year
279 - // 100 digit can just be interpreted as a month
280 - // 010 digit can just be interpreted as a day
281 - // 001 digit can just be interpreted as a year
282 - // the remaining combinations are also possible (if reasonable)
283 - // A date consisting of three digits therefore will have a 10 bit band.
284 - if ( count( $array ) != 0 ) {
285 - $band = 1;
286 - foreach ( $array as $tmp ) {
287 - $band = $band << 3;
288 - $band = $band | $this->checkDigit( $tmp );
289 - }
290 - } else {
291 - smwfLoadExtensionMessages( 'SemanticMediaWiki' );
292 - $this->addError( wfMsgForContent( 'smw_nodatetime', $value ) );
293 - return true;
294 - }
295 -
296 - $dateformats = $smwgContLang->getDateFormats(); // get the language dependent date formats
297 -
298 - $digitcount = count( $array ) - 1; // number of digits - 1 is used as an array index for $dateformats
299 - $found = false;
300 - $prelimModel = $this->findPrelimModel();
301 - foreach ( $dateformats[$digitcount] as $format ) { // check whether created band matches dateformats
302 - if ( !( ~$band & $format ) ) { // check if $format => $band ("the detected band supports the current format")
303 - $i = 0;
304 - foreach ( self::$m_formats[$format] as $globalvar ) { // map format digits to internal variables
305 - $globalvar = 'm_' . $globalvar; // (for searching this file) this is one of: m_year, m_month, m_day
306 - if ( $prelimModel == 'Jl' ) {
307 - $globalvar = $globalvar . 'j';
308 - }
309 - if ( !$this->$globalvar ) $this->$globalvar = intval( $array[$i] );
310 - $i++;
311 - }
312 - $found = true;
313 - break;
314 - }
315 - }
316 -
317 - // error catching
318 - if ( !$found ) { // no band matches the entered date
319 - smwfLoadExtensionMessages( 'SemanticMediaWiki' );
320 - $this->addError( wfMsgForContent( 'smw_nodatetime', $value ) );
321 - return true;
322 - } elseif ( ( $this->m_day > 0 ) && ( $this->m_day > self::$m_daysofmonths[$this->m_month] ) ) { // date does not exist in Gregorian calendar
323 - smwfLoadExtensionMessages( 'SemanticMediaWiki' );
324 - $this->addError( wfMsgForContent( 'smw_nodatetime', $value ) );
325 - return true;
326 - } elseif ( ( $this->m_dayj > 0 ) && ( $this->m_dayj > self::$m_daysofmonths[$this->m_monthj] ) ) { // date does not exist in Julian calendar
327 - smwfLoadExtensionMessages( 'SemanticMediaWiki' );
328 - $this->addError( wfMsgForContent( 'smw_nodatetime', $value ) );
329 - return true;
330 - } elseif ( ( $this->m_yearj != false ) && ( $this->m_yearj < - 4713 ) && ( $this->m_timeoffset != 0 ) ) { // no support for time offsets if year < -4713
331 - smwfLoadExtensionMessages( 'SemanticMediaWiki' );
332 - $this->addError( wfMsgForContent( 'smw_nodatetime', $value ) );
333 - return true;
334 - }
335 -
336 - // Handle OS: Increment the year if earlier than March 25.
337 - if ( $this->m_pref == 'OS' ) {
338 - if ( ( $this->m_monthj < 3 ) || ( ( $this->m_monthj == 3 ) && ( $this->m_dayj < 25 ) ) ) {
339 - $this->m_yearj++;
340 - }
341 - }
342 -
343 - // Handle BC: the year is negative.
344 - if ( $is_yearbc ) {
345 - if ( $this->m_yearj > 0 ) { // see class documentation on BC, "year 0", and ISO conformance ...
346 - $this->m_yearj = - ( $this->m_yearj );
347 - }
348 - }
349 -
350 - // Make the JD value and handle offset if applicable
351 - $this->createJD( $this->findModel() );
352 - if ( $this->m_jd > - 0.5 ) {
353 - $this->m_jd = $this->m_jd - $this->m_timeoffset;
354 - $this->JD2Date();
355 - } else {
356 - $this->m_day = $this->m_dayj;
357 - $this->m_month = $this->m_monthj;
358 - $this->m_year = $this->m_yearj;
359 - } // Copy Julian registers into Gregorian registers; needed for the XSD value
360 - return true;
361 - }
362 -
363 - protected static function findMonth( $label ) {
364 - global $smwgContLang;
365 - $retVal = $smwgContLang->findMonth( $label );
366 - if ( $retVal !== false ) {
367 - return $retVal;
368 - }
369 - $retVal = array_search( $label, self::$m_months );
370 - if ( $retVal !== false ) {
371 - return $retVal + 1;
372 - }
373 - $retVal = array_search( $label, self::$m_monthsshort );
374 - if ( $retVal !== false ) {
375 - return $retVal + 1;
376 - }
377 - return false;
378 - }
379 -
380 - protected function findPrelimModel() {
381 - if ( ( $this->m_pref == 'BC' ) || ( $this->m_pref == 'BCE' ) || ( $this->m_pref == 'Jl' ) || ( $this->m_pref == 'OS' ) ) {
382 - return 'Jl'; // Assume Julian model if specified in any way, shape or form.
383 - }
384 - return 'Gr';
385 - }
386 -
387 - protected function checkDigit( $digit ) {
388 - $prelimModel = $this->findPrelimModel();
389 - if ( !is_numeric( $digit ) ) { // check for alphanumeric day or month value
390 - if ( preg_match( "/[0-3]?[0-9](st|nd|rd|th)/u", $digit ) ) { // look for day value terminated by st/nd/th
391 - $dayVal = intval( substr( $digit, 0, strlen( $digit ) - 2 ) ); // remove st/nd/th
392 - if ( $prelimModel == 'Jl' ) {
393 - $this->m_dayj = $dayVal;
394 - } else {
395 - $this->m_day = $dayVal;
396 - }
397 - return SMW_DAY;
398 - }
399 - $monthnumber = SMWTimeValue::findMonth( $digit );
400 - if ( $monthnumber !== false ) {
401 - if ( $prelimModel == 'Jl' ) {
402 - $this->m_monthj = $monthnumber;
403 - } else {
404 - $this->m_month = $monthnumber;
405 - }
406 - return SMW_MONTH;
407 - }
408 - return 0;
409 - } elseif ( intval( $digit ) >= 1 && intval( $digit ) <= 12 ) { // number can be a month, a day or a year (111)
410 - return SMW_DAY_MONTH_YEAR;
411 - } elseif ( intval( $digit ) >= 1 && intval( $digit ) <= 31 ) { // number can be day or year
412 - return SMW_DAY_YEAR;
413 - } elseif ( is_numeric( $digit ) ) { // number can just be a year (011)
414 - return SMW_YEAR;
415 - } else {
416 - return 0;
417 - }
418 - }
419 -
420 - // finds the appropriate model to use.
421 - protected function findModel() {
422 - if ( ( $this->m_pref == 'BC' ) || ( $this->m_pref == 'BCE' ) ) {
423 - return 'Jl'; // BC dates are automatically Julian.
424 - }
425 - if ( $this->m_pref == 'OS' ) {
426 - $this->m_pref = ''; // Erase the OS marker; it will not be needed after this.
427 - return 'Jl'; // Old Style dates are converted per Julian rules.
428 - }
429 - if ( ( $this->m_pref == 'Gr' ) || ( $this->m_pref == 'Jl' ) ) {// Specified calendar models
430 - return $this->m_pref;
431 - }
432 - // Model unspecified: must be determined by examination of the date parts.
433 - if ( $this->m_year > 1582 ) {
434 - return 'Gr'; // All dates after 1582 are Gregorian dates.
435 - }
436 - if ( ( $this->m_year == 1582 ) && ( $this->m_month > 10 ) ) {
437 - return 'Gr'; // The Gregorian calendar was inaugurated after October 4, 1582.
438 - }
439 - if ( ( $this->m_year == 1582 ) && ( $this->m_month == 10 ) && ( $this->m_day > 4 ) ) {
440 - return 'Gr';
441 - } // Set $model to 'Jl' and move all specified date parts to the Julian set.
442 - $this->m_dayj = $this->m_day;
443 - $this->m_monthj = $this->m_month;
444 - $this->m_yearj = $this->m_year;
445 - return 'Jl';
446 - }
447 -
448 - protected function parseDBkeys( $args ) {
449 - $this->m_caption = false;
450 - if ( count( $args ) < 2 ) return;
451 - $timeparts = explode( 'T', $args[0], 2 );
452 - if ( count( $timeparts ) != 2 ) return;
453 - $date = reset( $timeparts );
454 - $this->m_time = end( $timeparts );
455 - $d = explode( '/', $date, 3 );
456 - if ( count( $d ) == 3 ) list( $this->m_year, $this->m_month, $this->m_day ) = $d;
457 - elseif ( count( $d ) == 2 ) list( $this->m_year, $this->m_month ) = $d;
458 - elseif ( count( $d ) == 1 ) list( $this->m_year ) = $d;
459 - if ( $this->m_year < - 4713 ) {
460 - $this->m_yearj = $this->m_year;
461 - $this->m_monthj = $this->m_month;
462 - $this->m_dayj = $this->m_day;
463 - $this->createJD( 'Jl' ); // This date falls earlier than the Julian Era.
464 - } else {
465 - $this->createJD( 'Gr' ); // This is a Gregorian or proleptic Gregorian date
466 - }
467 - if ( $this->m_jd > - 0.5 ) {// Back-convert only if the JD is suitable for that
468 - $this->JD2Date();
469 - }
470 - $this->makePrintoutValue();
471 - $this->m_caption = ( $this->m_jd < self::J1582 ) ? $this->m_julvalue : $this->m_gregvalue;
472 - $this->m_wikivalue = $this->m_gregvalue;
473 - }
474 -
475 - /// make sure that existing values are updated: set the format string and force
476 - /// a reconfiguration of all printouts.
477 - public function setOutputFormat( $formatstring ) {
478 - if ( $formatstring != $this->m_outformat ) {
479 - $this->m_outformat = $formatstring;
480 - $this->m_gregvalue = false;
481 - $this->m_julvalue = false;
482 - }
483 - }
484 -
485 - public function getShortWikiText( $linked = NULL ) {
486 - $this->unstub();
487 - if ( $this->m_caption !== false ) {
488 - return $this->m_caption;
489 - } else {
490 - $this->makePrintoutValue();
491 - return $this->m_gregvalue;
492 - }
493 - }
494 -
495 - public function getShortHTMLText( $linker = NULL ) {
496 - return $this->getShortWikiText( $linker ); // should be safe (based on xsdvalue)
497 - }
498 -
499 - public function getLongWikiText( $linked = NULL ) {
500 - if ( !$this->isValid() ) {
501 - return $this->getErrorText();
502 - } else {
503 - $this->makePrintoutValue();
504 - return $this->m_jd < self::J1582 ? $this->m_julvalue : $this->m_gregvalue;
505 - }
506 - }
507 -
508 - public function getLongHTMLText( $linker = NULL ) {
509 - return $this->getLongWikiText( $linker );
510 - }
511 -
512 - public function getDBkeys() {
513 - $this->unstub();
514 - if ( $this->m_xsdvalue === false ) {
515 - $this->m_xsdvalue = $this->m_year . "/" . $this->m_month . "/" . $this->m_day . "T" . $this->m_time;
516 - }
517 - return array( $this->m_xsdvalue, $this->m_jd );
518 - }
519 -
520 - public function getSignature() {
521 - return 'tf';
522 - }
523 -
524 - public function getValueIndex() {
525 - return 1;
526 - }
527 -
528 - public function getLabelIndex() {
529 - return 0;
530 - }
531 -
532 - public function getWikiValue() {
533 - $this->unstub();
534 - return $this->m_wikivalue;
535 - }
536 -
537 - public function getHash() {
538 - if ( $this->isValid() ) {
539 - return strval( $this->m_jd );
540 - } else {
541 - return implode( "\t", $this->getErrors() );
542 - }
543 - }
544 -
545 - public function isNumeric() {
546 - return true;
547 - }
548 -
549 - public function getExportData() {
550 - if ( $this->isValid() ) {
551 - $lit = new SMWExpLiteral( $this->getXMLSchemaDate(), $this, 'http://www.w3.org/2001/XMLSchema#dateTime' );
552 - return new SMWExpData( $lit );
553 - } else {
554 - return NULL;
555 - }
556 - }
557 -
558 - /**
559 - * Return the year as a number corresponding to the year in the Julian or
560 - * Gregorian calendar and using the astronomical year numbering (0 means 1 BC).
561 - */
562 - public function getYear( $model = 'Gr' ) {
563 - $this->unstub();
564 - switch ( $model ) {
565 - case 'Jl':
566 - return $this->m_yearj;
567 - default:
568 - return $this->m_year;
569 - }
570 - }
571 -
572 - /**
573 - * Return the month as a number (between 1 and 12) based on the Julian or
574 - * Gregorian calendar.
575 - * The parameter $default optionally specifies the value returned
576 - * if the date is valid but has no explicitly specified month. It can
577 - * also be set to FALSE to detect this situation.
578 - */
579 - public function getMonth( $model = 'Gr', $default = 1 ) {
580 - $this->unstub();
581 - switch ( $model ) {
582 - case 'Jl':
583 - return ( $this->m_monthj != false ) ? $this->m_monthj:$default;
584 - default:
585 - return ( $this->m_month != false ) ? $this->m_month:$default;
586 - }
587 - }
588 -
589 - /**
590 - * Return the day as a number based on the Julian or Gregorian calendar.
591 - * The parameter $default optionally specifies the value returned
592 - * if the date is valid but has no explicitly specified date. It can
593 - * also be set to FALSE to detect this situation.
594 - */
595 - public function getDay( $model = 'Gr', $default = 1 ) {
596 - $this->unstub();
597 - switch ( $model ) {
598 - case 'Jl':
599 - return ( $this->m_dayj != false ) ? $this->m_dayj:$default;
600 - default:
601 - return ( $this->m_day != false ) ? $this->m_day:$default;
602 - }
603 - }
604 -
605 - /**
606 - * Return the time as a string. The time string has the format HH:MM:SS,
607 - * without any timezone information (see class documentaion for details
608 - * on current timezone handling).
609 - * The parameter $default optionally specifies the value returned
610 - * if the date is valid but has no explicitly specified time. It can
611 - * also be set to FALSE to detect this situation.
612 - */
613 - public function getTimeString( $default = '00:00:00' ) {
614 - $this->unstub();
615 - return ( $this->m_time != false ) ? SMWTimeValue::normalizeTimeValue( $this->m_time ):$default;
616 - }
617 -
618 - /**
619 - * Return a representation of this date in canonical dateTime format without timezone, as
620 - * specified in XML Schema Part 2: Datatypes Second Edition (W3C Recommendation, 28 October 2004,
621 - * http://www.w3.org/TR/xmlschema-2). An example would be "2008-01-02T14:30:10". BC(E) years
622 - * are represented by a leading "-" as in "-123-01-02T14:30:10", the 2nd January of the year
623 - * 123 BC(E) at 2:30pm and 10 seconds.
624 - *
625 - * If the date was not fully specified, then the function will use defaults for the omitted values.
626 - * The boolean parameter $mindefault controls if those defaults are chosen minimally. If false, then
627 - * the latest possible value will be chosen instead.
628 - *
629 - * @note This function may return year numbers with less or more than 4 digits.
630 - */
631 - public function getXMLSchemaDate( $mindefault = true ) {
632 - if ( $this->isValid() ) {
633 - if ( $mindefault ) {
634 - return number_format( $this->m_year, 0, '.', '' ) . '-' . SMWTimeValue::normalizeValue( $this->getMonth() ) . '-' . SMWTimeValue::normalizeValue( $this->getDay() ) . 'T' . $this->getTimeString();
635 - } else {
636 - return number_format( $this->m_year, 0, '.', '' ) . '-' . SMWTimeValue::normalizeValue( $this->getMonth( 12 ) ) . '-' . SMWTimeValue::normalizeValue( $this->getDay( 31 ) ) . 'T' . $this->getTimeString( '23:59:59' );
637 - }
638 - } else {
639 - return false;
640 - }
641 - }
642 -
643 - /**
644 - * Build preferred values for printout, to be used as captions when setting up values
645 - * from the store. Note: Proleptic Hillel II and Biblical values are not permitted.
646 - */
647 - protected function makePrintoutValue() {
648 - $this->makeGregorianValue();
649 - $this->makeJulianValue();
650 - }
651 -
652 - protected function makeGregorianValue() {
653 - global $smwgContLang;
654 - if ( $this->m_gregvalue === false ) {
655 - // MediaWiki date function is not applicable any more (no support for BC Dates)
656 - if ( ( strtoupper( $this->m_outformat ) == 'ISO' ) || ( $this->m_outformat == '-' ) ) { // ISO8601 date formatting
657 - if ( $this->m_year > 0 ) {
658 - $this->m_gregvalue = str_pad( $this->m_year, 4, "0", STR_PAD_LEFT );
659 - } else {
660 - $this->m_gregvalue = '-' . str_pad( ( - ( $this->m_year ) ), 4, "0", STR_PAD_LEFT );
661 - }
662 - $this->m_gregvalue .= '-'
663 - . ( $this->m_month ? str_pad( $this->m_month, 2, "0", STR_PAD_LEFT ):'01' ) . '-'
664 - . ( $this->m_day ? str_pad( $this->m_day, 2, "0", STR_PAD_LEFT ):'01' )
665 - . ( $this->m_time ? 'T' . $this->m_time:'' );
666 - } else { // Default date formatting
667 - if ( $this->m_year > 0 ) {
668 - $this->m_gregvalue = number_format( $this->m_year, 0, '.', '' ) . ( ( ( $this->m_pref == 'AD' ) || ( $this->m_pref == 'CE' ) ) ? ( ' ' . $this->m_pref ) : '' );
669 - } else {
670 - $this->m_gregvalue = number_format( - ( $this->m_year ), 0, '.', '' ) . ( ( $this->m_pref == 'BCE' ) ? ' ' . 'BCE' : ' ' . 'BC' ); // note: there should be no digits after the comma anyway
671 - }
672 - if ( $this->m_month ) {
673 - $this->m_gregvalue = $smwgContLang->getMonthLabel( $this->m_month ) . " " . $this->m_gregvalue;
674 - }
675 - if ( $this->m_day ) {
676 - $this->m_gregvalue = $this->m_day . " " . $this->m_gregvalue;
677 - }
678 - if ( $this->m_time ) {
679 - $this->m_gregvalue .= " " . $this->m_time;
680 - }
681 - }
682 - }
683 - }
684 -
685 - protected function makeJulianValue() {
686 - global $smwgContLang;
687 - if ( $this->m_julvalue === false ) {
688 - // MediaWiki date function is not applicable any more (no support for BC Dates)
689 - if ( ( strtoupper( $this->m_outformat ) == 'ISO' ) || ( $this->m_outformat == '-' ) ) { // ISO8601 date formatting
690 - if ( $this->m_yearj > 0 ) {
691 - $this->m_julvalue = str_pad( $this->m_yearj, 4, "0", STR_PAD_LEFT );
692 - } else {
693 - $this->m_julvalue = '-' . str_pad( ( - ( $this->m_yearj ) ), 4, "0", STR_PAD_LEFT );
694 - }
695 - $this->m_julvalue .= '-'
696 - . ( $this->m_monthj ? str_pad( $this->m_monthj, 2, "0", STR_PAD_LEFT ):'01' ) . '-'
697 - . ( $this->m_dayj ? str_pad( $this->m_dayj, 2, "0", STR_PAD_LEFT ):'01' )
698 - . ( $this->m_time ? 'T' . $this->m_time:'' );
699 - } else {
700 - if ( $this->m_yearj > 0 ) {
701 - $this->m_julvalue = number_format( $this->m_yearj, 0, '.', '' ) . ( ( ( $this->m_pref == 'AD' ) || ( $this->m_pref == 'CE' ) ) ? ( ' ' . $this->m_pref ) : '' );
702 - } else {
703 - $this->m_julvalue = number_format( - ( $this->m_yearj ), 0, '.', '' ) . ( ( $this->m_pref == 'BCE' ) ? ' ' . 'BCE' : ' ' . 'BC' ); // note: there should be no digits after the comma anyway
704 - }
705 - if ( $this->m_monthj ) {
706 - $this->m_julvalue = $smwgContLang->getMonthLabel( $this->m_monthj ) . " " . $this->m_julvalue;
707 - }
708 - if ( $this->m_dayj ) {
709 - $this->m_julvalue = $this->m_dayj . " " . $this->m_julvalue;
710 - }
711 - if ( $this->m_time ) {
712 - $this->m_julvalue .= " " . $this->m_time;
713 - }
714 - }
715 - }
716 - }
717 -
718 - protected static function normalizeValue( $value ) {
719 - if ( strlen( $value ) == 1 ) {
720 - $value = "0" . $value;
721 - }
722 - return $value;
723 - }
724 -
725 - protected static function normalizeTimeValue( $value ) {
726 - $value = SMWTimeValue::normalizeValue( $value );
727 - $parts = explode( ":", $value );
728 - switch ( count( $parts ) ) {
729 - case 1: return $parts[0] . ":00:00";
730 - case 2: return $parts[0] . ":" . $parts[1] . ":00";
731 - default: return $value;
732 - }
733 - }
734 -
735 - /**
736 - * This function adds a time fraction to any Julian Day.
737 - */
738 - protected function createTime() {
739 - if ( $this->m_time != false ) { // Calculate fraction only if time is set -- the default time is 0
740 - list ( $hours, $minutes, $seconds ) = explode( ':', $this->getTimeString(), 3 );
741 - $time = ( $hours / 24 ) + ( $minutes / ( 60 * 24 ) ) + ( $seconds / ( 3600 * 24 ) );
742 - $this->m_jd += $time;
743 - }
744 - }
745 -
746 - /**
747 - * This function computes a numerical value based on the currently set date. If the year is
748 - * greater or equal to -4712 (4713 BC), then (something that is closely inspired by) the Julian Day
749 - * (JD) is computed. The JD has the form XXXX.YYYY where XXXX is the number of days having elapsed since
750 - * noon on 1 January 4713 BC and YYYY is the elapsed time of the day as fraction of 1.
751 - * See http://en.wikipedia.org/wiki/Julian_day
752 - * If the year is before -4713, then the computed number XXXX.YYYY has the following form: XXXX is
753 - * the number of years BC and YYYY represents the elapsed days of the year as fraction of 1. This
754 - * enables even large negative dates using 32bit floats.
755 - *
756 - * @note The result of this function is used only internally. It should not be assumed to be the
757 - * exact JD, even for dates after 4713 BC, unless a proper time-zone offset or moniker is specified.
758 - */
759 - protected function createJD( $model ) {
760 - switch( $model ) {
761 - case "Gr":
762 - $this->gregorian2JD();
763 - break;
764 - case "Jl":
765 - $this->julian2JD();
766 - break;
767 - }
768 - $this->createTime();
769 - }
770 -
771 - /// Calculate a Julian day according to Gregorian calendar rules
772 - protected function gregorian2JD() {
773 - $this->m_jd = 0;
774 - $a = intval( ( 14 - $this->getMonth( 'Gr' ) ) / 12 );
775 - $y = $this->m_year + 4800 - $a;
776 - $m = $this->getMonth( 'Gr' ) + 12 * $a - 3;
777 - $this->m_jd += $this->getDay( 'Gr' ) + intval( ( 153 * $m + 2 ) / 5 ) + 365 * $y + intval( $y / 4 ) - intval( $y / 100 ) + intval( $y / 400 ) - 32045.5;
778 - $this->m_format = ( $this->m_day != false ) ? 3 : ( ( $this->m_month != false ) ? 2 : 1 );
779 - }
780 -
781 - /// Calculate a Julian day according to Julian calendar rules
782 - protected function julian2JD() {
783 - if ( $this->m_yearj >= - 4713 ) {
784 - $this->m_jd = 0;
785 - $y1 = ( $this->m_yearj < 1 ) ? ( $this->m_yearj + 1 ) : $this->m_yearj;
786 - $m1 = $this->getMonth( 'Jl' );
787 - $y2 = ( $m1 <= 2 ) ? ( $y1 - 1 ) : $y1;
788 - $m2 = ( $m1 <= 2 ) ? ( $m1 + 12 ) : $m1;
789 - $this->m_jd += intval( ( 365.25 * ( $y2 + 4716 ) ) ) + intval( ( 30.6001 * ( $m2 + 1 ) ) ) + $this->getDay( 'Jl' ) - 1524.5;
790 - } else { // starting from the time when JD would be negative, use our own "stretched" representation, currently this just ignores local time
791 - $time = 1 - ( ( $this->getMonth( 'Jl' ) / 12 ) + ( $this->getDay( 'Jl' ) / 365 ) );
792 - $this->m_jd = $this->m_yearj - $time;
793 - }
794 - $this->m_format = ( $this->m_dayj != false ) ? 3 : ( ( $this->m_monthj != false ) ? 2 : 1 );
795 - }
796 -
797 - /// Convert the Julian Day fraction to the time string.
798 - protected function fracToTime() {
799 - $wjd = $this->m_jd + 0.5;
800 - $fraction = $wjd - intval( $wjd );
801 - $time = round( $fraction * 3600 * 24 );
802 - $hours = intval( $time / 3600 );
803 - $time = $time - $hours * 3600;
804 - $minutes = intval( $time / 60 );
805 - $seconds = intval( $time - $minutes * 60 );
806 - $this->m_time = SMWTimeValue::normalizeValue( $hours ) . ":" . SMWTimeValue::normalizeValue( $minutes ) . ":" . SMWTimeValue::normalizeValue( $seconds );
807 - }
808 -
809 - /// Convert Julian Day to m_year, m_month, and m_day according to the proper model.
810 - /// Do NOT invoke AM or Hillel conversion functions if the JD is less than their respective epochs.
811 - protected function JD2Date() {
812 - $this->JD2Julian();
813 - $this->JD2Gregorian();
814 - if ( $this->m_time != false ) { // Do not fill this in if it was not filled in to begin with
815 - $this->fracToTime();
816 - }
817 - }
818 -
819 - /// Convert Julian Day (see createJD) back to a Gregorian date.
820 - protected function JD2Gregorian() {
821 - $j = intval( $this->m_jd + 0.5 ) + 32044;
822 - $g = intval( $j / 146097 );
823 - $dg = $j % 146097;
824 - $c = intval( ( ( intval( $dg / 36524 ) + 1 ) * 3 ) / 4 );
825 - $dc = $dg - $c * 36524;
826 - $b = intval( $dc / 1461 );
827 - $db = $dc % 1461;
828 - $a = intval( ( ( intval( $db / 365 ) + 1 ) * 3 ) / 4 );
829 - $da = $db - ( $a * 365 );
830 - $y = $g * 400 + $c * 100 + $b * 4 + $a;
831 - $m = intval( ( $da * 5 + 308 ) / 153 ) - 2;
832 - $d = $da - intval( ( ( $m + 4 ) * 153 ) / 5 ) + 122;
833 - $this->m_year = $y - 4800 + intval( ( $m + 2 ) / 12 );
834 - $this->m_month = ( $this->m_format >= 2 ) ? ( ( $m + 2 ) % 12 + 1 ) : false;
835 - $this->m_day = ( $this->m_format == 3 ) ? ( $d + 1 ) : false;
836 - if ( ( $this->m_format == 2 ) && ( $d > 1 ) ) {
837 - $this->m_month++;
838 - if ( $this->m_month > 12 ) {
839 - $this->m_month = 1;
840 - $this->m_year++;
841 - }
842 - }
843 - }
844 -
845 - /// Convert Julian Day back to a Julian date.
846 - protected function JD2Julian() {
847 - $b = intval( $this->m_jd + 0.5 ) + 1524;
848 - $c = intval( ( $b - 122.1 ) / 365.25 );
849 - $d = intval( 365.25 * $c );
850 - $e = intval( ( $b - $d ) / 30.6001 );
851 - $m = intval( ( $e < 14 ) ? ( $e - 1 ) : ( $e - 13 ) );
852 - $y = intval( ( $m > 2 ) ? ( $c - 4716 ) : ( $c - 4715 ) );
853 - $this->m_yearj = ( $y < 1 ) ? ( $y - 1 ) : $y;
854 - $this->m_monthj = ( $this->m_format >= 2 ) ? $m : false;
855 - $this->m_dayj = ( $this->m_format == 3 ) ? ( $b - $d - intval( 30.6001 * $e ) ) : false;
856 - }
857 -}
Index: trunk/extensions/SemanticMediaWiki/includes/SMW_DV_WikiPage.php
@@ -1,377 +0,0 @@
2 -<?php
3 -/**
4 - * @file
5 - * @ingroup SMWDataValues
6 - */
7 -
8 -/**
9 - * This datavalue implements special processing suitable for defining
10 - * wikipages as values of properties. In contrast to most other types
11 - * of values, wiki pages are determined by multiple components, as
12 - * retruned by their getDBkeys() method: DBkey, namespace, interwiki
13 - * prefix and sortkey. The last of those has a somewhat nonstandard
14 - * behaviour, since it is not attached to every wiki page value, but
15 - * only to those that represent page subjects, which define the sortkey
16 - * globally for all places where this page value occurs.
17 - *
18 - * @author Nikolas Iwan
19 - * @author Markus Krötzsch
20 - * @ingroup SMWDataValues
21 - */
22 -class SMWWikiPageValue extends SMWDataValue {
23 -
24 - protected $m_textform = ''; // the isolated title as text
25 - protected $m_dbkeyform = ''; // the isolated title in DB form
26 - protected $m_interwiki = ''; // interwiki prefix or '', actually stored in SMWSQLStore2
27 - protected $m_sortkey = ''; // key for alphabetical sorting
28 - protected $m_fragment = ''; // not stored, but kept for printout on page
29 - protected $m_prefixedtext = ''; // full titletext with prefixes, including interwiki prefix
30 - protected $m_namespace = NS_MAIN;
31 - protected $m_id; // false if unset
32 - protected $m_title = null;
33 -
34 - protected $m_fixNamespace = NS_MAIN; // if namespace other than NS_MAIN, restrict inputs to this namespace
35 -
36 - /**
37 - * Static function for creating a new wikipage object from
38 - * data as it is typically stored internally. In particular,
39 - * the title string is supposed to be in DB key form.
40 - * @note The resulting wikipage object might be invalid if
41 - * the provided title is not allowed. An object is returned
42 - * in any case.
43 - *
44 - * @return SMWWikiPageValue
45 - */
46 - static public function makePage( $title, $namespace, $sortkey = '', $interwiki = '' ) {
47 - $page = new SMWWikiPageValue( '_wpg' );
48 - $page->setDBkeys( array( $title, $namespace, $interwiki, $sortkey ) );
49 - return $page;
50 - }
51 -
52 - /**
53 - * Static function for creating a new wikipage object from a
54 - * MediaWiki Title object.
55 - */
56 - static public function makePageFromTitle( $titleobject ) {
57 - $page = new SMWWikiPageValue( '_wpg' );
58 - $page->setTitle( $titleobject );
59 - return $page;
60 - }
61 -
62 - public function __construct( $typeid ) {
63 - parent::__construct( $typeid );
64 - switch ( $typeid ) {
65 - case '__typ':
66 - $this->m_fixNamespace = SMW_NS_TYPE;
67 - break;
68 - case '_wpp' : case '__sup':
69 - $this->m_fixNamespace = SMW_NS_PROPERTY;
70 - break;
71 - case '_wpc' : case '__suc': case '__sin':
72 - $this->m_fixNamespace = NS_CATEGORY;
73 - break;
74 - case '_wpf' : case '__spf':
75 - $this->m_fixNamespace = SF_NS_FORM;
76 - break;
77 - default: // case '_wpg':
78 - $this->m_fixNamespace = NS_MAIN;
79 - }
80 - }
81 -
82 - protected function parseUserValue( $value ) {
83 - global $wgContLang;
84 - $value = ltrim( rtrim( $value, ' ]' ), ' [' ); // support inputs like " [[Test]] "
85 - if ( $value != '' ) {
86 - $this->m_title = Title::newFromText( $value, $this->m_fixNamespace );
87 - ///TODO: Escape the text so users can see any punctuation problems (bug 11666).
88 - if ( $this->m_title === null ) {
89 - smwfLoadExtensionMessages( 'SemanticMediaWiki' );
90 - $this->addError( wfMsgForContent( 'smw_notitle', $value ) );
91 - } elseif ( ( $this->m_fixNamespace != NS_MAIN ) &&
92 - ( $this->m_fixNamespace != $this->m_title->getNamespace() ) ) {
93 - smwfLoadExtensionMessages( 'SemanticMediaWiki' );
94 - $this->addError( wfMsgForContent( 'smw_wrong_namespace', $wgContLang->getNsText( $this->m_fixNamespace ) ) );
95 - }
96 - if ( $this->m_title !== null ) {
97 - $this->m_textform = $this->m_title->getText();
98 - $this->m_dbkeyform = $this->m_title->getDBkey();
99 - $this->m_interwiki = $this->m_title->getInterwiki();
100 - $this->m_fragment = $this->m_title->getFragment();
101 - $this->m_prefixedtext = $this->m_title->getPrefixedText(); ///NOTE: may include interwiki prefix
102 - $this->m_namespace = $this->m_title->getNamespace();
103 - $this->m_id = false; // unset id
104 - if ( $this->m_caption === false ) {
105 - $this->m_caption = $value;
106 - }
107 - }
108 - } else {
109 - smwfLoadExtensionMessages( 'SemanticMediaWiki' );
110 - $this->addError( wfMsgForContent( 'smw_notitle', $value ) );
111 - }
112 - if ( $this->m_caption === false ) {
113 - $this->m_caption = '';
114 - }
115 - }
116 -
117 - protected function parseDBkeys( $args ) {
118 - $this->m_dbkeyform = $args[0];
119 - $this->m_namespace = array_key_exists( 1, $args ) ? $args[1]:$this->m_fixNamespace;
120 - $this->m_interwiki = array_key_exists( 2, $args ) ? $args[2]:'';
121 - $this->m_sortkey = array_key_exists( 3, $args ) ? $args[3]:'';
122 - $this->m_textform = str_replace( '_', ' ', $this->m_dbkeyform );
123 - $this->m_id = false;
124 - $this->m_title = null;
125 - $this->m_prefixedtext = false;
126 - $this->m_caption = false;
127 - if ( ( $this->m_fixNamespace != NS_MAIN ) && ( $this->m_fixNamespace != $this->m_namespace ) ) {
128 - smwfLoadExtensionMessages( 'SemanticMediaWiki' );
129 - $this->addError( wfMsgForContent( 'smw_notitle', $this->getPrefixedText() ) );
130 - }
131 - }
132 -
133 - public function getShortWikiText( $linked = null ) {
134 - $this->unstub();
135 - if ( ( $linked === null ) || ( $linked === false ) || ( $this->m_outformat == '-' ) || ( !$this->isValid() ) || ( $this->m_caption === '' ) ) {
136 - return $this->getCaption();
137 - } else {
138 - return '[[:' . str_replace( "'", '&#x0027;', $this->getPrefixedText() ) .
139 - ( $this->m_fragment ? "#$this->m_fragment":'' ) . '|' . $this->getCaption() . ']]';
140 - }
141 - }
142 -
143 - public function getShortHTMLText( $linker = null ) {
144 - $this->unstub();
145 - if ( ( $linker !== null ) && ( $this->m_caption !== '' ) && ( $this->m_outformat != '-' ) ) { $this->getTitle(); } // init the Title object, may reveal hitherto unnoticed errors
146 - if ( ( $linker === null ) || ( !$this->isValid() ) || ( $this->m_outformat == '-' ) || ( $this->m_caption === '' ) ) {
147 - return htmlspecialchars( $this->getCaption() );
148 - } elseif ( $this->getNamespace() == NS_MEDIA ) { /// NOTE: this extra case is indeed needed
149 - return $linker->makeMediaLinkObj( $this->getTitle(), $this->getCaption() );
150 - } else {
151 - return $linker->makeLinkObj( $this->getTitle(), $this->getCaption() );
152 - }
153 - }
154 -
155 - /**
156 - * @note The getLong... functions of this class always hide the fragment. Fragments are currently
157 - * not stored, and hence should not be shown in the Factbox (where the getLongWikiText method is used).
158 - * In all other uses, values come from the store and do not have fragments anyway.
159 - */
160 - public function getLongWikiText( $linked = null ) {
161 - $this->unstub();
162 - if ( !$this->isValid() ) {
163 - return $this->getErrorText();
164 - }
165 - if ( ( $linked === null ) || ( $linked === false ) || ( $this->m_outformat == '-' ) ) {
166 - return $this->m_fixNamespace == NS_MAIN ? $this->getPrefixedText():$this->getText();
167 - } elseif ( $this->m_namespace == NS_IMAGE ) { // embed images instead of linking to their page
168 - return '[[' . str_replace( "'", '&#x0027;', $this->getPrefixedText() ) . '|' . $this->m_textform . '|frameless|border|text-top]]';
169 - } else { // this takes care of all other cases, esp. it is right for Media:
170 - return '[[:' . str_replace( "'", '&#x0027;', $this->getPrefixedText() ) . '|' . $this->m_textform . ']]';
171 - }
172 - }
173 -
174 - public function getLongHTMLText( $linker = null ) {
175 - $this->unstub();
176 - if ( ( $linker !== null ) && ( $this->m_outformat != '-' ) ) { $this->getTitle(); } // init the Title object, may reveal hitherto unnoticed errors
177 - if ( !$this->isValid() ) {
178 - return $this->getErrorText();
179 - }
180 - if ( ( $linker === null ) || ( $this->m_outformat == '-' ) ) {
181 - return htmlspecialchars( $this->m_fixNamespace == NS_MAIN ? $this->getPrefixedText():$this->getText() );
182 - } elseif ( $this->getNamespace() == NS_MEDIA ) { // this extra case is really needed
183 - return $linker->makeMediaLinkObj( $this->getTitle(), $this->m_textform );
184 - } else { // all others use default linking, no embedding of images here
185 - return $linker->makeLinkObj( $this->getTitle(), $this->m_textform );
186 - }
187 - }
188 -
189 - public function getDBkeys() {
190 - $this->unstub();
191 - return array( $this->m_dbkeyform, $this->m_namespace, $this->m_interwiki, $this->getSortkey() );
192 - }
193 -
194 - public function getSignature() {
195 - return 'tnwt';
196 - }
197 -
198 - public function getValueIndex() {
199 - return 3;
200 - }
201 -
202 - public function getLabelIndex() {
203 - return 3;
204 - }
205 -
206 - public function getWikiValue() {
207 - $this->unstub();
208 - if ( $this->m_fixNamespace != NS_MAIN ) { // no explicit namespace needed!
209 - return $this->getText();
210 - } elseif ( $this->m_namespace == NS_CATEGORY ) {
211 - // escape to enable use in links; todo: not generally required/suitable :-/
212 - return ':' . $this->getPrefixedText();
213 - } else {
214 - return $this->getPrefixedText();
215 - }
216 - }
217 -
218 - public function getHash() {
219 - return $this->isValid() ? $this->getPrefixedText():implode( "\t", $this->getErrors() );
220 - }
221 -
222 - protected function getServiceLinkParams() {
223 - $this->unstub();
224 - // Create links to mapping services based on a wiki-editable message. The parameters
225 - // available to the message are:
226 - // $1: urlencoded article name (no namespace)
227 - return array( rawurlencode( str_replace( '_', ' ', $this->m_dbkeyform ) ) );
228 - }
229 -
230 - public function getExportData() {
231 - if ( !$this->isValid() ) return null;
232 - switch ( $this->getNamespace() ) {
233 - case NS_MEDIA: // special handling for linking media files directly
234 - $file = wfFindFile( $this->getTitle() );
235 - if ( $file ) {
236 - // $name = $file->getFullURL();
237 - /// TODO: the following just emulates getFullURL() which is not yet available in MW1.11:
238 - $uri = $file->getUrl();
239 - if ( substr( $uri, 0, 1 ) == '/' ) {
240 - global $wgServer;
241 - $uri = $wgServer . $uri;
242 - }
243 - return new SMWExpData( new SMWExpResource( $uri, $this ) );
244 - } else { // Medialink to non-existing file :-/
245 - return null;
246 - }
247 - break;
248 - default: // some true wiki page
249 - return new SMWExpData( SMWExporter::getResourceElement( $this ) );
250 - break;
251 - }
252 - }
253 -
254 -///// special interface for wiki page values
255 -
256 - /**
257 - * Return according Title object or NULL if no valid value was set.
258 - * NULL can be returned even if this object returns TRUE for isValid(),
259 - * since the latter function does not check whether MediaWiki can really
260 - * make a Title out of the given data.
261 - * However, isValid() will return FALSE *after* this function failed in
262 - * trying to create a title.
263 - */
264 - public function getTitle() {
265 - if ( ( $this->isValid() ) && ( $this->m_title === null ) ) {
266 - if ( $this->m_interwiki == '' ) {
267 - $this->m_title = Title::makeTitle( $this->m_namespace, $this->m_dbkeyform );
268 - } else { // interwiki title objects must be built from full input texts
269 - $this->m_title = Title::newFromText( $this->getPrefixedText() );
270 - }
271 - }
272 - if ( $this->m_title === null ) { // should not normally happen, but anyway ...
273 - global $wgContLang;
274 - smwfLoadExtensionMessages( 'SemanticMediaWiki' );
275 - $this->addError( wfMsgForContent( 'smw_notitle', $wgContLang->getNsText( $this->m_namespace ) . ':' . $this->m_dbkeyform ) );
276 - $this->m_dbkeyform = '';
277 - }
278 - return $this->m_title;
279 - }
280 -
281 - /**
282 - * Get MediaWiki's ID for this value, if any.
283 - */
284 - public function getArticleID() {
285 - $this->unstub();
286 - if ( $this->m_id === false ) {
287 - $this->m_id = ( $this->getTitle() !== null ) ? $this->m_title->getArticleID():0;
288 - }
289 - return $this->m_id;
290 - }
291 -
292 - /**
293 - * Get namespace constant for this value, if any. Otherwise
294 - * return FALSE.
295 - */
296 - public function getNamespace() {
297 - return $this->isValid() ? $this->m_namespace:false;
298 - }
299 -
300 - /**
301 - * Get DBKey for this value. Subclasses that allow for vlaues that do not
302 - * correspond to wiki pages may choose a DB key that is not a legal title
303 - * DB key but rather another suitable internal ID. Thus it is not suitable
304 - * to use this method in places where only MediaWiki Title keys are allowed.
305 - */
306 - public function getDBkey() {
307 - $this->unstub();
308 - return $this->m_dbkeyform;
309 - }
310 -
311 - /// Get text label for this value.
312 - public function getText() {
313 - $this->unstub();
314 - return str_replace( '_', ' ', $this->m_dbkeyform );
315 - }
316 -
317 - /// Get the prefixed text for this value, including a localised namespace prefix.
318 - public function getPrefixedText() {
319 - global $wgContLang;
320 - $this->unstub();
321 - if ( $this->m_prefixedtext === false ) {
322 - $nstext = $wgContLang->getNSText( $this->m_namespace );
323 - $this->m_prefixedtext = $this->m_interwiki . ( $this->m_interwiki != '' ? ':':'' ) .
324 - $nstext . ( $nstext != '' ? ':':'' ) . $this->m_textform;
325 - }
326 - return $this->m_prefixedtext;
327 - }
328 -
329 - /**
330 - * Get interwiki prefix or empty string.
331 - */
332 - public function getInterwiki() {
333 - $this->unstub();
334 - return $this->m_interwiki;
335 - }
336 -
337 - /**
338 - * Get sortkey or make one as default.
339 - */
340 - public function getSortkey() {
341 - $this->unstub();
342 - return $this->m_sortkey ? $this->m_sortkey:( str_replace( '_', ' ', $this->m_dbkeyform ) );
343 - }
344 -
345 - /**
346 - * Set sortkey
347 - */
348 - public function setSortkey( $sortkey ) {
349 - $this->unstub(); // unstub first, since the stubarray also may hold a sortkey
350 - $this->m_sortkey = $sortkey;
351 - }
352 -
353 - /**
354 - * Init this data value object based on a given Title object.
355 - */
356 - public function setTitle( $title ) {
357 - $this->setDBkeys( array( $title->getDBkey(), $title->getNamespace(), $title->getInterwiki(), '' ) );
358 - $this->m_title = $title;
359 - }
360 -
361 - /**
362 - * Get the (default) caption for this value.
363 - * If a fixed namespace is set, we do not return the namespace prefix explicitly.
364 - */
365 - protected function getCaption() {
366 - return $this->m_caption !== false ? $this->m_caption:
367 - ( $this->m_fixNamespace == NS_MAIN ? $this->getPrefixedText():$this->getText() );
368 - }
369 -
370 - /**
371 - * @deprecated Use setDBkeys()
372 - */
373 - public function setValues( $dbkey, $namespace, $id = false, $interwiki = '', $sortkey = '' ) {
374 - $this->setDBkeys( array( $dbkey, $namespace, $interwiki, $sortkey ) );
375 - }
376 -
377 -}
378 -
Index: trunk/extensions/SemanticMediaWiki/includes/SMW_DV_Types.php
@@ -1,156 +0,0 @@
2 -<?php
3 -/**
4 - * @file
5 - * @ingroup SMWDataValues
6 - */
7 -
8 -/**
9 - * This datavalue implements special processing suitable for defining types of
10 - * properties. Types behave largely like values of type SMWSimpleWikiPageValue
11 - * with three main differnces. First, they actively check if a value is an
12 - * alias for another type, modifying the internal representation accordingly.
13 - * Second, they have a modified display for emphasizing if some type is defined
14 - * in SMW (built-in). Third, they use type ids for storing data (DB keys)
15 - * instead of using page titles.
16 - *
17 - * @author Markus Krötzsch
18 - * @ingroup SMWDataValues
19 - */
20 -class SMWTypesValue extends SMWSimpleWikiPageValue {
21 -
22 - private $m_isalias; // record whether this is an alias to another type, used to avoid duplicates when listing page types
23 - protected $m_reallabel;
24 -
25 - protected function parseUserValue( $value ) {
26 - parent::parseUserValue( $value );
27 - $this->m_reallabel = SMWDataValueFactory::findTypeLabel( SMWDataValueFactory::findTypeID( $this->m_textform ) );
28 - $this->m_isalias = ( $this->m_reallabel === $this->m_textform ) ? false:true;
29 - }
30 -
31 - protected function parseDBkeys( $args ) {
32 - parent::parseDBkeys( array( str_replace( ' ', '_', SMWDataValueFactory::findTypeLabel( $args[0] ) ) ) );
33 - $this->m_reallabel = $this->m_textform;
34 - $this->m_isalias = false;
35 - }
36 -
37 - public function getLongWikiText( $linked = null ) {
38 - $this->unstub();
39 - if ( ( $linked === null ) || ( $linked === false ) ) {
40 - return $this->m_reallabel;
41 - } else {
42 - global $wgContLang;
43 - $typenamespace = $wgContLang->getNsText( SMW_NS_TYPE );
44 - $id = SMWDataValueFactory::findTypeID( $this->m_reallabel );
45 - if ( $id { 0 } == '_' ) { // builtin
46 - smwfLoadExtensionMessages( 'SemanticMediaWiki' );
47 - SMWOutputs::requireHeadItem( SMW_HEADER_TOOLTIP );
48 - return '<span class="smwttinline"><span class="smwbuiltin">[[' . $typenamespace . ':' . $this->m_reallabel . '|' . $this->m_reallabel . ']]</span><span class="smwttcontent">' . wfMsgForContent( 'smw_isknowntype' ) . '</span></span>';
49 - } else {
50 - return '[[' . $typenamespace . ':' . $this->m_reallabel . '|' . $this->m_reallabel . ']]';
51 - }
52 - }
53 - }
54 -
55 - public function getLongHTMLText( $linker = null ) {
56 - $this->unstub();
57 - if ( ( $linker === null ) || ( $linker === false ) ) {
58 - return $this->m_reallabel;
59 - } else {
60 - $title = $this->m_isalias ? Title::newFromText( $this->m_reallabel, SMW_NS_TYPE ) : $this->getTitle();
61 - $id = SMWDataValueFactory::findTypeID( $this->m_reallabel );
62 - if ( $id { 0 } == '_' ) { // builtin
63 - smwfLoadExtensionMessages( 'SemanticMediaWiki' );
64 - SMWOutputs::requireHeadItem( SMW_HEADER_TOOLTIP );
65 - return '<span class="smwttinline"><span class="smwbuiltin">' .
66 - $linker->makeLinkObj( $title, $this->m_reallabel ) . '</span><span class="smwttcontent">' .
67 - wfMsgForContent( 'smw_isknowntype' ) . '</span></span>';
68 - } else {
69 - return $linker->makeLinkObj( $title, $this->m_reallabel );
70 - }
71 - }
72 - }
73 -
74 - public function getDBkeys() {
75 - return ( $this->isValid() ) ? array( $this->getDBkey() ):array( false );
76 - }
77 -
78 - public function getSignature() {
79 - return 't';
80 - }
81 -
82 - public function getValueIndex() {
83 - return 0;
84 - }
85 -
86 - public function getLabelIndex() {
87 - return 0;
88 - }
89 -
90 - public function getWikiValue() {
91 - return implode( '; ', $this->getTypeLabels() );
92 - }
93 -
94 - public function getHash() {
95 - return implode( "\t", $this->getTypeLabels() );
96 - }
97 -
98 - /**
99 - * This class uses type ids as DB keys.
100 - */
101 - public function getDBkey() {
102 - return ( $this->isValid() ) ? SMWDataValueFactory::findTypeID( $this->m_reallabel ):'';
103 - }
104 -
105 - /**
106 - * Is this a built-in datatype shipped with SMW (or an extension of SMW)?
107 - * (Alternatively it would be a user-defined derived datatype.)
108 - */
109 - public function isBuiltIn() {
110 - $v = $this->getDBkey();
111 - return ( ( $this->isUnary() ) && ( $v { 0 } == '_' ) );
112 - }
113 -
114 - /**
115 - * Is this an alias for another datatype in SMW? This information is used to
116 - * explain entries in Special:Types that are found since they have pages.
117 - */
118 - public function isAlias() {
119 - $this->unstub();
120 - return $this->m_isalias;
121 - }
122 -
123 - /**
124 - * Retrieve type labels if needed. Can be done lazily.
125 - */
126 - public function getTypeLabels() {
127 - $this->unstub();
128 - return array( $this->m_reallabel );
129 - }
130 -
131 - /**
132 - * Retrieve type captions if needed. Can be done lazily. The captions
133 - * are different from the labels if type aliases are used.
134 - */
135 - public function getTypeCaptions() {
136 - $this->unstub();
137 - return array( $this->m_textform );
138 - }
139 -
140 - /**
141 - * Retrieve type values.
142 - * @deprecated This method is no longer meaningful and will vanish before SMW 1.6
143 - */
144 - public function getTypeValues() {
145 - return array( $this );
146 - }
147 -
148 - /**
149 - * Is this a simple unary type or some composed n-ary type?
150 - * @deprecated This method is no longer meaningful and will vanish before SMW 1.6
151 - */
152 - public function isUnary() {
153 - return true;
154 - }
155 -
156 -}
157 -
Index: trunk/extensions/SemanticMediaWiki/includes/SMW_DV_Linear.php
@@ -1,226 +0,0 @@
2 -<?php
3 -/**
4 - * @file
5 - * @ingroup SMWDataValues
6 - */
7 -
8 -/**
9 - * This datavalue implements unit support custom units, for which users have
10 - * provided linear conversion factors within the wiki. Those user settings
11 - * are retrieved from a type page, the DB key of which is the type id of this
12 - * object.
13 - *
14 - * @author Markus Krötzsch
15 - * @ingroup SMWDataValues
16 - */
17 -class SMWLinearValue extends SMWNumberValue {
18 -
19 - protected $m_unitfactors = false; // array mapping canonical unit strings to conversion factors
20 - protected $m_unitids = false; // array mapping (normalised) unit strings to canonical unit strings (ids)
21 - protected $m_displayunits = false; // array of units that should be displayed
22 - protected $m_mainunit = false; // main unit (recognised by the conversion factor 1)
23 -
24 - /**
25 - * Converts the current m_value and m_unit to the main unit, if possible.
26 - * This means, it changes the fileds m_value and m_unit accordingly, and
27 - * that it stores the ID of the originally given unit in $this->m_unitin.
28 - * This should obviously not be done more than once, so it is advisable to
29 - * first check if m_unitin is non-false. Also, it should be checked if the
30 - * value is valid before trying to calculate with its contents.
31 - */
32 - protected function convertToMainUnit() {
33 - if ( $this->m_unitin !== false ) return;
34 - $this->initConversionData();
35 - if ( !$this->isValid() ) { // give up, avoid calculations with non-numbers
36 - $this->m_unitin = $this->m_unit;
37 - return;
38 - }
39 -
40 - // Find ID for current unit
41 - if ( array_key_exists( $this->m_unit, $this->m_unitids ) ) {
42 - $this->m_unitin = $this->m_unitids[$this->m_unit];
43 - } else { // already unit id (possibly of an unknown unit)
44 - $this->m_unitin = $this->m_unit;
45 - }
46 -
47 - // Do conversion
48 - if ( ( array_key_exists( $this->m_unitin, $this->m_unitfactors ) ) && ( $this->m_mainunit !== false ) ) {
49 - $this->m_unit = $this->m_mainunit;
50 - $this->m_value = $this->m_value / $this->m_unitfactors[$this->m_unitin];
51 - } // else: unsupported unit, keep all as it is
52 - }
53 -
54 - /**
55 - * This method creates an array of unit-value-pairs that should be
56 - * printed. Units are the keys and should be canonical unit IDs.
57 - * The result is stored in $this->m_unitvalues. Again, any class that
58 - * requires effort for doing this should first check whether the array
59 - * is already set (i.e. not false) before doing any work.
60 - * Note that the values should be plain numbers. Output formatting is done
61 - * later when needed. Also, it should be checked if the value is valid
62 - * before trying to calculate with its contents.
63 - * This method also must call or implement convertToMainUnit().
64 - */
65 - protected function makeConversionValues() {
66 - if ( $this->m_unitvalues !== false ) return;
67 - $this->convertToMainUnit();
68 - if ( $this->m_unit !== $this->m_mainunit ) { // conversion failed, no choice for us
69 - $this->m_unitvalues = array( $this->m_unit => $this->m_value );
70 - return;
71 - }
72 - $this->initDisplayData();
73 -
74 - $this->m_unitvalues = array();
75 - if ( count( $this->m_displayunits ) == 0 ) { // no display units, just show all
76 - foreach ( $this->m_unitfactors as $unit => $factor ) {
77 - $this->m_unitvalues[$unit] = $this->m_value * $factor;
78 - }
79 - } else {
80 - foreach ( $this->m_displayunits as $unit ) { // do not use unit ids here (requires a small hack below, but allows to select representation of unit via displayunits)
81 - if ( array_key_exists( $this->m_unitids[$unit], $this->m_unitfactors ) ) {
82 - $this->m_unitvalues[$unit] = $this->m_value * $this->m_unitfactors[$this->m_unitids[$unit]];
83 - if ( $this->m_unitids[$unit] == $this->m_unitin ) { // use the display unit version of the input unit as id
84 - $this->m_unitin = $unit;
85 - }
86 - }
87 - }
88 - if ( count( $this->m_unitvalues ) == 0 ) { // none of the desired units matches
89 - // display just the current one (so one can disable unit tooltips by setting a nonunit for display)
90 - $this->m_unitvalues = array( $this->m_unit => $this->m_value );
91 - }
92 - }
93 - }
94 -
95 - /**
96 - * This method is used when no user input was given to find the best
97 - * values for m_wikivalue, m_unitin, and m_caption. After conversion,
98 - * these fields will look as if they were generated from user input,
99 - * and convertToMainUnit() will have been called (if not, it would be
100 - * blocked by the presence of m_unitin).
101 - */
102 - protected function makeUserValue() {
103 - $this->convertToMainUnit();
104 -
105 - $value = false;
106 - if ( $this->m_unit === $this->m_mainunit ) { // only try if conversion worked
107 - if ( ( $value === false ) && ( $this->m_outformat ) && ( $this->m_outformat != '-' ) ) { // first try given output unit
108 - $unit = $this->normalizeUnit( $this->m_outformat );
109 - $printunit = $unit;
110 - if ( array_key_exists( $unit, $this->m_unitids ) ) { // find id for output unit
111 - $unit = $this->m_unitids[$unit];
112 - if ( array_key_exists( $unit, $this->m_unitfactors ) ) { // find factor for this id
113 - $value = $this->m_value * $this->m_unitfactors[$unit];
114 - }
115 - }
116 - }
117 - if ( $value === false ) { // next look for the first given display unit
118 - $this->initDisplayData();
119 - if ( count( $this->m_displayunits ) > 0 ) {
120 - $unit = $this->m_unitids[$this->m_displayunits[0]]; // was already verified to exist before
121 - if ( array_key_exists( $unit, $this->m_unitfactors ) ) { // find factor for this id
122 - $value = $this->m_value * $this->m_unitfactors[$unit];
123 - $printunit = $this->m_displayunits[0];
124 - }
125 - }
126 - }
127 - }
128 -
129 - if ( $value === false ) { // finally fallback to current value
130 - $value = $this->m_value;
131 - $unit = $this->m_unit;
132 - $printunit = $unit;
133 - }
134 -
135 - $this->m_caption = '';
136 - if ( $this->m_outformat != '-u' ) { // -u is the format for displaying the unit only
137 - $this->m_caption .= ( ( $this->m_outformat != '-' ) && ( $this->m_outformat != '-n' ) ? smwfNumberFormat( $value ) : $value );
138 - }
139 - if ( ( $printunit != '' ) && ( $this->m_outformat != '-n' ) ) { // -n is the format for displaying the number only
140 - if ( $this->m_outformat != '-u' ) {
141 - $this->m_caption .= ( $this->m_outformat != '-' ? '&#160;' : ' ' );
142 - }
143 - $this->m_caption .= $printunit;
144 - }
145 - $this->m_wikivalue = $this->m_caption;
146 - $this->m_unitin = $unit;
147 - }
148 -
149 - /**
150 - * Return an array of major unit strings (ids only recommended) supported by
151 - * this datavalue.
152 - */
153 - public function getUnitList() {
154 - $this->initConversionData();
155 - return array_keys( $this->m_unitfactors );
156 - }
157 -
158 -/// The remaining functions are relatively "private" but are kept protected since
159 -/// subclasses might exploit this to, e.g., "fake" conversion factors instead of
160 -/// getting them from the database. A cheap way of making built-in types.
161 -
162 - /**
163 - * This method fills $m_unitfactors and $m_unitids with required values.
164 - */
165 - protected function initConversionData() {
166 - if ( $this->m_unitids !== false ) return;
167 - $this->m_unitids = array();
168 - $this->m_unitfactors = array();
169 -
170 - $typepage = SMWWikiPageValue::makePage( $this->m_typeid, SMW_NS_TYPE );
171 - if ( !$typepage->isValid() ) return;
172 - $factors = smwfGetStore()->getPropertyValues( $typepage, SMWPropertyValue::makeProperty( '_CONV' ) );
173 - if ( count( $factors ) == 0 ) { // no custom type
174 - // delete all previous errors, this is our real problem
175 - /// TODO: probably we should check for this earlier, but avoid unnecessary DB requests ...
176 - smwfLoadExtensionMessages( 'SemanticMediaWiki' );
177 - $this->addError( wfMsgForContent( 'smw_unknowntype', SMWDataValueFactory::findTypeLabel( $this->getTypeID() ) ) );
178 - return;
179 - }
180 - $numdv = SMWDataValueFactory::newTypeIDValue( '_num' ); // used for parsing the factors
181 - foreach ( $factors as $dv ) {
182 - $numdv->setUserValue( $dv->getWikiValue() );
183 - if ( !$numdv->isValid() || ( $numdv->getValueKey() === 0 ) ) {
184 - continue; // ignore problematic conversions
185 - }
186 - $unit_aliases = preg_split( '/\s*,\s*/u', $numdv->getUnit() );
187 - $first = true;
188 - foreach ( $unit_aliases as $unit ) {
189 - $unit = $this->normalizeUnit( $unit );
190 - if ( $first ) {
191 - $unitid = $unit;
192 - if ( $numdv->getValueKey() == 1 ) { // add main unit to front of array (displyed first)
193 - $this->m_mainunit = $unit;
194 - $this->m_unitfactors = array( $unit => $numdv->getValueKey() ) + $this->m_unitfactors;
195 - } else { // non-main units are not ordered -- they might come out in any way the DB likes (can be modified via display units)
196 - $this->m_unitfactors[$unit] = $numdv->getValueKey();
197 - }
198 - $first = false;
199 - }
200 - // add all known units to m_unitids to simplify checking for them
201 - $this->m_unitids[$unit] = $unitid;
202 - }
203 - }
204 - }
205 -
206 - /**
207 - * This method fills $m_displayunits.
208 - */
209 - protected function initDisplayData() {
210 - if ( $this->m_displayunits !== false ) return;
211 - $this->initConversionData(); // needed to normalise unit strings
212 - $this->m_displayunits = array();
213 - if ( ( $this->m_property === null ) || ( $this->m_property->getWikiPageValue() === null ) ) return;
214 - $values = smwfGetStore()->getPropertyValues( $this->m_property->getWikiPageValue(), SMWPropertyValue::makeProperty( '_UNIT' ) );
215 - $units = array();
216 - foreach ( $values as $value ) { // Join all if many annotations exist. Discouraged (random order) but possible.
217 - $units = $units + preg_split( '/\s*,\s*/u', $value->getWikiValue() );
218 - }
219 - foreach ( $units as $unit ) {
220 - $unit = $this->normalizeUnit( $unit );
221 - if ( array_key_exists( $unit, $this->m_unitids ) ) {
222 - $this->m_displayunits[] = $unit; // avoid duplicates
223 - } // note: we ignore unsuppported units, as they are printed anyway for lack of alternatives
224 - }
225 - }
226 -
227 -}
Index: trunk/extensions/SemanticMediaWiki/includes/SMW_DV_Record.php
@@ -1,249 +0,0 @@
2 -<?php
3 -/**
4 - * @file
5 - * @ingroup SMWDataValues
6 - */
7 -
8 -/**
9 - * SMWDataValue implements the handling of short lists of values,
10 - * where the order governs the type of each entry.
11 - *
12 - * @todo Enforce limitation of maximal number of values.
13 - * @todo Complete internationalisation.
14 - *
15 - * @author Markus Krötzsch
16 - * @ingroup SMWDataValues
17 - */
18 -class SMWRecordValue extends SMWContainerValue {
19 -
20 - /// cache for datavalues of types belonging to this object
21 - private $m_typevalues = null;
22 -
23 - protected function parseUserValue( $value ) {
24 - $this->m_data->clear();
25 - $this->parseUserValueOrQuery( $value, false );
26 - }
27 -
28 - protected function parseUserValueOrQuery( $value, $querymode ) {
29 - if ( $value == '' ) {
30 - $this->addError( wfMsg( 'smw_novalues' ) );
31 - return $querymode ? new SMWThingDescription():$this->m_data;
32 - }
33 -
34 - $subdescriptions = array(); // only used for query mode
35 - $types = $this->getTypeValues();
36 - $values = preg_split( '/[\s]*;[\s]*/u', trim( $value ) );
37 - $vi = 0; // index in value array
38 - $empty = true;
39 - for ( $i = 0; $i < max( 5, count( $types ) ); $i++ ) { // iterate over slots
40 - // special handling for supporting query parsing
41 - if ( $querymode ) {
42 - $comparator = SMW_CMP_EQ;
43 - SMWDataValue::prepareValue( $values[$vi], $comparator );
44 - }
45 - // generating the DVs:
46 - if ( ( count( $values ) > $vi ) &&
47 - ( ( $values[$vi] == '' ) || ( $values[$vi] == '?' ) ) ) { // explicit omission
48 - $vi++;
49 - } elseif ( array_key_exists( $vi, $values ) && array_key_exists( $i, $types ) ) { // some values left, try next slot
50 - $dv = SMWDataValueFactory::newTypeObjectValue( $types[$i], $values[$vi] );
51 - if ( $dv->isValid() ) { // valid DV: keep
52 - if ( $querymode ) {
53 - $subdescriptions[] = new SMWRecordFieldDescription( $i, new SMWValueDescription( $dv, $comparator ) );
54 - } else {
55 - $property = SMWPropertyValue::makeProperty( '_' . ( $i + 1 ) );
56 - $this->m_data->addPropertyObjectValue( $property, $dv );
57 - }
58 - $vi++;
59 - $empty = false;
60 - } elseif ( ( count( $values ) - $vi ) == ( count( $types ) - $i ) ) {
61 - // too many errors: keep this one to have enough slots left
62 - $this->m_data->addPropertyObjectValue( SMWPropertyValue::makeProperty( '_' . ( $i + 1 ) ), $dv );
63 - $this->addError( $dv->getErrors() );
64 - $vi++;
65 - }
66 - }
67 - }
68 - if ( $empty ) {
69 - $this->addError( wfMsg( 'smw_novalues' ) );
70 - }
71 - if ( $querymode ) {
72 - return $empty ? new SMWThingDescription():new SMWRecordDescription( $subdescriptions );
73 - }
74 - }
75 -
76 - /**
77 - * This function resembles SMWContainerValue::parseDBkeys() but it already unstubs
78 - * the values instead of passing on initialisation strings. This is required since
79 - * the datatype of each entry is not determined by the property here (since we are
80 - * using generic _1, _2, ... properties that can have any type).
81 - */
82 - protected function parseDBkeys( $args ) {
83 - $this->m_data->clear();
84 - $types = $this->getTypeValues();
85 - if ( count( $args ) > 0 ) {
86 - foreach ( reset( $args ) as $value ) {
87 - if ( is_array( $value ) && ( count( $value ) == 2 ) ) {
88 - $property = SMWPropertyValue::makeProperty( reset( $value ) );
89 - $pnum = intval( substr( reset( $value ), 1 ) ); // try to find the number of this property
90 - if ( array_key_exists( $pnum - 1, $types ) ) {
91 - $dv = SMWDataValueFactory::newTypeObjectValue( $types[$pnum - 1] );
92 - $dv->setDBkeys( end( $value ) );
93 - $this->m_data->addPropertyObjectValue( $property, $dv );
94 - }
95 - }
96 - }
97 - }
98 - }
99 -
100 - /**
101 - * Overwrite SMWDataValue::getQueryDescription() to be able to process
102 - * comparators between all values.
103 - */
104 - public function getQueryDescription( $value ) {
105 - return $this->parseUserValueOrQuery( $value, true );
106 - }
107 -
108 - public function getShortWikiText( $linked = null ) {
109 - if ( $this->m_caption !== false ) {
110 - return $this->m_caption;
111 - }
112 - return $this->makeOutputText( 0, $linked );
113 - }
114 -
115 - public function getShortHTMLText( $linker = null ) {
116 - if ( $this->m_caption !== false ) {
117 - return $this->m_caption;
118 - }
119 - return $this->makeOutputText( 1, $linker );
120 - }
121 -
122 - public function getLongWikiText( $linked = null ) {
123 - return $this->makeOutputText( 2, $linked );
124 - }
125 -
126 - public function getLongHTMLText( $linker = null ) {
127 - return $this->makeOutputText( 3, $linker );
128 - }
129 -
130 - public function getWikiValue() {
131 - return $this->makeOutputText( 4 );
132 - }
133 -
134 - /// @todo Allowed values for multi-valued properties are not supported yet.
135 - protected function checkAllowedValues() { }
136 -
137 - /**
138 - * Make sure that the content is reset in this case.
139 - * @todo This is not a full reset yet (the case that property is changed after a value
140 - * was set does not occur in the normal flow of things, hence this has low priority).
141 - */
142 - public function setProperty( SMWPropertyValue $property ) {
143 - parent::setProperty( $property );
144 - $this->m_typevalues = null;
145 - }
146 -
147 - /**
148 - * @todo Since containers are always exported in a similar fashion, it
149 - * would be preferrable to have their export controlled where it happens,
150 - * and minimize the below special code.
151 - */
152 - public function getExportData() {
153 - if ( !$this->isValid() ) return null;
154 -
155 - $result = new SMWExpData( new SMWExpElement( '', $this ) ); // bnode
156 - $ed = new SMWExpData( SMWExporter::getSpecialElement( 'swivt', 'Container' ) );
157 - $result->addPropertyObjectValue( SMWExporter::getSpecialElement( 'rdf', 'type' ), $ed );
158 - $count = 0;
159 - foreach ( $this->getDVs() as $value ) {
160 - $count++;
161 - if ( ( $value === null ) || ( !$value->isValid() ) ) {
162 - continue;
163 - }
164 - if ( ( $value->getTypeID() == '_wpg' ) || ( $value->getTypeID() == '_uri' ) || ( $value->getTypeID() == '_ema' ) ) {
165 - $result->addPropertyObjectValue(
166 - SMWExporter::getSpecialElement( 'swivt', 'object' . $count ),
167 - $value->getExportData() );
168 - } else {
169 - $result->addPropertyObjectValue(
170 - SMWExporter::getSpecialElement( 'swivt', 'value' . $count ),
171 - $value->getExportData() );
172 - }
173 - }
174 - return $result;
175 - }
176 -
177 -////// Additional API for value lists
178 -
179 - /**
180 - * Create a list (array with numeric keys) containing the datavalue objects
181 - * that this SMWRecordValue object holds. Values that are not present are
182 - * set to null. Note that the first index in the array is 0, not 1.
183 - */
184 - public function getDVs() {
185 - if ( !$this->isValid() ) return array();
186 - $result = array();
187 - foreach ( $this->m_data->getProperties() as $prop ) {
188 - $propname = $prop->getPropertyID();
189 - $propnum = substr( $propname, 1 );
190 - if ( ( $propname != false ) && ( is_numeric( $propnum ) ) ) {
191 - $result[( $propnum - 1 )] = reset( $this->m_data->getPropertyValues( $prop ) );
192 - }
193 - }
194 - return $result;
195 - }
196 -
197 - /**
198 - * Return the array (list) of datatypes that the individual entries of this datatype consist of.
199 - * @todo Add some check to account for maximal number of list entries (maybe this should go to a
200 - * variant of the SMWTypesValue).
201 - */
202 - public function getTypeValues() {
203 - if ( $this->m_typevalues !== null ) return $this->m_typevalues; // local cache
204 - if ( ( $this->m_property === null ) || ( $this->m_property->getWikiPageValue() === null ) ) {
205 - $this->m_typevalues = array(); // no property known -> no types
206 - } else { // query for type values
207 - $typelist = smwfGetStore()->getPropertyValues( $this->m_property->getWikiPageValue(), SMWPropertyValue::makeProperty( '_LIST' ) );
208 - if ( count( $typelist ) == 1 ) {
209 - $this->m_typevalues = reset( $typelist )->getTypeValues();
210 - } else { ///TODO internalionalize
211 - $this->addError( 'List type not properly specified for this property.' );
212 - $this->m_typevalues = array();
213 - }
214 - }
215 - return $this->m_typevalues;
216 - }
217 -
218 -////// Internal helper functions
219 -
220 - private function makeOutputText( $type = 0, $linker = null ) {
221 - if ( !$this->isValid() ) {
222 - return ( ( $type == 0 ) || ( $type == 1 ) ) ? '' : $this->getErrorText();
223 - }
224 - $result = '';
225 - for ( $i = 0; $i < count( $this->getTypeValues() ); $i++ ) {
226 - if ( $i == 1 ) {
227 - $result .= ( $type == 4 ) ? '; ':' (';
228 - } elseif ( $i > 1 ) {
229 - $result .= ( $type == 4 ) ? '; ':", ";
230 - }
231 - $property = SMWPropertyValue::makeProperty( '_' . ( $i + 1 ) );
232 - $dv = reset( $this->m_data->getPropertyValues( $property ) );
233 - $result .= ( $dv !== false ) ? $this->makeValueOutputText( $type, $dv, $linker ): '?';
234 - }
235 - if ( ( $i > 1 ) && ( $type != 4 ) ) $result .= ')';
236 - return $result;
237 - }
238 -
239 - private function makeValueOutputText( $type, $datavalue, $linker ) {
240 - switch ( $type ) {
241 - case 0: return $datavalue->getShortWikiText( $linker );
242 - case 1: return $datavalue->getShortHTMLText( $linker );
243 - case 2: return $datavalue->getShortWikiText( $linker );
244 - case 3: return $datavalue->getShortHTMLText( $linker );
245 - case 4: return $datavalue->getWikiValue();
246 - }
247 - }
248 -
249 -}
250 -
Index: trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_Temperature.php
@@ -0,0 +1,160 @@
 2+<?php
 3+/**
 4+ * @file
 5+ * @ingroup SMWDataValues
 6+ */
 7+
 8+/**
 9+ * This datavalue implements unit support for measuring temperatures. This is
 10+ * mostly an example implementation of how to realise custom unit types easily.
 11+ *
 12+ * @author Markus Krötzsch
 13+ * @ingroup SMWDataValues
 14+ */
 15+class SMWTemperatureValue extends SMWNumberValue {
 16+
 17+ /**
 18+ * Converts the current m_value and m_unit to the main unit, if possible.
 19+ * This means, it changes the fileds m_value and m_unit accordingly, and
 20+ * that it stores the ID of the originally given unit in $this->m_unitin.
 21+ * This should obviously not be done more than once, so it is advisable to
 22+ * first check if m_unitin is non-false. Also, it should be checked if the
 23+ * value is valid before trying to calculate with its contents.
 24+ */
 25+ protected function convertToMainUnit() {
 26+ if ( $this->m_unitin !== false ) return;
 27+ if ( !$this->isValid() ) { // give up, avoid calculations with non-numbers
 28+ $this->m_unitin = $this->m_unit;
 29+ return;
 30+ }
 31+
 32+ // Find current ID and covert main values to Kelvin, if possible
 33+ // Note: there is no error when unknown units are used.
 34+ $this->m_unitin = $this->getUnitID( $this->m_unit );
 35+ switch ( $this->m_unitin ) {
 36+ case 'K':
 37+ $this->m_unit = 'K';
 38+ break;
 39+ case '°C':
 40+ $this->m_unit = 'K';
 41+ $this->m_value = $this->m_value + 273.15;
 42+ break;
 43+ case '°F':
 44+ $this->m_unit = 'K';
 45+ $this->m_value = ( $this->m_value - 32 ) / 1.8 + 273.15;
 46+ break;
 47+ case '°R':
 48+ $this->m_unit = 'K';
 49+ $this->m_value = ( $this->m_value ) / 1.8;
 50+ break;
 51+ default: // unsupported unit
 52+ // create error here, assuming that our temperature units should not be augmented by unknown units
 53+ smwfLoadExtensionMessages( 'SemanticMediaWiki' );
 54+ $this->addError( wfMsgForContent( 'smw_unsupportedunit', $this->m_unit ) );
 55+ $this->m_unit = $this->m_unitin;
 56+ break;
 57+ }
 58+ }
 59+
 60+ /**
 61+ * This method creates an array of unit-value-pairs that should be
 62+ * printed. Units are the keys and should be canonical unit IDs.
 63+ * The result is stored in $this->m_unitvalues. Again, any class that
 64+ * requires effort for doing this should first check whether the array
 65+ * is already set (i.e. not false) before doing any work.
 66+ * Note that the values should be plain numbers. Output formatting is done
 67+ * later when needed. Also, it should be checked if the value is valid
 68+ * before trying to calculate with its contents.
 69+ * This method also must call or implement convertToMainUnit().
 70+ */
 71+ protected function makeConversionValues() {
 72+ if ( $this->m_unitvalues !== false ) return;
 73+ $this->convertToMainUnit();
 74+ $this->m_unitvalues = array( $this->m_unit => $this->m_value );
 75+ if ( $this->isValid() && ( $this->m_unit == 'K' ) ) {
 76+ $this->m_unitvalues['°C'] = $this->m_value - 273.15;
 77+ $this->m_unitvalues['°F'] = ( $this->m_value - 273.15 ) * 1.8 + 32;
 78+ $this->m_unitvalues['°R'] = ( $this->m_value ) * 1.8;
 79+ }
 80+ }
 81+
 82+ /**
 83+ * This method is used when no user input was given to find the best
 84+ * values for m_wikivalue, m_unitin, and m_caption. After conversion,
 85+ * these fields will look as if they were generated from user input,
 86+ * and convertToMainUnit() will have been called (if not, it would be
 87+ * blocked by the presence of m_unitin).
 88+ */
 89+ protected function makeUserValue() {
 90+ $this->convertToMainUnit();
 91+
 92+ $value = false;
 93+ if ( ( $this->m_unit === 'K' ) && $this->m_outformat && ( $this->m_outformat != '-' ) ) { // try given output unit (only if conversion worked)
 94+ $unit = $this->getUnitID( $this->normalizeUnit( $this->m_outformat ) );
 95+ $printunit = $this->m_outformat;
 96+ switch ( $unit ) {
 97+ case 'K':
 98+ $value = $this->m_value;
 99+ break; // nothing to do
 100+ case '°C':
 101+ $value = $this->m_value - 273.15;
 102+ break;
 103+ case '°F':
 104+ $value = ( $this->m_value - 273.15 ) * 1.8 + 32;
 105+ break;
 106+ case '°R':
 107+ $value = ( $this->m_value ) * 1.8;
 108+ break;
 109+ // default: unit not supported
 110+ }
 111+ }
 112+ if ( $value === false ) { // finally fallback to current value
 113+ $value = $this->m_value;
 114+ $unit = $this->m_unit;
 115+ $printunit = $unit;
 116+ }
 117+
 118+ $this->m_caption = smwfNumberFormat( $value );
 119+ if ( $printunit != '' ) {
 120+ $this->m_caption .= '&#160;' . $printunit;
 121+ }
 122+ $this->m_wikivalue = $this->m_caption;
 123+ $this->m_unitin = $unit;
 124+ }
 125+
 126+
 127+
 128+ /**
 129+ * Helper method to find the main representation of a certain unit.
 130+ */
 131+ protected function getUnitID( $unit ) {
 132+ /// TODO possibly localise some of those strings
 133+ switch ( $unit ) {
 134+ case '': case 'K': case 'Kelvin': case 'kelvin': case 'kelvins':
 135+ return 'K';
 136+ // There's a dedicated Unicode character (℃, U+2103) for degrees C.
 137+ // Your font may or may not display it; do not be alarmed.
 138+ case '°C': case '℃': case 'Celsius': case 'centigrade':
 139+ return '°C';
 140+ break;
 141+ case '°F': case 'Fahrenheit':
 142+ return '°F';
 143+ break;
 144+ case '°R': case 'Rankine':
 145+ return '°R';
 146+ break;
 147+ default: // unsupported unit
 148+ return $unit;
 149+ break;
 150+ }
 151+ }
 152+
 153+ /**
 154+ * Return an array of major unit strings (ids only recommended) supported by
 155+ * this datavalue.
 156+ */
 157+ public function getUnitList() {
 158+ return array( 'K', '°C', '°F', '°R' );
 159+ }
 160+
 161+}
Property changes on: trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_Temperature.php
___________________________________________________________________
Added: svn:eol-style
1162 + native
Index: trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_Time.php
@@ -0,0 +1,856 @@
 2+<?php
 3+/**
 4+ * @file
 5+ * @ingroup SMWDataValues
 6+ */
 7+
 8+/**
 9+ * This datavalue captures values of dates and times. All dates and times refer to
 10+ * Coordinated Universal Time (UTC), or the local time of the wiki server.
 11+ * A wiki may define what timezone this refers to by common conventions.
 12+ * For export, times are given without timezone information. However, time offsets to
 13+ * that local time, or to UTC, are supported (see below). The difference is arbitrary.
 14+ *
 15+ * Dates can be given in many formats, using numbers, month names, and abbreviated
 16+ * month names. The preferred interpretation of ambiguous dates ("1 2 2008" or even
 17+ * "1 2 3 BC") is controlled by the language file, as is the local naming of months.
 18+ * English month names are always supported.
 19+ *
 20+ * Currently, the twelve-hour clock annotations "am" and "pm", and the calendar
 21+ * symbols "BC", "AD", "Gr", "Jl", "JD", "MJD", and "OS" are supported,
 22+ * and localised to most SMW-supported languages. Civilian and military time-zone monikers
 23+ * are also supported; these do not require internationalization, except perhaps into
 24+ * Cyrillic. Cyrillic support will be added when deemed necessary.
 25+ *
 26+ * The standard calendar model is the Gregorian calendar, inaugurated October 15, 1582.
 27+ * Tooltip outputs in the Gregorian or proleptic Gregorian calendar (for dates earlier
 28+ * than the proclamation date) always appear. However, the printout for browsing or
 29+ * queries will be governed by the expressed preference, so that annotation in certain
 30+ * calendar models will be preserved at query or browse. All annotated dates will *sort*
 31+ * by a common key, regardless of model. (See below for details.)
 32+ *
 33+ * By default, a date annotated without preference is always treated as a Gregorian
 34+ * calendar date (if later than October 4, 1582), or a Julian calendar date (if October
 35+ * 4, 1582 or earlier). But users may override the default interpretation by specifying
 36+ * the symbols "Gr" or "Jl", as appropriate, for any date falling within the Common Era
 37+ * (aka Anno Domini). The annotation of a proleptic Gregorian date *before* the common
 38+ * era is not supported; all BC(E) dates are treated as Julian. However, the proleptic
 39+ * Gregorian date will appear in the tooltip.
 40+ *
 41+ * The "OS" (Old Style) symbol is supported in English, and dates annotated with this
 42+ * symbol are processed accordingly: the year is incremented by one if the date falls
 43+ * between 1 January and 24 March inclusive, and the resultant day is converted
 44+ * according to Julian rules. The printout will be Julian or Gregorian, according to the
 45+ * epoch. As before, the tooltip dialog will show a Gregorian or proleptic Gregorian date.
 46+ *
 47+ * The primary sort key for this datatype is the Julian Day, developed by J. J. Scaliger.
 48+ * All dates are converted to JD and back-converted to the supported models for purposes
 49+ * of output and captioning. In addition, this datatype supports the direct annotation of
 50+ * a JD or a Modified Julian Day (MJD), which might be given in an astronomical table or
 51+ * the flight schedule of a spacecraft, satellite, or rocket probe. For dates falling
 52+ * earlier than midnight 1 January 4713 BC(E) (Julian), the program stores a negative
 53+ * value consisting of the year (as a negative integer) and a fraction of a year. For
 54+ * all other dates, the type stores the conventional JD, normalized to noon UTC.
 55+ *
 56+ * As such, this type can handle dates across history with full precision for storing,
 57+ * and substantial precision for sorting and querying. The range of supported past
 58+ * dates should encompass the Beginning of Time according to most of today's theories.
 59+ * The range of supported future dates is limited more strictly, but it does also allow
 60+ * year numbers in the order of 10^9.
 61+ *
 62+ * Years before common era (aka BC) can be denoted using "BC" in a date. The internal
 63+ * numeric date model supports the year 0, and considers it to be the same as "1 BC"
 64+ * in the Julian calendar. (The proleptic Gregorian calendar accepts a year of 0, but
 65+ * this usage is not permitted here). All outputs follow ISO6801 and the remarks in
 66+ * XML Schema Datatypes 2nd Edition (the latter uses a different convention that
 67+ * disallows year 0, but it explicitly endorses the ISO convention and announces the
 68+ * future use of this in XML). Note that the implementation currently does not support
 69+ * the specification of negative year numbers as input; negative numbers are only used
 70+ * internally. Likewise, "proleptic" negative He and AM inputs are not allowed.
 71+ *
 72+ * The implementation notices and stores whether parts of a date/time have been
 73+ * omitted (as in "2008" or "May 2007"). For all exporting and sorting purposes,
 74+ * incomplete dates are completed with defaults (usually using the earliest possible
 75+ * time, i.e. interpreting "2008" as "Jan 1 2008 00:00:00"). The information
 76+ * on what was unspecified is kept internally for improving behaviour e.g. for
 77+ * outputs (defaults are not printed when querying for a value). Functions are
 78+ * provided to access the individual time components (getYear, getMonth, getDay,
 79+ * getTimeString), and those can also be used to find out what was unspecified.
 80+ *
 81+ * Time offsets are supported (e.g. "1 1 2008 12:00-2:00"). A time offset is the number
 82+ * of hours:minutes to be added to UTC (GMT) to obtain the local-clock reading. Time zone
 83+ * monikers (EST, CST, CET, MEZ, etc.) and military time (e.g. 1240Z, equivalent to 12:40
 84+ * UTC) are also supported.
 85+ *
 86+ * Time offsets take leap years into account, e.g. the date
 87+ * "Feb 28 2004 23:00+2:00" is equivalent to "29 February 2004 01:00:00", while
 88+ * "Feb 28 1900 23:00+2:00" is equivalent to "1 March 1900 01:00:00".
 89+ *
 90+ * @todo Add support for additional calendar models (mainly requires conversion algorithms and
 91+ * internationalization support).
 92+ * @todo Try to reuse more of MediaWiki's records, e.g. to obtain month names or to
 93+ * format dates. The problem is that MW is based on SIO timestamps that don't extend to
 94+ * very ancient or future dates, and that MW uses PHP functions that are bound to UNIX time.
 95+ *
 96+ * @author Fabian Howahl
 97+ * @author Terry A. Hurlbut
 98+ * @author Markus Krötzsch
 99+ * @ingroup SMWDataValues
 100+ */
 101+class SMWTimeValue extends SMWDataValue {
 102+
 103+ protected $m_wikivalue; // a suitable wiki input value
 104+ protected $m_xsdvalue = false; // cache for DB key
 105+ protected $m_gregvalue = false; // cache for (proleptic) Gregorian value
 106+ protected $m_julvalue = false; // cache for (proleptic) Julian value
 107+ protected $m_pref = false; // holds a symbol for the calendar model
 108+ protected $m_day = false; // Gregorian day, remains false if unspecified
 109+ protected $m_month = false; // Gregorian month, remains false if unspecified
 110+ protected $m_year = false; // Gregorian year, remains false if unspecified
 111+ protected $m_time = false; // time, remains false if unspecified
 112+ protected $m_jd = 0; // numerical time representation similiar to Julian Day; for ancient times, a more compressed number is used (preserving ordering of time points)
 113+ protected $m_format = false; // number of parts of the date that were specified
 114+ protected $m_outformat = false; // A special code governing printout formats.
 115+ protected $m_timeoffset; // contains offset (e.g. timezone)
 116+ protected $m_timeannotation; // contains am or pm
 117+ protected $m_dayj = false; // Julian day, remains false if unspecified
 118+ protected $m_monthj = false; // Julian month, remains false if unspecified
 119+ protected $m_yearj = false; // Julian year, remains false if unspecified
 120+ // The following are constant (array-valued constants are not supported, hence the declaration as private static variable):
 121+ private static $m_months = array( "January", "February", "March", "April" , "May" , "June" , "July" , "August" , "September" , "October" , "November" , "December" );
 122+ private static $m_monthsshort = array( "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" );
 123+ private static $m_formats = array( SMW_Y => array( 'year' ), SMW_YM => array( 'year', 'month' ), SMW_MY => array( 'month', 'year' ), SMW_YDM => array( 'year', 'day', 'month' ), SMW_YMD => array( 'year', 'month', 'day' ), SMW_DMY => array( 'day', 'month', 'year' ), SMW_MDY => array( 'month', 'day', 'year' ) );
 124+ private static $m_daysofmonths = array ( 1 => 31, 2 => 29, 3 => 31, 4 => 30, 5 => 31, 6 => 30, 7 => 31, 8 => 31, 9 => 30, 10 => 31, 11 => 30, 12 => 31 );
 125+ private static $m_daysofmonthsam = array ( 1 => 30, 2 => 30, 3 => 30, 4 => 30, 5 => 30, 6 => 30, 7 => 30, 8 => 30, 9 => 30, 10 => 30, 11 => 30, 12 => 60 );
 126+ // Time zone monikers and their associated offsets in hours and fractions of hours
 127+ private static $m_tz = array( "A" => 1, "ACDT" => 10.5, "ACST" => 9.5, "ADT" => - 3, "AEDT" => 11,
 128+ "AEST" => 10, "AKDT" => - 8, "AKST" => - 9, "AST" => - 4, "AWDT" => 9, "AWST" => 8,
 129+ "B" => 2, "BST" => 1, "C" => 3, "CDT" => - 5, "CEDT" => 2, "CEST" => 2,
 130+ "CET" => 1, "CST" => - 6, "CXT" => 7, "D" => 4, "E" => 5, "EDT" => - 4,
 131+ "EEDT" => 3, "EEST" => 3, "EET" => 2, "EST" => - 5, "F" => 6, "G" => 7,
 132+ "GMT" => 0, "H" => 8, "HAA" => - 3, "HAC" => - 5, "HADT" => - 9, "HAE" => - 4,
 133+ "HAP" => - 7, "HAR" => - 6, "HAST" => - 10, "HAT" => - 2.5, "HAY" => - 8,
 134+ "HNA" => - 4, "HNC" => - 6, "HNE" => - 5, "HNP" => - 8, "HNR" => - 7, "HNT" => - 3.5,
 135+ "HNY" => - 9, "I" => 9, "IST" => 1, "K" => 10, "L" => 11, "M" => 12,
 136+ "MDT" => - 6, "MESZ" => 2, "MEZ" => 1, "MSD" => 4, "MSK" => 3, "MST" => - 7,
 137+ "N" => - 1, "NDT" => - 2.5, "NFT" => 11.5, "NST" => - 3.5, "O" => - 2, "P" => - 3,
 138+ "PDT" => - 7, "PST" => - 8, "Q" => - 4, "R" => - 5, "S" => - 6, "T" => - 7,
 139+ "U" => - 8, "UTC" => 0, "V" => - 9, "W" => - 10, "WDT" => 9, "WEDT" => 1,
 140+ "WEST" => 1, "WET" => 0, "WST" => 8, "X" => - 11, "Y" => - 12, "Z" => 0 );
 141+
 142+// constant epochal values
 143+ const J1582 = 2299160.5; // Date of switchover to Gregorian calendar
 144+ const MJD_EPOCH = 2400000.5; // Normalizes the Modified JD to midnight 17 Nov 1858 Gregorian.
 145+
 146+ protected function parseUserValue( $value ) {
 147+ global $smwgContLang;
 148+
 149+ $band = false; // group of bits storing information about the possible meaning of each digit of the entered date
 150+ $this->m_pref = false;
 151+ $this->m_day = false;
 152+ $this->m_month = false;
 153+ $this->m_year = false;
 154+ $this->m_jd = false;
 155+ $this->m_time = false;
 156+ $this->m_timeoffset = 0;
 157+ $this->m_timeannotation = false;
 158+ $this->m_format = false;
 159+ $this->m_dayj = false;
 160+ $this->m_monthj = false;
 161+ $this->m_yearj = false;
 162+
 163+ $value = trim( $value ); // ignore whitespace
 164+ if ( $this->m_caption === false ) { // Store the caption now.
 165+ $this->m_caption = $value;
 166+ }
 167+
 168+ // if the value is a number, and it has at least six places left of decimal, we know
 169+ // it's not a year, so treat it as a Julian day, but leave it as the caption and wikivalue.
 170+ if ( is_numeric( $value ) && $value >= 100000 ) {
 171+ $this->m_jd = $value;
 172+ $this->m_format = 3;
 173+ $this->JD2Date();
 174+ $this->fracToTime();
 175+ $this->m_wikivalue = $value;
 176+ return true;
 177+ }
 178+
 179+ $this->m_wikivalue = $value;
 180+ $filteredvalue = $value; // value without time definition and further abbreviations like PM or BC
 181+
 182+ // browse string for special abbreviations referring to time like am, pm
 183+ if ( preg_match( "/([Aa]|[Pp])[Mm]/u", $filteredvalue, $match ) ) {
 184+ $this->m_timeannotation = strtolower( trim( $match[0] ) );
 185+ $regexp = "/(\040|T){0,1}" . str_replace( "+", "\+", $match[0] ) . "(\040){0,1}/u"; // delete pm/am, preceding and following chars
 186+ $filteredvalue = preg_replace( $regexp, '', $filteredvalue ); // value without am/pm
 187+ }
 188+
 189+ // browse string in advance for timezone monikers ("EST", "WET", "MESZ", etc.)
 190+ $regexptz = "/A[CEKW]?[DS]T|BST|CXT|[CEW]([DES]|E[DS])T|" .
 191+ "GMT|H(A[DS]T|[AN][ACEPRTY])|IST|M(DT|E(S)?Z|S[DKT])|N[DFS]T|P[DS]T|UTC/u";
 192+ if ( preg_match( $regexptz, $filteredvalue, $match ) ) {
 193+ // Retrieve the offset and store it as the initial time offset value.
 194+ $this->m_timeoffset = $this->m_timeoffset + self::$m_tz[$match[0]] / 24;
 195+ $regexp = "/(\040|T){0,1}" . str_replace( "+", "\+", $match[0] ) . "(\040){0,1}/u"; // delete tz moniker and preceding and following chars
 196+ $filteredvalue = preg_replace( $regexp, '', $filteredvalue ); // value without the tz moniker
 197+ }
 198+
 199+ // browse string for special abbreviations referring to year like AD, BC, and OS
 200+ $is_yearbc = false;
 201+ if ( preg_match( "/(A[DM]|BC(E)?|CE|Gr|He|Jl|(M)?JD|OS)/u", $filteredvalue, $match ) ) {
 202+ $this->m_pref = trim( $match[0] );
 203+ if ( ( $this->m_pref == 'BC' ) || ( $this->m_pref == 'BCE' ) ) {
 204+ $is_yearbc = true;
 205+ }
 206+ $regexp = "/(\040|T){0,1}" . str_replace( "+", "\+", $match[0] ) . "(\040){0,1}/u"; // delete ad/bc value and preceding and following chars
 207+ $filteredvalue = preg_replace( $regexp, '', $filteredvalue ); // value without ad/bc
 208+ }
 209+
 210+ // handle direct entry of Julian or Modified Julian days here; don't bother browsing for times.
 211+ if ( ( $this->m_pref == 'JD' ) || ( $this->m_pref == 'MJD' ) ) {
 212+ if ( !( is_numeric( $filteredvalue ) ) ) {// Immediate error check
 213+ smwfLoadExtensionMessages( 'SemanticMediaWiki' );
 214+ $this->addError( wfMsgForContent( 'smw_nodatetime', $value ) );
 215+ return true;
 216+ }
 217+ $this->m_jd = ( $this->m_pref == 'JD' ) ? $filteredvalue : ( $filteredvalue + self::MJD_EPOCH );
 218+ $this->m_pref = "Gr";
 219+ $this->m_format = 3; // Specify all three parts of the date (see below)
 220+ $this->JD2Date();
 221+ $this->fracToTime();
 222+ return true;
 223+ }
 224+
 225+ // browse string for civilian time value
 226+ if ( preg_match( "/[0-2]?[0-9]:[0-5][0-9](:[0-5][0-9])?([+\-][0-2]?[0-9](:(30|00))?)?/u", $filteredvalue, $match ) ) {
 227+ $time = $match[0];
 228+
 229+ // timezone direct offset handling
 230+ if ( preg_match( "/([+\-][0-2]?[0-9](:(30|00))?)/u", $time, $match2 ) ) { // get timezone definition
 231+ $offset = SMWTimeValue::normalizeTimeValue( $match2[0] );
 232+ $sign = 1;
 233+ if ( $offset[0] == '-' ) $sign = - 1;
 234+ $offset = substr( $offset, 1 );
 235+ list ( $offhours, $offminutes, $offseconds ) = explode( ':', $offset, 3 );
 236+ $offset = $sign * ( ( $offhours / 24 ) + ( $offminutes / ( 60 * 24 ) ) + ( $offseconds / ( 3600 * 24 ) ) );
 237+ $this->m_timeoffset = $this->m_timeoffset + $offset;
 238+ $time = str_replace( $match2[0], '', $time );
 239+ }
 240+
 241+ list( $hours, $minutes, $seconds ) = explode( ':', SMWTimeValue::normalizeTimeValue( $time ), 3 );
 242+
 243+ // am/pm handling
 244+ if ( $this->m_timeannotation != false ) {
 245+ if ( !strcmp( $this->m_timeannotation, 'am' ) && $hours == 12 ) $hours = 0;
 246+ if ( !strcmp( $this->m_timeannotation, 'pm' ) && $hours <= 11 ) {
 247+ $this->m_timeoffset = $this->m_timeoffset - 0.5;
 248+ }
 249+ }
 250+
 251+ $this->m_time = SMWTimeValue::normalizeValue( $hours ) . ":" . SMWTimeValue::normalizeValue( $minutes ) . ":" . SMWTimeValue::normalizeValue( $seconds );
 252+ $regexp = "/(\040|T){0,1}" . str_replace( "+", "\+", $match[0] ) . "(\040){0,1}/u"; // delete time value and preceding and following chars
 253+ $filteredvalue = preg_replace( $regexp, '', $filteredvalue ); // value without time
 254+ }
 255+
 256+ // browse string for military time value
 257+ if ( preg_match( "/([0-1][0-9]|2[0-3])[0-5][0-9]([0-5][0-9])?[A-IK-Z]/u", $filteredvalue, $match ) ) {
 258+ $time = $match[0];
 259+ // timezone handling (Zulu, Romeo, Sierra, etc.)
 260+ if ( preg_match( "/[A-IK-Z]/u", $time, $match2 ) ) {// get military timezone offset
 261+ $this->m_timeoffset = $this->m_timeoffset + self::$m_tz[$match2[0]] / 24;
 262+ $time = str_replace( $match2[0], '', $time );// strip away the one-letter moniker
 263+ }
 264+ $hours = substr( $time, 0, 2 );
 265+ $minutes = substr( $time, 2, 2 );
 266+ $seconds = ( strlen( $time ) > 4 ) ? substr( $time, 4, 2 ) : '00';
 267+ $this->m_time = SMWTimeValue::normalizeValue( $hours ) . ":" . SMWTimeValue::normalizeValue( $minutes ) . ":" . SMWTimeValue::normalizeValue( $seconds );
 268+ $regexp = "/(\040|T){0,1}" . str_replace( "+", "\+", $match[0] ) . "(\040){0,1}/u"; // delete time value and preceding and following chars
 269+ $filteredvalue = preg_replace( $regexp, '', $filteredvalue ); // value without time
 270+ }
 271+
 272+ // split array in order to separate the date digits
 273+ $array = preg_split( "/[\040|.|,|\-|\/]+/u", $filteredvalue, 3 ); // TODO: support &nbsp and - again;
 274+
 275+ // The following code segment creates a band by finding out which role each digit of the entered date can take
 276+ // (date, year, month). The band starts with 1 and for each digit of the entered date a binary code with three
 277+ // bits is attached. Examples:
 278+ // 111 states that the digit can be interpreted as a month, a day or a year
 279+ // 100 digit can just be interpreted as a month
 280+ // 010 digit can just be interpreted as a day
 281+ // 001 digit can just be interpreted as a year
 282+ // the remaining combinations are also possible (if reasonable)
 283+ // A date consisting of three digits therefore will have a 10 bit band.
 284+ if ( count( $array ) != 0 ) {
 285+ $band = 1;
 286+ foreach ( $array as $tmp ) {
 287+ $band = $band << 3;
 288+ $band = $band | $this->checkDigit( $tmp );
 289+ }
 290+ } else {
 291+ smwfLoadExtensionMessages( 'SemanticMediaWiki' );
 292+ $this->addError( wfMsgForContent( 'smw_nodatetime', $value ) );
 293+ return true;
 294+ }
 295+
 296+ $dateformats = $smwgContLang->getDateFormats(); // get the language dependent date formats
 297+
 298+ $digitcount = count( $array ) - 1; // number of digits - 1 is used as an array index for $dateformats
 299+ $found = false;
 300+ $prelimModel = $this->findPrelimModel();
 301+ foreach ( $dateformats[$digitcount] as $format ) { // check whether created band matches dateformats
 302+ if ( !( ~$band & $format ) ) { // check if $format => $band ("the detected band supports the current format")
 303+ $i = 0;
 304+ foreach ( self::$m_formats[$format] as $globalvar ) { // map format digits to internal variables
 305+ $globalvar = 'm_' . $globalvar; // (for searching this file) this is one of: m_year, m_month, m_day
 306+ if ( $prelimModel == 'Jl' ) {
 307+ $globalvar = $globalvar . 'j';
 308+ }
 309+ if ( !$this->$globalvar ) $this->$globalvar = intval( $array[$i] );
 310+ $i++;
 311+ }
 312+ $found = true;
 313+ break;
 314+ }
 315+ }
 316+
 317+ // error catching
 318+ if ( !$found ) { // no band matches the entered date
 319+ smwfLoadExtensionMessages( 'SemanticMediaWiki' );
 320+ $this->addError( wfMsgForContent( 'smw_nodatetime', $value ) );
 321+ return true;
 322+ } elseif ( ( $this->m_day > 0 ) && ( $this->m_day > self::$m_daysofmonths[$this->m_month] ) ) { // date does not exist in Gregorian calendar
 323+ smwfLoadExtensionMessages( 'SemanticMediaWiki' );
 324+ $this->addError( wfMsgForContent( 'smw_nodatetime', $value ) );
 325+ return true;
 326+ } elseif ( ( $this->m_dayj > 0 ) && ( $this->m_dayj > self::$m_daysofmonths[$this->m_monthj] ) ) { // date does not exist in Julian calendar
 327+ smwfLoadExtensionMessages( 'SemanticMediaWiki' );
 328+ $this->addError( wfMsgForContent( 'smw_nodatetime', $value ) );
 329+ return true;
 330+ } elseif ( ( $this->m_yearj != false ) && ( $this->m_yearj < - 4713 ) && ( $this->m_timeoffset != 0 ) ) { // no support for time offsets if year < -4713
 331+ smwfLoadExtensionMessages( 'SemanticMediaWiki' );
 332+ $this->addError( wfMsgForContent( 'smw_nodatetime', $value ) );
 333+ return true;
 334+ }
 335+
 336+ // Handle OS: Increment the year if earlier than March 25.
 337+ if ( $this->m_pref == 'OS' ) {
 338+ if ( ( $this->m_monthj < 3 ) || ( ( $this->m_monthj == 3 ) && ( $this->m_dayj < 25 ) ) ) {
 339+ $this->m_yearj++;
 340+ }
 341+ }
 342+
 343+ // Handle BC: the year is negative.
 344+ if ( $is_yearbc ) {
 345+ if ( $this->m_yearj > 0 ) { // see class documentation on BC, "year 0", and ISO conformance ...
 346+ $this->m_yearj = - ( $this->m_yearj );
 347+ }
 348+ }
 349+
 350+ // Make the JD value and handle offset if applicable
 351+ $this->createJD( $this->findModel() );
 352+ if ( $this->m_jd > - 0.5 ) {
 353+ $this->m_jd = $this->m_jd - $this->m_timeoffset;
 354+ $this->JD2Date();
 355+ } else {
 356+ $this->m_day = $this->m_dayj;
 357+ $this->m_month = $this->m_monthj;
 358+ $this->m_year = $this->m_yearj;
 359+ } // Copy Julian registers into Gregorian registers; needed for the XSD value
 360+ return true;
 361+ }
 362+
 363+ protected static function findMonth( $label ) {
 364+ global $smwgContLang;
 365+ $retVal = $smwgContLang->findMonth( $label );
 366+ if ( $retVal !== false ) {
 367+ return $retVal;
 368+ }
 369+ $retVal = array_search( $label, self::$m_months );
 370+ if ( $retVal !== false ) {
 371+ return $retVal + 1;
 372+ }
 373+ $retVal = array_search( $label, self::$m_monthsshort );
 374+ if ( $retVal !== false ) {
 375+ return $retVal + 1;
 376+ }
 377+ return false;
 378+ }
 379+
 380+ protected function findPrelimModel() {
 381+ if ( ( $this->m_pref == 'BC' ) || ( $this->m_pref == 'BCE' ) || ( $this->m_pref == 'Jl' ) || ( $this->m_pref == 'OS' ) ) {
 382+ return 'Jl'; // Assume Julian model if specified in any way, shape or form.
 383+ }
 384+ return 'Gr';
 385+ }
 386+
 387+ protected function checkDigit( $digit ) {
 388+ $prelimModel = $this->findPrelimModel();
 389+ if ( !is_numeric( $digit ) ) { // check for alphanumeric day or month value
 390+ if ( preg_match( "/[0-3]?[0-9](st|nd|rd|th)/u", $digit ) ) { // look for day value terminated by st/nd/th
 391+ $dayVal = intval( substr( $digit, 0, strlen( $digit ) - 2 ) ); // remove st/nd/th
 392+ if ( $prelimModel == 'Jl' ) {
 393+ $this->m_dayj = $dayVal;
 394+ } else {
 395+ $this->m_day = $dayVal;
 396+ }
 397+ return SMW_DAY;
 398+ }
 399+ $monthnumber = SMWTimeValue::findMonth( $digit );
 400+ if ( $monthnumber !== false ) {
 401+ if ( $prelimModel == 'Jl' ) {
 402+ $this->m_monthj = $monthnumber;
 403+ } else {
 404+ $this->m_month = $monthnumber;
 405+ }
 406+ return SMW_MONTH;
 407+ }
 408+ return 0;
 409+ } elseif ( intval( $digit ) >= 1 && intval( $digit ) <= 12 ) { // number can be a month, a day or a year (111)
 410+ return SMW_DAY_MONTH_YEAR;
 411+ } elseif ( intval( $digit ) >= 1 && intval( $digit ) <= 31 ) { // number can be day or year
 412+ return SMW_DAY_YEAR;
 413+ } elseif ( is_numeric( $digit ) ) { // number can just be a year (011)
 414+ return SMW_YEAR;
 415+ } else {
 416+ return 0;
 417+ }
 418+ }
 419+
 420+ // finds the appropriate model to use.
 421+ protected function findModel() {
 422+ if ( ( $this->m_pref == 'BC' ) || ( $this->m_pref == 'BCE' ) ) {
 423+ return 'Jl'; // BC dates are automatically Julian.
 424+ }
 425+ if ( $this->m_pref == 'OS' ) {
 426+ $this->m_pref = ''; // Erase the OS marker; it will not be needed after this.
 427+ return 'Jl'; // Old Style dates are converted per Julian rules.
 428+ }
 429+ if ( ( $this->m_pref == 'Gr' ) || ( $this->m_pref == 'Jl' ) ) {// Specified calendar models
 430+ return $this->m_pref;
 431+ }
 432+ // Model unspecified: must be determined by examination of the date parts.
 433+ if ( $this->m_year > 1582 ) {
 434+ return 'Gr'; // All dates after 1582 are Gregorian dates.
 435+ }
 436+ if ( ( $this->m_year == 1582 ) && ( $this->m_month > 10 ) ) {
 437+ return 'Gr'; // The Gregorian calendar was inaugurated after October 4, 1582.
 438+ }
 439+ if ( ( $this->m_year == 1582 ) && ( $this->m_month == 10 ) && ( $this->m_day > 4 ) ) {
 440+ return 'Gr';
 441+ } // Set $model to 'Jl' and move all specified date parts to the Julian set.
 442+ $this->m_dayj = $this->m_day;
 443+ $this->m_monthj = $this->m_month;
 444+ $this->m_yearj = $this->m_year;
 445+ return 'Jl';
 446+ }
 447+
 448+ protected function parseDBkeys( $args ) {
 449+ $this->m_caption = false;
 450+ if ( count( $args ) < 2 ) return;
 451+ $timeparts = explode( 'T', $args[0], 2 );
 452+ if ( count( $timeparts ) != 2 ) return;
 453+ $date = reset( $timeparts );
 454+ $this->m_time = end( $timeparts );
 455+ $d = explode( '/', $date, 3 );
 456+ if ( count( $d ) == 3 ) list( $this->m_year, $this->m_month, $this->m_day ) = $d;
 457+ elseif ( count( $d ) == 2 ) list( $this->m_year, $this->m_month ) = $d;
 458+ elseif ( count( $d ) == 1 ) list( $this->m_year ) = $d;
 459+ if ( $this->m_year < - 4713 ) {
 460+ $this->m_yearj = $this->m_year;
 461+ $this->m_monthj = $this->m_month;
 462+ $this->m_dayj = $this->m_day;
 463+ $this->createJD( 'Jl' ); // This date falls earlier than the Julian Era.
 464+ } else {
 465+ $this->createJD( 'Gr' ); // This is a Gregorian or proleptic Gregorian date
 466+ }
 467+ if ( $this->m_jd > - 0.5 ) {// Back-convert only if the JD is suitable for that
 468+ $this->JD2Date();
 469+ }
 470+ $this->makePrintoutValue();
 471+ $this->m_caption = ( $this->m_jd < self::J1582 ) ? $this->m_julvalue : $this->m_gregvalue;
 472+ $this->m_wikivalue = $this->m_gregvalue;
 473+ }
 474+
 475+ /// make sure that existing values are updated: set the format string and force
 476+ /// a reconfiguration of all printouts.
 477+ public function setOutputFormat( $formatstring ) {
 478+ if ( $formatstring != $this->m_outformat ) {
 479+ $this->m_outformat = $formatstring;
 480+ $this->m_gregvalue = false;
 481+ $this->m_julvalue = false;
 482+ }
 483+ }
 484+
 485+ public function getShortWikiText( $linked = NULL ) {
 486+ $this->unstub();
 487+ if ( $this->m_caption !== false ) {
 488+ return $this->m_caption;
 489+ } else {
 490+ $this->makePrintoutValue();
 491+ return $this->m_gregvalue;
 492+ }
 493+ }
 494+
 495+ public function getShortHTMLText( $linker = NULL ) {
 496+ return $this->getShortWikiText( $linker ); // should be safe (based on xsdvalue)
 497+ }
 498+
 499+ public function getLongWikiText( $linked = NULL ) {
 500+ if ( !$this->isValid() ) {
 501+ return $this->getErrorText();
 502+ } else {
 503+ $this->makePrintoutValue();
 504+ return $this->m_jd < self::J1582 ? $this->m_julvalue : $this->m_gregvalue;
 505+ }
 506+ }
 507+
 508+ public function getLongHTMLText( $linker = NULL ) {
 509+ return $this->getLongWikiText( $linker );
 510+ }
 511+
 512+ public function getDBkeys() {
 513+ $this->unstub();
 514+ if ( $this->m_xsdvalue === false ) {
 515+ $this->m_xsdvalue = $this->m_year . "/" . $this->m_month . "/" . $this->m_day . "T" . $this->m_time;
 516+ }
 517+ return array( $this->m_xsdvalue, $this->m_jd );
 518+ }
 519+
 520+ public function getSignature() {
 521+ return 'tf';
 522+ }
 523+
 524+ public function getValueIndex() {
 525+ return 1;
 526+ }
 527+
 528+ public function getLabelIndex() {
 529+ return 0;
 530+ }
 531+
 532+ public function getWikiValue() {
 533+ $this->unstub();
 534+ return $this->m_wikivalue;
 535+ }
 536+
 537+ public function getHash() {
 538+ if ( $this->isValid() ) {
 539+ return strval( $this->m_jd );
 540+ } else {
 541+ return implode( "\t", $this->getErrors() );
 542+ }
 543+ }
 544+
 545+ public function isNumeric() {
 546+ return true;
 547+ }
 548+
 549+ public function getExportData() {
 550+ if ( $this->isValid() ) {
 551+ $lit = new SMWExpLiteral( $this->getXMLSchemaDate(), $this, 'http://www.w3.org/2001/XMLSchema#dateTime' );
 552+ return new SMWExpData( $lit );
 553+ } else {
 554+ return NULL;
 555+ }
 556+ }
 557+
 558+ /**
 559+ * Return the year as a number corresponding to the year in the Julian or
 560+ * Gregorian calendar and using the astronomical year numbering (0 means 1 BC).
 561+ */
 562+ public function getYear( $model = 'Gr' ) {
 563+ $this->unstub();
 564+ switch ( $model ) {
 565+ case 'Jl':
 566+ return $this->m_yearj;
 567+ default:
 568+ return $this->m_year;
 569+ }
 570+ }
 571+
 572+ /**
 573+ * Return the month as a number (between 1 and 12) based on the Julian or
 574+ * Gregorian calendar.
 575+ * The parameter $default optionally specifies the value returned
 576+ * if the date is valid but has no explicitly specified month. It can
 577+ * also be set to FALSE to detect this situation.
 578+ */
 579+ public function getMonth( $model = 'Gr', $default = 1 ) {
 580+ $this->unstub();
 581+ switch ( $model ) {
 582+ case 'Jl':
 583+ return ( $this->m_monthj != false ) ? $this->m_monthj:$default;
 584+ default:
 585+ return ( $this->m_month != false ) ? $this->m_month:$default;
 586+ }
 587+ }
 588+
 589+ /**
 590+ * Return the day as a number based on the Julian or Gregorian calendar.
 591+ * The parameter $default optionally specifies the value returned
 592+ * if the date is valid but has no explicitly specified date. It can
 593+ * also be set to FALSE to detect this situation.
 594+ */
 595+ public function getDay( $model = 'Gr', $default = 1 ) {
 596+ $this->unstub();
 597+ switch ( $model ) {
 598+ case 'Jl':
 599+ return ( $this->m_dayj != false ) ? $this->m_dayj:$default;
 600+ default:
 601+ return ( $this->m_day != false ) ? $this->m_day:$default;
 602+ }
 603+ }
 604+
 605+ /**
 606+ * Return the time as a string. The time string has the format HH:MM:SS,
 607+ * without any timezone information (see class documentaion for details
 608+ * on current timezone handling).
 609+ * The parameter $default optionally specifies the value returned
 610+ * if the date is valid but has no explicitly specified time. It can
 611+ * also be set to FALSE to detect this situation.
 612+ */
 613+ public function getTimeString( $default = '00:00:00' ) {
 614+ $this->unstub();
 615+ return ( $this->m_time != false ) ? SMWTimeValue::normalizeTimeValue( $this->m_time ):$default;
 616+ }
 617+
 618+ /**
 619+ * Return a representation of this date in canonical dateTime format without timezone, as
 620+ * specified in XML Schema Part 2: Datatypes Second Edition (W3C Recommendation, 28 October 2004,
 621+ * http://www.w3.org/TR/xmlschema-2). An example would be "2008-01-02T14:30:10". BC(E) years
 622+ * are represented by a leading "-" as in "-123-01-02T14:30:10", the 2nd January of the year
 623+ * 123 BC(E) at 2:30pm and 10 seconds.
 624+ *
 625+ * If the date was not fully specified, then the function will use defaults for the omitted values.
 626+ * The boolean parameter $mindefault controls if those defaults are chosen minimally. If false, then
 627+ * the latest possible value will be chosen instead.
 628+ *
 629+ * @note This function may return year numbers with less or more than 4 digits.
 630+ */
 631+ public function getXMLSchemaDate( $mindefault = true ) {
 632+ if ( $this->isValid() ) {
 633+ if ( $mindefault ) {
 634+ return number_format( $this->m_year, 0, '.', '' ) . '-' . SMWTimeValue::normalizeValue( $this->getMonth() ) . '-' . SMWTimeValue::normalizeValue( $this->getDay() ) . 'T' . $this->getTimeString();
 635+ } else {
 636+ return number_format( $this->m_year, 0, '.', '' ) . '-' . SMWTimeValue::normalizeValue( $this->getMonth( 12 ) ) . '-' . SMWTimeValue::normalizeValue( $this->getDay( 31 ) ) . 'T' . $this->getTimeString( '23:59:59' );
 637+ }
 638+ } else {
 639+ return false;
 640+ }
 641+ }
 642+
 643+ /**
 644+ * Build preferred values for printout, to be used as captions when setting up values
 645+ * from the store. Note: Proleptic Hillel II and Biblical values are not permitted.
 646+ */
 647+ protected function makePrintoutValue() {
 648+ $this->makeGregorianValue();
 649+ $this->makeJulianValue();
 650+ }
 651+
 652+ protected function makeGregorianValue() {
 653+ global $smwgContLang;
 654+ if ( $this->m_gregvalue === false ) {
 655+ // MediaWiki date function is not applicable any more (no support for BC Dates)
 656+ if ( ( strtoupper( $this->m_outformat ) == 'ISO' ) || ( $this->m_outformat == '-' ) ) { // ISO8601 date formatting
 657+ if ( $this->m_year > 0 ) {
 658+ $this->m_gregvalue = str_pad( $this->m_year, 4, "0", STR_PAD_LEFT );
 659+ } else {
 660+ $this->m_gregvalue = '-' . str_pad( ( - ( $this->m_year ) ), 4, "0", STR_PAD_LEFT );
 661+ }
 662+ $this->m_gregvalue .= '-'
 663+ . ( $this->m_month ? str_pad( $this->m_month, 2, "0", STR_PAD_LEFT ):'01' ) . '-'
 664+ . ( $this->m_day ? str_pad( $this->m_day, 2, "0", STR_PAD_LEFT ):'01' )
 665+ . ( $this->m_time ? 'T' . $this->m_time:'' );
 666+ } else { // Default date formatting
 667+ if ( $this->m_year > 0 ) {
 668+ $this->m_gregvalue = number_format( $this->m_year, 0, '.', '' ) . ( ( ( $this->m_pref == 'AD' ) || ( $this->m_pref == 'CE' ) ) ? ( ' ' . $this->m_pref ) : '' );
 669+ } else {
 670+ $this->m_gregvalue = number_format( - ( $this->m_year ), 0, '.', '' ) . ( ( $this->m_pref == 'BCE' ) ? ' ' . 'BCE' : ' ' . 'BC' ); // note: there should be no digits after the comma anyway
 671+ }
 672+ if ( $this->m_month ) {
 673+ $this->m_gregvalue = $smwgContLang->getMonthLabel( $this->m_month ) . " " . $this->m_gregvalue;
 674+ }
 675+ if ( $this->m_day ) {
 676+ $this->m_gregvalue = $this->m_day . " " . $this->m_gregvalue;
 677+ }
 678+ if ( $this->m_time ) {
 679+ $this->m_gregvalue .= " " . $this->m_time;
 680+ }
 681+ }
 682+ }
 683+ }
 684+
 685+ protected function makeJulianValue() {
 686+ global $smwgContLang;
 687+ if ( $this->m_julvalue === false ) {
 688+ // MediaWiki date function is not applicable any more (no support for BC Dates)
 689+ if ( ( strtoupper( $this->m_outformat ) == 'ISO' ) || ( $this->m_outformat == '-' ) ) { // ISO8601 date formatting
 690+ if ( $this->m_yearj > 0 ) {
 691+ $this->m_julvalue = str_pad( $this->m_yearj, 4, "0", STR_PAD_LEFT );
 692+ } else {
 693+ $this->m_julvalue = '-' . str_pad( ( - ( $this->m_yearj ) ), 4, "0", STR_PAD_LEFT );
 694+ }
 695+ $this->m_julvalue .= '-'
 696+ . ( $this->m_monthj ? str_pad( $this->m_monthj, 2, "0", STR_PAD_LEFT ):'01' ) . '-'
 697+ . ( $this->m_dayj ? str_pad( $this->m_dayj, 2, "0", STR_PAD_LEFT ):'01' )
 698+ . ( $this->m_time ? 'T' . $this->m_time:'' );
 699+ } else {
 700+ if ( $this->m_yearj > 0 ) {
 701+ $this->m_julvalue = number_format( $this->m_yearj, 0, '.', '' ) . ( ( ( $this->m_pref == 'AD' ) || ( $this->m_pref == 'CE' ) ) ? ( ' ' . $this->m_pref ) : '' );
 702+ } else {
 703+ $this->m_julvalue = number_format( - ( $this->m_yearj ), 0, '.', '' ) . ( ( $this->m_pref == 'BCE' ) ? ' ' . 'BCE' : ' ' . 'BC' ); // note: there should be no digits after the comma anyway
 704+ }
 705+ if ( $this->m_monthj ) {
 706+ $this->m_julvalue = $smwgContLang->getMonthLabel( $this->m_monthj ) . " " . $this->m_julvalue;
 707+ }
 708+ if ( $this->m_dayj ) {
 709+ $this->m_julvalue = $this->m_dayj . " " . $this->m_julvalue;
 710+ }
 711+ if ( $this->m_time ) {
 712+ $this->m_julvalue .= " " . $this->m_time;
 713+ }
 714+ }
 715+ }
 716+ }
 717+
 718+ protected static function normalizeValue( $value ) {
 719+ if ( strlen( $value ) == 1 ) {
 720+ $value = "0" . $value;
 721+ }
 722+ return $value;
 723+ }
 724+
 725+ protected static function normalizeTimeValue( $value ) {
 726+ $value = SMWTimeValue::normalizeValue( $value );
 727+ $parts = explode( ":", $value );
 728+ switch ( count( $parts ) ) {
 729+ case 1: return $parts[0] . ":00:00";
 730+ case 2: return $parts[0] . ":" . $parts[1] . ":00";
 731+ default: return $value;
 732+ }
 733+ }
 734+
 735+ /**
 736+ * This function adds a time fraction to any Julian Day.
 737+ */
 738+ protected function createTime() {
 739+ if ( $this->m_time != false ) { // Calculate fraction only if time is set -- the default time is 0
 740+ list ( $hours, $minutes, $seconds ) = explode( ':', $this->getTimeString(), 3 );
 741+ $time = ( $hours / 24 ) + ( $minutes / ( 60 * 24 ) ) + ( $seconds / ( 3600 * 24 ) );
 742+ $this->m_jd += $time;
 743+ }
 744+ }
 745+
 746+ /**
 747+ * This function computes a numerical value based on the currently set date. If the year is
 748+ * greater or equal to -4712 (4713 BC), then (something that is closely inspired by) the Julian Day
 749+ * (JD) is computed. The JD has the form XXXX.YYYY where XXXX is the number of days having elapsed since
 750+ * noon on 1 January 4713 BC and YYYY is the elapsed time of the day as fraction of 1.
 751+ * See http://en.wikipedia.org/wiki/Julian_day
 752+ * If the year is before -4713, then the computed number XXXX.YYYY has the following form: XXXX is
 753+ * the number of years BC and YYYY represents the elapsed days of the year as fraction of 1. This
 754+ * enables even large negative dates using 32bit floats.
 755+ *
 756+ * @note The result of this function is used only internally. It should not be assumed to be the
 757+ * exact JD, even for dates after 4713 BC, unless a proper time-zone offset or moniker is specified.
 758+ */
 759+ protected function createJD( $model ) {
 760+ switch( $model ) {
 761+ case "Gr":
 762+ $this->gregorian2JD();
 763+ break;
 764+ case "Jl":
 765+ $this->julian2JD();
 766+ break;
 767+ }
 768+ $this->createTime();
 769+ }
 770+
 771+ /// Calculate a Julian day according to Gregorian calendar rules
 772+ protected function gregorian2JD() {
 773+ $this->m_jd = 0;
 774+ $a = intval( ( 14 - $this->getMonth( 'Gr' ) ) / 12 );
 775+ $y = $this->m_year + 4800 - $a;
 776+ $m = $this->getMonth( 'Gr' ) + 12 * $a - 3;
 777+ $this->m_jd += $this->getDay( 'Gr' ) + intval( ( 153 * $m + 2 ) / 5 ) + 365 * $y + intval( $y / 4 ) - intval( $y / 100 ) + intval( $y / 400 ) - 32045.5;
 778+ $this->m_format = ( $this->m_day != false ) ? 3 : ( ( $this->m_month != false ) ? 2 : 1 );
 779+ }
 780+
 781+ /// Calculate a Julian day according to Julian calendar rules
 782+ protected function julian2JD() {
 783+ if ( $this->m_yearj >= - 4713 ) {
 784+ $this->m_jd = 0;
 785+ $y1 = ( $this->m_yearj < 1 ) ? ( $this->m_yearj + 1 ) : $this->m_yearj;
 786+ $m1 = $this->getMonth( 'Jl' );
 787+ $y2 = ( $m1 <= 2 ) ? ( $y1 - 1 ) : $y1;
 788+ $m2 = ( $m1 <= 2 ) ? ( $m1 + 12 ) : $m1;
 789+ $this->m_jd += intval( ( 365.25 * ( $y2 + 4716 ) ) ) + intval( ( 30.6001 * ( $m2 + 1 ) ) ) + $this->getDay( 'Jl' ) - 1524.5;
 790+ } else { // starting from the time when JD would be negative, use our own "stretched" representation, currently this just ignores local time
 791+ $time = 1 - ( ( $this->getMonth( 'Jl' ) / 12 ) + ( $this->getDay( 'Jl' ) / 365 ) );
 792+ $this->m_jd = $this->m_yearj - $time;
 793+ }
 794+ $this->m_format = ( $this->m_dayj != false ) ? 3 : ( ( $this->m_monthj != false ) ? 2 : 1 );
 795+ }
 796+
 797+ /// Convert the Julian Day fraction to the time string.
 798+ protected function fracToTime() {
 799+ $wjd = $this->m_jd + 0.5;
 800+ $fraction = $wjd - intval( $wjd );
 801+ $time = round( $fraction * 3600 * 24 );
 802+ $hours = intval( $time / 3600 );
 803+ $time = $time - $hours * 3600;
 804+ $minutes = intval( $time / 60 );
 805+ $seconds = intval( $time - $minutes * 60 );
 806+ $this->m_time = SMWTimeValue::normalizeValue( $hours ) . ":" . SMWTimeValue::normalizeValue( $minutes ) . ":" . SMWTimeValue::normalizeValue( $seconds );
 807+ }
 808+
 809+ /// Convert Julian Day to m_year, m_month, and m_day according to the proper model.
 810+ /// Do NOT invoke AM or Hillel conversion functions if the JD is less than their respective epochs.
 811+ protected function JD2Date() {
 812+ $this->JD2Julian();
 813+ $this->JD2Gregorian();
 814+ if ( $this->m_time != false ) { // Do not fill this in if it was not filled in to begin with
 815+ $this->fracToTime();
 816+ }
 817+ }
 818+
 819+ /// Convert Julian Day (see createJD) back to a Gregorian date.
 820+ protected function JD2Gregorian() {
 821+ $j = intval( $this->m_jd + 0.5 ) + 32044;
 822+ $g = intval( $j / 146097 );
 823+ $dg = $j % 146097;
 824+ $c = intval( ( ( intval( $dg / 36524 ) + 1 ) * 3 ) / 4 );
 825+ $dc = $dg - $c * 36524;
 826+ $b = intval( $dc / 1461 );
 827+ $db = $dc % 1461;
 828+ $a = intval( ( ( intval( $db / 365 ) + 1 ) * 3 ) / 4 );
 829+ $da = $db - ( $a * 365 );
 830+ $y = $g * 400 + $c * 100 + $b * 4 + $a;
 831+ $m = intval( ( $da * 5 + 308 ) / 153 ) - 2;
 832+ $d = $da - intval( ( ( $m + 4 ) * 153 ) / 5 ) + 122;
 833+ $this->m_year = $y - 4800 + intval( ( $m + 2 ) / 12 );
 834+ $this->m_month = ( $this->m_format >= 2 ) ? ( ( $m + 2 ) % 12 + 1 ) : false;
 835+ $this->m_day = ( $this->m_format == 3 ) ? ( $d + 1 ) : false;
 836+ if ( ( $this->m_format == 2 ) && ( $d > 1 ) ) {
 837+ $this->m_month++;
 838+ if ( $this->m_month > 12 ) {
 839+ $this->m_month = 1;
 840+ $this->m_year++;
 841+ }
 842+ }
 843+ }
 844+
 845+ /// Convert Julian Day back to a Julian date.
 846+ protected function JD2Julian() {
 847+ $b = intval( $this->m_jd + 0.5 ) + 1524;
 848+ $c = intval( ( $b - 122.1 ) / 365.25 );
 849+ $d = intval( 365.25 * $c );
 850+ $e = intval( ( $b - $d ) / 30.6001 );
 851+ $m = intval( ( $e < 14 ) ? ( $e - 1 ) : ( $e - 13 ) );
 852+ $y = intval( ( $m > 2 ) ? ( $c - 4716 ) : ( $c - 4715 ) );
 853+ $this->m_yearj = ( $y < 1 ) ? ( $y - 1 ) : $y;
 854+ $this->m_monthj = ( $this->m_format >= 2 ) ? $m : false;
 855+ $this->m_dayj = ( $this->m_format == 3 ) ? ( $b - $d - intval( 30.6001 * $e ) ) : false;
 856+ }
 857+}
Property changes on: trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_Time.php
___________________________________________________________________
Added: svn:eol-style
1858 + native
Index: trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_URI.php
@@ -0,0 +1,283 @@
 2+<?php
 3+/**
 4+ * @file
 5+ * @ingroup SMWDataValues
 6+ */
 7+
 8+define( 'SMW_URI_MODE_EMAIL', 1 );
 9+define( 'SMW_URI_MODE_URI', 3 );
 10+define( 'SMW_URI_MODE_ANNOURI', 4 );
 11+define( 'SMW_URI_MODE_TEL', 5 );
 12+
 13+/**
 14+ * This datavalue implements URL/URI/ANNURI/PHONE/EMAIL-Datavalues suitable for defining
 15+ * the respective types of properties.
 16+ *
 17+ * @author Nikolas Iwan
 18+ * @author Markus Krötzsch
 19+ * @ingroup SMWDataValues
 20+ * @bug Correctly create safe HTML and Wiki text.
 21+ */
 22+class SMWURIValue extends SMWDataValue {
 23+
 24+ /// Value; usually a human readable version of the URI (esp. "mailto:" might be ommitted)
 25+ private $m_value = '';
 26+ /// Only set if a link should be created in the wiki.
 27+ private $m_url = '';
 28+ /// Canonical URI for identifying the object
 29+ private $m_uri = '';
 30+ /// Distinguish different modes (emails, URL, ...)
 31+ private $m_mode = '';
 32+
 33+ public function SMWURIValue( $typeid ) {
 34+ SMWDataValue::__construct( $typeid );
 35+ switch ( $typeid ) {
 36+ case '_ema':
 37+ $this->m_mode = SMW_URI_MODE_EMAIL;
 38+ break;
 39+ case '_anu':
 40+ $this->m_mode = SMW_URI_MODE_ANNOURI;
 41+ break;
 42+ case '_tel':
 43+ $this->m_mode = SMW_URI_MODE_TEL;
 44+ break;
 45+ case '_uri': case '_url': case '__spu': default:
 46+ $this->m_mode = SMW_URI_MODE_URI;
 47+ break;
 48+ }
 49+ }
 50+
 51+ protected function parseUserValue( $value ) {
 52+ smwfLoadExtensionMessages( 'SemanticMediaWiki' );
 53+ $value = trim( $value );
 54+ $this->m_url = '';
 55+ $this->m_uri = '';
 56+ $this->m_value = $value;
 57+ if ( $this->m_caption === false ) {
 58+ $this->m_caption = $this->m_value;
 59+ }
 60+ if ( $value != '' ) { // do not accept empty strings
 61+ switch ( $this->m_mode ) {
 62+ case SMW_URI_MODE_URI: case SMW_URI_MODE_ANNOURI:
 63+ $parts = explode( ':', $value, 2 ); // try to split "schema:rest"
 64+ if ( count( $parts ) == 1 ) { // take "http" as default
 65+ $value = 'http://' . $value;
 66+ $parts[1] = $parts[0];
 67+ $parts[0] = 'http';
 68+ } elseif ( ( count( $parts ) < 1 ) || ( $parts[0] == '' ) || ( $parts[1] == '' ) || ( preg_match( '/[^a-zA-Z]/u', $parts[0] ) ) ) {
 69+ $this->addError( wfMsgForContent( 'smw_baduri', $value ) );
 70+ return true;
 71+ }
 72+
 73+ // check against blacklist
 74+ $uri_blacklist = explode( "\n", wfMsgForContent( 'smw_uri_blacklist' ) );
 75+ foreach ( $uri_blacklist as $uri ) {
 76+ $uri = trim( $uri );
 77+ if ( $uri == mb_substr( $value, 0, mb_strlen( $uri ) ) ) { // disallowed URI!
 78+ $this->addError( wfMsgForContent( 'smw_baduri', $uri ) );
 79+ return true;
 80+ }
 81+ }
 82+ // simple check for invalid characters: ' ', '{', '}'
 83+// $check1 = "@(\}|\{| )+@u";
 84+// if (preg_match($check1, $value, $matches)) {
 85+// $this->addError(wfMsgForContent('smw_baduri', $value));
 86+// break;
 87+// }
 88+/// TODO: the remaining checks need improvement
 89+// // validate last part of URI (after #) if provided
 90+// $uri_ex = explode('#',$value);
 91+// $check2 = "@^[a-zA-Z0-9-_\%]+$@u"; ///FIXME: why only ascii symbols?
 92+// if(sizeof($uri_ex)>2 ){ // URI should only contain at most one '#'
 93+// $this->addError(wfMsgForContent('smw_baduri', $value) . 'Debug3');
 94+// break;
 95+// } elseif ( (sizeof($uri_ex) == 2) && !(preg_match($check2, $uri_ex[1])) ) {
 96+// $this->addError(wfMsgForContent('smw_baduri', $value) . 'Debug4');
 97+// break;
 98+// }
 99+// // validate protocol + domain part of URI
 100+//// $check3 = "@^([a-zA-Z]{0,6}:)[a-zA-Z0-9\.\/%]+$@"; //simple regexp for protocol+domain part of URI
 101+// $check3 = "@^([a-zA-Z]:)[a-zA-Z0-9\.\/%]+$@"; //simple regexp for protocol+domain part of URI
 102+// /// FIXME: why {0,6}?
 103+// if (!preg_match($check3, $uri_ex[0],$matches)){
 104+// $this->addError(wfMsgForContent('smw_baduri', $value) . 'Debug5');
 105+// break;
 106+// }
 107+
 108+ // encode most characters, but leave special symbols as given by user:
 109+ $this->m_uri = str_replace( array( '%3A', '%2F', '%23', '%40', '%3F', '%3D', '%26', '%25' ), array( ':', '/', '#', '@', '?', '=', '&', '%' ), rawurlencode( $value ) );
 110+ /// NOTE: we do not support raw [ (%5D) and ] (%5E), although they are needed for ldap:// (but rarely in a wiki)
 111+ /// NOTE: we do not check the validity of the use of the raw symbols -- does RFC 3986 as such care?
 112+ /// NOTE: "+" gets encoded, as it is interpreted as space by most browsers when part of a URL;
 113+ /// this prevents tel: from working directly, but we should have a datatype for this anyway.
 114+ global $wgUrlProtocols;
 115+ foreach ( $wgUrlProtocols as $prot ) { // only set URL if wiki-enabled protocol
 116+ if ( ( $prot == $parts[0] . ':' ) || ( $prot == $parts[0] . '://' ) ) {
 117+ $this->m_url = $this->m_uri;
 118+ break;
 119+ }
 120+ }
 121+ break;
 122+ case SMW_URI_MODE_TEL:
 123+ if ( substr( $value, 0, 4 ) === 'tel:' ) {
 124+ $value = substr( $value, 4 );
 125+ $this->m_value = $value;
 126+ }
 127+ $value = preg_replace( '/(?<=[0-9]) (?=[0-9])/', '\1-\2', $value );
 128+ $value = str_replace( ' ', '', $value );
 129+ if ( substr( $value, 0, 2 ) == '00' ) {
 130+ $value = '+' . substr( $value, 2 );
 131+ }
 132+ $value = 'tel:' . $value;
 133+ if ( ( strlen( preg_replace( '/[^0-9]/', '', $value ) ) < 6 ) ||
 134+ ( preg_match( '<[-+./][-./]>', $value ) ) ||
 135+ ( !SMWURIValue::isValidTelURI( $value ) ) ) { ///TODO: introduce error-message for "bad" phone number
 136+ $this->addError( wfMsgForContent( 'smw_baduri', $this->m_value ) );
 137+ }
 138+ $this->m_uri = $value;
 139+ break;
 140+ case SMW_URI_MODE_EMAIL:
 141+ if ( strpos( $value, 'mailto:' ) === 0 ) { // accept optional "mailto"
 142+ $value = substr( $value, 7 );
 143+ $this->m_value = $value;
 144+ }
 145+ $check = "#^([_a-zA-Z0-9-]+)((\.[_a-zA-Z0-9-]+)*)@([_a-zA-Z0-9-]+(\.[_a-zA-Z0-9-]+)*)\.([a-zA-Z]{2,6})$#u";
 146+ if ( !preg_match( $check, $value ) ) {
 147+ ///TODO: introduce error-message for "bad" email
 148+ $this->addError( wfMsgForContent( 'smw_baduri', $value ) );
 149+ break;
 150+ }
 151+ $this->m_url = 'mailto:' . str_replace( array( '%3A', '%2F', '%23', '%40', '%3F', '%3D', '%26', '%25' ), array( ':', '/', '#', '@', '?', '=', '&', '%' ), rawurlencode( $value ) );
 152+ $this->m_uri = $this->m_url;
 153+ }
 154+ } else {
 155+ $this->addError( wfMsgForContent( 'smw_emptystring' ) );
 156+ }
 157+
 158+ return true;
 159+ }
 160+
 161+ /**
 162+ * Returns true if the argument is a valid RFC 3966 phone number.
 163+ * Only global phone numbers are supported, and no full validation
 164+ * of parameters (appended via ;param=value) is performed.
 165+ */
 166+ protected static function isValidTelURI( $s ) {
 167+ $tel_uri_regex = '<^tel:\+[0-9./-]*[0-9][0-9./-]*(;[0-9a-zA-Z-]+=(%[0-9a-zA-Z][0-9a-zA-Z]|[0-9a-zA-Z._~:/?#[\]@!$&\'()*+,;=-])*)*$>';
 168+ return (bool) preg_match( $tel_uri_regex, $s );
 169+ }
 170+
 171+
 172+ protected function parseDBkeys( $args ) {
 173+ $this->m_uri = $args[0];
 174+ $this->m_value = $this->m_uri;
 175+ $this->m_caption = $this->m_value;
 176+ if ( $this->m_mode == SMW_URI_MODE_EMAIL ) {
 177+ $this->m_url = $this->m_value;
 178+ if ( strpos( $this->m_uri, 'mailto:' ) === 0 ) { // catch inconsistencies in DB, should usually be the case
 179+ $this->m_caption = substr( $this->m_value, 7 );
 180+ $this->m_value = $this->m_caption;
 181+ } else { // this case is only for backwards compatibility/repair; may vanish at some point
 182+ $this->m_uri = 'mailto:' . $this->m_value;
 183+ $this->m_url = $this->m_uri;
 184+ }
 185+ } elseif ( $this->m_mode == SMW_URI_MODE_TEL ) {
 186+ $this->m_url = '';
 187+ if ( strpos( $this->m_uri, 'tel:' ) === 0 ) { // catch inconsistencies in DB, should usually be the case
 188+ $this->m_caption = substr( $this->m_value, 4 );
 189+ $this->m_value = $this->m_caption;
 190+ }
 191+ } else {
 192+ $parts = explode( ':', $this->m_uri, 2 ); // try to split "schema:rest"
 193+ global $wgUrlProtocols;
 194+ $this->m_url = '';
 195+ foreach ( $wgUrlProtocols as $prot ) { // only set URL if wiki-enabled protocol
 196+ if ( ( $prot == $parts[0] . ':' ) || ( $prot == $parts[0] . '://' ) ) {
 197+ $this->m_url = $this->m_uri;
 198+ break;
 199+ }
 200+ }
 201+ }
 202+ }
 203+
 204+ public function getShortWikiText( $linked = null ) {
 205+ $this->unstub();
 206+ if ( ( $linked === null ) || ( $linked === false ) || ( $this->m_outformat == '-' ) || ( $this->m_url == '' ) || ( $this->m_caption == '' ) ) {
 207+ return $this->m_caption;
 208+ } else {
 209+ return '[' . $this->m_url . ' ' . $this->m_caption . ']';
 210+ }
 211+ }
 212+
 213+ public function getShortHTMLText( $linker = null ) {
 214+ $this->unstub();
 215+ if ( ( $linker === null ) || ( !$this->isValid() ) || ( $this->m_outformat == '-' ) || ( $this->m_url == '' ) || ( $this->m_caption == '' ) ) {
 216+ return $this->m_caption;
 217+ } else {
 218+ return $linker->makeExternalLink( $this->m_url, $this->m_caption );
 219+ }
 220+ }
 221+
 222+ public function getLongWikiText( $linked = null ) {
 223+ if ( !$this->isValid() ) {
 224+ return $this->getErrorText();
 225+ }
 226+ if ( ( $linked === null ) || ( $linked === false ) || ( $this->m_outformat == '-' ) || ( $this->m_url == '' ) ) {
 227+ return $this->m_value;
 228+ } else {
 229+ return '[' . $this->m_url . ' ' . $this->m_value . ']';
 230+ }
 231+ }
 232+
 233+ public function getLongHTMLText( $linker = null ) {
 234+ if ( !$this->isValid() ) {
 235+ return $this->getErrorText();
 236+ }
 237+ if ( ( $linker === null ) || ( $this->m_outformat == '-' ) || ( $this->m_url == '' ) ) {
 238+ return htmlspecialchars( $this->m_value );
 239+ } else {
 240+ return $linker->makeExternalLink( $this->m_url, $this->m_value );
 241+ }
 242+ }
 243+
 244+ public function getDBkeys() {
 245+ $this->unstub();
 246+ return array( $this->m_uri );
 247+ }
 248+
 249+ public function getSignature() {
 250+ return 't';
 251+ }
 252+
 253+ public function getValueIndex() {
 254+ return 0;
 255+ }
 256+
 257+ public function getLabelIndex() {
 258+ return 0;
 259+ }
 260+
 261+ public function getWikiValue() {
 262+ $this->unstub();
 263+ return $this->m_value;
 264+ }
 265+
 266+ protected function getServiceLinkParams() {
 267+ $this->unstub();
 268+ // Create links to mapping services based on a wiki-editable message. The parameters
 269+ // available to the message are:
 270+ // $1: urlencoded version of URI/URL value (includes mailto: for emails)
 271+ return array( rawurlencode( $this->m_uri ) );
 272+ }
 273+
 274+ public function getExportData() {
 275+ if ( $this->isValid() ) {
 276+ $res = new SMWExpResource( str_replace( '&', '&amp;', $this->m_uri ), $this );
 277+ return new SMWExpData( $res );
 278+ } else {
 279+ return null;
 280+ }
 281+ }
 282+
 283+}
 284+
Property changes on: trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_URI.php
___________________________________________________________________
Added: svn:eol-style
1285 + native
Index: trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_WikiPage.php
@@ -0,0 +1,377 @@
 2+<?php
 3+/**
 4+ * @file
 5+ * @ingroup SMWDataValues
 6+ */
 7+
 8+/**
 9+ * This datavalue implements special processing suitable for defining
 10+ * wikipages as values of properties. In contrast to most other types
 11+ * of values, wiki pages are determined by multiple components, as
 12+ * retruned by their getDBkeys() method: DBkey, namespace, interwiki
 13+ * prefix and sortkey. The last of those has a somewhat nonstandard
 14+ * behaviour, since it is not attached to every wiki page value, but
 15+ * only to those that represent page subjects, which define the sortkey
 16+ * globally for all places where this page value occurs.
 17+ *
 18+ * @author Nikolas Iwan
 19+ * @author Markus Krötzsch
 20+ * @ingroup SMWDataValues
 21+ */
 22+class SMWWikiPageValue extends SMWDataValue {
 23+
 24+ protected $m_textform = ''; // the isolated title as text
 25+ protected $m_dbkeyform = ''; // the isolated title in DB form
 26+ protected $m_interwiki = ''; // interwiki prefix or '', actually stored in SMWSQLStore2
 27+ protected $m_sortkey = ''; // key for alphabetical sorting
 28+ protected $m_fragment = ''; // not stored, but kept for printout on page
 29+ protected $m_prefixedtext = ''; // full titletext with prefixes, including interwiki prefix
 30+ protected $m_namespace = NS_MAIN;
 31+ protected $m_id; // false if unset
 32+ protected $m_title = null;
 33+
 34+ protected $m_fixNamespace = NS_MAIN; // if namespace other than NS_MAIN, restrict inputs to this namespace
 35+
 36+ /**
 37+ * Static function for creating a new wikipage object from
 38+ * data as it is typically stored internally. In particular,
 39+ * the title string is supposed to be in DB key form.
 40+ * @note The resulting wikipage object might be invalid if
 41+ * the provided title is not allowed. An object is returned
 42+ * in any case.
 43+ *
 44+ * @return SMWWikiPageValue
 45+ */
 46+ static public function makePage( $title, $namespace, $sortkey = '', $interwiki = '' ) {
 47+ $page = new SMWWikiPageValue( '_wpg' );
 48+ $page->setDBkeys( array( $title, $namespace, $interwiki, $sortkey ) );
 49+ return $page;
 50+ }
 51+
 52+ /**
 53+ * Static function for creating a new wikipage object from a
 54+ * MediaWiki Title object.
 55+ */
 56+ static public function makePageFromTitle( $titleobject ) {
 57+ $page = new SMWWikiPageValue( '_wpg' );
 58+ $page->setTitle( $titleobject );
 59+ return $page;
 60+ }
 61+
 62+ public function __construct( $typeid ) {
 63+ parent::__construct( $typeid );
 64+ switch ( $typeid ) {
 65+ case '__typ':
 66+ $this->m_fixNamespace = SMW_NS_TYPE;
 67+ break;
 68+ case '_wpp' : case '__sup':
 69+ $this->m_fixNamespace = SMW_NS_PROPERTY;
 70+ break;
 71+ case '_wpc' : case '__suc': case '__sin':
 72+ $this->m_fixNamespace = NS_CATEGORY;
 73+ break;
 74+ case '_wpf' : case '__spf':
 75+ $this->m_fixNamespace = SF_NS_FORM;
 76+ break;
 77+ default: // case '_wpg':
 78+ $this->m_fixNamespace = NS_MAIN;
 79+ }
 80+ }
 81+
 82+ protected function parseUserValue( $value ) {
 83+ global $wgContLang;
 84+ $value = ltrim( rtrim( $value, ' ]' ), ' [' ); // support inputs like " [[Test]] "
 85+ if ( $value != '' ) {
 86+ $this->m_title = Title::newFromText( $value, $this->m_fixNamespace );
 87+ ///TODO: Escape the text so users can see any punctuation problems (bug 11666).
 88+ if ( $this->m_title === null ) {
 89+ smwfLoadExtensionMessages( 'SemanticMediaWiki' );
 90+ $this->addError( wfMsgForContent( 'smw_notitle', $value ) );
 91+ } elseif ( ( $this->m_fixNamespace != NS_MAIN ) &&
 92+ ( $this->m_fixNamespace != $this->m_title->getNamespace() ) ) {
 93+ smwfLoadExtensionMessages( 'SemanticMediaWiki' );
 94+ $this->addError( wfMsgForContent( 'smw_wrong_namespace', $wgContLang->getNsText( $this->m_fixNamespace ) ) );
 95+ }
 96+ if ( $this->m_title !== null ) {
 97+ $this->m_textform = $this->m_title->getText();
 98+ $this->m_dbkeyform = $this->m_title->getDBkey();
 99+ $this->m_interwiki = $this->m_title->getInterwiki();
 100+ $this->m_fragment = $this->m_title->getFragment();
 101+ $this->m_prefixedtext = $this->m_title->getPrefixedText(); ///NOTE: may include interwiki prefix
 102+ $this->m_namespace = $this->m_title->getNamespace();
 103+ $this->m_id = false; // unset id
 104+ if ( $this->m_caption === false ) {
 105+ $this->m_caption = $value;
 106+ }
 107+ }
 108+ } else {
 109+ smwfLoadExtensionMessages( 'SemanticMediaWiki' );
 110+ $this->addError( wfMsgForContent( 'smw_notitle', $value ) );
 111+ }
 112+ if ( $this->m_caption === false ) {
 113+ $this->m_caption = '';
 114+ }
 115+ }
 116+
 117+ protected function parseDBkeys( $args ) {
 118+ $this->m_dbkeyform = $args[0];
 119+ $this->m_namespace = array_key_exists( 1, $args ) ? $args[1]:$this->m_fixNamespace;
 120+ $this->m_interwiki = array_key_exists( 2, $args ) ? $args[2]:'';
 121+ $this->m_sortkey = array_key_exists( 3, $args ) ? $args[3]:'';
 122+ $this->m_textform = str_replace( '_', ' ', $this->m_dbkeyform );
 123+ $this->m_id = false;
 124+ $this->m_title = null;
 125+ $this->m_prefixedtext = false;
 126+ $this->m_caption = false;
 127+ if ( ( $this->m_fixNamespace != NS_MAIN ) && ( $this->m_fixNamespace != $this->m_namespace ) ) {
 128+ smwfLoadExtensionMessages( 'SemanticMediaWiki' );
 129+ $this->addError( wfMsgForContent( 'smw_notitle', $this->getPrefixedText() ) );
 130+ }
 131+ }
 132+
 133+ public function getShortWikiText( $linked = null ) {
 134+ $this->unstub();
 135+ if ( ( $linked === null ) || ( $linked === false ) || ( $this->m_outformat == '-' ) || ( !$this->isValid() ) || ( $this->m_caption === '' ) ) {
 136+ return $this->getCaption();
 137+ } else {
 138+ return '[[:' . str_replace( "'", '&#x0027;', $this->getPrefixedText() ) .
 139+ ( $this->m_fragment ? "#$this->m_fragment":'' ) . '|' . $this->getCaption() . ']]';
 140+ }
 141+ }
 142+
 143+ public function getShortHTMLText( $linker = null ) {
 144+ $this->unstub();
 145+ if ( ( $linker !== null ) && ( $this->m_caption !== '' ) && ( $this->m_outformat != '-' ) ) { $this->getTitle(); } // init the Title object, may reveal hitherto unnoticed errors
 146+ if ( ( $linker === null ) || ( !$this->isValid() ) || ( $this->m_outformat == '-' ) || ( $this->m_caption === '' ) ) {
 147+ return htmlspecialchars( $this->getCaption() );
 148+ } elseif ( $this->getNamespace() == NS_MEDIA ) { /// NOTE: this extra case is indeed needed
 149+ return $linker->makeMediaLinkObj( $this->getTitle(), $this->getCaption() );
 150+ } else {
 151+ return $linker->makeLinkObj( $this->getTitle(), $this->getCaption() );
 152+ }
 153+ }
 154+
 155+ /**
 156+ * @note The getLong... functions of this class always hide the fragment. Fragments are currently
 157+ * not stored, and hence should not be shown in the Factbox (where the getLongWikiText method is used).
 158+ * In all other uses, values come from the store and do not have fragments anyway.
 159+ */
 160+ public function getLongWikiText( $linked = null ) {
 161+ $this->unstub();
 162+ if ( !$this->isValid() ) {
 163+ return $this->getErrorText();
 164+ }
 165+ if ( ( $linked === null ) || ( $linked === false ) || ( $this->m_outformat == '-' ) ) {
 166+ return $this->m_fixNamespace == NS_MAIN ? $this->getPrefixedText():$this->getText();
 167+ } elseif ( $this->m_namespace == NS_IMAGE ) { // embed images instead of linking to their page
 168+ return '[[' . str_replace( "'", '&#x0027;', $this->getPrefixedText() ) . '|' . $this->m_textform . '|frameless|border|text-top]]';
 169+ } else { // this takes care of all other cases, esp. it is right for Media:
 170+ return '[[:' . str_replace( "'", '&#x0027;', $this->getPrefixedText() ) . '|' . $this->m_textform . ']]';
 171+ }
 172+ }
 173+
 174+ public function getLongHTMLText( $linker = null ) {
 175+ $this->unstub();
 176+ if ( ( $linker !== null ) && ( $this->m_outformat != '-' ) ) { $this->getTitle(); } // init the Title object, may reveal hitherto unnoticed errors
 177+ if ( !$this->isValid() ) {
 178+ return $this->getErrorText();
 179+ }
 180+ if ( ( $linker === null ) || ( $this->m_outformat == '-' ) ) {
 181+ return htmlspecialchars( $this->m_fixNamespace == NS_MAIN ? $this->getPrefixedText():$this->getText() );
 182+ } elseif ( $this->getNamespace() == NS_MEDIA ) { // this extra case is really needed
 183+ return $linker->makeMediaLinkObj( $this->getTitle(), $this->m_textform );
 184+ } else { // all others use default linking, no embedding of images here
 185+ return $linker->makeLinkObj( $this->getTitle(), $this->m_textform );
 186+ }
 187+ }
 188+
 189+ public function getDBkeys() {
 190+ $this->unstub();
 191+ return array( $this->m_dbkeyform, $this->m_namespace, $this->m_interwiki, $this->getSortkey() );
 192+ }
 193+
 194+ public function getSignature() {
 195+ return 'tnwt';
 196+ }
 197+
 198+ public function getValueIndex() {
 199+ return 3;
 200+ }
 201+
 202+ public function getLabelIndex() {
 203+ return 3;
 204+ }
 205+
 206+ public function getWikiValue() {
 207+ $this->unstub();
 208+ if ( $this->m_fixNamespace != NS_MAIN ) { // no explicit namespace needed!
 209+ return $this->getText();
 210+ } elseif ( $this->m_namespace == NS_CATEGORY ) {
 211+ // escape to enable use in links; todo: not generally required/suitable :-/
 212+ return ':' . $this->getPrefixedText();
 213+ } else {
 214+ return $this->getPrefixedText();
 215+ }
 216+ }
 217+
 218+ public function getHash() {
 219+ return $this->isValid() ? $this->getPrefixedText():implode( "\t", $this->getErrors() );
 220+ }
 221+
 222+ protected function getServiceLinkParams() {
 223+ $this->unstub();
 224+ // Create links to mapping services based on a wiki-editable message. The parameters
 225+ // available to the message are:
 226+ // $1: urlencoded article name (no namespace)
 227+ return array( rawurlencode( str_replace( '_', ' ', $this->m_dbkeyform ) ) );
 228+ }
 229+
 230+ public function getExportData() {
 231+ if ( !$this->isValid() ) return null;
 232+ switch ( $this->getNamespace() ) {
 233+ case NS_MEDIA: // special handling for linking media files directly
 234+ $file = wfFindFile( $this->getTitle() );
 235+ if ( $file ) {
 236+ // $name = $file->getFullURL();
 237+ /// TODO: the following just emulates getFullURL() which is not yet available in MW1.11:
 238+ $uri = $file->getUrl();
 239+ if ( substr( $uri, 0, 1 ) == '/' ) {
 240+ global $wgServer;
 241+ $uri = $wgServer . $uri;
 242+ }
 243+ return new SMWExpData( new SMWExpResource( $uri, $this ) );
 244+ } else { // Medialink to non-existing file :-/
 245+ return null;
 246+ }
 247+ break;
 248+ default: // some true wiki page
 249+ return new SMWExpData( SMWExporter::getResourceElement( $this ) );
 250+ break;
 251+ }
 252+ }
 253+
 254+///// special interface for wiki page values
 255+
 256+ /**
 257+ * Return according Title object or NULL if no valid value was set.
 258+ * NULL can be returned even if this object returns TRUE for isValid(),
 259+ * since the latter function does not check whether MediaWiki can really
 260+ * make a Title out of the given data.
 261+ * However, isValid() will return FALSE *after* this function failed in
 262+ * trying to create a title.
 263+ */
 264+ public function getTitle() {
 265+ if ( ( $this->isValid() ) && ( $this->m_title === null ) ) {
 266+ if ( $this->m_interwiki == '' ) {
 267+ $this->m_title = Title::makeTitle( $this->m_namespace, $this->m_dbkeyform );
 268+ } else { // interwiki title objects must be built from full input texts
 269+ $this->m_title = Title::newFromText( $this->getPrefixedText() );
 270+ }
 271+ }
 272+ if ( $this->m_title === null ) { // should not normally happen, but anyway ...
 273+ global $wgContLang;
 274+ smwfLoadExtensionMessages( 'SemanticMediaWiki' );
 275+ $this->addError( wfMsgForContent( 'smw_notitle', $wgContLang->getNsText( $this->m_namespace ) . ':' . $this->m_dbkeyform ) );
 276+ $this->m_dbkeyform = '';
 277+ }
 278+ return $this->m_title;
 279+ }
 280+
 281+ /**
 282+ * Get MediaWiki's ID for this value, if any.
 283+ */
 284+ public function getArticleID() {
 285+ $this->unstub();
 286+ if ( $this->m_id === false ) {
 287+ $this->m_id = ( $this->getTitle() !== null ) ? $this->m_title->getArticleID():0;
 288+ }
 289+ return $this->m_id;
 290+ }
 291+
 292+ /**
 293+ * Get namespace constant for this value, if any. Otherwise
 294+ * return FALSE.
 295+ */
 296+ public function getNamespace() {
 297+ return $this->isValid() ? $this->m_namespace:false;
 298+ }
 299+
 300+ /**
 301+ * Get DBKey for this value. Subclasses that allow for vlaues that do not
 302+ * correspond to wiki pages may choose a DB key that is not a legal title
 303+ * DB key but rather another suitable internal ID. Thus it is not suitable
 304+ * to use this method in places where only MediaWiki Title keys are allowed.
 305+ */
 306+ public function getDBkey() {
 307+ $this->unstub();
 308+ return $this->m_dbkeyform;
 309+ }
 310+
 311+ /// Get text label for this value.
 312+ public function getText() {
 313+ $this->unstub();
 314+ return str_replace( '_', ' ', $this->m_dbkeyform );
 315+ }
 316+
 317+ /// Get the prefixed text for this value, including a localised namespace prefix.
 318+ public function getPrefixedText() {
 319+ global $wgContLang;
 320+ $this->unstub();
 321+ if ( $this->m_prefixedtext === false ) {
 322+ $nstext = $wgContLang->getNSText( $this->m_namespace );
 323+ $this->m_prefixedtext = $this->m_interwiki . ( $this->m_interwiki != '' ? ':':'' ) .
 324+ $nstext . ( $nstext != '' ? ':':'' ) . $this->m_textform;
 325+ }
 326+ return $this->m_prefixedtext;
 327+ }
 328+
 329+ /**
 330+ * Get interwiki prefix or empty string.
 331+ */
 332+ public function getInterwiki() {
 333+ $this->unstub();
 334+ return $this->m_interwiki;
 335+ }
 336+
 337+ /**
 338+ * Get sortkey or make one as default.
 339+ */
 340+ public function getSortkey() {
 341+ $this->unstub();
 342+ return $this->m_sortkey ? $this->m_sortkey:( str_replace( '_', ' ', $this->m_dbkeyform ) );
 343+ }
 344+
 345+ /**
 346+ * Set sortkey
 347+ */
 348+ public function setSortkey( $sortkey ) {
 349+ $this->unstub(); // unstub first, since the stubarray also may hold a sortkey
 350+ $this->m_sortkey = $sortkey;
 351+ }
 352+
 353+ /**
 354+ * Init this data value object based on a given Title object.
 355+ */
 356+ public function setTitle( $title ) {
 357+ $this->setDBkeys( array( $title->getDBkey(), $title->getNamespace(), $title->getInterwiki(), '' ) );
 358+ $this->m_title = $title;
 359+ }
 360+
 361+ /**
 362+ * Get the (default) caption for this value.
 363+ * If a fixed namespace is set, we do not return the namespace prefix explicitly.
 364+ */
 365+ protected function getCaption() {
 366+ return $this->m_caption !== false ? $this->m_caption:
 367+ ( $this->m_fixNamespace == NS_MAIN ? $this->getPrefixedText():$this->getText() );
 368+ }
 369+
 370+ /**
 371+ * @deprecated Use setDBkeys()
 372+ */
 373+ public function setValues( $dbkey, $namespace, $id = false, $interwiki = '', $sortkey = '' ) {
 374+ $this->setDBkeys( array( $dbkey, $namespace, $interwiki, $sortkey ) );
 375+ }
 376+
 377+}
 378+
Property changes on: trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_WikiPage.php
___________________________________________________________________
Added: svn:eol-style
1379 + native
Index: trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_Types.php
@@ -0,0 +1,156 @@
 2+<?php
 3+/**
 4+ * @file
 5+ * @ingroup SMWDataValues
 6+ */
 7+
 8+/**
 9+ * This datavalue implements special processing suitable for defining types of
 10+ * properties. Types behave largely like values of type SMWSimpleWikiPageValue
 11+ * with three main differnces. First, they actively check if a value is an
 12+ * alias for another type, modifying the internal representation accordingly.
 13+ * Second, they have a modified display for emphasizing if some type is defined
 14+ * in SMW (built-in). Third, they use type ids for storing data (DB keys)
 15+ * instead of using page titles.
 16+ *
 17+ * @author Markus Krötzsch
 18+ * @ingroup SMWDataValues
 19+ */
 20+class SMWTypesValue extends SMWSimpleWikiPageValue {
 21+
 22+ private $m_isalias; // record whether this is an alias to another type, used to avoid duplicates when listing page types
 23+ protected $m_reallabel;
 24+
 25+ protected function parseUserValue( $value ) {
 26+ parent::parseUserValue( $value );
 27+ $this->m_reallabel = SMWDataValueFactory::findTypeLabel( SMWDataValueFactory::findTypeID( $this->m_textform ) );
 28+ $this->m_isalias = ( $this->m_reallabel === $this->m_textform ) ? false:true;
 29+ }
 30+
 31+ protected function parseDBkeys( $args ) {
 32+ parent::parseDBkeys( array( str_replace( ' ', '_', SMWDataValueFactory::findTypeLabel( $args[0] ) ) ) );
 33+ $this->m_reallabel = $this->m_textform;
 34+ $this->m_isalias = false;
 35+ }
 36+
 37+ public function getLongWikiText( $linked = null ) {
 38+ $this->unstub();
 39+ if ( ( $linked === null ) || ( $linked === false ) ) {
 40+ return $this->m_reallabel;
 41+ } else {
 42+ global $wgContLang;
 43+ $typenamespace = $wgContLang->getNsText( SMW_NS_TYPE );
 44+ $id = SMWDataValueFactory::findTypeID( $this->m_reallabel );
 45+ if ( $id { 0 } == '_' ) { // builtin
 46+ smwfLoadExtensionMessages( 'SemanticMediaWiki' );
 47+ SMWOutputs::requireHeadItem( SMW_HEADER_TOOLTIP );
 48+ return '<span class="smwttinline"><span class="smwbuiltin">[[' . $typenamespace . ':' . $this->m_reallabel . '|' . $this->m_reallabel . ']]</span><span class="smwttcontent">' . wfMsgForContent( 'smw_isknowntype' ) . '</span></span>';
 49+ } else {
 50+ return '[[' . $typenamespace . ':' . $this->m_reallabel . '|' . $this->m_reallabel . ']]';
 51+ }
 52+ }
 53+ }
 54+
 55+ public function getLongHTMLText( $linker = null ) {
 56+ $this->unstub();
 57+ if ( ( $linker === null ) || ( $linker === false ) ) {
 58+ return $this->m_reallabel;
 59+ } else {
 60+ $title = $this->m_isalias ? Title::newFromText( $this->m_reallabel, SMW_NS_TYPE ) : $this->getTitle();
 61+ $id = SMWDataValueFactory::findTypeID( $this->m_reallabel );
 62+ if ( $id { 0 } == '_' ) { // builtin
 63+ smwfLoadExtensionMessages( 'SemanticMediaWiki' );
 64+ SMWOutputs::requireHeadItem( SMW_HEADER_TOOLTIP );
 65+ return '<span class="smwttinline"><span class="smwbuiltin">' .
 66+ $linker->makeLinkObj( $title, $this->m_reallabel ) . '</span><span class="smwttcontent">' .
 67+ wfMsgForContent( 'smw_isknowntype' ) . '</span></span>';
 68+ } else {
 69+ return $linker->makeLinkObj( $title, $this->m_reallabel );
 70+ }
 71+ }
 72+ }
 73+
 74+ public function getDBkeys() {
 75+ return ( $this->isValid() ) ? array( $this->getDBkey() ):array( false );
 76+ }
 77+
 78+ public function getSignature() {
 79+ return 't';
 80+ }
 81+
 82+ public function getValueIndex() {
 83+ return 0;
 84+ }
 85+
 86+ public function getLabelIndex() {
 87+ return 0;
 88+ }
 89+
 90+ public function getWikiValue() {
 91+ return implode( '; ', $this->getTypeLabels() );
 92+ }
 93+
 94+ public function getHash() {
 95+ return implode( "\t", $this->getTypeLabels() );
 96+ }
 97+
 98+ /**
 99+ * This class uses type ids as DB keys.
 100+ */
 101+ public function getDBkey() {
 102+ return ( $this->isValid() ) ? SMWDataValueFactory::findTypeID( $this->m_reallabel ):'';
 103+ }
 104+
 105+ /**
 106+ * Is this a built-in datatype shipped with SMW (or an extension of SMW)?
 107+ * (Alternatively it would be a user-defined derived datatype.)
 108+ */
 109+ public function isBuiltIn() {
 110+ $v = $this->getDBkey();
 111+ return ( ( $this->isUnary() ) && ( $v { 0 } == '_' ) );
 112+ }
 113+
 114+ /**
 115+ * Is this an alias for another datatype in SMW? This information is used to
 116+ * explain entries in Special:Types that are found since they have pages.
 117+ */
 118+ public function isAlias() {
 119+ $this->unstub();
 120+ return $this->m_isalias;
 121+ }
 122+
 123+ /**
 124+ * Retrieve type labels if needed. Can be done lazily.
 125+ */
 126+ public function getTypeLabels() {
 127+ $this->unstub();
 128+ return array( $this->m_reallabel );
 129+ }
 130+
 131+ /**
 132+ * Retrieve type captions if needed. Can be done lazily. The captions
 133+ * are different from the labels if type aliases are used.
 134+ */
 135+ public function getTypeCaptions() {
 136+ $this->unstub();
 137+ return array( $this->m_textform );
 138+ }
 139+
 140+ /**
 141+ * Retrieve type values.
 142+ * @deprecated This method is no longer meaningful and will vanish before SMW 1.6
 143+ */
 144+ public function getTypeValues() {
 145+ return array( $this );
 146+ }
 147+
 148+ /**
 149+ * Is this a simple unary type or some composed n-ary type?
 150+ * @deprecated This method is no longer meaningful and will vanish before SMW 1.6
 151+ */
 152+ public function isUnary() {
 153+ return true;
 154+ }
 155+
 156+}
 157+
Property changes on: trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_Types.php
___________________________________________________________________
Added: svn:eol-style
1158 + native
Index: trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_String.php
@@ -0,0 +1,162 @@
 2+<?php
 3+/**
 4+ * @file
 5+ * @ingroup SMWDataValues
 6+ */
 7+
 8+/**
 9+ * This datavalue implements String-Datavalues suitable for defining
 10+ * String-types of properties.
 11+ *
 12+ * @author Nikolas Iwan
 13+ * @author Markus Krötzsch
 14+ * @ingroup SMWDataValues
 15+ */
 16+class SMWStringValue extends SMWDataValue {
 17+
 18+ /// Wiki-compatible value representation, possibly unsafe for plain HTML.
 19+ protected $m_value = '';
 20+
 21+ protected function parseUserValue( $value ) {
 22+ smwfLoadExtensionMessages( 'SemanticMediaWiki' );
 23+ if ( $value != '' ) {
 24+ $this->m_value = $value;
 25+ if ( ( $this->m_typeid != '_txt' ) && ( $this->m_typeid != '_cod' ) && ( strlen( $this->m_value ) > 255 ) ) { // limit size (for DB indexing)
 26+ $this->addError( wfMsgForContent( 'smw_maxstring', mb_substr( $value, 0, 42 ) . ' <span class="smwwarning">[…]</span> ' . mb_substr( $value, mb_strlen( $this->m_value ) - 42 ) ) );
 27+ }
 28+ } else {
 29+ $this->addError( wfMsgForContent( 'smw_emptystring' ) );
 30+ }
 31+ if ( $this->m_caption === false ) {
 32+ $this->m_caption = ( $this->m_typeid == '_cod' ) ? $this->getCodeDisplay( $value ):$value;
 33+ }
 34+ return true;
 35+ }
 36+
 37+ protected function parseDBkeys( $args ) {
 38+ $this->parseUserValue( $args[0] );
 39+ $this->m_caption = $this->m_value; // this is our output text
 40+ }
 41+
 42+ public function getShortWikiText( $linked = null ) {
 43+ $this->unstub();
 44+ // TODO: Support linking?
 45+ return $this->m_caption;
 46+ }
 47+
 48+ /**
 49+ * @todo Rather parse input to obtain properly formatted HTML.
 50+ */
 51+ public function getShortHTMLText( $linker = null ) {
 52+ return smwfXMLContentEncode( $this->getShortWikiText( $linker ) );
 53+ }
 54+
 55+ public function getLongWikiText( $linked = null ) {
 56+ return $this->isValid() ? $this->getAbbValue( $linked, $this->m_value ):$this->getErrorText();
 57+ }
 58+
 59+ /**
 60+ * @todo Rather parse input to obtain properly formatted HTML.
 61+ */
 62+ public function getLongHTMLText( $linker = null ) {
 63+ return $this->isValid() ? $this->getAbbValue( $linker, smwfXMLContentEncode( $this->m_value ) ):$this->getErrorText();
 64+ }
 65+
 66+ public function getDBkeys() {
 67+ $this->unstub();
 68+ return array( $this->m_value );
 69+ }
 70+
 71+ public function getSignature() {
 72+ return ( ( $this->m_typeid == '_txt' ) || ( $this->m_typeid == '_cod' ) ) ? 'l':'t';
 73+ }
 74+
 75+ /**
 76+ * For perfomance reasons, long text data like _txt and _cod does not
 77+ * support sorting. This class can be subclassed to change this.
 78+ */
 79+ public function getValueIndex() {
 80+ return ( $this->m_typeid == '_txt' || $this->m_typeid == '_cod' ) ? - 1 : 0;
 81+ }
 82+
 83+ /**
 84+ * For perfomance reasons, long text data like _txt and _cod does not
 85+ * support string matching. This class can be subclassed to change this.
 86+ */
 87+ public function getLabelIndex() {
 88+ return ( $this->m_typeid == '_txt' || $this->m_typeid == '_cod' ) ? - 1 : 0;
 89+ }
 90+
 91+ public function getWikiValue() {
 92+ $this->unstub();
 93+ return $this->m_value;
 94+ }
 95+
 96+ public function getInfolinks() {
 97+ $this->unstub();
 98+ if ( ( $this->m_typeid != '_txt' ) && ( $this->m_typeid != '_cod' ) ) {
 99+ return SMWDataValue::getInfolinks();
 100+ } else {
 101+ return $this->m_infolinks;
 102+ }
 103+ }
 104+
 105+ protected function getServiceLinkParams() {
 106+ $this->unstub();
 107+ // Create links to mapping services based on a wiki-editable message. The parameters
 108+ // available to the message are:
 109+ // $1: urlencoded string
 110+ if ( ( $this->m_typeid != '_txt' ) && ( $this->m_typeid != '_cod' ) ) {
 111+ return array( rawurlencode( $this->m_value ) );
 112+ } else {
 113+ return false; // no services for Type:Text and Type:Code
 114+ }
 115+ }
 116+
 117+ public function getExportData() {
 118+ if ( $this->isValid() ) {
 119+ $lit = new SMWExpLiteral( smwfHTMLtoUTF8( $this->m_value ), $this, 'http://www.w3.org/2001/XMLSchema#string' );
 120+ return new SMWExpData( $lit );
 121+ } else {
 122+ return null;
 123+ }
 124+ }
 125+
 126+ /**
 127+ * Make a possibly shortened printout string for displaying the value.
 128+ * The value must be specified as an input since necessary HTML escaping
 129+ * must be applied to it first, if desired. The result of getAbbValue()
 130+ * may contain wiki-compatible HTML mark-up that should not be escaped.
 131+ * @todo The method abbreviates very long strings for display by simply
 132+ * taking substrings. This is not in all cases a good idea, since it may
 133+ * break XML entities and mark-up.
 134+ */
 135+ protected function getAbbValue( $linked, $value ) {
 136+ $len = mb_strlen( $value );
 137+ if ( ( $len > 255 ) && ( $this->m_typeid != '_cod' ) ) {
 138+ if ( ( $linked === null ) || ( $linked === false ) ) {
 139+ return mb_substr( $value, 0, 42 ) . ' <span class="smwwarning">…</span> ' . mb_substr( $value, $len - 42 );
 140+ } else {
 141+ SMWOutputs::requireHeadItem( SMW_HEADER_TOOLTIP );
 142+ return mb_substr( $value, 0, 42 ) . ' <span class="smwttpersist"> … <span class="smwttcontent">' . $value . '</span></span> ' . mb_substr( $value, $len - 42 );
 143+ }
 144+ } elseif ( $this->m_typeid == '_cod' ) {
 145+ return $this->getCodeDisplay( $value, true );
 146+ } else {
 147+ return $value;
 148+ }
 149+ }
 150+
 151+ /**
 152+ * Special features for Type:Code formatting.
 153+ */
 154+ protected function getCodeDisplay( $value, $scroll = false ) {
 155+ SMWOutputs::requireHeadItem( SMW_HEADER_STYLE );
 156+ $result = str_replace( array( '<', '>', ' ', '=', "'", ':', "\n" ), array( '&lt;', '&gt;', '&#160;', '&#x003D;', '&#x0027;', '&#58;', "<br />" ), $value );
 157+ if ( $scroll ) {
 158+ $result = "<div style=\"height:5em; overflow:auto;\">$result</div>";
 159+ }
 160+ return "<div class=\"smwpre\">$result</div>";
 161+ }
 162+
 163+}
Property changes on: trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_String.php
___________________________________________________________________
Added: svn:eol-style
1164 + native
Index: trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_Import.php
@@ -0,0 +1,191 @@
 2+<?php
 3+/**
 4+ * @file
 5+ * @ingroup SMWDataValues
 6+ */
 7+
 8+/**
 9+ * This datavalue implements datavalues used by special property '_IMPO' used for assigning
 10+ * imported vocabulary to some page of the wiki.
 11+ * It looks up a MediaWiki message to find out whether a user-supplied vocabulary name
 12+ * can be imported in the wiki, and whether its declaration is correct (to the extend
 13+ * that this can be checked).
 14+ *
 15+ * @author Fabian Howahl
 16+ * @author Markus Krötzsch
 17+ * @ingroup SMWDataValues
 18+ */
 19+class SMWImportValue extends SMWDataValue {
 20+
 21+ protected $m_value = ''; // stores string provided by user which is used to look up data on Mediawiki:*-Page
 22+ protected $m_uri = ''; // URI of namespace (without local name)
 23+ protected $m_namespace = ''; // namespace id (e.g. "foaf")
 24+ protected $m_section = ''; // stores local name (e.g. "knows")
 25+ protected $m_name = ''; // stores wiki name of the vocab (e.g. "Friend of a Friend")
 26+ protected $m_wikilink = ''; // store string to be displayed in factbox
 27+
 28+ protected function parseUserValue( $value ) {
 29+ global $wgContLang;
 30+
 31+ $this->m_value = $value;
 32+ list( $onto_ns, $onto_section ) = explode( ':', $value, 2 );
 33+
 34+ $msglines = preg_split( "([\n][\s]?)", wfMsgForContent( "smw_import_$onto_ns" ) ); // get the definition for "$namespace:$section"
 35+
 36+ if ( count( $msglines ) < 2 ) { // error: no elements for this namespace
 37+ $this->addError( wfMsgForContent( 'smw_unknown_importns', $onto_ns ) );
 38+ return true;
 39+ }
 40+
 41+ // browse list in smw_import_* for section
 42+ list( $onto_uri, $onto_name ) = explode( '|', array_shift( $msglines ), 2 );
 43+
 44+ if ( $onto_uri[0] == ' ' ) $onto_uri = mb_substr( $onto_uri, 1 ); // tolerate initial space
 45+
 46+ $this->m_uri = $onto_uri;
 47+ $this->m_namespace = $onto_ns;
 48+ $this->m_section = $onto_section;
 49+ $this->m_name = $onto_name;
 50+
 51+ $elemtype = - 1;
 52+ foreach ( $msglines as $msgline ) {
 53+ list( $secname, $typestring ) = explode( '|', $msgline, 2 );
 54+ if ( $secname === $onto_section ) {
 55+ list( $namespace, ) = explode( ':', $typestring, 2 );
 56+ // check whether type matches
 57+ switch ( $namespace ) {
 58+ case $wgContLang->getNsText( SMW_NS_TYPE ):
 59+ $elemtype = SMW_NS_PROPERTY;
 60+ break;
 61+ case $wgContLang->getNsText( SMW_NS_PROPERTY ):
 62+ $elemtype = SMW_NS_PROPERTY;
 63+ break;
 64+ case $wgContLang->getNsText( NS_CATEGORY ):
 65+ $elemtype = NS_CATEGORY;
 66+ break;
 67+ case $wgContLang->getNsText( SMW_NS_CONCEPT ):
 68+ $elemtype = NS_CATEGORY;
 69+ break;
 70+ default: // match all other namespaces
 71+ $elemtype = NS_MAIN;
 72+ }
 73+ break;
 74+ }
 75+ }
 76+
 77+ // check whether element of correct type was found (extracts data from factbox)
 78+ ///TODO: parser needed to do that
 79+// if(SMWParseData::getSMWData($parser) instanceof SMWSemanticData) {
 80+// $this_ns = SMWParseData::getSMWData($parser)->getSubject()->getNamespace();
 81+// $error = null;
 82+// switch ($elemtype) {
 83+// case SMW_NS_PROPERTY: case NS_CATEGORY:
 84+// if ($this_ns != $elemtype) {
 85+// $error = wfMsgForContent('smw_nonright_importtype',$value, $wgContLang->getNsText($elemtype));
 86+// }
 87+// break;
 88+// case NS_MAIN:
 89+// if ( (SMW_NS_PROPERTY == $this_ns) || (NS_CATEGORY == $this_ns)) {
 90+// $error = wfMsgForContent('smw_wrong_importtype',$value, $wgContLang->getNsText($this_ns));
 91+// }
 92+// break;
 93+// case -1:
 94+// $error = wfMsgForContent('smw_no_importelement',$value);
 95+// }
 96+//
 97+// if (null != $error) {
 98+// $this->addError($error);
 99+// return true;
 100+// }
 101+// }
 102+
 103+ // create String to be returned by getShort/LongWikiText
 104+ $this->m_wikilink = "[" . $this->m_uri . " " . $this->m_value . "] (" . $this->m_name . ")";
 105+
 106+ // check whether caption is set, otherwise assign link statement to caption
 107+ if ( $this->m_caption === false ) {
 108+ $this->m_caption = $this->m_wikilink;
 109+ }
 110+
 111+ return true;
 112+ }
 113+
 114+ protected function parseDBkeys( $args ) {
 115+ $parts = explode( ' ', $args[0], 3 );
 116+ if ( array_key_exists( 0, $parts ) ) {
 117+ $this->m_namespace = $parts[0];
 118+ }
 119+ if ( array_key_exists( 1, $parts ) ) {
 120+ $this->m_section = $parts[1];
 121+ }
 122+ if ( array_key_exists( 2, $parts ) ) {
 123+ $this->m_uri = $parts[2];
 124+ }
 125+ $this->m_value = $this->m_namespace . ':' . $this->m_section;
 126+ $this->m_caption = $this->m_value; // not as pretty as on input, don't care
 127+ $this->m_wikilink = $this->m_value; // not as pretty as on input, don't care
 128+ }
 129+
 130+ public function getShortWikiText( $linked = null ) {
 131+ $this->unstub();
 132+ return $this->m_caption;
 133+ }
 134+
 135+ public function getShortHTMLText( $linker = null ) {
 136+ $this->unstub();
 137+ return htmlspecialchars( $this->m_value );
 138+ }
 139+
 140+ public function getLongWikiText( $linked = null ) {
 141+ if ( !$this->isValid() ) {
 142+ return $this->getErrorText();
 143+ } else {
 144+ return $this->m_wikilink;
 145+ }
 146+ }
 147+
 148+ public function getLongHTMLText( $linker = null ) {
 149+ if ( !$this->isValid() ) {
 150+ return $this->getErrorText();
 151+ } else {
 152+ return htmlspecialchars( $this->m_value );
 153+ }
 154+ }
 155+
 156+ public function getDBkeys() {
 157+ $this->unstub();
 158+ return array( $this->m_namespace . ' ' . $this->m_section . ' ' . $this->m_uri );
 159+ }
 160+
 161+ public function getSignature() {
 162+ return 't';
 163+ }
 164+
 165+ public function getValueIndex() {
 166+ return 0;
 167+ }
 168+
 169+ public function getLabelIndex() {
 170+ return 0;
 171+ }
 172+
 173+ public function getWikiValue() {
 174+ $this->unstub();
 175+ return $this->m_value;
 176+ }
 177+
 178+ public function getNS() {
 179+ $this->unstub();
 180+ return $this->m_uri;
 181+ }
 182+
 183+ public function getNSID() {
 184+ $this->unstub();
 185+ return $this->m_namespace;
 186+ }
 187+
 188+ public function getLocalName() {
 189+ $this->unstub();
 190+ return $this->m_section;
 191+ }
 192+}
Property changes on: trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_Import.php
___________________________________________________________________
Added: svn:eol-style
1193 + native
Index: trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_Linear.php
@@ -0,0 +1,226 @@
 2+<?php
 3+/**
 4+ * @file
 5+ * @ingroup SMWDataValues
 6+ */
 7+
 8+/**
 9+ * This datavalue implements unit support custom units, for which users have
 10+ * provided linear conversion factors within the wiki. Those user settings
 11+ * are retrieved from a type page, the DB key of which is the type id of this
 12+ * object.
 13+ *
 14+ * @author Markus Krötzsch
 15+ * @ingroup SMWDataValues
 16+ */
 17+class SMWLinearValue extends SMWNumberValue {
 18+
 19+ protected $m_unitfactors = false; // array mapping canonical unit strings to conversion factors
 20+ protected $m_unitids = false; // array mapping (normalised) unit strings to canonical unit strings (ids)
 21+ protected $m_displayunits = false; // array of units that should be displayed
 22+ protected $m_mainunit = false; // main unit (recognised by the conversion factor 1)
 23+
 24+ /**
 25+ * Converts the current m_value and m_unit to the main unit, if possible.
 26+ * This means, it changes the fileds m_value and m_unit accordingly, and
 27+ * that it stores the ID of the originally given unit in $this->m_unitin.
 28+ * This should obviously not be done more than once, so it is advisable to
 29+ * first check if m_unitin is non-false. Also, it should be checked if the
 30+ * value is valid before trying to calculate with its contents.
 31+ */
 32+ protected function convertToMainUnit() {
 33+ if ( $this->m_unitin !== false ) return;
 34+ $this->initConversionData();
 35+ if ( !$this->isValid() ) { // give up, avoid calculations with non-numbers
 36+ $this->m_unitin = $this->m_unit;
 37+ return;
 38+ }
 39+
 40+ // Find ID for current unit
 41+ if ( array_key_exists( $this->m_unit, $this->m_unitids ) ) {
 42+ $this->m_unitin = $this->m_unitids[$this->m_unit];
 43+ } else { // already unit id (possibly of an unknown unit)
 44+ $this->m_unitin = $this->m_unit;
 45+ }
 46+
 47+ // Do conversion
 48+ if ( ( array_key_exists( $this->m_unitin, $this->m_unitfactors ) ) && ( $this->m_mainunit !== false ) ) {
 49+ $this->m_unit = $this->m_mainunit;
 50+ $this->m_value = $this->m_value / $this->m_unitfactors[$this->m_unitin];
 51+ } // else: unsupported unit, keep all as it is
 52+ }
 53+
 54+ /**
 55+ * This method creates an array of unit-value-pairs that should be
 56+ * printed. Units are the keys and should be canonical unit IDs.
 57+ * The result is stored in $this->m_unitvalues. Again, any class that
 58+ * requires effort for doing this should first check whether the array
 59+ * is already set (i.e. not false) before doing any work.
 60+ * Note that the values should be plain numbers. Output formatting is done
 61+ * later when needed. Also, it should be checked if the value is valid
 62+ * before trying to calculate with its contents.
 63+ * This method also must call or implement convertToMainUnit().
 64+ */
 65+ protected function makeConversionValues() {
 66+ if ( $this->m_unitvalues !== false ) return;
 67+ $this->convertToMainUnit();
 68+ if ( $this->m_unit !== $this->m_mainunit ) { // conversion failed, no choice for us
 69+ $this->m_unitvalues = array( $this->m_unit => $this->m_value );
 70+ return;
 71+ }
 72+ $this->initDisplayData();
 73+
 74+ $this->m_unitvalues = array();
 75+ if ( count( $this->m_displayunits ) == 0 ) { // no display units, just show all
 76+ foreach ( $this->m_unitfactors as $unit => $factor ) {
 77+ $this->m_unitvalues[$unit] = $this->m_value * $factor;
 78+ }
 79+ } else {
 80+ foreach ( $this->m_displayunits as $unit ) { // do not use unit ids here (requires a small hack below, but allows to select representation of unit via displayunits)
 81+ if ( array_key_exists( $this->m_unitids[$unit], $this->m_unitfactors ) ) {
 82+ $this->m_unitvalues[$unit] = $this->m_value * $this->m_unitfactors[$this->m_unitids[$unit]];
 83+ if ( $this->m_unitids[$unit] == $this->m_unitin ) { // use the display unit version of the input unit as id
 84+ $this->m_unitin = $unit;
 85+ }
 86+ }
 87+ }
 88+ if ( count( $this->m_unitvalues ) == 0 ) { // none of the desired units matches
 89+ // display just the current one (so one can disable unit tooltips by setting a nonunit for display)
 90+ $this->m_unitvalues = array( $this->m_unit => $this->m_value );
 91+ }
 92+ }
 93+ }
 94+
 95+ /**
 96+ * This method is used when no user input was given to find the best
 97+ * values for m_wikivalue, m_unitin, and m_caption. After conversion,
 98+ * these fields will look as if they were generated from user input,
 99+ * and convertToMainUnit() will have been called (if not, it would be
 100+ * blocked by the presence of m_unitin).
 101+ */
 102+ protected function makeUserValue() {
 103+ $this->convertToMainUnit();
 104+
 105+ $value = false;
 106+ if ( $this->m_unit === $this->m_mainunit ) { // only try if conversion worked
 107+ if ( ( $value === false ) && ( $this->m_outformat ) && ( $this->m_outformat != '-' ) ) { // first try given output unit
 108+ $unit = $this->normalizeUnit( $this->m_outformat );
 109+ $printunit = $unit;
 110+ if ( array_key_exists( $unit, $this->m_unitids ) ) { // find id for output unit
 111+ $unit = $this->m_unitids[$unit];
 112+ if ( array_key_exists( $unit, $this->m_unitfactors ) ) { // find factor for this id
 113+ $value = $this->m_value * $this->m_unitfactors[$unit];
 114+ }
 115+ }
 116+ }
 117+ if ( $value === false ) { // next look for the first given display unit
 118+ $this->initDisplayData();
 119+ if ( count( $this->m_displayunits ) > 0 ) {
 120+ $unit = $this->m_unitids[$this->m_displayunits[0]]; // was already verified to exist before
 121+ if ( array_key_exists( $unit, $this->m_unitfactors ) ) { // find factor for this id
 122+ $value = $this->m_value * $this->m_unitfactors[$unit];
 123+ $printunit = $this->m_displayunits[0];
 124+ }
 125+ }
 126+ }
 127+ }
 128+
 129+ if ( $value === false ) { // finally fallback to current value
 130+ $value = $this->m_value;
 131+ $unit = $this->m_unit;
 132+ $printunit = $unit;
 133+ }
 134+
 135+ $this->m_caption = '';
 136+ if ( $this->m_outformat != '-u' ) { // -u is the format for displaying the unit only
 137+ $this->m_caption .= ( ( $this->m_outformat != '-' ) && ( $this->m_outformat != '-n' ) ? smwfNumberFormat( $value ) : $value );
 138+ }
 139+ if ( ( $printunit != '' ) && ( $this->m_outformat != '-n' ) ) { // -n is the format for displaying the number only
 140+ if ( $this->m_outformat != '-u' ) {
 141+ $this->m_caption .= ( $this->m_outformat != '-' ? '&#160;' : ' ' );
 142+ }
 143+ $this->m_caption .= $printunit;
 144+ }
 145+ $this->m_wikivalue = $this->m_caption;
 146+ $this->m_unitin = $unit;
 147+ }
 148+
 149+ /**
 150+ * Return an array of major unit strings (ids only recommended) supported by
 151+ * this datavalue.
 152+ */
 153+ public function getUnitList() {
 154+ $this->initConversionData();
 155+ return array_keys( $this->m_unitfactors );
 156+ }
 157+
 158+/// The remaining functions are relatively "private" but are kept protected since
 159+/// subclasses might exploit this to, e.g., "fake" conversion factors instead of
 160+/// getting them from the database. A cheap way of making built-in types.
 161+
 162+ /**
 163+ * This method fills $m_unitfactors and $m_unitids with required values.
 164+ */
 165+ protected function initConversionData() {
 166+ if ( $this->m_unitids !== false ) return;
 167+ $this->m_unitids = array();
 168+ $this->m_unitfactors = array();
 169+
 170+ $typepage = SMWWikiPageValue::makePage( $this->m_typeid, SMW_NS_TYPE );
 171+ if ( !$typepage->isValid() ) return;
 172+ $factors = smwfGetStore()->getPropertyValues( $typepage, SMWPropertyValue::makeProperty( '_CONV' ) );
 173+ if ( count( $factors ) == 0 ) { // no custom type
 174+ // delete all previous errors, this is our real problem
 175+ /// TODO: probably we should check for this earlier, but avoid unnecessary DB requests ...
 176+ smwfLoadExtensionMessages( 'SemanticMediaWiki' );
 177+ $this->addError( wfMsgForContent( 'smw_unknowntype', SMWDataValueFactory::findTypeLabel( $this->getTypeID() ) ) );
 178+ return;
 179+ }
 180+ $numdv = SMWDataValueFactory::newTypeIDValue( '_num' ); // used for parsing the factors
 181+ foreach ( $factors as $dv ) {
 182+ $numdv->setUserValue( $dv->getWikiValue() );
 183+ if ( !$numdv->isValid() || ( $numdv->getValueKey() === 0 ) ) {
 184+ continue; // ignore problematic conversions
 185+ }
 186+ $unit_aliases = preg_split( '/\s*,\s*/u', $numdv->getUnit() );
 187+ $first = true;
 188+ foreach ( $unit_aliases as $unit ) {
 189+ $unit = $this->normalizeUnit( $unit );
 190+ if ( $first ) {
 191+ $unitid = $unit;
 192+ if ( $numdv->getValueKey() == 1 ) { // add main unit to front of array (displyed first)
 193+ $this->m_mainunit = $unit;
 194+ $this->m_unitfactors = array( $unit => $numdv->getValueKey() ) + $this->m_unitfactors;
 195+ } else { // non-main units are not ordered -- they might come out in any way the DB likes (can be modified via display units)
 196+ $this->m_unitfactors[$unit] = $numdv->getValueKey();
 197+ }
 198+ $first = false;
 199+ }
 200+ // add all known units to m_unitids to simplify checking for them
 201+ $this->m_unitids[$unit] = $unitid;
 202+ }
 203+ }
 204+ }
 205+
 206+ /**
 207+ * This method fills $m_displayunits.
 208+ */
 209+ protected function initDisplayData() {
 210+ if ( $this->m_displayunits !== false ) return;
 211+ $this->initConversionData(); // needed to normalise unit strings
 212+ $this->m_displayunits = array();
 213+ if ( ( $this->m_property === null ) || ( $this->m_property->getWikiPageValue() === null ) ) return;
 214+ $values = smwfGetStore()->getPropertyValues( $this->m_property->getWikiPageValue(), SMWPropertyValue::makeProperty( '_UNIT' ) );
 215+ $units = array();
 216+ foreach ( $values as $value ) { // Join all if many annotations exist. Discouraged (random order) but possible.
 217+ $units = $units + preg_split( '/\s*,\s*/u', $value->getWikiValue() );
 218+ }
 219+ foreach ( $units as $unit ) {
 220+ $unit = $this->normalizeUnit( $unit );
 221+ if ( array_key_exists( $unit, $this->m_unitids ) ) {
 222+ $this->m_displayunits[] = $unit; // avoid duplicates
 223+ } // note: we ignore unsuppported units, as they are printed anyway for lack of alternatives
 224+ }
 225+ }
 226+
 227+}
Property changes on: trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_Linear.php
___________________________________________________________________
Added: svn:eol-style
1228 + native
Index: trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_SimpleWikiPage.php
@@ -0,0 +1,51 @@
 2+<?php
 3+/**
 4+ * @file
 5+ * @ingroup SMWDataValues
 6+ */
 7+
 8+/**
 9+ * This datavalue is similiar to SMWWikiPageValue in that it represents pages
 10+ * in the wiki. However, it is tailored for uses where it is enough to store
 11+ * the title string of the page without namespace, interwiki prefix, or
 12+ * sortkey. This is useful for "special" properties like "Has type" where the
 13+ * namespace is fixed, and which do not need any of the other settings. The
 14+ * advantage of the reduction of data is that these important values can be
 15+ * stored in smaller tables that allow for faster direct access than general
 16+ * page type values.
 17+ *
 18+ * @author Markus Krötzsch
 19+ * @ingroup SMWDataValues
 20+ */
 21+class SMWSimpleWikiPageValue extends SMWWikiPageValue {
 22+
 23+ protected function parseDBkeys( $args ) {
 24+ $this->m_dbkeyform = $args[0];
 25+ $this->m_namespace = $this->m_fixNamespace;
 26+ $this->m_interwiki = '';
 27+ $this->m_sortkey = $this->m_dbkeyform;
 28+ $this->m_textform = str_replace( '_', ' ', $this->m_dbkeyform );
 29+ $this->m_id = false;
 30+ $this->m_title = null;
 31+ $this->m_prefixedtext = false;
 32+ $this->m_caption = false;
 33+ }
 34+
 35+ public function getDBkeys() {
 36+ $this->unstub();
 37+ return array( $this->m_dbkeyform );
 38+ }
 39+
 40+ public function getSignature() {
 41+ return 't';
 42+ }
 43+
 44+ public function getValueIndex() {
 45+ return 1;
 46+ }
 47+
 48+ public function getLabelIndex() {
 49+ return 1;
 50+ }
 51+
 52+}
\ No newline at end of file
Property changes on: trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_SimpleWikiPage.php
___________________________________________________________________
Added: svn:eol-style
153 + native
Index: trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_TypeList.php
@@ -0,0 +1,119 @@
 2+<?php
 3+/**
 4+ * @file
 5+ * @ingroup SMWDataValues
 6+ */
 7+
 8+/**
 9+ * This datavalue implements special processing suitable for defining the list
 10+ * of types that is required for SMWRecordValue objects. The input is a plain
 11+ * semicolon-separated list of type labels.
 12+ *
 13+ * @author Markus Krötzsch
 14+ * @ingroup SMWDataValues
 15+ */
 16+class SMWTypeListValue extends SMWDataValue {
 17+
 18+ private $m_typevalues = false;
 19+
 20+ protected function parseUserValue( $value ) {
 21+ $this->m_typevalues = array();
 22+ $types = explode( ';', $value );
 23+ foreach ( $types as $type ) {
 24+ $tval = SMWDataValueFactory::newTypeIDValue( '__typ', $type );
 25+ $this->m_typevalues[] = $tval;
 26+ }
 27+ }
 28+
 29+ protected function parseDBkeys( $args ) {
 30+ $this->m_typevalues = array();
 31+ $ids = explode( ';', $args[0] );
 32+ foreach ( $ids as $id ) {
 33+ $this->m_typevalues[] = SMWDataValueFactory::newTypeIDValue( '__typ', SMWDataValueFactory::findTypeLabel( $id ) );
 34+ }
 35+ }
 36+
 37+ /**
 38+ * The special feature of this implementation of getDBkeys is that it uses
 39+ * internal type ids to obtain a short internal value for the type. Note
 40+ * that this also given language independence but that this is of little
 41+ * use: if the value is given in another language in the wiki, then either
 42+ * the value is still understood, or the language-independent database
 43+ * entry is only of temporary use until someine edits the respective page.
 44+ */
 45+ public function getDBkeys() {
 46+ if ( $this->isvalid() ) {
 47+ $result = '';
 48+ foreach ( $this->m_typevalues as $tv ) {
 49+ if ( $result != '' ) $result .= ';';
 50+ $result .= $tv->getDBkey();
 51+ }
 52+ return array( $result );
 53+ } else {
 54+ return array( false );
 55+ }
 56+ }
 57+
 58+ public function getSignature() {
 59+ return 't';
 60+ }
 61+
 62+ public function getValueIndex() {
 63+ return 0;
 64+ }
 65+
 66+ public function getLabelIndex() {
 67+ return 0;
 68+ }
 69+
 70+ public function getShortWikiText( $linked = null ) {
 71+ return ( $this->m_caption !== false ) ? $this->m_caption : $this->makeOutputText( 0, $linked );
 72+ }
 73+
 74+ public function getShortHTMLText( $linker = null ) {
 75+ return ( $this->m_caption !== false ) ? $this->m_caption : $this->makeOutputText( 1, $linker );
 76+ }
 77+
 78+ public function getLongWikiText( $linked = null ) {
 79+ return $this->makeOutputText( 2, $linked );
 80+ }
 81+
 82+ public function getLongHTMLText( $linker = null ) {
 83+ return $this->makeOutputText( 3, $linker );
 84+ }
 85+
 86+ public function getWikiValue() {
 87+ return $this->makeOutputText( 4 );
 88+ }
 89+
 90+ public function getTypeValues() {
 91+ $this->unstub();
 92+ return $this->m_typevalues;
 93+ }
 94+
 95+////// Internal helper functions
 96+
 97+ private function makeOutputText( $type = 0, $linker = null ) {
 98+ if ( !$this->isValid() ) {
 99+ return ( ( $type == 0 ) || ( $type == 1 ) ) ? '' : $this->getErrorText();
 100+ }
 101+ $result = '';
 102+ $sep = ( $type == 4 ) ? '; ' : ', ';
 103+ foreach ( $this->m_typevalues as $tv ) {
 104+ if ( $result != '' ) $result .= $sep;
 105+ $result .= $this->makeValueOutputText( $type, $tv, $linker );
 106+ }
 107+ return $result;
 108+ }
 109+
 110+ private function makeValueOutputText( $type, $datavalue, $linker ) {
 111+ switch ( $type ) {
 112+ case 0: return $datavalue->getShortWikiText( $linker );
 113+ case 1: return $datavalue->getShortHTMLText( $linker );
 114+ case 2: return $datavalue->getLongWikiText( $linker );
 115+ case 3: return $datavalue->getLongHTMLText( $linker );
 116+ case 4: return $datavalue->getWikiValue();
 117+ }
 118+ }
 119+
 120+}
\ No newline at end of file
Property changes on: trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_TypeList.php
___________________________________________________________________
Added: svn:eol-style
1121 + native
Index: trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_Record.php
@@ -0,0 +1,249 @@
 2+<?php
 3+/**
 4+ * @file
 5+ * @ingroup SMWDataValues
 6+ */
 7+
 8+/**
 9+ * SMWDataValue implements the handling of short lists of values,
 10+ * where the order governs the type of each entry.
 11+ *
 12+ * @todo Enforce limitation of maximal number of values.
 13+ * @todo Complete internationalisation.
 14+ *
 15+ * @author Markus Krötzsch
 16+ * @ingroup SMWDataValues
 17+ */
 18+class SMWRecordValue extends SMWContainerValue {
 19+
 20+ /// cache for datavalues of types belonging to this object
 21+ private $m_typevalues = null;
 22+
 23+ protected function parseUserValue( $value ) {
 24+ $this->m_data->clear();
 25+ $this->parseUserValueOrQuery( $value, false );
 26+ }
 27+
 28+ protected function parseUserValueOrQuery( $value, $querymode ) {
 29+ if ( $value == '' ) {
 30+ $this->addError( wfMsg( 'smw_novalues' ) );
 31+ return $querymode ? new SMWThingDescription():$this->m_data;
 32+ }
 33+
 34+ $subdescriptions = array(); // only used for query mode
 35+ $types = $this->getTypeValues();
 36+ $values = preg_split( '/[\s]*;[\s]*/u', trim( $value ) );
 37+ $vi = 0; // index in value array
 38+ $empty = true;
 39+ for ( $i = 0; $i < max( 5, count( $types ) ); $i++ ) { // iterate over slots
 40+ // special handling for supporting query parsing
 41+ if ( $querymode ) {
 42+ $comparator = SMW_CMP_EQ;
 43+ SMWDataValue::prepareValue( $values[$vi], $comparator );
 44+ }
 45+ // generating the DVs:
 46+ if ( ( count( $values ) > $vi ) &&
 47+ ( ( $values[$vi] == '' ) || ( $values[$vi] == '?' ) ) ) { // explicit omission
 48+ $vi++;
 49+ } elseif ( array_key_exists( $vi, $values ) && array_key_exists( $i, $types ) ) { // some values left, try next slot
 50+ $dv = SMWDataValueFactory::newTypeObjectValue( $types[$i], $values[$vi] );
 51+ if ( $dv->isValid() ) { // valid DV: keep
 52+ if ( $querymode ) {
 53+ $subdescriptions[] = new SMWRecordFieldDescription( $i, new SMWValueDescription( $dv, $comparator ) );
 54+ } else {
 55+ $property = SMWPropertyValue::makeProperty( '_' . ( $i + 1 ) );
 56+ $this->m_data->addPropertyObjectValue( $property, $dv );
 57+ }
 58+ $vi++;
 59+ $empty = false;
 60+ } elseif ( ( count( $values ) - $vi ) == ( count( $types ) - $i ) ) {
 61+ // too many errors: keep this one to have enough slots left
 62+ $this->m_data->addPropertyObjectValue( SMWPropertyValue::makeProperty( '_' . ( $i + 1 ) ), $dv );
 63+ $this->addError( $dv->getErrors() );
 64+ $vi++;
 65+ }
 66+ }
 67+ }
 68+ if ( $empty ) {
 69+ $this->addError( wfMsg( 'smw_novalues' ) );
 70+ }
 71+ if ( $querymode ) {
 72+ return $empty ? new SMWThingDescription():new SMWRecordDescription( $subdescriptions );
 73+ }
 74+ }
 75+
 76+ /**
 77+ * This function resembles SMWContainerValue::parseDBkeys() but it already unstubs
 78+ * the values instead of passing on initialisation strings. This is required since
 79+ * the datatype of each entry is not determined by the property here (since we are
 80+ * using generic _1, _2, ... properties that can have any type).
 81+ */
 82+ protected function parseDBkeys( $args ) {
 83+ $this->m_data->clear();
 84+ $types = $this->getTypeValues();
 85+ if ( count( $args ) > 0 ) {
 86+ foreach ( reset( $args ) as $value ) {
 87+ if ( is_array( $value ) && ( count( $value ) == 2 ) ) {
 88+ $property = SMWPropertyValue::makeProperty( reset( $value ) );
 89+ $pnum = intval( substr( reset( $value ), 1 ) ); // try to find the number of this property
 90+ if ( array_key_exists( $pnum - 1, $types ) ) {
 91+ $dv = SMWDataValueFactory::newTypeObjectValue( $types[$pnum - 1] );
 92+ $dv->setDBkeys( end( $value ) );
 93+ $this->m_data->addPropertyObjectValue( $property, $dv );
 94+ }
 95+ }
 96+ }
 97+ }
 98+ }
 99+
 100+ /**
 101+ * Overwrite SMWDataValue::getQueryDescription() to be able to process
 102+ * comparators between all values.
 103+ */
 104+ public function getQueryDescription( $value ) {
 105+ return $this->parseUserValueOrQuery( $value, true );
 106+ }
 107+
 108+ public function getShortWikiText( $linked = null ) {
 109+ if ( $this->m_caption !== false ) {
 110+ return $this->m_caption;
 111+ }
 112+ return $this->makeOutputText( 0, $linked );
 113+ }
 114+
 115+ public function getShortHTMLText( $linker = null ) {
 116+ if ( $this->m_caption !== false ) {
 117+ return $this->m_caption;
 118+ }
 119+ return $this->makeOutputText( 1, $linker );
 120+ }
 121+
 122+ public function getLongWikiText( $linked = null ) {
 123+ return $this->makeOutputText( 2, $linked );
 124+ }
 125+
 126+ public function getLongHTMLText( $linker = null ) {
 127+ return $this->makeOutputText( 3, $linker );
 128+ }
 129+
 130+ public function getWikiValue() {
 131+ return $this->makeOutputText( 4 );
 132+ }
 133+
 134+ /// @todo Allowed values for multi-valued properties are not supported yet.
 135+ protected function checkAllowedValues() { }
 136+
 137+ /**
 138+ * Make sure that the content is reset in this case.
 139+ * @todo This is not a full reset yet (the case that property is changed after a value
 140+ * was set does not occur in the normal flow of things, hence this has low priority).
 141+ */
 142+ public function setProperty( SMWPropertyValue $property ) {
 143+ parent::setProperty( $property );
 144+ $this->m_typevalues = null;
 145+ }
 146+
 147+ /**
 148+ * @todo Since containers are always exported in a similar fashion, it
 149+ * would be preferrable to have their export controlled where it happens,
 150+ * and minimize the below special code.
 151+ */
 152+ public function getExportData() {
 153+ if ( !$this->isValid() ) return null;
 154+
 155+ $result = new SMWExpData( new SMWExpElement( '', $this ) ); // bnode
 156+ $ed = new SMWExpData( SMWExporter::getSpecialElement( 'swivt', 'Container' ) );
 157+ $result->addPropertyObjectValue( SMWExporter::getSpecialElement( 'rdf', 'type' ), $ed );
 158+ $count = 0;
 159+ foreach ( $this->getDVs() as $value ) {
 160+ $count++;
 161+ if ( ( $value === null ) || ( !$value->isValid() ) ) {
 162+ continue;
 163+ }
 164+ if ( ( $value->getTypeID() == '_wpg' ) || ( $value->getTypeID() == '_uri' ) || ( $value->getTypeID() == '_ema' ) ) {
 165+ $result->addPropertyObjectValue(
 166+ SMWExporter::getSpecialElement( 'swivt', 'object' . $count ),
 167+ $value->getExportData() );
 168+ } else {
 169+ $result->addPropertyObjectValue(
 170+ SMWExporter::getSpecialElement( 'swivt', 'value' . $count ),
 171+ $value->getExportData() );
 172+ }
 173+ }
 174+ return $result;
 175+ }
 176+
 177+////// Additional API for value lists
 178+
 179+ /**
 180+ * Create a list (array with numeric keys) containing the datavalue objects
 181+ * that this SMWRecordValue object holds. Values that are not present are
 182+ * set to null. Note that the first index in the array is 0, not 1.
 183+ */
 184+ public function getDVs() {
 185+ if ( !$this->isValid() ) return array();
 186+ $result = array();
 187+ foreach ( $this->m_data->getProperties() as $prop ) {
 188+ $propname = $prop->getPropertyID();
 189+ $propnum = substr( $propname, 1 );
 190+ if ( ( $propname != false ) && ( is_numeric( $propnum ) ) ) {
 191+ $result[( $propnum - 1 )] = reset( $this->m_data->getPropertyValues( $prop ) );
 192+ }
 193+ }
 194+ return $result;
 195+ }
 196+
 197+ /**
 198+ * Return the array (list) of datatypes that the individual entries of this datatype consist of.
 199+ * @todo Add some check to account for maximal number of list entries (maybe this should go to a
 200+ * variant of the SMWTypesValue).
 201+ */
 202+ public function getTypeValues() {
 203+ if ( $this->m_typevalues !== null ) return $this->m_typevalues; // local cache
 204+ if ( ( $this->m_property === null ) || ( $this->m_property->getWikiPageValue() === null ) ) {
 205+ $this->m_typevalues = array(); // no property known -> no types
 206+ } else { // query for type values
 207+ $typelist = smwfGetStore()->getPropertyValues( $this->m_property->getWikiPageValue(), SMWPropertyValue::makeProperty( '_LIST' ) );
 208+ if ( count( $typelist ) == 1 ) {
 209+ $this->m_typevalues = reset( $typelist )->getTypeValues();
 210+ } else { ///TODO internalionalize
 211+ $this->addError( 'List type not properly specified for this property.' );
 212+ $this->m_typevalues = array();
 213+ }
 214+ }
 215+ return $this->m_typevalues;
 216+ }
 217+
 218+////// Internal helper functions
 219+
 220+ private function makeOutputText( $type = 0, $linker = null ) {
 221+ if ( !$this->isValid() ) {
 222+ return ( ( $type == 0 ) || ( $type == 1 ) ) ? '' : $this->getErrorText();
 223+ }
 224+ $result = '';
 225+ for ( $i = 0; $i < count( $this->getTypeValues() ); $i++ ) {
 226+ if ( $i == 1 ) {
 227+ $result .= ( $type == 4 ) ? '; ':' (';
 228+ } elseif ( $i > 1 ) {
 229+ $result .= ( $type == 4 ) ? '; ':", ";
 230+ }
 231+ $property = SMWPropertyValue::makeProperty( '_' . ( $i + 1 ) );
 232+ $dv = reset( $this->m_data->getPropertyValues( $property ) );
 233+ $result .= ( $dv !== false ) ? $this->makeValueOutputText( $type, $dv, $linker ): '?';
 234+ }
 235+ if ( ( $i > 1 ) && ( $type != 4 ) ) $result .= ')';
 236+ return $result;
 237+ }
 238+
 239+ private function makeValueOutputText( $type, $datavalue, $linker ) {
 240+ switch ( $type ) {
 241+ case 0: return $datavalue->getShortWikiText( $linker );
 242+ case 1: return $datavalue->getShortHTMLText( $linker );
 243+ case 2: return $datavalue->getShortWikiText( $linker );
 244+ case 3: return $datavalue->getShortHTMLText( $linker );
 245+ case 4: return $datavalue->getWikiValue();
 246+ }
 247+ }
 248+
 249+}
 250+
Property changes on: trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_Record.php
___________________________________________________________________
Added: svn:eol-style
1251 + native
Index: trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_Container.php
@@ -0,0 +1,105 @@
 2+<?php
 3+/**
 4+ * @file
 5+ * @ingroup SMWDataValues
 6+ */
 7+
 8+/**
 9+ * Abstract datavalue class to implement a generic container for
 10+ * complex values (internal objects) that do not have a single
 11+ * value but a set of nested property-value pairs.
 12+ *
 13+ * @author Markus Krötzsch
 14+ * @ingroup SMWDataValues
 15+ */
 16+abstract class SMWContainerValue extends SMWDataValue {
 17+
 18+ protected $m_data;
 19+
 20+ public function __construct( $typeid ) {
 21+ parent::__construct( $typeid );
 22+ $this->m_data = new SMWSemanticData( null );
 23+ }
 24+
 25+ /**
 26+ * We use the internal SMWSemanticData object to store some of this objects
 27+ * data. Clone it to make sure that data can be modified independelty from
 28+ * the original object's content.
 29+ */
 30+ public function __clone() {
 31+ $this->m_data = clone $this->m_data; // note that this is always set
 32+ }
 33+
 34+ /**
 35+ * Containers have one DB key, so the value of this function should be an array with one
 36+ * element. This one DB key should consist of an array of arbitrary length where each
 37+ * entry encodes one property-value pair. The pairs are encoded as arrays of size two
 38+ * that correspond to the input arguments of SMWSemanticData::addPropertyStubValue():
 39+ * a property DB key (string), and a value DB key array (array).
 40+ */
 41+ protected function parseDBkeys( $args ) {
 42+ $this->m_data->clear();
 43+ if ( count( $args ) > 0 ) {
 44+ foreach ( reset( $args ) as $value ) {
 45+ if ( is_array( $value ) && ( count( $value ) == 2 ) ) {
 46+ $this->m_data->addPropertyStubValue( reset( $value ), end( $value ) );
 47+ }
 48+ }
 49+ }
 50+ }
 51+
 52+ /**
 53+ * Serialize data in the format described for parseDBkeys(). However, it is usually
 54+ * expected that callers are aware of containers (this is the main purpose of this
 55+ * abstract class) so they can use specific methods for accessing the data in a more
 56+ * convenient form that contains the (probably available) information about property
 57+ * and data *objects* (not just their plain strings).
 58+ */
 59+ public function getDBkeys() {
 60+ $data = array();
 61+ foreach ( $this->m_data->getProperties() as $property ) {
 62+ foreach ( $this->m_data->getPropertyValues( $property ) as $dv ) {
 63+ $data[] = array( $property->getDBkey(), $dv->getDBkeys() );
 64+ }
 65+ }
 66+ return array( $data );
 67+ }
 68+
 69+ public function getSignature() {
 70+ return 'c';
 71+ }
 72+
 73+ public function getValueIndex() {
 74+ return -1;
 75+ }
 76+
 77+ public function getLabelIndex() {
 78+ return -1;
 79+ }
 80+
 81+ public function getHash() {
 82+ if ( $this->isValid() ) {
 83+ return $this->m_data->getHash();
 84+ } else {
 85+ return implode( "\t", $this->getErrors() );
 86+ }
 87+ }
 88+
 89+ // Methods for parsing, serialisation, and display are not defined in this abstract class:
 90+ // public function getShortWikiText($linked = null);
 91+ // public function getShortHTMLText($linker = null);
 92+ // public function getLongWikiText($linked = null);
 93+ // public function getLongHTMLText($linker = null);
 94+ // protected function parseUserValue($value);
 95+ // public function getWikiValue();
 96+
 97+ /**
 98+ * Return the stored data as a SMWSemanticData object. This is more conveniently to access than
 99+ * what getDBkeys() gives, but intended only for reading. It may not be safe to write to the returned
 100+ * object.
 101+ */
 102+ public function getData() {
 103+ return $this->m_data;
 104+ }
 105+
 106+}
Property changes on: trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_Container.php
___________________________________________________________________
Added: svn:eol-style
1107 + native
Index: trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_Property.php
@@ -0,0 +1,471 @@
 2+<?php
 3+/**
 4+ * File holding class SMWPropertyValue.
 5+ *
 6+ * @author Markus Krötzsch
 7+ *
 8+ * @file
 9+ * @ingroup SMWDataValues
 10+ */
 11+
 12+/**
 13+ * Objects of this class represent properties in SMW.
 14+ *
 15+ * This class represents both normal (user-defined) properties and
 16+ * predefined ("special") properties. Predefined properties may still
 17+ * have a standard label (and associated wiki article) and they will
 18+ * behave just like user-defined properties in most cases (e.g. when
 19+ * asking for a printout text, a link to the according page is produced).
 20+ * It is possible that predefined properties have no visible label at all,
 21+ * if they are used only internally and never specified by or shown to
 22+ * the user. Those will use their internal ID as DB key, and
 23+ * empty texts for most printouts. All other proeprties use their
 24+ * canonical DB key (even if they are predefined and have an id).
 25+ * Functions are provided to check whether a property is visible or
 26+ * user-defined, and to get the internal ID, if any.
 27+ *
 28+ * @note This datavalue is used only for representing properties and,
 29+ * possibly objects/values, but never for subjects (pages as such). Hence
 30+ * it does not provide a complete Title-like interface, or support for
 31+ * things like sortkey.
 32+ *
 33+ * @author Markus Krötzsch
 34+ * @ingroup SMWDataValues
 35+ */
 36+class SMWPropertyValue extends SMWDataValue {
 37+
 38+ /** Array for assigning types to predefined properties. Each
 39+ * property is associated with an array with the following
 40+ * elements:
 41+ *
 42+ * * ID of datatype to be used for this property
 43+ *
 44+ * * Boolean, stating if this property is shown in Factbox, Browse, and similar interfaces;
 45+ * (note that this is only relevant if the property can be displayed at all, i.e. has an
 46+ * translated label in the given language; we still set invisible properties to false here)
 47+ */
 48+ static private $mPropertyTypes;
 49+ static private $mPropertyLabels;
 50+ static private $mPropertyAliases;
 51+
 52+ /// If the property is predefined, its internal key is stored here. Otherwise FALSE.
 53+ protected $m_propertyid;
 54+ /// If the property is associated with a wikipage, it is stored here. Otherwise NULL.
 55+ protected $m_wikipage = null;
 56+ /// Store if this property is an inverse
 57+ protected $m_inv = false;
 58+
 59+ /**
 60+ * Remember the type value of this property once it has been calculated.
 61+ * @var unknown_type
 62+ */
 63+ private $mPropTypeValue;
 64+
 65+ /**
 66+ * Remember the type id of this property once it has been calculated.
 67+ * @var unknown_type
 68+ */
 69+ private $mPropTypeId;
 70+
 71+ /**
 72+ * Static function for creating a new property object from a
 73+ * propertyname (string) as a user might enter it.
 74+ * @note The resulting property object might be invalid if
 75+ * the provided name is not allowed. An object is returned
 76+ * in any case.
 77+ *
 78+ * @param string $propertyName
 79+ *
 80+ * @return SMWPropertyValue
 81+ */
 82+ static public function makeUserProperty( $propertyName ) {
 83+ $property = new SMWPropertyValue( '__pro' );
 84+ $property->setUserValue( $propertyName );
 85+ return $property;
 86+ }
 87+
 88+ /**
 89+ * Static function for creating a new property object from a
 90+ * property identifier (string) as it might be used internally.
 91+ * This might be the DB-key version of some property title
 92+ * text or the id of a predefined property (such as '_TYPE').
 93+ * @note The resulting property object might be invalid if
 94+ * the provided name is not allowed. An object is returned
 95+ * in any case.
 96+ */
 97+ static public function makeProperty( $propertyid ) {
 98+ $property = new SMWPropertyValue( '__pro' );
 99+ $property->setDBkeys( array( $propertyid ) );
 100+ return $property;
 101+ }
 102+
 103+ /**
 104+ * We use the internal wikipage object to store some of this objects data.
 105+ * Clone it to make sure that data can be modified independelty from the
 106+ * original object's content.
 107+ */
 108+ public function __clone() {
 109+ if ( $this->m_wikipage !== null ) $this->m_wikipage = clone $this->m_wikipage;
 110+ }
 111+
 112+ /**
 113+ * Extended parsing function to first check whether value refers to pre-defined
 114+ * property, resolve aliases, and set internal property id accordingly.
 115+ * @todo Accept/enforce property namespace.
 116+ */
 117+ protected function parseUserValue( $value ) {
 118+ $this->mPropTypeValue = null;
 119+ $this->mPropTypeId = null;
 120+ $this->m_inv = false;
 121+ if ( $this->m_caption === false ) { // always use this as caption
 122+ $this->m_caption = $value;
 123+ }
 124+ $value = smwfNormalTitleText( ltrim( rtrim( $value, ' ]' ), ' [' ) ); // slightly normalise label
 125+ if ( ( $value !== '' ) && ( $value { 0 } == '-' ) ) { // check if this property refers to an inverse
 126+ $value = substr( $value, 1 );
 127+ $this->m_inv = true;
 128+ }
 129+ $this->m_propertyid = SMWPropertyValue::findPropertyID( $value );
 130+ if ( $this->m_propertyid !== false ) {
 131+ $value = SMWPropertyValue::findPropertyLabel( $this->m_propertyid );
 132+ }
 133+ if ( $value !== false ) {
 134+ $this->m_wikipage = SMWDataValueFactory::newTypeIDValue( '_wpp' );
 135+ $this->m_wikipage->setUserValue( $value, $this->m_caption );
 136+ $this->addError( $this->m_wikipage->getErrors() );
 137+ } else { // should rarely happen ($value is only changed if the input $value really was a label for a predefined prop)
 138+ $this->m_wikipage = null;
 139+ }
 140+ }
 141+
 142+ /**
 143+ * Extended parsing function to first check whether value is the id of a
 144+ * pre-defined property, to resolve property names and aliases, and to set
 145+ * internal property id accordingly.
 146+ */
 147+ protected function parseDBkeys( $args ) {
 148+ $this->mPropTypeValue = null;
 149+ $this->mPropTypeId = null;
 150+ $this->m_inv = false;
 151+ if ( $args[0] { 0 } == '-' ) { // check if this property refers to an inverse
 152+ $args[0] = substr( $args[0], 1 );
 153+ $this->m_inv = true;
 154+ }
 155+ SMWPropertyValue::initProperties();
 156+ if ( $args[0] { 0 } == '_' ) { // internal id, use as is (and hope it is still known)
 157+ $this->m_propertyid = $args[0];
 158+ } else { // possibly name of special property
 159+ $this->m_propertyid = SMWPropertyValue::findPropertyID( str_replace( '_', ' ', $args[0] ) );
 160+ }
 161+ $label = ( $this->m_propertyid !== false ) ? SMWPropertyValue::findPropertyLabel( $this->m_propertyid ):$args[0];
 162+ if ( $label != '' ) {
 163+ $this->m_wikipage = SMWDataValueFactory::newTypeIDValue( '_wpp' );
 164+ $this->m_wikipage->setDBkeys( array( str_replace( ' ', '_', $label ), SMW_NS_PROPERTY, '', '' ) );
 165+ $this->m_wikipage->setOutputFormat( $this->m_outformat );
 166+ $this->m_caption = $label;
 167+ $this->addError( $this->m_wikipage->getErrors() ); // NOTE: this unstubs the wikipage, should we rather ignore errors here to prevent this?
 168+ } else { // predefined property without label
 169+ $this->m_wikipage = null;
 170+ $this->m_caption = $this->m_propertyid;
 171+ }
 172+ }
 173+
 174+ public function setCaption( $caption ) {
 175+ parent::setCaption( $caption );
 176+ if ( $this->m_wikipage instanceof SMWDataValue ) { // pass caption to embedded datavalue (used for printout)
 177+ $this->m_wikipage->setCaption( $caption );
 178+ }
 179+ }
 180+
 181+
 182+ public function setInverse( $isinverse ) {
 183+ $this->unstub(); // make sure later unstubbing does not overwrite this
 184+ return $this->m_inv = ( $isinverse == true );
 185+ }
 186+
 187+ /**
 188+ * Return TRUE if this is a usual wiki property that is defined by a wiki page, as
 189+ * opposed to a property that is pre-defined in the wiki.
 190+ */
 191+ public function isUserDefined() {
 192+ $this->unstub();
 193+ return ( $this->m_propertyid == '' );
 194+ }
 195+
 196+ /**
 197+ * Return TRUE if this is a property that can be displayed, and not a pre-defined
 198+ * property that is used only internally and does not even have a user-readable name.
 199+ * @note Every user defined property is necessarily visible.
 200+ */
 201+ public function isVisible() {
 202+ $this->unstub();
 203+ return ( $this->m_wikipage !== null );
 204+ }
 205+
 206+ /**
 207+ * Specifies whether values of this property should be shown in typical
 208+ * browsing interfaces. A property may wish to prevent this if either
 209+ * (1) its information is really dull, e.g. being a mere copy of
 210+ * information that is obvious from other things that are shown, or (2) the
 211+ * property is set in a hook after parsing, so that it is not reliably
 212+ * available when Factboxes are displayed. If a property is internal so it
 213+ * should never be observed by users, then it is better to just not
 214+ * associate any translated label with it, so it never appears anywhere.
 215+ */
 216+ public function isShown() {
 217+ $this->unstub();
 218+ return ( ( $this->m_propertyid == '' ) ||
 219+ ( array_key_exists( $this->m_propertyid, SMWPropertyvalue::$mPropertyTypes ) &&
 220+ SMWPropertyvalue::$mPropertyTypes[$this->m_propertyid][1] ) );
 221+ }
 222+
 223+ /**
 224+ * Return TRUE if this property is an inverse.
 225+ */
 226+ public function isInverse() {
 227+ $this->unstub();
 228+ return $this->m_inv;
 229+ }
 230+
 231+ public function setOutputFormat( $formatstring ) {
 232+ $this->m_outformat = $formatstring;
 233+ if ( $this->m_wikipage !== null ) { // do not unstub if not needed
 234+ $this->m_wikipage->setOutputFormat( $formatstring );
 235+ }
 236+ }
 237+
 238+ public function getShortWikiText( $linked = null ) {
 239+ return $this->isVisible() ? $this->highlightText( $this->m_wikipage->getShortWikiText( $linked ) ):'';
 240+ }
 241+
 242+ public function getShortHTMLText( $linker = null ) {
 243+ return $this->isVisible() ? $this->highlightText( $this->m_wikipage->getShortHTMLText( $linker ) ):'';
 244+ }
 245+
 246+ public function getLongWikiText( $linked = null ) {
 247+ return $this->isVisible() ? $this->highlightText( $this->m_wikipage->getLongWikiText( $linked ) ):'';
 248+ }
 249+
 250+ public function getLongHTMLText( $linker = null ) {
 251+ return $this->isVisible() ? $this->highlightText( $this->m_wikipage->getLongHTMLText( $linker ) ):'';
 252+ }
 253+
 254+ /**
 255+ * Return internal property id or page DBkey, either of which is sufficient for storing property references.
 256+ */
 257+ public function getDBkeys() {
 258+ $this->unstub();
 259+ return $this->isVisible() ? array( $this->m_wikipage->getDBkey() ):array( $this->m_propertyid );
 260+ }
 261+
 262+ public function getSignature() {
 263+ return 't';
 264+ }
 265+
 266+ public function getValueIndex() {
 267+ return 0;
 268+ }
 269+
 270+ public function getLabelIndex() {
 271+ return 0;
 272+ }
 273+
 274+ public function getWikiValue() {
 275+ return $this->isVisible() ? ( ( $this->isInverse() ? '-':'' ) . $this->m_wikipage->getWikiValue() ):'';
 276+ }
 277+
 278+ /**
 279+ * If this property is associated with a wiki page, return an SMWWikiPageValue for
 280+ * that page. Otherwise return NULL.
 281+ */
 282+ public function getWikiPageValue() {
 283+ $this->unstub();
 284+ return $this->m_wikipage;
 285+ }
 286+
 287+ /**
 288+ * If this property was not user defined, return the internal ID string referring to
 289+ * that property. Otherwise return FALSE;
 290+ */
 291+ public function getPropertyID() {
 292+ $this->unstub();
 293+ return $this->m_propertyid;
 294+ }
 295+
 296+ /**
 297+ * Return an SMWTypesValue object representing the datatype of this property.
 298+ */
 299+ public function getTypesValue() {
 300+ global $smwgPDefaultType;
 301+ if ( $this->mPropTypeValue !== null ) return $this->mPropTypeValue;
 302+ if ( !$this->isValid() ) { // errors in property, return invalid types value with same errors
 303+ $result = SMWDataValueFactory::newTypeIDValue( '__typ' );
 304+ $result->setDBkeys( array( '__err' ) );
 305+ $result->addError( $this->getErrors() );
 306+ } elseif ( $this->isUserDefined() ) { // normal property
 307+ $typearray = smwfGetStore()->getPropertyValues( $this->getWikiPageValue(), SMWPropertyValue::makeProperty( '_TYPE' ) );
 308+ if ( count( $typearray ) == 1 ) { // unique type given
 309+ $result = current( $typearray );
 310+ } elseif ( count( $typearray ) == 0 ) { // no type given
 311+ $result = SMWDataValueFactory::newTypeIDValue( '__typ' );
 312+ $result->setDBkeys( array( $smwgPDefaultType ) );
 313+ } else { // many types given, error
 314+ smwfLoadExtensionMessages( 'SemanticMediaWiki' );
 315+ $result = SMWDataValueFactory::newTypeIDValue( '__typ' );
 316+ $result->setDBkeys( array( '__err' ) );
 317+ $result->addError( wfMsgForContent( 'smw_manytypes' ) );
 318+ }
 319+ } else { // pre-defined property
 320+ $result = SMWDataValueFactory::newTypeIDValue( '__typ' );
 321+ if ( array_key_exists( $this->m_propertyid, SMWPropertyValue::$mPropertyTypes ) ) {
 322+ $result->setDBkeys( array( SMWPropertyValue::$mPropertyTypes[$this->m_propertyid][0] ) );
 323+ } else { // unknown type; it may still be that the property is "type-polymorphic" (like _1, _2, ... for Records)
 324+ $result->setDBkeys( array( '__err' ) ); // use "__err" to make sure that it gets noticed if this information is really used to create values
 325+ }
 326+ }
 327+ $this->mPropTypeValue = $result;
 328+ return $result;
 329+ }
 330+
 331+ /**
 332+ * Quickly get the type id of some property without necessarily making
 333+ * another datavalue. Note that this is not the same as getTypeID(), which
 334+ * returns the id of this property datavalue.
 335+ */
 336+ public function getPropertyTypeID() {
 337+ if ( $this->mPropTypeId === null ) {
 338+ $type = $this->getTypesValue();
 339+ if ( $type instanceof SMWTypesValue ) {
 340+ $this->mPropTypeId = $type->getDBkey();
 341+ } else {
 342+ $this->mPropTypeId = '__err';
 343+ }
 344+ }
 345+ return $this->mPropTypeId;
 346+ }
 347+
 348+ /**
 349+ * Return a DB-key-like string: for visible properties, it is the actual DB key,
 350+ * for internal (invisible) properties, it is the property ID. The value agrees
 351+ * with the first component of getDBkeys() and it can be used in its place.
 352+ */
 353+ public function getDBkey() {
 354+ return $this->isVisible() ? $this->m_wikipage->getDBkey():$this->m_propertyid;
 355+ }
 356+
 357+ public function getText() {
 358+ return $this->isVisible() ? $this->m_wikipage->getWikiValue():'';
 359+ }
 360+
 361+ /**
 362+ * Create special highlighting for hinting at special properties.
 363+ */
 364+ protected function highlightText( $text ) {
 365+ if ( $this->isUserDefined() ) {
 366+ return $text;
 367+ } else {
 368+ SMWOutputs::requireHeadItem( SMW_HEADER_TOOLTIP );
 369+ smwfLoadExtensionMessages( 'SemanticMediaWiki' );
 370+ return '<span class="smwttinline"><span class="smwbuiltin">' . $text .
 371+ '</span><span class="smwttcontent">' . wfMsgForContent( 'smw_isspecprop' ) . '</span></span>';
 372+ }
 373+ }
 374+
 375+ /**
 376+ * Find and return the id for the pre-defined property of the given local label.
 377+ * If the label does not belong to a pre-defined property, return false.
 378+ * The given label should be slightly normalised, i.e. as returned by Title
 379+ * or smwfNormalTitleText().
 380+ *
 381+ * This function is protected. The public way of getting this data is to simply
 382+ * create a new property object and to retrieve its ID (if any).
 383+ */
 384+ static protected function findPropertyID( $label, $useAlias = true ) {
 385+ SMWPropertyValue::initProperties();
 386+ $id = array_search( $label, SMWPropertyValue::$mPropertyLabels );
 387+ if ( $id !== false ) {
 388+ return $id;
 389+ } elseif ( ( $useAlias ) && ( array_key_exists( $label, SMWPropertyValue::$mPropertyAliases ) ) ) {
 390+ return SMWPropertyValue::$mPropertyAliases[$label];
 391+ } else {
 392+ return false;
 393+ }
 394+ }
 395+
 396+ /**
 397+ * Get the translated user label for a given internal property ID.
 398+ * Returns false for properties without a translation (these are usually the
 399+ * internal ones generated by SMW but not shown to the user).
 400+ */
 401+ static protected function findPropertyLabel( $id ) {
 402+ SMWPropertyValue::initProperties();
 403+ if ( array_key_exists( $id, SMWPropertyValue::$mPropertyLabels ) ) {
 404+ return SMWPropertyValue::$mPropertyLabels[$id];
 405+ } else { // incomplete translation (language bug) or deliberately invisible property
 406+ return false;
 407+ }
 408+ }
 409+
 410+ /**
 411+ * Set up predefined properties, including their label, aliases, and typing information.
 412+ */
 413+ static protected function initProperties() {
 414+ if ( is_array( SMWPropertyValue::$mPropertyTypes ) ) {
 415+ return; // init happened before
 416+ }
 417+
 418+ global $smwgContLang, $smwgUseCategoryHierarchy;
 419+ SMWPropertyValue::$mPropertyLabels = $smwgContLang->getPropertyLabels();
 420+ SMWPropertyValue::$mPropertyAliases = $smwgContLang->getPropertyAliases();
 421+ // Setup built-in predefined properties.
 422+ // NOTE: all ids must start with underscores, where two underscores informally indicate
 423+ // truly internal (non user-accessible properties). All others should also get a
 424+ // translation in the language files, or they won't be available for users.
 425+ SMWPropertyValue::$mPropertyTypes = array(
 426+ '_TYPE' => array( '__typ', true ),
 427+ '_URI' => array( '__spu', true ),
 428+ '_INST' => array( '__sin', false ),
 429+ '_UNIT' => array( '__sps', true ),
 430+ '_IMPO' => array( '__imp', true ),
 431+ '_CONV' => array( '__sps', true ),
 432+ '_SERV' => array( '__sps', true ),
 433+ '_PVAL' => array( '__sps', true ),
 434+ '_REDI' => array( '__red', true ),
 435+ '_SUBP' => array( '__sup', true ),
 436+ '_SUBC' => array( '__suc', !$smwgUseCategoryHierarchy ),
 437+ '_CONC' => array( '__con', false ),
 438+ '_MDAT' => array( '_dat', false ),
 439+ '_ERRP' => array( '_wpp', false ),
 440+ '_LIST' => array( '__tls', true ),
 441+ // "virtual" properties for encoding lists in n-ary datatypes (their type must never be used, hence use __err)
 442+// '_1' => array('__err',false),
 443+// '_2' => array('__err',false),
 444+// '_3' => array('__err',false),
 445+// '_4' => array('__err',false),
 446+// '_5' => array('__err',false),
 447+ );
 448+ wfRunHooks( 'smwInitProperties' );
 449+ }
 450+
 451+ /**
 452+ * A function for registering/overwriting predefined properties for SMW. Should be called from
 453+ * within the hook 'smwInitProperties'. Ids should start with three underscores "___" to avoid
 454+ * current and future confusion with SMW built-ins.
 455+ */
 456+ static public function registerProperty( $id, $typeid, $label = false, $show = false ) {
 457+ SMWPropertyValue::$mPropertyTypes[$id] = array( $typeid, $show );
 458+ if ( $label != false ) {
 459+ SMWPropertyValue::$mPropertyLabels[$id] = $label;
 460+ }
 461+ }
 462+
 463+ /**
 464+ * Add a new alias label to an existing datatype id. Note that every ID should have a primary
 465+ * label, either provided by SMW or registered with registerDatatype. This function should be
 466+ * called from within the hook 'smwInitDatatypes'.
 467+ */
 468+ static public function registerPropertyAlias( $id, $label ) {
 469+ SMWPropertyValue::$mPropertyAliases[$label] = $id;
 470+ }
 471+
 472+}
Property changes on: trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_Property.php
___________________________________________________________________
Added: svn:eol-style
1473 + native
Index: trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_Number.php
@@ -0,0 +1,300 @@
 2+<?php
 3+/**
 4+ * @file
 5+ * @ingroup SMWDataValues
 6+ */
 7+
 8+/**
 9+ * This datavalue implements numerical datavalues, and supports optional
 10+ * unit conversions. It parses and manages unit strings, since even plain
 11+ * numbers may have (not further specified) units that are stored. However,
 12+ * only subclasses implement full unit conversion by extending the methods
 13+ * convertToMainUnit() and makeConversionValues().
 14+ *
 15+ * Units work as follows: a unit is a string, but many such strings might
 16+ * refer to the same unit of measurement. There is always one string, that
 17+ * canonically represents the unit, and we will call this version of writing
 18+ * the unit the /unit id/. IDs for units are needed for tasks like duplicate
 19+ * avoidance. If no conversion information is given, any unit is its own ID.
 20+ * In any case, units are /normalised/, i.e. given a more standardised meaning
 21+ * before being processed. All units, IDs or otherwise, should be suitable for
 22+ * printout in wikitext, and main IDs should moreover be suitable for printout
 23+ * in HTML.
 24+ *
 25+ * @author Markus Krötzsch
 26+ * @ingroup SMWDataValues
 27+ *
 28+ * @todo Wiki-HTML-conversion for unit strings must be revisited, as the current
 29+ * solution might be unsafe.
 30+ * @todo Respect desired output unit (relevant for queries).
 31+ */
 32+class SMWNumberValue extends SMWDataValue {
 33+
 34+ protected $m_wikivalue = ''; // local language value, user input if given
 35+ protected $m_value = ''; // numerical value, in $m_unit
 36+ protected $m_unit = ''; // HTML-safe unit string, if any
 37+ protected $m_unitin; // if set, specifies the originally given input unit in a standard writing
 38+ protected $m_unitvalues; // array with entries unit=>value
 39+
 40+ protected function parseUserValue( $value ) {
 41+ $this->m_wikivalue = $value;
 42+ $this->m_unitin = false;
 43+ $this->m_unitvalues = false;
 44+
 45+ smwfLoadExtensionMessages( 'SemanticMediaWiki' );
 46+
 47+ // Parse to find value and unit
 48+ $decseparator = wfMsgForContent( 'smw_decseparator' );
 49+ $kiloseparator = wfMsgForContent( 'smw_kiloseparator' );
 50+
 51+ $parts = preg_split( '/([-+]?\s*\d+(?:\\' . $kiloseparator . '\d\d\d)*' .
 52+ '(?:\\' . $decseparator . '\d+)?\s*(?:[eE][-+]?\d+)?)/u',
 53+ trim( str_replace( array( '&nbsp;', '&#160;', '&thinsp;', ' ' ), '', $value ) ),
 54+ 2, PREG_SPLIT_DELIM_CAPTURE );
 55+
 56+ if ( count( $parts ) >= 2 ) {
 57+ $numstring = str_replace( $kiloseparator, '', preg_replace( '/\s*/u', '', $parts[1] ) ); // simplify
 58+ if ( $decseparator != '.' ) {
 59+ $numstring = str_replace( $decseparator, '.', $numstring );
 60+ }
 61+ list( $this->m_value ) = sscanf( $numstring, "%f" );
 62+ }
 63+ if ( count( $parts ) >= 3 ) $this->m_unit = $this->normalizeUnit( $parts[2] );
 64+
 65+ if ( ( count( $parts ) == 1 ) || ( $numstring == '' ) ) { // no number found
 66+ $this->addError( wfMsgForContent( 'smw_nofloat', $value ) );
 67+ } elseif ( is_infinite( $this->m_value ) ) {
 68+ wfMsgForContent( 'smw_infinite', $value );
 69+ }
 70+
 71+ // Set caption
 72+ if ( $this->m_caption === false ) {
 73+ $this->m_caption = $value;
 74+ }
 75+ return true;
 76+ }
 77+
 78+ protected function parseDBkeys( $args ) {
 79+ $this->m_value = $args[0];
 80+ $this->m_unit = array_key_exists( 2, $args ) ? $args[2]:'';
 81+ $this->m_caption = false;
 82+ $this->m_unitin = false;
 83+ $this->makeUserValue();
 84+ $this->m_unitvalues = false;
 85+ }
 86+
 87+ public function setOutputFormat( $formatstring ) {
 88+ $oldformat = $this->m_outformat;
 89+ $this->m_outformat = $formatstring;
 90+ if ( ( $formatstring != $oldformat ) && $this->isValid() ) {
 91+ // recompute conversion if outputformat is changed after initialisation
 92+ $this->m_stubvalues = array( $this->m_value, $this->m_value, $this->m_unit );
 93+ }
 94+ }
 95+
 96+ public function getShortWikiText( $linked = null ) {
 97+ $this->unstub();
 98+ if ( ( $linked === null ) || ( $linked === false ) || ( $this->m_outformat == '-' ) || ( $this->m_outformat == '-u' ) || ( $this->m_outformat == '-n' ) ) {
 99+ return $this->m_caption;
 100+ }
 101+ $this->makeConversionValues();
 102+ $tooltip = '';
 103+ $i = 0;
 104+ $sep = '';
 105+ foreach ( $this->m_unitvalues as $unit => $value ) {
 106+ if ( $unit != $this->m_unitin ) {
 107+ $tooltip .= $sep . smwfNumberFormat( $value );
 108+ if ( $unit != '' ) {
 109+ $tooltip .= '&#160;' . $unit;
 110+ }
 111+ $sep = ' <br />';
 112+ $i++;
 113+ if ( $i >= 5 ) { // limit number of printouts in tooltip
 114+ break;
 115+ }
 116+ }
 117+ }
 118+ if ( $tooltip != '' ) {
 119+ SMWOutputs::requireHeadItem( SMW_HEADER_TOOLTIP );
 120+ return '<span class="smwttinline">' . $this->m_caption . '<span class="smwttcontent">' . $tooltip . '</span></span>';
 121+ } else {
 122+ return $this->m_caption;
 123+ }
 124+ }
 125+
 126+ public function getShortHTMLText( $linker = null ) {
 127+ return $this->getShortWikiText( $linker );
 128+ }
 129+
 130+ public function getLongWikiText( $linked = null ) {
 131+ $this->unstub();
 132+ if ( !$this->isValid() ) {
 133+ return $this->getErrorText();
 134+ } else {
 135+ $this->makeConversionValues();
 136+ $result = '';
 137+ $i = 0;
 138+ foreach ( $this->m_unitvalues as $unit => $value ) {
 139+ if ( $i == 1 ) {
 140+ $result .= ' (';
 141+ } elseif ( $i > 1 ) {
 142+ $result .= ', ';
 143+ }
 144+ $result .= ( $this->m_outformat != '-' ? smwfNumberFormat( $value ):$value );
 145+ if ( $unit != '' ) {
 146+ $result .= '&#160;' . $unit;
 147+ }
 148+ $i++;
 149+ if ( $this->m_outformat == '-' ) { // no further conversions for plain output format
 150+ break;
 151+ }
 152+ }
 153+ if ( $i > 1 ) {
 154+ $result .= ')';
 155+ }
 156+ return $result;
 157+ }
 158+ }
 159+
 160+ public function getLongHTMLText( $linker = null ) {
 161+ return $this->getLongWikiText( $linker );
 162+ }
 163+
 164+ public function getDBkeys() {
 165+ $this->unstub();
 166+ $this->convertToMainUnit();
 167+ return array( $this->m_value, floatval( $this->m_value ), $this->m_unit );
 168+ }
 169+
 170+ public function getSignature() {
 171+ return 'tfu';
 172+ }
 173+
 174+ public function getValueIndex() {
 175+ return 1;
 176+ }
 177+
 178+ public function getLabelIndex() {
 179+ return 0;
 180+ }
 181+
 182+ public function getWikiValue() {
 183+ $this->unstub();
 184+ return $this->m_wikivalue;
 185+ }
 186+
 187+ public function getUnit() {
 188+ $values = $this->getDBkeys();
 189+ return $values[2];
 190+ }
 191+
 192+ public function getHash() {
 193+ $this->unstub();
 194+ if ( $this->isValid() ) {
 195+ $this->convertToMainUnit();
 196+ return $this->m_value . $this->m_unit;
 197+ } else {
 198+ return implode( "\t", $this->getErrors() );
 199+ }
 200+ }
 201+
 202+ protected function getServiceLinkParams() {
 203+ $this->unstub();
 204+ // Create links to mapping services based on a wiki-editable message. The parameters
 205+ // available to the message are:
 206+ // $1: string of numerical value in English punctuation
 207+ // $2: string of integer version of value, in English punctuation
 208+ // $3: string of unit (if any)
 209+ return array( (string)$this->m_value, (string)round( $this->m_value ), $this->m_unit );
 210+ }
 211+
 212+ public function getExportData() {
 213+ $this->unstub();
 214+ if ( $this->isValid() ) {
 215+ $lit = new SMWExpLiteral( $this->m_value, $this, 'http://www.w3.org/2001/XMLSchema#double' );
 216+ return new SMWExpData( $lit );
 217+ } else {
 218+ return null;
 219+ }
 220+ }
 221+
 222+ /**
 223+ * Transform a (typically unit-) string into a normalised form,
 224+ * so that, e.g., "km²" and "km<sup>2</sup>" do not need to be
 225+ * distinguished.
 226+ */
 227+ protected function normalizeUnit( $unit ) {
 228+ $unit = str_replace( array( '[[', ']]' ), '', trim( $unit ) ); // allow simple links to be used inside annotations
 229+ $unit = str_replace( array( '²', '<sup>2</sup>' ), '&sup2;', $unit );
 230+ $unit = str_replace( array( '³', '<sup>3</sup>' ), '&sup3;', $unit );
 231+ return smwfXMLContentEncode( $unit );
 232+ }
 233+
 234+ /**
 235+ * Converts the current m_value and m_unit to the main unit, if possible.
 236+ * This means, it changes the fileds m_value and m_unit accordingly, and
 237+ * that it stores the ID of the originally given unit in $this->m_unitin.
 238+ * This should obviously not be done more than once, so it is advisable to
 239+ * first check if m_unitin is non-false. Also, it should be checked if the
 240+ * value is valid before trying to calculate with its contents.
 241+ *
 242+ * Overwritten by subclasses that support units.
 243+ */
 244+ protected function convertToMainUnit() {
 245+ $this->m_unitin = $this->m_unit; // just use unit as ID (no check needed, we can do this as often as desired)
 246+ }
 247+
 248+ /**
 249+ * This method creates an array of unit-value-pairs that should be
 250+ * printed. Units are the keys and should be canonical unit IDs.
 251+ * The result is stored in $this->m_unitvalues. Again, any class that
 252+ * requires effort for doing this should first check whether the array
 253+ * is already set (i.e. not false) before doing any work.
 254+ * Note that the values should be plain numbers. Output formatting is done
 255+ * later when needed. Also, it should be checked if the value is valid
 256+ * before trying to calculate with its contents.
 257+ * This method also must call or implement convertToMainUnit().
 258+ *
 259+ * Overwritten by subclasses that support units.
 260+ */
 261+ protected function makeConversionValues() {
 262+ $this->convertToMainUnit();
 263+ $this->m_unitvalues = array( $this->m_unit => $this->m_value );
 264+ }
 265+
 266+ /**
 267+ * This method is used when no user input was given to find the best
 268+ * values for m_wikivalue, m_unitin, and m_caption. After conversion,
 269+ * these fields will look as if they were generated from user input,
 270+ * and convertToMainUnit() will have been called (if not, it would be
 271+ * blocked by the presence of m_unitin).
 272+ *
 273+ * Overwritten by subclasses that support units.
 274+ */
 275+ protected function makeUserValue() {
 276+ $this->convertToMainUnit();
 277+ $this->m_caption = '';
 278+ if ( $this->m_outformat != '-u' ) { // -u is the format for displaying the unit only
 279+ $this->m_caption .= ( ( $this->m_outformat != '-' ) && ( $this->m_outformat != '-n' ) ? smwfNumberFormat( $this->m_value ) : $this->m_value );
 280+ }
 281+ if ( ( $this->m_unit != '' ) && ( $this->m_outformat != '-n' ) ) { // -n is the format for displaying the number only
 282+ if ( $this->m_outformat != '-u' ) {
 283+ $this->m_caption .= ( $this->m_outformat != '-' ? '&#160;' : ' ' );
 284+ }
 285+ $this->m_caption .= $this->m_unit;
 286+ }
 287+ $this->m_wikivalue = $this->m_caption;
 288+ $this->m_unitin = $this->m_unit;
 289+ }
 290+
 291+ /**
 292+ * Return an array of major unit strings (ids only recommended) supported by
 293+ * this datavalue.
 294+ *
 295+ * Overwritten by subclasses that support units.
 296+ */
 297+ public function getUnitList() {
 298+ return array();
 299+ }
 300+
 301+}
Property changes on: trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_Number.php
___________________________________________________________________
Added: svn:eol-style
1302 + native
Index: trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_Error.php
@@ -0,0 +1,76 @@
 2+<?php
 3+/**
 4+ * @file
 5+ * @ingroup SMWDataValues
 6+ */
 7+
 8+/**
 9+ * This datavalue implements Error-Datavalues.
 10+ *
 11+ * @author Nikolas Iwan
 12+ * @ingroup SMWDataValues
 13+ */
 14+class SMWErrorValue extends SMWDataValue {
 15+
 16+ private $m_value;
 17+
 18+ public function SMWErrorValue( $errormsg = '', $uservalue = '', $caption = false ) {
 19+ $this->setUserValue( $uservalue, $caption );
 20+ if ( $errormsg != '' ) $this->addError( $errormsg );
 21+ }
 22+
 23+ protected function parseUserValue( $value ) {
 24+ if ( $this->m_caption === false ) {
 25+ $this->m_caption = $value;
 26+ }
 27+ $this->m_value = $value;
 28+ return true;
 29+ }
 30+
 31+ protected function parseDBkeys( $args ) {
 32+ $this->setUserValue( strval( $args[0] ) ); // compatible syntax
 33+ // Note that errors are never a proper result of reading data from the
 34+ // store, so it is quite unlikely that the data we get here fits this
 35+ // datatype. Normally, it will not be displayed either since this value
 36+ // is not valid by default. So keeping the DB key here is rather
 37+ // irrelevant.
 38+ }
 39+
 40+ public function setOutputFormat( $formatstring ) {
 41+ // no output formats
 42+ }
 43+
 44+ public function getShortWikiText( $linked = null ) {
 45+ $this->unstub();
 46+ // TODO: support linking?
 47+ return $this->m_caption;
 48+ }
 49+
 50+ public function getShortHTMLText( $linker = null ) {
 51+ return htmlspecialchars( $this->getShortWikiText( $linker ) );
 52+ }
 53+
 54+ public function getLongWikiText( $linked = null ) {
 55+ // TODO: support linking?
 56+ $this->unstub();
 57+ return $this->getErrorText();
 58+ }
 59+
 60+ public function getLongHTMLText( $linker = null ) {
 61+ $this->unstub();
 62+ return $this->getErrorText();
 63+ }
 64+
 65+ public function getDBkeys() {
 66+ return array( $this->getShortWikiText() ); ///TODO: really? (errors are not meant to be saved, or are they?)
 67+ }
 68+
 69+ public function getWikiValue() {
 70+ return $this->getShortWikiText(); /// FIXME: wikivalue must not be influenced by the caption
 71+ }
 72+
 73+ public function isValid() {
 74+ return false;
 75+ }
 76+
 77+}
Property changes on: trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_Error.php
___________________________________________________________________
Added: svn:eol-style
178 + native
Index: trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_Bool.php
@@ -0,0 +1,134 @@
 2+<?php
 3+/**
 4+ * @file
 5+ * @ingroup SMWDataValues
 6+ */
 7+
 8+/**
 9+ * This datavalue implements Boolean datavalues.
 10+ *
 11+ * @author Markus Krötzsch
 12+ * @ingroup SMWDataValues
 13+ */
 14+class SMWBoolValue extends SMWDataValue {
 15+
 16+ protected $m_value = null; // true, false, or NULL (unset)
 17+ protected $m_stdcaption = ''; // a localised standard label for that value (if value is not NULL)
 18+ protected $m_truecaption = null; // a desired label for "true" if given
 19+ protected $m_falsecaption = null; // a desired label for "false" if given
 20+
 21+ protected function parseUserValue( $value ) {
 22+ smwfLoadExtensionMessages( 'SemanticMediaWiki' );
 23+ $value = trim( $value );
 24+ $lcv = strtolower( $value );
 25+ $this->m_value = null;
 26+ if ( $lcv === '1' ) { // note: if English "true" should be possible, specify in smw_true_words
 27+ $this->m_value = true;
 28+ } elseif ( $lcv === '0' ) { // note: English "false" may be added to smw_true_words
 29+ $this->m_value = false;
 30+ } elseif ( in_array( $lcv, explode( ',', wfMsgForContent( 'smw_true_words' ) ), TRUE ) ) {
 31+ $this->m_value = true;
 32+ } elseif ( in_array( $lcv, explode( ',', wfMsgForContent( 'smw_false_words' ) ), TRUE ) ) {
 33+ $this->m_value = false;
 34+ } else {
 35+ $this->addError( wfMsgForContent( 'smw_noboolean', $value ) );
 36+ }
 37+
 38+ if ( $this->m_caption === false ) {
 39+ $this->m_caption = $value;
 40+ }
 41+ if ( $this->m_value === true ) {
 42+ if ( $this->m_truecaption !== null ) {
 43+ $this->m_stdcaption = $this->m_truecaption;
 44+ } else {
 45+ $vals = explode( ',', wfMsgForContent( 'smw_true_words' ) );
 46+ $this->m_stdcaption = $vals[0];
 47+ }
 48+ } elseif ( $this->m_value === false ) {
 49+ if ( $this->m_falsecaption !== null ) {
 50+ $this->m_stdcaption = $this->m_falsecaption;
 51+ } else {
 52+ $vals = explode( ',', wfMsgForContent( 'smw_false_words' ) );
 53+ $this->m_stdcaption = $vals[0];
 54+ }
 55+ } else {
 56+ $this->m_stdcaption = '';
 57+ }
 58+ return true;
 59+ }
 60+
 61+ protected function parseDBkeys( $args ) {
 62+ $this->parseUserValue( $args[0] );
 63+ $this->m_caption = $this->m_stdcaption; // use default for this language
 64+ }
 65+
 66+ public function setOutputFormat( $formatstring ) {
 67+ if ( $formatstring == '' ) {
 68+ // ignore
 69+ } elseif ( strtolower( $formatstring ) == 'x' ) {
 70+ $this->m_truecaption = '<span style="font-family: sans-serif; ">X</span>';
 71+ $this->m_falsecaption = '';
 72+ } else { // try format "truelabel, falselabel"
 73+ $captions = explode( ',', $formatstring, 2 );
 74+ if ( count( $captions ) == 2 ) { // note: escaping needed to be safe; MW-sanitising would be an alternative
 75+ $this->m_truecaption = htmlspecialchars( trim( $captions[0] ) );
 76+ $this->m_falsecaption = htmlspecialchars( trim( $captions[1] ) );
 77+ } // else ignore
 78+ }
 79+ if ( ( $formatstring != $this->m_outformat ) && $this->isValid() && ( $this->m_truecaption !== null ) ) { // also adjust display
 80+ $this->m_caption = $this->m_stdcaption = ( $this->m_value ? $this->m_truecaption:$this->m_falsecaption );
 81+ }
 82+ $this->m_outformat = $formatstring;
 83+ }
 84+
 85+ public function getShortWikiText( $linked = null ) {
 86+ $this->unstub();
 87+ return $this->m_caption;
 88+ }
 89+
 90+ public function getShortHTMLText( $linker = null ) {
 91+ $this->unstub();
 92+ return $this->m_caption;
 93+ }
 94+
 95+ public function getLongWikiText( $linked = null ) {
 96+ return $this->isValid() ? $this->m_stdcaption:$this->getErrorText();
 97+ }
 98+
 99+ public function getLongHTMLText( $linker = null ) {
 100+ return $this->isValid() ? $this->m_stdcaption:$this->getErrorText();
 101+ }
 102+
 103+ public function getDBkeys() {
 104+ $this->unstub();
 105+ return $this->m_value ? array( '1', 1 ):array( '0', 0 );
 106+ }
 107+
 108+ public function getSignature() {
 109+ return 'tn';
 110+ }
 111+
 112+ public function getValueIndex() {
 113+ return 1;
 114+ }
 115+
 116+ public function getLabelIndex() {
 117+ return 0;
 118+ }
 119+
 120+ public function getWikiValue() {
 121+ $this->unstub();
 122+ return $this->m_stdcaption;
 123+ }
 124+
 125+ public function getExportData() {
 126+ if ( $this->isValid() ) {
 127+ $xsdvalue = $this->m_value ? 'true':'false';
 128+ $lit = new SMWExpLiteral( $xsdvalue, $this, 'http://www.w3.org/2001/XMLSchema#boolean' );
 129+ return new SMWExpData( $lit );
 130+ } else {
 131+ return null;
 132+ }
 133+ }
 134+
 135+}
Property changes on: trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_Bool.php
___________________________________________________________________
Added: svn:eol-style
1136 + native
Index: trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_Concept.php
@@ -0,0 +1,224 @@
 2+<?php
 3+/**
 4+ * @file
 5+ * @ingroup SMWDataValues
 6+ */
 7+
 8+/**
 9+ * This datavalue is used as a container for concept descriptions as used
 10+ * on Concept pages with the #concept parserfunction. It has a somewhat
 11+ * non-standard interface as compared to other datavalues, but this is not
 12+ * an issue.
 13+ *
 14+ * @author Markus Krötzsch
 15+ * @ingroup SMWDataValues
 16+ */
 17+class SMWConceptValue extends SMWDataValue {
 18+
 19+ protected $m_concept = ''; // XML-safe, HTML-safe, Wiki-compatible concept expression (query string)
 20+ protected $m_docu = ''; // text description of concept, can only be set by special function "setvalues"
 21+
 22+ protected function parseUserValue( $value ) {
 23+ $this->clear();
 24+ // this function is normally not used for this class, not created from user input directly
 25+ $this->m_concept = smwfXMLContentEncode( $value );
 26+ if ( $this->m_caption === false ) {
 27+ $this->m_caption = $value;
 28+ }
 29+ return true;
 30+ }
 31+
 32+ protected function parseDBkeys( $args ) {
 33+ $this->m_concept = $args[0];
 34+ $this->m_caption = $args[0]; // is this useful?
 35+ $this->m_docu = $args[1] ? smwfXMLContentEncode( $args[1] ):'';
 36+ $this->m_queryfeatures = $args[2];
 37+ $this->m_size = $args[3];
 38+ $this->m_depth = $args[4];
 39+ }
 40+
 41+ protected function clear() {
 42+ $this->m_concept = '';
 43+ $this->m_docu = '';
 44+ $this->m_queryfeatures = 0;
 45+ $this->m_size = - 1;
 46+ $this->m_depth = - 1;
 47+ }
 48+
 49+ public function getShortWikiText( $linked = null ) {
 50+ $this->unstub();
 51+ return $this->m_caption;
 52+ }
 53+
 54+ public function getShortHTMLText( $linker = null ) {
 55+ return $this->getShortWikiText( $linker ); // should be save (based on xsdvalue)
 56+ }
 57+
 58+ public function getLongWikiText( $linked = null ) {
 59+ if ( !$this->isValid() ) {
 60+ return $this->getErrorText();
 61+ } else {
 62+ return $this->m_caption;
 63+ }
 64+ }
 65+
 66+ public function getLongHTMLText( $linker = null ) {
 67+ if ( !$this->isValid() ) {
 68+ return $this->getErrorText();
 69+ } else {
 70+ return $this->m_caption; // should be save (based on xsdvalue)
 71+ }
 72+ }
 73+
 74+ public function getDBkeys() {
 75+ $this->unstub();
 76+ return array( $this->m_concept, $this->m_docu, $this->m_queryfeatures, $this->m_size, $this->m_depth );
 77+ }
 78+
 79+ public function getSignature() {
 80+ return 'tllnnn';
 81+ }
 82+
 83+ public function getValueIndex() {
 84+ return 0;
 85+ }
 86+
 87+ public function getLabelIndex() {
 88+ return 0;
 89+ }
 90+
 91+ public function getWikiValue() {
 92+ $this->unstub();
 93+ return str_replace( array( '&lt;', '&gt;', '&amp;' ), array( '<', '>', '&' ), $this->m_concept );
 94+ }
 95+
 96+ public function getExportData() {
 97+ if ( $this->isValid() ) {
 98+ $qp = new SMWQueryParser();
 99+ $desc = $qp->getQueryDescription( $this->getWikiValue() );
 100+ $exact = true;
 101+ $owldesc = $this->descriptionToExpData( $desc, $exact );
 102+ if ( $owldesc === false ) {
 103+ $element = new SMWExpData( SMWExporter::getSpecialElement( 'owl', 'Thing' ) );
 104+ }
 105+ if ( !$exact ) {
 106+ $result = new SMWExpData( new SMWExpElement( '' ) );
 107+ $result->addPropertyObjectValue( SMWExporter::getSpecialElement( 'rdf', 'type' ),
 108+ new SMWExpData( SMWExporter::getSpecialElement( 'owl', 'Class' ) ) );
 109+ $result->addPropertyObjectValue( SMWExporter::getSpecialElement( 'rdfs', 'subClassOf' ), $owldesc );
 110+ return $result;
 111+ } else {
 112+ return $owldesc;
 113+ }
 114+ } else {
 115+ return null;
 116+ }
 117+ }
 118+
 119+ public function descriptionToExpData( $desc, &$exact ) {
 120+ if ( ( $desc instanceof SMWConjunction ) || ( $desc instanceof SMWDisjunction ) ) {
 121+ $result = new SMWExpData( new SMWExpElement( '' ) );
 122+ $result->addPropertyObjectValue( SMWExporter::getSpecialElement( 'rdf', 'type' ),
 123+ new SMWExpData( SMWExporter::getSpecialElement( 'owl', 'Class' ) ) );
 124+ $elements = array();
 125+ foreach ( $desc->getDescriptions() as $subdesc ) {
 126+ $element = $this->descriptionToExpData( $subdesc, $exact );
 127+ if ( $element === false ) {
 128+ $element = new SMWExpData( SMWExporter::getSpecialElement( 'owl', 'Thing' ) );
 129+ }
 130+ $elements[] = $element;
 131+ }
 132+ $prop = ( $desc instanceof SMWConjunction ) ? 'intersectionOf':'unionOf';
 133+ $result->addPropertyObjectValue( SMWExporter::getSpecialElement( 'owl', $prop ),
 134+ SMWExpData::makeCollection( $elements ) );
 135+ } elseif ( $desc instanceof SMWClassDescription ) {
 136+ if ( count( $desc->getCategories() ) == 1 ) { // single category
 137+ $result = new SMWExpData( SMWExporter::getResourceElement( end( $desc->getCategories() ) ) );
 138+ } else { // disjunction of categories
 139+ $result = new SMWExpData( new SMWExpElement( '' ) );
 140+ $elements = array();
 141+ foreach ( $desc->getCategories() as $cat ) {
 142+ $elements[] = new SMWExpData( SMWExporter::getResourceElement( $cat ) ); ;
 143+ }
 144+ $result->addPropertyObjectValue( SMWExporter::getSpecialElement( 'owl', 'unionOf' ),
 145+ SMWExpData::makeCollection( $elements ) );
 146+ }
 147+ $result->addPropertyObjectValue( SMWExporter::getSpecialElement( 'rdf', 'type' ),
 148+ new SMWExpData( SMWExporter::getSpecialElement( 'owl', 'Class' ) ) );
 149+ } elseif ( $desc instanceof SMWConceptDescription ) {
 150+ $result = new SMWExpData( SMWExporter::getResourceElement( $desc->getConcept() ) );
 151+ } elseif ( $desc instanceof SMWSomeProperty ) {
 152+ $result = new SMWExpData( new SMWExpElement( '' ) );
 153+ $result->addPropertyObjectValue( SMWExporter::getSpecialElement( 'rdf', 'type' ),
 154+ new SMWExpData( SMWExporter::getSpecialElement( 'owl', 'Restriction' ) ) );
 155+ $result->addPropertyObjectValue( SMWExporter::getSpecialElement( 'owl', 'onProperty' ),
 156+ new SMWExpData( SMWExporter::getResourceElement( $desc->getProperty() ) ) );
 157+ $subdata = $this->descriptionToExpData( $desc->getDescription(), $exact );
 158+ if ( ( $desc->getDescription() instanceof SMWValueDescription ) &&
 159+ ( $desc->getDescription()->getComparator() == SMW_CMP_EQ ) ) {
 160+ $result->addPropertyObjectValue( SMWExporter::getSpecialElement( 'owl', 'hasValue' ), $subdata );
 161+ } else {
 162+ if ( $subdata === false ) {
 163+ $owltype = SMWExporter::getOWLPropertyType( $desc->getProperty()->getPropertyTypeID() );
 164+ if ( $owltype == 'ObjectProperty' ) {
 165+ $subdata = new SMWExpData( SMWExporter::getSpecialElement( 'owl', 'Thing' ) );
 166+ } elseif ( $owltype == 'DatatypeProperty' ) {
 167+ $subdata = new SMWExpData( SMWExporter::getSpecialElement( 'rdfs', 'Literal' ) );
 168+ } else { // no restrictions at all with annotation properties ...
 169+ return new SMWExpData( SMWExporter::getSpecialElement( 'owl', 'Thing' ) );
 170+ }
 171+ }
 172+ $result->addPropertyObjectValue( SMWExporter::getSpecialElement( 'owl', 'someValuesFrom' ), $subdata );
 173+ }
 174+ } elseif ( $desc instanceof SMWValueDescription ) {
 175+ if ( $desc->getComparator() == SMW_CMP_EQ ) {
 176+ $result = $desc->getDataValue()->getExportData();
 177+ } else { // alas, OWL cannot represent <= and >= ...
 178+ $exact = false;
 179+ $result = false;
 180+ }
 181+ } elseif ( $desc instanceof SMWThingDescription ) {
 182+ $result = false;
 183+ } else {
 184+ $result = false;
 185+ $exact = false;
 186+ }
 187+ return $result;
 188+ }
 189+
 190+ /// Return the concept's defining text (in SMW query syntax)
 191+ public function getConceptText() {
 192+ $this->unstub();
 193+ return $this->m_concept;
 194+ }
 195+
 196+ /// Return the optional concept documentation.
 197+ public function getDocu() {
 198+ $this->unstub();
 199+ return $this->m_docu;
 200+ }
 201+
 202+ /// Return the concept's size (a metric used to estimate computation complexity).
 203+ public function getSize() {
 204+ $this->unstub();
 205+ return $this->m_size;
 206+ }
 207+
 208+ /// Return the concept's depth (a metric used to estimate computation complexity).
 209+ public function getDepth() {
 210+ $this->unstub();
 211+ return $this->m_depth;
 212+ }
 213+
 214+ /// Return the concept's query feature bit field (a metric used to estimate computation complexity).
 215+ public function getQueryFeatures() {
 216+ $this->unstub();
 217+ return $this->m_queryfeatures;
 218+ }
 219+
 220+ /// @deprecated Use setDBkeys(). This method will vanish before SMW 1.6
 221+ public function setValues( $concept, $docu, $queryfeatures, $size, $depth ) {
 222+ $this->setDBkeys( array( $concept, $docu, $queryfeatures, $size, $depth ) );
 223+ }
 224+
 225+}
Property changes on: trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_Concept.php
___________________________________________________________________
Added: svn:eol-style
1226 + native
Index: trunk/extensions/SemanticMediaWiki/includes/SMW_Setup.php
@@ -73,6 +73,9 @@
7474 $wgAutoloadClasses['SMWPropertyPage'] = $smwgIP . 'includes/articlepages/SMW_PropertyPage.php';
7575 $wgAutoloadClasses['SMWConceptPage'] = $smwgIP . 'includes/articlepages/SMW_ConceptPage.php';
7676 $wgAutoloadClasses['SMWResultPrinter'] = $smwgIP . 'includes/SMW_QueryPrinter.php';
 77+ $wgAutoloadClasses['SMWDataValueFactory'] = $smwgIP . 'includes/SMW_DataValueFactory.php';
 78+ $wgAutoloadClasses['SMWDataValue'] = $smwgIP . 'includes/SMW_DataValue.php';
 79+
7780 // Printers
7881 $qpDir = $smwgIP . 'includes/queryprinters/';
7982 $wgAutoloadClasses['SMWAutoResultPrinter'] = $qpDir . 'SMW_QP_Auto.php';
@@ -83,27 +86,27 @@
8487 $wgAutoloadClasses['SMWRSSResultPrinter'] = $qpDir . 'SMW_QP_RSSlink.php';
8588 $wgAutoloadClasses['SMWCsvResultPrinter'] = $qpDir . 'SMW_QP_CSV.php';
8689 $wgAutoloadClasses['SMWJSONResultPrinter'] = $qpDir . 'SMW_QP_JSONlink.php';
 90+
8791 // Datavalues
88 - $wgAutoloadClasses['SMWDataValueFactory'] = $smwgIP . 'includes/SMW_DataValueFactory.php';
89 - $wgAutoloadClasses['SMWDataValue'] = $smwgIP . 'includes/SMW_DataValue.php';
90 - $wgAutoloadClasses['SMWContainerValue'] = $smwgIP . 'includes/SMW_DV_Container.php';
91 - $wgAutoloadClasses['SMWRecordValue'] = $smwgIP . 'includes/SMW_DV_Record.php';
92 - $wgAutoloadClasses['SMWErrorvalue'] = $smwgIP . 'includes/SMW_DV_Error.php';
93 - $wgAutoloadClasses['SMWStringValue'] = $smwgIP . 'includes/SMW_DV_String.php';
94 - $wgAutoloadClasses['SMWWikiPageValue'] = $smwgIP . 'includes/SMW_DV_WikiPage.php';
95 - $wgAutoloadClasses['SMWSimpleWikiPageValue'] = $smwgIP . 'includes/SMW_DV_SimpleWikiPage.php';
96 - $wgAutoloadClasses['SMWPropertyValue'] = $smwgIP . 'includes/SMW_DV_Property.php';
97 - $wgAutoloadClasses['SMWURIValue'] = $smwgIP . 'includes/SMW_DV_URI.php';
98 - $wgAutoloadClasses['SMWTypesValue'] = $smwgIP . 'includes/SMW_DV_Types.php';
99 - $wgAutoloadClasses['SMWTypeListValue'] = $smwgIP . 'includes/SMW_DV_TypeList.php';
100 - $wgAutoloadClasses['SMWErrorValue'] = $smwgIP . 'includes/SMW_DV_Error.php';
101 - $wgAutoloadClasses['SMWNumberValue'] = $smwgIP . 'includes/SMW_DV_Number.php';
102 - $wgAutoloadClasses['SMWTemperatureValue'] = $smwgIP . 'includes/SMW_DV_Temperature.php';
103 - $wgAutoloadClasses['SMWLinearValue'] = $smwgIP . 'includes/SMW_DV_Linear.php';
104 - $wgAutoloadClasses['SMWTimeValue'] = $smwgIP . 'includes/SMW_DV_Time.php';
105 - $wgAutoloadClasses['SMWBoolValue'] = $smwgIP . 'includes/SMW_DV_Bool.php';
106 - $wgAutoloadClasses['SMWConceptValue'] = $smwgIP . 'includes/SMW_DV_Concept.php';
107 - $wgAutoloadClasses['SMWImportValue'] = $smwgIP . 'includes/SMW_DV_Import.php';
 92+ $dvDir = $smwgIP . 'includes/datavalues/';
 93+ $wgAutoloadClasses['SMWContainerValue'] = $dvDir . 'SMW_DV_Container.php';
 94+ $wgAutoloadClasses['SMWRecordValue'] = $dvDir . 'SMW_DV_Record.php';
 95+ $wgAutoloadClasses['SMWErrorvalue'] = $dvDir . 'SMW_DV_Error.php';
 96+ $wgAutoloadClasses['SMWStringValue'] = $dvDir . 'SMW_DV_String.php';
 97+ $wgAutoloadClasses['SMWWikiPageValue'] = $dvDir . 'SMW_DV_WikiPage.php';
 98+ $wgAutoloadClasses['SMWSimpleWikiPageValue'] = $dvDir . 'SMW_DV_SimpleWikiPage.php';
 99+ $wgAutoloadClasses['SMWPropertyValue'] = $dvDir . 'SMW_DV_Property.php';
 100+ $wgAutoloadClasses['SMWURIValue'] = $dvDir . 'SMW_DV_URI.php';
 101+ $wgAutoloadClasses['SMWTypesValue'] = $dvDir . 'SMW_DV_Types.php';
 102+ $wgAutoloadClasses['SMWTypeListValue'] = $dvDir . 'SMW_DV_TypeList.php';
 103+ $wgAutoloadClasses['SMWErrorValue'] = $dvDir . 'SMW_DV_Error.php';
 104+ $wgAutoloadClasses['SMWNumberValue'] = $dvDir . 'SMW_DV_Number.php';
 105+ $wgAutoloadClasses['SMWTemperatureValue'] = $dvDir . 'SMW_DV_Temperature.php';
 106+ $wgAutoloadClasses['SMWLinearValue'] = $dvDir . 'SMW_DV_Linear.php';
 107+ $wgAutoloadClasses['SMWTimeValue'] = $dvDir . 'SMW_DV_Time.php';
 108+ $wgAutoloadClasses['SMWBoolValue'] = $dvDir . 'SMW_DV_Bool.php';
 109+ $wgAutoloadClasses['SMWConceptValue'] = $dvDir . 'SMW_DV_Concept.php';
 110+ $wgAutoloadClasses['SMWImportValue'] = $dvDir . 'SMW_DV_Import.php';
108111 // Export
109112 $wgAutoloadClasses['SMWExporter'] = $smwgIP . 'includes/export/SMW_Exporter.php';
110113 $wgAutoloadClasses['SMWExpData'] = $smwgIP . 'includes/export/SMW_Exp_Data.php';

Follow-up revisions

RevisionCommit summaryAuthorDate
r72991Follow up to r72987jeroendedauw16:45, 14 September 2010
r72993Follow up to r72987jeroendedauw17:02, 14 September 2010

Status & tagging log