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 ); |
||
0 ignored issues
–
show
|
|||
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(); |
||
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 ); |
||
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 ) ); |
||
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 | ' ' . $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 |
This method has been deprecated. The supplier of the class has supplied an explanatory message.
The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.