These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace SRF; |
||
4 | |||
5 | use File; |
||
6 | use FormatJson; |
||
7 | use Html; |
||
8 | use Skin; |
||
9 | use SMW\ResultPrinter; |
||
10 | use SMWDataItem; |
||
11 | use SMWDataValue; |
||
12 | use SMWOutputs; |
||
13 | use SMWQueryResult; |
||
14 | use SRFUtils; |
||
15 | use Title; |
||
16 | |||
17 | /** |
||
18 | * HTML5 Audio / Video media query printer |
||
19 | * |
||
20 | * This printer integrates jPlayer which is a HTML5 Audio / Video |
||
21 | * Javascript libray under GPL/MIT license. |
||
22 | * |
||
23 | * @see http://www.semantic-mediawiki.org/wiki/Help:Media_format |
||
24 | * |
||
25 | * @since 1.9 |
||
26 | * |
||
27 | * @file |
||
28 | * @ingroup SRF |
||
29 | * @ingroup QueryPrinter |
||
30 | * |
||
31 | * @licence GNU GPL v2 or later |
||
32 | * @author mwjames |
||
33 | */ |
||
34 | |||
35 | /** |
||
36 | * This printer integrates jPlayer which is a HTML5 Audio / Video |
||
37 | * Javascript libray under GPL/MIT license. |
||
38 | * |
||
39 | * @ingroup SRF |
||
40 | * @ingroup QueryPrinter |
||
41 | */ |
||
42 | class MediaPlayer extends ResultPrinter { |
||
43 | |||
44 | /** |
||
45 | * Specifies valid mime types supported by jPlayer |
||
46 | * |
||
47 | * @var array |
||
48 | */ |
||
49 | protected $validMimeTypes = [ 'mp3', 'mp4', 'webm', 'webma', 'webmv', 'ogg', 'oga', 'ogv', 'm4v', 'm4a' ]; |
||
50 | |||
51 | /** |
||
52 | * @see SMWResultPrinter::getName |
||
53 | * @return string |
||
54 | */ |
||
55 | public function getName() { |
||
56 | return $this->msg( 'srf-printername-media' )->text(); |
||
57 | } |
||
58 | |||
59 | /** |
||
60 | * @see SMWResultPrinter::getResultText |
||
61 | * |
||
62 | * @param SMWQueryResult $result |
||
63 | * @param $outputMode |
||
64 | * |
||
65 | * @return string |
||
66 | */ |
||
67 | protected function getResultText( SMWQueryResult $result, $outputMode ) { |
||
68 | |||
69 | // Data processing |
||
70 | $data = $this->getResultData( $result, $outputMode ); |
||
71 | |||
72 | // Check if the data processing returned any results otherwise just bailout |
||
73 | if ( $data === [] ) { |
||
74 | if ( $this->params['default'] !== '' ) { |
||
75 | return $this->params['default']; |
||
76 | } else { |
||
77 | $result->addErrors( [ $this->msg( 'srf-no-results' )->inContentLanguage()->text() ] ); |
||
78 | return ''; |
||
79 | } |
||
80 | } else { |
||
81 | // Return formatted results |
||
82 | return $this->getFormatOutput( $data ); |
||
83 | } |
||
84 | } |
||
85 | |||
86 | /** |
||
87 | * Returns an array with data |
||
88 | * |
||
89 | * @since 1.9 |
||
90 | * |
||
91 | * @param SMWQueryResult $result |
||
92 | * @param $outputMode |
||
93 | * |
||
94 | * @return array |
||
95 | */ |
||
96 | protected function getResultData( SMWQueryResult $result, $outputMode ) { |
||
97 | |||
98 | $data = []; |
||
99 | |||
100 | /** |
||
101 | * Get all values for all rows that belong to the result set |
||
102 | * |
||
103 | * @var SMWResultArray $rows |
||
104 | */ |
||
105 | while ( $rows = $result->getNext() ) { |
||
106 | $rowData = []; |
||
107 | $mediaType = null; |
||
108 | $mimeType = null; |
||
109 | |||
110 | /** |
||
111 | * @var SMWResultArray $field |
||
112 | * @var SMWDataValue $dataValue |
||
113 | */ |
||
114 | foreach ( $rows as $field ) { |
||
115 | |||
116 | // Label for the current property |
||
117 | $propertyLabel = $field->getPrintRequest()->getLabel(); |
||
118 | |||
119 | // Label for the current subject |
||
120 | $subjectLabel = $field->getResultSubject()->getTitle()->getFullText(); |
||
121 | |||
122 | if ( $propertyLabel === '' || $propertyLabel === '-' ) { |
||
123 | $propertyLabel = 'subject'; |
||
124 | } elseif ( $propertyLabel === 'poster' ) { |
||
125 | // Label "poster" is a special case where we set the media type to video in order |
||
126 | // to use the same resources that can display video and cover art |
||
127 | // $data['mediaTypes'][] = 'video'; |
||
128 | } |
||
129 | |||
130 | // Check if the subject itself is a media source |
||
131 | if ( $field->getResultSubject()->getTitle()->getNamespace() === NS_FILE && $mimeType === null ) { |
||
132 | list( $mediaType, $mimeType, $source ) = $this->getMediaSource( |
||
133 | $field->getResultSubject()->getTitle() |
||
134 | ); |
||
135 | $rowData[$mimeType] = $source; |
||
136 | } |
||
137 | |||
138 | while ( ( $dataValue = $field->getNextDataValue() ) !== false ) { |
||
139 | // Get other data value item details |
||
140 | $value = $this->getDataValueItem( |
||
141 | $propertyLabel, |
||
142 | $dataValue->getDataItem()->getDIType(), |
||
143 | $dataValue, |
||
144 | $mediaType, |
||
145 | $mimeType, |
||
146 | $rowData |
||
147 | ); |
||
148 | $rowData[$propertyLabel] = $value; |
||
149 | } |
||
150 | } |
||
151 | |||
152 | // Only select relevant source data that match the validMimeTypes |
||
153 | if ( $mimeType !== '' && in_array( $mimeType, $this->validMimeTypes ) ) { |
||
154 | $data['mimeTypes'][] = $mimeType; |
||
155 | $data['mediaTypes'][] = $mediaType; |
||
156 | $data[$subjectLabel] = $rowData; |
||
0 ignored issues
–
show
|
|||
157 | } |
||
158 | } |
||
159 | |||
160 | return $data; |
||
161 | } |
||
162 | |||
163 | /** |
||
164 | * Returns media source information |
||
165 | * |
||
166 | * @since 1.9 |
||
167 | * |
||
168 | * @param Title $title |
||
169 | */ |
||
170 | private function getMediaSource( Title $title ) { |
||
171 | |||
172 | // Find the file source |
||
173 | $source = wfFindFile( $title ); |
||
174 | if ( $source ) { |
||
175 | // $source->getExtension() returns ogg even though it is a ogv/oga (same goes for m4p) file |
||
176 | // this doesn't help much therefore we do it ourselves |
||
177 | $extension = $source->getExtension(); |
||
178 | |||
179 | if ( in_array( $extension, [ 'ogg', 'oga', 'ogv' ] ) ) { |
||
180 | $extension = strtolower( substr( $source->getName(), strrpos( $source->getName(), '.' ) + 1 ) ); |
||
181 | |||
182 | // Xiph.Org recommends that .ogg only be used for Ogg Vorbis audio files |
||
183 | $extension = $extension === 'ogg' ? 'oga' : $extension; |
||
184 | |||
185 | $params = [ $extension === 'ogv' ? 'video' : 'audio', $extension, $source->getUrl() ]; |
||
186 | } elseif ( in_array( $extension, [ 'm4v', 'm4a', 'm4p' ] ) ) { |
||
187 | $params = [ $extension === 'm4v' ? 'video' : 'audio', $extension, $source->getUrl() ]; |
||
188 | } else { |
||
189 | list( $major, $minor ) = File::splitMime( $source->getMimeType() ); |
||
190 | $params = [ $major, $extension, $source->getUrl() ]; |
||
191 | } |
||
192 | } else { |
||
193 | $params = []; |
||
194 | } |
||
195 | return $params; |
||
196 | } |
||
197 | |||
198 | /** |
||
199 | * Returns single data value item |
||
200 | * |
||
201 | * @since 1.9 |
||
202 | * |
||
203 | * @param string $label |
||
204 | * @param integer $type |
||
205 | * @param SMWDataValue $dataValue |
||
206 | * @param string $mediaType |
||
207 | * @param string $mimeType |
||
208 | * |
||
209 | * @return mixed |
||
210 | */ |
||
211 | private function getDataValueItem( &$label, $type, SMWDataValue $dataValue, &$mediaType, &$mimeType, &$rowData ) { |
||
212 | |||
213 | if ( $type == SMWDataItem::TYPE_WIKIPAGE && $dataValue->getTitle()->getNamespace() === NS_FILE ) { |
||
0 ignored issues
–
show
It seems like you code against a specific sub-type and not the parent class
SMWDataValue as the method getTitle() does only exist in the following sub-classes of SMWDataValue : SMWWikiPageValue . Maybe you want to instanceof check for one of these explicitly?
Let’s take a look at an example: abstract class User
{
/** @return string */
abstract public function getPassword();
}
class MyUser extends User
{
public function getPassword()
{
// return something
}
public function getDisplayName()
{
// return some name.
}
}
class AuthSystem
{
public function authenticate(User $user)
{
$this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
// do something.
}
}
In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break. Available Fixes
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types
inside the if block in such a case.
Loading history...
|
|||
214 | |||
215 | if ( $label === 'source' && $mimeType === null ) { |
||
216 | |||
217 | // Identify the media source |
||
218 | // and get media information |
||
219 | list( $mediaType, $mimeType, $source ) = $this->getMediaSource( $dataValue->getTitle() ); |
||
0 ignored issues
–
show
It seems like you code against a specific sub-type and not the parent class
SMWDataValue as the method getTitle() does only exist in the following sub-classes of SMWDataValue : SMWWikiPageValue . Maybe you want to instanceof check for one of these explicitly?
Let’s take a look at an example: abstract class User
{
/** @return string */
abstract public function getPassword();
}
class MyUser extends User
{
public function getPassword()
{
// return something
}
public function getDisplayName()
{
// return some name.
}
}
class AuthSystem
{
public function authenticate(User $user)
{
$this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
// do something.
}
}
In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break. Available Fixes
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types
inside the if block in such a case.
Loading history...
|
|||
220 | $label = $mimeType; |
||
221 | return $source; |
||
222 | } elseif ( $label === 'poster' ) { |
||
223 | $mediaType = 'video'; |
||
224 | |||
225 | // Get the cover art image url |
||
226 | $source = wfFindFile( $dataValue->getTitle() ); |
||
0 ignored issues
–
show
It seems like you code against a specific sub-type and not the parent class
SMWDataValue as the method getTitle() does only exist in the following sub-classes of SMWDataValue : SMWWikiPageValue . Maybe you want to instanceof check for one of these explicitly?
Let’s take a look at an example: abstract class User
{
/** @return string */
abstract public function getPassword();
}
class MyUser extends User
{
public function getPassword()
{
// return something
}
public function getDisplayName()
{
// return some name.
}
}
class AuthSystem
{
public function authenticate(User $user)
{
$this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
// do something.
}
}
In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break. Available Fixes
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types
inside the if block in such a case.
Loading history...
|
|||
227 | return $source->getUrl(); |
||
228 | } |
||
229 | } |
||
230 | |||
231 | if ( $type == SMWDataItem::TYPE_URI ) { |
||
232 | |||
233 | $source = $dataValue->getDataItem()->getURI(); |
||
0 ignored issues
–
show
It seems like you code against a specific sub-type and not the parent class
SMWDataItem as the method getURI() does only exist in the following sub-classes of SMWDataItem : SMWDIUri . Maybe you want to instanceof check for one of these explicitly?
Let’s take a look at an example: abstract class User
{
/** @return string */
abstract public function getPassword();
}
class MyUser extends User
{
public function getPassword()
{
// return something
}
public function getDisplayName()
{
// return some name.
}
}
class AuthSystem
{
public function authenticate(User $user)
{
$this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
// do something.
}
}
In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break. Available Fixes
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types
inside the if block in such a case.
Loading history...
|
|||
234 | $mimeType = ''; |
||
235 | |||
236 | // Get file extension from the URI |
||
237 | $extension = strtolower( substr( $source, strrpos( $source, '.' ) + 1 ) ); |
||
238 | |||
239 | // Xiph.Org recommends that .ogg only be used for Ogg Vorbis audio files |
||
240 | if ( in_array( $extension, [ 'ogg', 'oga', 'ogv' ] ) ) { |
||
241 | $mimeType = $extension === 'ogg' ? 'oga' : $extension; |
||
242 | $mediaType = $extension === 'ogv' ? 'video' : 'audio'; |
||
243 | } elseif ( in_array( $extension, [ 'm4v', 'm4a', 'm4p' ] ) ) { |
||
244 | $mimeType = $extension; |
||
245 | $mediaType = $extension === 'm4v' ? 'video' : 'audio'; |
||
246 | } else { |
||
247 | $mimeType = $extension; |
||
248 | $mediaType = strpos( $extension, 'v' ) !== false ? 'video' : 'audio'; |
||
249 | } |
||
250 | |||
251 | if ( $mimeType !== '' ) { |
||
252 | $rowData[$mimeType] = $source; |
||
253 | } |
||
254 | |||
255 | return $source; |
||
256 | } |
||
257 | |||
258 | return $dataValue->getWikiValue(); |
||
259 | } |
||
260 | |||
261 | /** |
||
262 | * Prepare data for the output |
||
263 | * |
||
264 | * @since 1.9 |
||
265 | * |
||
266 | * @param array $data |
||
267 | * |
||
268 | * @return string |
||
269 | */ |
||
270 | protected function getFormatOutput( $data ) { |
||
271 | |||
272 | $ID = 'srf-' . uniqid(); |
||
273 | $this->isHTML = true; |
||
274 | |||
275 | // Get the media/mime types |
||
276 | if ( in_array( 'video', $data['mediaTypes'] ) ) { |
||
277 | $mediaType = 'video'; |
||
278 | } else { |
||
279 | $mediaType = 'audio'; |
||
280 | } |
||
281 | unset( $data['mediaTypes'] ); |
||
282 | |||
283 | $mimeTypes = array_unique( $data['mimeTypes'] ); |
||
284 | unset( $data['mimeTypes'] ); |
||
285 | |||
286 | // Reassign output array |
||
287 | $output = [ |
||
288 | 'data' => $data, |
||
289 | 'count' => count( $data ), |
||
290 | 'mediaType' => $mediaType, |
||
291 | 'mimeTypes' => implode( ',', $mimeTypes ), |
||
292 | 'inspector' => $this->params['inspector'] |
||
293 | ]; |
||
294 | |||
295 | $requireHeadItem = [ $ID => FormatJson::encode( $output ) ]; |
||
296 | SMWOutputs::requireHeadItem( $ID, Skin::makeVariablesScript( $requireHeadItem ) ); |
||
297 | |||
298 | SMWOutputs::requireResource( 'ext.jquery.jplayer.skin.' . $this->params['theme'] ); |
||
299 | SMWOutputs::requireResource( 'ext.srf.formats.media' ); |
||
300 | |||
301 | $processing = SRFUtils::htmlProcessingElement(); |
||
302 | |||
303 | return Html::rawElement( |
||
304 | 'div', |
||
305 | [ |
||
306 | 'class' => $this->params['class'] !== '' ? 'srf-media ' . $this->params['class'] : 'srf-media' |
||
307 | ], |
||
308 | $processing . Html::element( |
||
309 | 'div', |
||
310 | [ |
||
311 | 'id' => $ID, |
||
312 | 'class' => 'media-container', |
||
313 | 'style' => 'display:none;' |
||
314 | ], |
||
315 | null |
||
316 | ) |
||
317 | ); |
||
318 | } |
||
319 | |||
320 | /** |
||
321 | * @see SMWResultPrinter::getParamDefinitions |
||
322 | * |
||
323 | * @since 1.9 |
||
324 | * |
||
325 | * @param $definitions array of IParamDefinition |
||
326 | * |
||
327 | * @return array of IParamDefinition|array |
||
328 | */ |
||
329 | public function getParamDefinitions( array $definitions ) { |
||
330 | $params = parent::getParamDefinitions( $definitions ); |
||
331 | |||
332 | $params['class'] = [ |
||
333 | 'message' => 'srf-paramdesc-class', |
||
334 | 'default' => '', |
||
335 | ]; |
||
336 | |||
337 | $params['theme'] = [ |
||
338 | 'message' => 'srf-paramdesc-theme', |
||
339 | 'default' => 'blue.monday', |
||
340 | 'values' => [ 'blue.monday', 'morning.light' ], |
||
341 | ]; |
||
342 | |||
343 | $params['inspector'] = [ |
||
344 | 'type' => 'boolean', |
||
345 | 'message' => 'srf-paramdesc-mediainspector', |
||
346 | 'default' => false, |
||
347 | ]; |
||
348 | |||
349 | return $params; |
||
350 | } |
||
351 | } |
||
352 |
If you define a variable conditionally, it can happen that it is not defined for all execution paths.
Let’s take a look at an example:
In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.
Available Fixes
Check for existence of the variable explicitly:
Define a default value for the variable:
Add a value for the missing path: