Completed
Push — master ( 2472c5...a814e8 )
by mw
35:03
created

includes/articlepages/SMW_PropertyPage.php (3 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
use SMW\ApplicationFactory;
4
use SMW\DataValueFactory;
5
use SMW\Localizer;
6
use SMW\RequestOptions;
7
use SMW\StringCondition;
8
use SMW\PropertyRegistry;
9
use SMWDataValue as DataValue;
10
use SMW\DataValues\ValueFormatters\DataValueFormatter;
11
use SMW\DIProperty;
12
13
/**
14
 * Implementation of MediaWiki's Article that shows additional information on
15
 * property pages. Very similar to CategoryPage, but with different printout
16
 * that also displays values for each subject with the given property.
17
 *
18
 * @ingroup SMW
19
 *
20
 * @author Markus Krötzsch
21
 */
22
class SMWPropertyPage extends SMWOrderedListPage {
23
24
	/**
25
	 * @see SMWOrderedListPage::initParameters()
26
	 * @note We use a smaller limit here; property pages might become large.
27
	 */
28
	protected function initParameters() {
29
		global $smwgPropertyPagingLimit;
30
		$this->limit = $smwgPropertyPagingLimit;
31
		$this->mProperty = DIProperty::newFromUserLabel( $this->mTitle->getText() );
32
		$this->store = ApplicationFactory::getInstance()->getStore();
33
		$this->propertyValue = DataValueFactory::getInstance()->newDataItemValue( $this->mProperty );
34
		return true;
35
	}
36
37
	/**
38
	 * Returns the HTML which is added to $wgOut after the article text.
39
	 *
40
	 * @return string
41
	 */
42
	protected function getHtml() {
43
44
		if ( !$this->store->getRedirectTarget( $this->mProperty )->equals( $this->mProperty ) ) {
45
			return '';
46
		}
47
48
		$dv = DataValueFactory::getInstance()->newDataValueByItem(
49
			$this->mProperty
50
		);
51
52
		$title = $dv->getFormattedLabel( DataValueFormatter::WIKI_LONG );
53
		$this->getContext()->getOutput()->setPageTitle( $title );
54
55
		$list = $this->getSubpropertyList() . $this->getPropertyValueList();
56
		$result = ( $list !== '' ? Html::element( 'div', array( 'id' => 'smwfootbr' ) ) . $list : '' );
57
58
		return $result;
59
	}
60
61
	/**
62
	 * Returns an introductory text for a predefined property
63
	 *
64
	 * @note In order to enable a more detailed description for a specific
65
	 * predefined property a concatenated message key can be used (e.g
66
	 * 'smw-pa-property-predefined' + <internal property key> => '_asksi' )
67
	 *
68
	 * @since 1.9
69
	 *
70
	 * @return string
71
	 */
72
	protected function getIntroductoryText() {
73
74
		$dv = DataValueFactory::getInstance()->newDataValueByItem(
75
			$this->mProperty
76
		);
77
78
		$propertyName = $dv->getFormattedLabel();
79
		$message = '';
80
81
		if ( $this->mProperty->isUserDefined() ) {
82
			return $message;
83
		}
84
85
		$key = $this->mProperty->getKey();
86
87
		if ( ( $messageKey = PropertyRegistry::getInstance()->findPropertyDescriptionMsgKeyById( $key ) ) !== '' ) {
88
			$messageKeyLong = $messageKey . '-long';
89
		} else {
90
			$messageKey = 'smw-pa-property-predefined' . strtolower( $key );
91
			$messageKeyLong = 'smw-pa-property-predefined-long' . strtolower( $key );
92
		}
93
94
		$message .= wfMessage( $messageKey )->exists() ? wfMessage( $messageKey, $propertyName )->parse() : wfMessage( 'smw-pa-property-predefined-default', $propertyName )->parse();
95
		$message .= wfMessage( $messageKeyLong )->exists() ? ' ' . wfMessage( $messageKeyLong )->parse() : '';
96
		$message .= ' ' . wfMessage( 'smw-pa-property-predefined-common' )->parse();
97
98
		return Html::rawElement( 'div', array( 'class' => 'smw-property-predefined-intro plainlinks' ), $message );
99
	}
100
101
	protected function getTopIndicator() {
102
103
		$propertyName = htmlspecialchars( $this->mTitle->getText() );
104
		$usageCountHtml = '';
105
106
		$requestOptions = new RequestOptions();
107
		$requestOptions->setLimit( 1 );
108
		$requestOptions->addStringCondition( $propertyName, StringCondition::COND_EQ );
109
110
		$cachedLookupList = $this->store->getPropertiesSpecial( $requestOptions );
111
		$usageList = $cachedLookupList->fetchList();
112
113
		if ( $usageList && $usageList !== array() ) {
114
			$usage = end( $usageList );
115
			$usageCount = $usage[1];
116
			$usageCountHtml = Html::rawElement(
117
				'div', array(
118
					'title' => $this->getContext()->getLanguage()->timeanddate( $cachedLookupList->getTimestamp() ),
119
					'class' => 'smw-page-indicator usage-count' . ( $usageCount < 25000 ? ( $usageCount > 5000 ? ' moderate' : '' ) : ' high' ) ),
120
				$usageCount
121
			);
122
		}
123
124
		return Html::rawElement( 'div', array(), Html::rawElement(
125
				'div', array(
126
				'class' => 'smw-page-indicator property-type',
127
				'title' => wfMessage( 'smw-page-indicator-type-info', $this->mProperty->isUserDefined() )->parse()
128
			), ( $this->mProperty->isUserDefined() ? 'U' : 'S' )
129
		) . $usageCountHtml );
130
	}
131
132
	/**
133
	 * Get the HTML for displaying subproperties of this property. This list
134
	 * is usually short and we implement no additional navigation.
135
	 *
136
	 * @return string
137
	 */
138
	protected function getSubpropertyList() {
139
140
		$more = false;
141
		$requestOptions = new RequestOptions();
142
		$requestOptions->sort = true;
143
		$requestOptions->ascending = true;
144
145
		// +1 look-ahead
146
		$requestOptions->setLimit( $GLOBALS['smwgSubPropertyListLimit'] + 1 );
147
		$subproperties = $this->store->getPropertySubjects( new DIProperty( '_SUBP' ), $this->getDataItem(), $requestOptions );
148
149
		// Pop the +1 look-ahead from the list
150
		if ( count( $subproperties ) > $GLOBALS['smwgSubPropertyListLimit'] ) {
151
			array_pop( $subproperties );
152
			$more = true;
153
		}
154
155
		$result = '';
156
		$resultCount = count( $subproperties );
157
158
		if ( $more ) {
159
			$message = Html::rawElement(
160
				'span',
161
				array( 'class' => 'plainlinks' ),
162
				wfMessage( 'smw-subpropertylist-count-with-restricted-note', $resultCount, $GLOBALS['smwgSubPropertyListLimit'] )->parse()
163
			);
164
		} else {
165
			$message = wfMessage( 'smw-subpropertylist-count', $resultCount )->text();
166
		}
167
168
		if ( $resultCount > 0 ) {
169
			$titleText = htmlspecialchars( $this->mTitle->getText() );
170
			$result .= "<div id=\"mw-subcategories\">\n<h2>" . wfMessage( 'smw_subproperty_header', $titleText )->text() . "</h2>\n<p>";
171
172
			if ( !$this->mProperty->isUserDefined() ) {
173
				$result .= wfMessage( 'smw_isspecprop' )->text() . ' ';
174
			}
175
176
			$result .= $message . "</p>"  ."\n";
177
178
			if ( $resultCount < 6 ) {
179
				$result .= SMWPageLister::getShortList( 0, $resultCount, $subproperties, null );
180
			} else {
181
				$result .= SMWPageLister::getColumnList( 0, $resultCount, $subproperties, null );
182
			}
183
184
			$result .= "\n</div>";
185
		}
186
187
		return $result;
188
	}
189
190
	/**
191
	 * Get the HTML for displaying values of this property, based on the
192
	 * current from/until and limit settings.
193
	 *
194
	 * @return string
195
	 */
196
	protected function getPropertyValueList() {
197
		global $smwgPropertyPagingLimit, $wgRequest;
198
199
		 // limit==0: configuration setting to disable this completely
200
		if ( $this->limit < 1 ) {
201
			return '';
202
		}
203
204
		$diWikiPages = array();
0 ignored issues
show
$diWikiPages is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
205
		$options = SMWPageLister::getRequestOptions( $this->limit, $this->from, $this->until );
206
207
		$options->limit = $wgRequest->getVal( 'limit', $smwgPropertyPagingLimit );
208
		$options->offset = $wgRequest->getVal( 'offset', '0' );
209
210
		if ( ( $value = $wgRequest->getVal( 'value', '' ) ) !== '' ) {
211
			$diWikiPages = $this->doQuerySubjectListWithValue( $value, $options );
212
		} else {
213
			$diWikiPages = $this->store->getAllPropertySubjects( $this->mProperty, $options );
214
		}
215
216
		if ( !$options->ascending ) {
217
			$diWikiPages = array_reverse( $diWikiPages );
218
		}
219
220
		$result = '';
221
222
		if ( count( $diWikiPages ) > 0 ) {
223
			$pageLister = new SMWPageLister( $diWikiPages, null, $this->limit, $this->from, $this->until );
224
225
			$this->mTitle->setFragment( '#SMWResults' ); // Make navigation point to the result list.
226
			$navigation = $pageLister->getNavigationLinks( $this->mTitle );
0 ignored issues
show
$navigation is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
227
228
			$dvWikiPage = DataValueFactory::getInstance()->newDataValueByItem(
229
				$this->mProperty
230
			);
231
232
			// Allow the DV formatter to access a specific language code
233
			$dvWikiPage->setOption(
234
				DataValue::OPT_USER_LANGUAGE,
235
				Localizer::getInstance()->getUserLanguage()->getCode()
236
			);
237
238
			$titleText = htmlspecialchars( $dvWikiPage->getWikiValue() );
239
			$resultNumber = min( $this->limit, count( $diWikiPages ) );
0 ignored issues
show
$resultNumber is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
240
241
			$result .= "<a name=\"SMWResults\"></a><div id=\"mw-pages\">\n" .
242
			           '<h2>' . wfMessage( 'smw_attribute_header', $titleText )->text() . "</h2>\n<p>";
243
244
			$result .= $this->getNavigationLinks( 'smw_attributearticlecount', $diWikiPages, $smwgPropertyPagingLimit ) .
245
			           $this->subjectObjectList( $diWikiPages ) . "\n</div>";
246
		}
247
248
		return $result;
249
	}
250
251
	/**
252
	 * Format $diWikiPages chunked by letter in a table that shows subject
253
	 * articles in one column and object articles/values in the other one.
254
	 *
255
	 * @param $diWikiPages array
256
	 * @return string
257
	 */
258
	protected function subjectObjectList( array $diWikiPages ) {
259
		global $wgContLang, $smwgMaxPropertyValues;
260
261
		$ac = count( $diWikiPages );
262
263
		if ( $ac > $this->limit ) {
264
			if ( $this->until !== '' ) {
265
				$start = 1;
266
			} else {
267
				$start = 0;
268
				$ac = $ac - 1;
269
			}
270
		} else {
271
			$start = 0;
272
		}
273
274
		$r = '<table class="property-page-results" style="width: 100%;" cellspacing="0" cellpadding="0">';
275
		$prev_start_char = 'None';
276
277
		for ( $index = $start; $index < $ac; $index++ ) {
278
			$diWikiPage = $diWikiPages[$index];
279
			$dvWikiPage = DataValueFactory::getInstance()->newDataValueByItem( $diWikiPage, null );
280
281
			$sortkey = $this->store->getWikiPageSortKey( $diWikiPage );
282
			$start_char = $wgContLang->convert( $wgContLang->firstChar( $sortkey ) );
283
284
			// Header for index letters
285
			if ( $start_char != $prev_start_char ) {
286
				$r .= '<tr class="header-row" ><th class="smwpropname"><div class="header-title">' . htmlspecialchars( $start_char ) . "</div></th><th></th></tr>\n";
287
				$prev_start_char = $start_char;
288
			}
289
290
			// Property name
291
			$searchlink = SMWInfolink::newBrowsingLink( '+', $dvWikiPage->getWikiValue() );
292
			$r .= '<tr class="value-row" ><td class="smwpropname">' . $dvWikiPage->getShortHTMLText( smwfGetLinker() ) .
293
			      '&#160;' . $searchlink->getHTML( smwfGetLinker() ) . '</td><td class="smwprops">';
294
295
			// Property values
296
			$ropts = new RequestOptions();
297
			$ropts->limit = $smwgMaxPropertyValues + 1;
298
			$values = $this->store->getPropertyValues( $diWikiPage, $this->mProperty, $ropts );
299
			$i = 0;
300
301
			foreach ( $values as $di ) {
302
				if ( $i != 0 ) {
303
					$r .= ', ';
304
				}
305
				$i++;
306
307
				if ( $i < $smwgMaxPropertyValues + 1 ) {
308
					$dv = DataValueFactory::getInstance()->newDataValueByItem( $di, $this->mProperty );
309
310
					$dv->setOutputFormat( 'LOCL' );
311
312
					$r .= $dv->getShortHTMLText( smwfGetLinker() ) . $dv->getInfolinkText( SMW_OUTPUT_HTML, smwfGetLinker() );
313
				} else {
314
					$searchlink = SMWInfolink::newInversePropertySearchLink( '…', $dvWikiPage->getWikiValue(), $this->mTitle->getText() );
315
					$r .= $searchlink->getHTML( smwfGetLinker() );
316
				}
317
			}
318
319
			$r .= "</td></tr>\n";
320
		}
321
322
		$r .= '</table>';
323
324
		return $r;
325
	}
326
327
	private function doQuerySubjectListWithValue( $value, $options ) {
328
329
		$applicationFactory = ApplicationFactory::getInstance();
330
331
		$dataValue = $applicationFactory->getDataValueFactory()->newDataValueByProperty( $this->mProperty );
332
		$dataValue->setOption( DataValue::OPT_QUERY_CONTEXT, true );
333
		$dataValue->setUserValue( $value );
334
		$queryFactory = $applicationFactory->getQueryFactory();
335
336
		$description = $queryFactory->newDescriptionFactory()->newFromDataValue(
337
			$dataValue
338
		);
339
340
		$query = $queryFactory->newQuery( $description );
341
		$query->setLimit( $options->limit );
342
		$query->setOffset( $options->offset );
343
		$query->setSortKeys( array( '' => 'asc' ) );
344
345
		return $this->store->getQueryResult( $query )->getResults();
346
	}
347
348
}
349