Completed
Push — master ( ea0e5d...10ff2a )
by mw
02:37
created

formats/media/MediaPlayer.php (1 issue)

Labels
Severity

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
namespace SRF;
4
5
use SMW\ResultPrinter;
6
use SMWQueryResult;
7
use SMWDataItem;
8
use SMWDataValue;
9
use SMWOutputs;
10
use SRFUtils;
11
12
use FormatJson;
13
use Skin;
14
use Html;
15
use Title;
16
use File;
17
18
/**
19
 * HTML5 Audio / Video media query printer
20
 *
21
 * This printer integrates jPlayer which is a HTML5 Audio / Video
22
 * Javascript libray under GPL/MIT license.
23
 *
24
 * @see http://www.semantic-mediawiki.org/wiki/Help:Media_format
25
 *
26
 * @since 1.9
27
 *
28
 * @file
29
 * @ingroup SRF
30
 * @ingroup QueryPrinter
31
 *
32
 * @licence GNU GPL v2 or later
33
 * @author mwjames
34
 */
35
36
/**
37
 * This printer integrates jPlayer which is a HTML5 Audio / Video
38
 * Javascript libray under GPL/MIT license.
39
 *
40
 * @ingroup SRF
41
 * @ingroup QueryPrinter
42
 */
43
class MediaPlayer extends ResultPrinter {
44
45
	/**
46
	 * Specifies valid mime types supported by jPlayer
47
	 * @var array
48
	 */
49
	protected $validMimeTypes = array( '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 === array() ) {
74
			if ( $this->params['default'] !== '' ) {
75
				return $this->params['default'];
76
			} else{
77
				$result->addErrors( array( $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 = array();
99
100
		/**
101
		 * Get all values for all rows that belong to the result set
102
		 * @var SMWResultArray $rows
103
		 */
104
		while ( $rows = $result->getNext() ) {
105
			$rowData = array();
106
			$mediaType = null;
107
			$mimeType = null;
108
109
			/**
110
			 * @var SMWResultArray $field
111
			 * @var SMWDataValue $dataValue
112
			 */
113
			foreach ( $rows as $field ) {
114
115
				// Label for the current property
116
				$propertyLabel = $field->getPrintRequest()->getLabel();
117
118
				// Label for the current subject
119
				$subjectLabel = $field->getResultSubject()->getTitle()->getFullText();
120
121
				if ( $propertyLabel === '' || $propertyLabel === '-' ){
122
					$propertyLabel = 'subject';
123
				} elseif ( $propertyLabel === 'poster' ){
124
					// Label "poster" is a special case where we set the media type to video in order
125
					// to use the same resources that can display video and cover art
126
					// $data['mediaTypes'][] = 'video';
127
				}
128
129
				// Check if the subject itself is a media source
130
				if ( $field->getResultSubject()->getTitle()->getNamespace() === NS_FILE && $mimeType === null ){
131
					list( $mediaType, $mimeType, $source ) = $this->getMediaSource( $field->getResultSubject()->getTitle() );
132
					$rowData[$mimeType] = $source;
133
				}
134
135
				while ( ( $dataValue = $field->getNextDataValue() ) !== false ) {
136
					// Get other data value item details
137
					$value = $this->getDataValueItem( $propertyLabel, $dataValue->getDataItem()->getDIType(), $dataValue, $mediaType, $mimeType, $rowData );
138
					$rowData[$propertyLabel] = $value;
139
				}
140
			}
141
142
			// Only select relevant source data that match the validMimeTypes
143
			if ( $mimeType !== '' && in_array( $mimeType, $this->validMimeTypes ) ){
144
				$data['mimeTypes'][]  = $mimeType;
145
				$data['mediaTypes'][] = $mediaType;
146
				$data[$subjectLabel]  = $rowData;
147
			}
148
		}
149
150
		return $data;
151
	}
152
153
	/**
154
	 * Returns media source information
155
	 *
156
	 * @since 1.9
157
	 *
158
	 * @param Title $title
159
	 */
160
	private function getMediaSource( Title $title ){
161
162
		// Find the file source
163
		$source = wfFindFile ( $title );
164
		if ( $source ){
165
			// $source->getExtension() returns ogg even though it is a ogv/oga (same goes for m4p) file
166
			// this doesn't help much therefore we do it ourselves
167
			$extension = $source->getExtension();
168
169
			if ( in_array( $extension, array( 'ogg', 'oga', 'ogv' ) ) ) {
170
				$extension = strtolower( substr( $source->getName(), strrpos( $source->getName(), '.' ) + 1 ) );
171
172
				// Xiph.Org recommends that .ogg only be used for Ogg Vorbis audio files
173
				$extension = $extension === 'ogg' ? 'oga' : $extension;
174
175
				$params = array( $extension === 'ogv' ? 'video' : 'audio', $extension, $source->getUrl() );
176
			} elseif ( in_array( $extension, array( 'm4v', 'm4a', 'm4p' ) ) ) {
177
				$params = array( $extension === 'm4v' ? 'video' : 'audio', $extension, $source->getUrl() );
178
			} else {
179
				list( $major, $minor ) = File::splitMime( $source->getMimeType() );
180
				$params = array( $major, $extension, $source->getUrl() );
181
			}
182
		} else {
183
			$params = array();
184
		}
185
		return $params;
186
	}
187
188
	/**
189
	 * Returns single data value item
190
	 *
191
	 * @since 1.9
192
	 *
193
	 * @param string $label
194
	 * @param integer $type
195
	 * @param SMWDataValue $dataValue
196
	 * @param string $mediaType
197
	 * @param string $mimeType
198
	 *
199
	 * @return mixed
200
	 */
201
	private function getDataValueItem( &$label, $type, SMWDataValue $dataValue, &$mediaType, &$mimeType, &$rowData ) {
202
203
		if ( $type == SMWDataItem::TYPE_WIKIPAGE && $dataValue->getTitle()->getNamespace() === NS_FILE ) {
204
205
			if ( $label === 'source' && $mimeType === null ) {
206
207
				// Identify the media source
208
				// and get media information
209
				list( $mediaType, $mimeType, $source ) = $this->getMediaSource( $dataValue->getTitle() );
210
				$label = $mimeType;
211
				return $source;
212
			} elseif ( $label === 'poster' ) {
213
				$mediaType = 'video';
214
215
				// Get the cover art image url
216
				$source = wfFindFile ( $dataValue->getTitle() );
217
				return $source->getUrl();
218
			}
219
		}
220
221
		if ( $type == SMWDataItem::TYPE_URI ) {
222
223
			$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

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
224
			$mimeType = '';
225
226
			// Get file extension from the URI
227
			$extension = strtolower( substr( $source, strrpos( $source, '.' ) + 1 ) );
228
229
			// Xiph.Org recommends that .ogg only be used for Ogg Vorbis audio files
230
			if ( in_array( $extension, array( 'ogg', 'oga', 'ogv' ) ) ) {
231
				$mimeType = $extension === 'ogg' ? 'oga' : $extension;
232
				$mediaType = $extension === 'ogv' ? 'video' : 'audio';
233
			} elseif ( in_array( $extension, array( 'm4v', 'm4a', 'm4p' ) ) ) {
234
				$mimeType = $extension;
235
				$mediaType = $extension === 'm4v' ? 'video' : 'audio';
236
			} else {
237
				$mimeType = $extension;
238
				$mediaType = strpos( $extension, 'v' ) !== false ? 'video' : 'audio';
239
			}
240
241
			if ( $mimeType !== '' ) {
242
				$rowData[$mimeType] = $source;
243
			}
244
245
			return $source;
246
		}
247
248
		return $dataValue->getWikiValue();
249
	}
250
251
	/**
252
	 * Prepare data for the output
253
	 *
254
	 * @since 1.9
255
	 *
256
	 * @param array $data
257
	 *
258
	 * @return string
259
	 */
260
	protected function getFormatOutput( $data ) {
261
262
		$ID = 'srf-' . uniqid();
263
		$this->isHTML = true;
264
265
		// Get the media/mime types
266
		if ( in_array( 'video', $data['mediaTypes'] ) ){
267
			$mediaType = 'video';
268
		} else {
269
			$mediaType = 'audio';
270
		}
271
		unset( $data['mediaTypes'] );
272
273
		$mimeTypes = array_unique( $data['mimeTypes'] );
274
		unset( $data['mimeTypes'] );
275
276
		// Reassign output array
277
		$output = array(
278
			'data'  => $data,
279
			'count' => count( $data ),
280
			'mediaType' => $mediaType,
281
			'mimeTypes' => implode( ',', $mimeTypes ),
282
			'inspector' => $this->params['inspector']
283
		);
284
285
		$requireHeadItem = array ( $ID => FormatJson::encode( $output ) );
286
		SMWOutputs::requireHeadItem( $ID, Skin::makeVariablesScript( $requireHeadItem ) );
287
288
		SMWOutputs::requireResource( 'ext.jquery.jplayer.skin.' . $this->params['theme'] );
289
		SMWOutputs::requireResource( 'ext.srf.formats.media' );
290
291
		$processing = SRFUtils::htmlProcessingElement();
292
293
		return Html::rawElement(
294
			'div',
295
			array(
296
				'class' => $this->params['class'] !== '' ? 'srf-media ' . $this->params['class'] : 'srf-media'
297
			),
298
			$processing . Html::element(
299
				'div',
300
				array(
301
					'id' => $ID,
302
					'class' => 'media-container',
303
					'style' => 'display:none;'
304
				),
305
				null
306
			)
307
		);
308
	}
309
310
	/**
311
	 * @see SMWResultPrinter::getParamDefinitions
312
	 *
313
	 * @since 1.9
314
	 *
315
	 * @param $definitions array of IParamDefinition
316
	 *
317
	 * @return array of IParamDefinition|array
318
	 */
319
	public function getParamDefinitions( array $definitions ) {
320
		$params = parent::getParamDefinitions( $definitions );
321
322
		$params['class'] = array(
323
			'message' => 'srf-paramdesc-class',
324
			'default' => '',
325
		);
326
327
		$params['theme'] = array(
328
			'message' => 'srf-paramdesc-theme',
329
			'default' => 'blue.monday',
330
			'values' => array( 'blue.monday', 'morning.light' ),
331
		);
332
333
		$params['inspector'] = array(
334
			'type' => 'boolean',
335
			'message' => 'srf-paramdesc-mediainspector',
336
			'default' => false,
337
		);
338
339
		return $params;
340
	}
341
}
342