Index: trunk/extensions/SemanticMediaWiki/includes/datavalues/SMW_DV_WikiPage.php |
— | — | @@ -12,6 +12,15 @@ |
13 | 13 | * namespace, Whether a namespace is fixed is decided based on the |
14 | 14 | * type ID when the object is constructed. |
15 | 15 | * |
| 16 | + * The short display simulates the behaviour of the MediaWiki "pipe trick" |
| 17 | + * but always includes fragments. This can be overwritten by setting a |
| 18 | + * caption, which is also done by default when generating a value from user |
| 19 | + * input. The long display always includes all relevant information. Only if a |
| 20 | + * fixed namespace is used for the datatype, the namespace prefix is omitted. |
| 21 | + * This behavior has changed in SMW 1.7: up to this time, short displays have |
| 22 | + * always inlcuded the namespace and long displays used the pipe trick, leading |
| 23 | + * to a paradoxical confusion of "long" and "short". |
| 24 | + * |
16 | 25 | * @author Nikolas Iwan |
17 | 26 | * @author Markus Krötzsch |
18 | 27 | * @ingroup SMWDataValues |
— | — | @@ -19,12 +28,6 @@ |
20 | 29 | class SMWWikiPageValue extends SMWDataValue { |
21 | 30 | |
22 | 31 | /** |
23 | | - * The isolated title as text. Always set when this object is valid. |
24 | | - * @var string |
25 | | - */ |
26 | | - protected $m_textform; |
27 | | - |
28 | | - /** |
29 | 32 | * Fragment text for user-specified title. Not stored, but kept for |
30 | 33 | * printout on page. |
31 | 34 | * @var string |
— | — | @@ -111,9 +114,9 @@ |
112 | 115 | $this->addError( wfMsgForContent( 'smw_notitle', $value ) ); |
113 | 116 | } elseif ( ( $this->m_fixNamespace != NS_MAIN ) && |
114 | 117 | ( $this->m_fixNamespace != $this->m_title->getNamespace() ) ) { |
115 | | - $this->addError( wfMsgForContent( 'smw_wrong_namespace', $wgContLang->getNsText( $this->m_fixNamespace ) ) ); |
| 118 | + $this->addError( wfMsgForContent( 'smw_wrong_namespace', |
| 119 | + $wgContLang->getNsText( $this->m_fixNamespace ) ) ); |
116 | 120 | } else { |
117 | | - $this->m_textform = $this->m_title->getText(); |
118 | 121 | $this->m_fragment = $this->m_title->getFragment(); |
119 | 122 | $this->m_prefixedtext = ''; |
120 | 123 | $this->m_id = -1; // unset id |
— | — | @@ -137,14 +140,15 @@ |
138 | 141 | |
139 | 142 | if ( $dataItem->getDIType() == SMWDataItem::TYPE_WIKIPAGE ) { |
140 | 143 | $this->m_dataitem = $dataItem; |
141 | | - $this->m_textform = str_replace( '_', ' ', $dataItem->getDBkey() ); |
142 | 144 | $this->m_id = -1; |
143 | 145 | $this->m_title = null; |
144 | 146 | $this->m_fragment = $dataItem->getSubobjectName(); |
145 | 147 | $this->m_prefixedtext = ''; |
146 | | - $this->m_caption = false; |
147 | | - if ( ( $this->m_fixNamespace != NS_MAIN ) && ( $this->m_fixNamespace != $dataItem->getNamespace() ) ) { |
148 | | - $this->addError( wfMsgForContent( 'smw_notitle', $this->getPrefixedText() ) ); |
| 148 | + $this->m_caption = false; // this class can handle this |
| 149 | + if ( ( $this->m_fixNamespace != NS_MAIN ) && |
| 150 | + ( $this->m_fixNamespace != $dataItem->getNamespace() ) ) { |
| 151 | + $this->addError( wfMsgForContent( 'smw_wrong_namespace', |
| 152 | + $wgContLang->getNsText( $this->m_fixNamespace ) ) ); |
149 | 153 | } |
150 | 154 | return true; |
151 | 155 | } else { |
— | — | @@ -152,73 +156,146 @@ |
153 | 157 | } |
154 | 158 | } |
155 | 159 | |
| 160 | + /** |
| 161 | + * Display the value on a wiki page. This is used to display the value |
| 162 | + * in the place where it was annotated on a wiki page. The desired |
| 163 | + * behavior is that the display in this case looks as if no property |
| 164 | + * annotation had been given, i.e. an annotation [[property::page|foo]] |
| 165 | + * should display like [[page|foo]] in MediaWiki. But this should lead |
| 166 | + * to a link, not to a category assignment. This means that: |
| 167 | + * |
| 168 | + * (1) If Image: is used (instead of Media:) then let MediaWiki embed |
| 169 | + * the image. |
| 170 | + * |
| 171 | + * (2) If Category: is used, treat it as a page and link to it (do not |
| 172 | + * categorize the page) |
| 173 | + * |
| 174 | + * (3) Preserve everything given after "|" for display (caption, image |
| 175 | + * parameters, ...) |
| 176 | + * |
| 177 | + * (4) Use the (default) caption for display. When the value comes from |
| 178 | + * user input, this includes the full value that one would also see in |
| 179 | + * MediaWiki. |
| 180 | + * |
| 181 | + * @param $linked mixed generate links if not null or false |
| 182 | + * @return string |
| 183 | + */ |
156 | 184 | public function getShortWikiText( $linked = null ) { |
157 | | - if ( ( $linked === null ) || ( $linked === false ) || ( $this->m_outformat == '-' ) || ( !$this->isValid() ) || ( $this->m_caption === '' ) ) { |
158 | | - return $this->getCaption(); |
| 185 | + if ( is_null( $linked ) || $linked === false || |
| 186 | + $this->m_outformat == '-' || !$this->isValid() || |
| 187 | + $this->m_caption === '' ) { |
| 188 | + return $this->m_caption !== false ? $this->m_caption : $this->getWikiValue(); |
159 | 189 | } else { |
160 | | - return '[[:' . $this->getWikiLinkTarget() . '|' . $this->getCaption() . ']]'; |
| 190 | + if ( $this->m_dataitem->getNamespace() == NS_FILE ) { |
| 191 | + $linkEscape = ''; |
| 192 | + $defaultCaption = '|' . $this->getShortCaptionText() . '|frameless|border|text-top'; |
| 193 | + } else { |
| 194 | + $linkEscape = ':'; |
| 195 | + $defaultCaption = '|' . $this->getShortCaptionText(); |
| 196 | + } |
| 197 | + if ( $this->m_caption === false ) { |
| 198 | + return '[[' . $linkEscape . $this->getWikiLinkTarget() . $defaultCaption . ']]'; |
| 199 | + } else { |
| 200 | + return '[[' . $linkEscape . $this->getWikiLinkTarget() . '|' . $this->m_caption . ']]'; |
| 201 | + } |
161 | 202 | } |
162 | 203 | } |
163 | 204 | |
| 205 | + /** |
| 206 | + * Display the value as in getShortWikiText() but create HTML. |
| 207 | + * The only difference is that images are not embedded. |
| 208 | + * |
| 209 | + * @param $linker mixed the Linker object to use or null if no linking is desired |
| 210 | + * @return string |
| 211 | + */ |
164 | 212 | public function getShortHTMLText( $linker = null ) { |
165 | | - if ( ( $linker !== null ) && ( $this->m_caption !== '' ) && ( $this->m_outformat != '-' ) ) $this->getTitle(); // init the Title object, may reveal hitherto unnoticed errors |
166 | | - if ( is_null( $linker ) || $linker === false || ( !$this->isValid() ) || ( $this->m_outformat == '-' ) || ( $this->m_caption === '' ) ) { |
167 | | - return htmlspecialchars( $this->getCaption() ); |
168 | | - } elseif ( $this->getNamespace() == NS_MEDIA ) { // this extra case *is* needed |
169 | | - return $linker->makeMediaLinkObj( $this->getTitle(), $this->getCaption() ); |
| 213 | + // init the Title object, may reveal hitherto unnoticed errors: |
| 214 | + if ( !is_null( $linker ) && $linker !== false && |
| 215 | + $this->m_caption !== '' && $this->m_outformat != '-' ) { |
| 216 | + $this->getTitle(); |
| 217 | + } |
| 218 | + |
| 219 | + if ( is_null( $linker ) || $linker === false || !$this->isValid() || |
| 220 | + $this->m_outformat == '-' || $this->m_caption === '' ) { |
| 221 | + return htmlspecialchars( $this->m_caption !== false ? $this->m_caption : $this->getWikiValue() ); |
170 | 222 | } else { |
171 | | - return $linker->makeLinkObj( $this->getTitle(), htmlspecialchars( $this->getCaption() ) ); |
| 223 | + $caption = htmlspecialchars( |
| 224 | + $this->m_caption !== false ? $this->m_caption : $this->getShortCaptionText() ); |
| 225 | + if ( $this->getNamespace() == NS_MEDIA ) { // this extra case *is* needed |
| 226 | + return $linker->makeMediaLinkObj( $this->getTitle(), $caption ); |
| 227 | + } else { |
| 228 | + return $linker->makeLinkObj( $this->getTitle(), $caption ); |
| 229 | + } |
172 | 230 | } |
173 | 231 | } |
174 | 232 | |
175 | 233 | /** |
176 | | - * @note The getLong... functions of this class always hide the fragment. Fragments are currently |
177 | | - * not stored, and hence should not be shown in the Factbox (where the getLongWikiText method is used). |
178 | | - * In all other uses, values come from the store and do not have fragments anyway. |
| 234 | + * Display the "long" value on a wiki page. This behaves largely like |
| 235 | + * getShortWikiText() but does not use the caption. Instead, it always |
| 236 | + * takes the long display form (wiki value). |
| 237 | + * |
| 238 | + * @param $linked mixed if true the result will be linked |
| 239 | + * @return string |
179 | 240 | */ |
180 | 241 | public function getLongWikiText( $linked = null ) { |
181 | 242 | if ( !$this->isValid() ) { |
182 | 243 | return $this->getErrorText(); |
183 | 244 | } |
184 | | - if ( ( $linked === null ) || ( $linked === false ) || ( $this->m_outformat == '-' ) ) { |
185 | | - return ( $this->m_fixNamespace == NS_MAIN ? $this->getPrefixedText() : $this->getText() ) . |
186 | | - ( $this->m_fragment ? "#{$this->m_fragment}" : '' ); |
| 245 | + |
| 246 | + if ( is_null( $linked ) || $linked === false || $this->m_outformat == '-' ) { |
| 247 | + return $this->getWikiValue(); |
187 | 248 | } elseif ( $this->m_dataitem->getNamespace() == NS_FILE ) { |
188 | | - // For images and other files, embed them and display |
189 | | - // their name, instead of just displaying their name |
190 | | - // TODO? We forget about subobjecs/fragments here. |
191 | | - $fileName = str_replace( "'", ''', $this->getPrefixedText() ); |
192 | | - return '[[' . $fileName . '|' . $this->m_textform . '|frameless|border|text-top]]' . "<br />\n" . '[[:' . $fileName . '|' . $this->m_textform . ']]'; |
| 249 | + // Embed images and other files |
| 250 | + // Note that the embedded file links to the image, hence needs no additional link text. |
| 251 | + // There should not be a linebreak after an impage, just like there is no linebreak after |
| 252 | + // other values (whether formatted or not). |
| 253 | + return '[[' . $this->getWikiLinkTarget() . '|' . |
| 254 | + $this->getWikiValue() . '|frameless|border|text-top]]'; |
193 | 255 | } else { |
194 | | - return '[[' . $this->getWikiLinkTarget() . '|' . $this->m_textform . ']]'; |
| 256 | + return '[[:' . $this->getWikiLinkTarget() . '|' . $this->getWikiValue() . ']]'; |
195 | 257 | } |
196 | 258 | } |
197 | 259 | |
| 260 | + /** |
| 261 | + * Display the "long" value in HTML. This behaves largely like |
| 262 | + * getLongWikiText() but does not embed images. |
| 263 | + * |
| 264 | + * @param $linker mixed if a Linker is given, the result will be linked |
| 265 | + * @return string |
| 266 | + */ |
198 | 267 | public function getLongHTMLText( $linker = null ) { |
199 | | - if ( ( $linker !== null ) && ( $this->m_outformat != '-' ) ) { $this->getTitle(); } // init the Title object, may reveal hitherto unnoticed errors |
| 268 | + // init the Title object, may reveal hitherto unnoticed errors: |
| 269 | + if ( !is_null( $linker ) && ( $this->m_outformat != '-' ) ) { |
| 270 | + $this->getTitle(); |
| 271 | + } |
200 | 272 | if ( !$this->isValid() ) { |
201 | 273 | return $this->getErrorText(); |
202 | 274 | } |
203 | | - if ( ( $linker === null ) || ( $this->m_outformat == '-' ) ) { |
204 | | - return htmlspecialchars( $this->m_fixNamespace == NS_MAIN ? $this->getPrefixedText():$this->getText() ); |
| 275 | + |
| 276 | + if ( is_null( $linker ) || $this->m_outformat == '-' ) { |
| 277 | + return htmlspecialchars( $this->getWikiValue() ); |
205 | 278 | } elseif ( $this->getNamespace() == NS_MEDIA ) { // this extra case is really needed |
206 | | - return $linker->makeMediaLinkObj( $this->getTitle(), $this->m_textform ); |
| 279 | + return $linker->makeMediaLinkObj( $this->getTitle(), |
| 280 | + htmlspecialchars( $this->getWikiValue() ) ); |
207 | 281 | } else { // all others use default linking, no embedding of images here |
208 | | - return $linker->makeLinkObj( $this->getTitle(), htmlspecialchars( $this->m_textform ) ); |
| 282 | + return $linker->makeLinkObj( $this->getTitle(), |
| 283 | + htmlspecialchars( $this->getWikiValue() ) ); |
209 | 284 | } |
210 | 285 | } |
211 | 286 | |
| 287 | + /** |
| 288 | + * Return a string that could be used in an in-page property assignment |
| 289 | + * for setting this value. This does not include initial ":" for |
| 290 | + * escaping things like Category: links since the property value does |
| 291 | + * not include such escapes either. Fragment information is included. |
| 292 | + * Namespaces are omitted if a fixed namespace is used, since they are |
| 293 | + * not needed in this case when making a property assignment. |
| 294 | + * |
| 295 | + * @return string |
| 296 | + */ |
212 | 297 | public function getWikiValue() { |
213 | | - if ( $this->m_fixNamespace != NS_MAIN ) { // no explicit namespace needed! |
214 | | - $result = $this->getText(); |
215 | | - } elseif ( $this->m_dataitem->getNamespace() == NS_CATEGORY ) { |
216 | | - // escape to enable use in links; todo: not generally required/suitable :-/ |
217 | | - $result = ':' . $this->getPrefixedText(); |
218 | | - } else { |
219 | | - $result = $this->getPrefixedText(); |
220 | | - } |
221 | | - |
222 | | - return $result . ( $this->m_fragment ? "#{$this->m_fragment}" : '' ); |
| 298 | + return ( $this->m_fixNamespace == NS_MAIN ? $this->getPrefixedText() : $this->getText() ) . |
| 299 | + ( $this->m_fragment ? "#{$this->m_fragment}" : '' ); |
223 | 300 | } |
224 | 301 | |
225 | 302 | public function getHash() { |
— | — | @@ -265,7 +342,9 @@ |
266 | 343 | } |
267 | 344 | |
268 | 345 | /** |
269 | | - * Get MediaWiki's ID for this value, if any. |
| 346 | + * Get MediaWiki's ID for this value or 0 if not available. |
| 347 | + * |
| 348 | + * @return integer |
270 | 349 | */ |
271 | 350 | public function getArticleID() { |
272 | 351 | if ( $this->m_id === false ) { |
— | — | @@ -276,6 +355,8 @@ |
277 | 356 | |
278 | 357 | /** |
279 | 358 | * Get namespace constant for this value. |
| 359 | + * |
| 360 | + * @return integer |
280 | 361 | */ |
281 | 362 | public function getNamespace() { |
282 | 363 | return $this->m_dataitem->getNamespace(); |
— | — | @@ -286,18 +367,24 @@ |
287 | 368 | * correspond to wiki pages may choose a DB key that is not a legal title |
288 | 369 | * DB key but rather another suitable internal ID. Thus it is not suitable |
289 | 370 | * to use this method in places where only MediaWiki Title keys are allowed. |
| 371 | + * |
| 372 | + * @return string |
290 | 373 | */ |
291 | 374 | public function getDBkey() { |
292 | 375 | return $this->m_dataitem->getDBkey(); |
293 | 376 | } |
294 | 377 | |
295 | | - /// Get text label for this value. |
| 378 | + /** |
| 379 | + * Get text label for this value, just like Title::getText(). |
| 380 | + * |
| 381 | + * @return string |
| 382 | + */ |
296 | 383 | public function getText() { |
297 | 384 | return str_replace( '_', ' ', $this->m_dataitem->getDBkey() ); |
298 | 385 | } |
299 | 386 | |
300 | 387 | /** |
301 | | - * Get the prefixed text for this value, including a localised namespace |
| 388 | + * Get the prefixed text for this value, including a localized namespace |
302 | 389 | * prefix. |
303 | 390 | * |
304 | 391 | * @return string |
— | — | @@ -307,8 +394,10 @@ |
308 | 395 | if ( $this->m_prefixedtext == '' ) { |
309 | 396 | if ( $this->isValid() ) { |
310 | 397 | $nstext = $wgContLang->getNSText( $this->m_dataitem->getNamespace() ); |
311 | | - $this->m_prefixedtext = ( $this->m_dataitem->getInterwiki() != '' ? $this->m_dataitem->getInterwiki() . ':' : '' ) . |
312 | | - ( $nstext != '' ? "$nstext:" : '' ) . $this->m_textform; |
| 398 | + $this->m_prefixedtext = |
| 399 | + ( $this->m_dataitem->getInterwiki() != '' ? |
| 400 | + $this->m_dataitem->getInterwiki() . ':' : '' ) . |
| 401 | + ( $nstext != '' ? "$nstext:" : '' ) . $this->getText(); |
313 | 402 | } else { |
314 | 403 | $this->m_prefixedtext = 'NO_VALID_VALUE'; |
315 | 404 | } |
— | — | @@ -318,29 +407,42 @@ |
319 | 408 | |
320 | 409 | /** |
321 | 410 | * Get interwiki prefix or empty string. |
| 411 | + * |
| 412 | + * @return string |
322 | 413 | */ |
323 | 414 | public function getInterwiki() { |
324 | 415 | return $this->m_dataitem->getInterwiki(); |
325 | 416 | } |
326 | 417 | |
327 | 418 | /** |
328 | | - * Get the (default) caption for this value. |
329 | | - * If a fixed namespace is set, we do not return the namespace prefix explicitly. |
| 419 | + * Get a short caption used to label this value. In particular, this |
| 420 | + * omits namespace and interwiki prefixes (similar to the MediaWiki |
| 421 | + * "pipe trick"). Fragments are included unless they start with an |
| 422 | + * underscore (used for generated fragment names that are not helpful |
| 423 | + * for users and that might change easily). |
| 424 | + * |
| 425 | + * @since 1.7 |
| 426 | + * @return string |
330 | 427 | */ |
331 | | - protected function getCaption() { |
332 | | - return $this->m_caption !== false ? $this->m_caption : |
333 | | - ( $this->m_fixNamespace == NS_MAIN ? $this->getPrefixedText() : $this->getText() ) . |
334 | | - ( $this->m_fragment ? "#{$this->m_fragment}" : '' ); |
| 428 | + protected function getShortCaptionText() { |
| 429 | + if ( $this->m_fragment && $this->m_fragment{0} != '_' ) { |
| 430 | + $fragmentText = '#' . $this->m_fragment; |
| 431 | + } else { |
| 432 | + $fragmentText = ''; |
| 433 | + } |
| 434 | + return $this->getText() . $fragmentText; |
335 | 435 | } |
336 | 436 | |
337 | 437 | /** |
338 | 438 | * Compute a text that can be used in wiki text to link to this |
339 | 439 | * datavalue. Processing includes some escaping and adding the |
340 | 440 | * fragment. |
| 441 | + * |
| 442 | + * @since 1.7 |
| 443 | + * @return string |
341 | 444 | */ |
342 | 445 | protected function getWikiLinkTarget() { |
343 | | - return ':' . |
344 | | - str_replace( "'", ''', $this->getPrefixedText() ) . |
| 446 | + return str_replace( "'", ''', $this->getPrefixedText() ) . |
345 | 447 | ( $this->m_fragment ? "#{$this->m_fragment}" : '' ); |
346 | 448 | } |
347 | 449 | |
Index: trunk/extensions/SemanticMediaWiki/includes/queryprinters/SMW_QP_Table.php |
— | — | @@ -188,10 +188,7 @@ |
189 | 189 | $values = array(); |
190 | 190 | |
191 | 191 | foreach ( $dataValues as $dv ) { |
192 | | - $value = ( ( $dv->getTypeID() == '_wpg' ) || ( $dv->getTypeID() == '__sin' ) ) ? |
193 | | - $dv->getLongText( $outputmode, $this->getLinker( $isSubject ) ) : |
194 | | - $dv->getShortText( $outputmode, $this->getLinker( $isSubject ) ); |
195 | | - |
| 192 | + $value = $dv->getShortText( $outputmode, $this->getLinker( $isSubject ) ); |
196 | 193 | $values[] = $value; |
197 | 194 | } |
198 | 195 | |
Index: trunk/extensions/SemanticMediaWiki/includes/storage/SMW_Description.php |
— | — | @@ -442,7 +442,11 @@ |
443 | 443 | if ( $asvalue ) { |
444 | 444 | return $comparator . $dataValue->getWikiValue(); |
445 | 445 | } else { // this only is possible for values of Type:Page |
446 | | - return '[[' . $comparator . $dataValue->getWikiValue() . ']]'; |
| 446 | + if ( $comparator == '' ) { // some extra care for Category: pages |
| 447 | + return '[[:' . $dataValue->getWikiValue() . ']]'; |
| 448 | + } else { |
| 449 | + return '[[' . $comparator . $dataValue->getWikiValue() . ']]'; |
| 450 | + } |
447 | 451 | } |
448 | 452 | } |
449 | 453 | |
Index: trunk/extensions/SemanticMediaWiki/includes/storage/SMW_QueryResult.php |
— | — | @@ -430,20 +430,16 @@ |
431 | 431 | * |
432 | 432 | * The parameter $linker controls linking of title values and should |
433 | 433 | * be some Linker object (or NULL for no linking). |
434 | | - * |
| 434 | + * |
435 | 435 | * @param integer $outputMode |
436 | 436 | * @param mixed $linker |
437 | | - * |
| 437 | + * |
438 | 438 | * @return string or false |
439 | 439 | */ |
440 | 440 | public function getNextText( $outputMode, $linker = null ) { |
441 | 441 | $dataValue = $this->getNextDataValue(); |
442 | 442 | if ( $dataValue !== false ) { // Print data values. |
443 | | - if ( ( $dataValue->getTypeID() == '_wpg' ) || ( $dataValue->getTypeID() == '__sin' ) ) { // Prefer "long" text for page-values. |
444 | | - return $dataValue->getLongText( $outputMode, $linker ); |
445 | | - } else { |
446 | | - return $dataValue->getShortText( $outputMode, $linker ); |
447 | | - } |
| 443 | + return $dataValue->getShortText( $outputMode, $linker ); |
448 | 444 | } else { |
449 | 445 | return false; |
450 | 446 | } |