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 { |
||
0 ignored issues
–
show
|
|||
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; |
||
0 ignored issues
–
show
Compatibility
Best Practice
introduced
by
Use of
global functionality is not recommended; it makes your code harder to test, and less reusable.
Instead of relying on 1. Pass all data via parametersfunction myFunction($a, $b) {
// Do something
}
2. Create a class that maintains your stateclass MyClass {
private $a;
private $b;
public function __construct($a, $b) {
$this->a = $a;
$this->b = $b;
}
public function myFunction() {
// Do something
}
}
Loading history...
|
|||
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
The method
SMW\DataValueFactory::newDataItemValue() has been deprecated with message: since 2.4, use DataValueFactory::newDataValueByItem
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.
Loading history...
|
|||
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() { |
||
0 ignored issues
–
show
getSubpropertyList uses the super-global variable $GLOBALS which is generally not recommended.
Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable: // Bad
class Router
{
public function generate($path)
{
return $_SERVER['HOST'].$path;
}
}
// Better
class Router
{
private $host;
public function __construct($host)
{
$this->host = $host;
}
public function generate($path)
{
return $this->host.$path;
}
}
class Controller
{
public function myAction(Request $request)
{
// Instead of
$page = isset($_GET['page']) ? intval($_GET['page']) : 1;
// Better (assuming you use the Symfony2 request)
$page = $request->query->get('page', 1);
}
}
Loading history...
|
|||
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; |
||
0 ignored issues
–
show
Compatibility
Best Practice
introduced
by
Use of
global functionality is not recommended; it makes your code harder to test, and less reusable.
Instead of relying on 1. Pass all data via parametersfunction myFunction($a, $b) {
// Do something
}
2. Create a class that maintains your stateclass MyClass {
private $a;
private $b;
public function __construct($a, $b) {
$this->a = $a;
$this->b = $b;
}
public function myFunction() {
// Do something
}
}
Loading history...
|
|||
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
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
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
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; |
||
0 ignored issues
–
show
Compatibility
Best Practice
introduced
by
Use of
global functionality is not recommended; it makes your code harder to test, and less reusable.
Instead of relying on 1. Pass all data via parametersfunction myFunction($a, $b) {
// Do something
}
2. Create a class that maintains your stateclass MyClass {
private $a;
private $b;
public function __construct($a, $b) {
$this->a = $a;
$this->b = $b;
}
public function myFunction() {
// Do something
}
}
Loading history...
|
|||
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 |
You can fix this by adding a namespace to your class:
When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.