Completed
Push — add/pathinfo-sitemap ( eb9d33...02fba8 )
by Jeremy
14:23 queued 04:10
created

AudioShortcode::audio_shortcode()   F

Complexity

Conditions 45
Paths > 20000

Size

Total Lines 342
Code Lines 186

Duplication

Lines 20
Ratio 5.85 %

Importance

Changes 0
Metric Value
cc 45
eloc 186
nc 429496.7295
nop 1
dl 20
loc 342
rs 2
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
* Class wrapper for audio shortcode
5
*/
6
class AudioShortcode {
7
8
	static $add_script = false;
0 ignored issues
show
Coding Style introduced by
The visibility should be declared for property $add_script.

The PSR-2 coding standard requires that all properties in a class have their visibility explicitly declared. If you declare a property using

class A {
    var $property;
}

the property is implicitly global.

To learn more about the PSR-2, please see the PHP-FIG site on the PSR-2.

Loading history...
9
10
	/**
11
	 * Add all the actions & resgister the shortcode
12
	 */
13
	function __construct() {
14
		add_shortcode( 'audio', array( $this, 'audio_shortcode' ) );
15
		add_action( 'wp_enqueue_scripts', array( $this, 'check_infinite' ) );
16
		add_action( 'infinite_scroll_render', array( $this, 'audio_shortcode_infinite' ), 11 );
17
	}
18
19
	/**
20
	 * Return the $url of the audio
21
	 */
22
	static function get_audio_id( $atts ) {
23
		if ( isset( $atts[0] ) )
24
			return $atts[0];
25
		else
26
			return 0;
27
	}
28
29
	/**
30
	 * Shortcode for audio
31
	 * [audio http://wpcom.files.wordpress.com/2007/01/mattmullenweg-interview.mp3|width=180|titles=1|artists=2]
32
	 *
33
	 * The important question here is whether the shortcode applies to widget_text:
34
	 * add_filter('widget_text', 'do_shortcode');
35
	 * */
36
	function audio_shortcode( $atts ) {
37
		global $ap_playerID;
38
		global $post;
39
40
		if ( ! is_array( $atts ) ) {
41
			return '<!-- Audio shortcode passed invalid attributes -->';
42
		}
43
44 View Code Duplication
		if ( ! isset( $atts[0] ) ) {
45
			if ( isset( $atts['src'] ) ) {
46
				$atts[0] = $atts['src'];
47
				unset( $atts['src'] );
48
			} else {
49
				return '<!-- Audio shortcode source not set -->';
50
			}
51
		}
52
53
		$post_id = 0;
54
		if ( isset( $post ) ) {
55
		    $post_id = $post->ID;
56
		}
57
58
		// add the special .js
59
		wp_enqueue_script(
60
			'audio-shortcode',
61
			plugins_url( 'js/audio-shortcode.js', __FILE__ ),
62
			array( 'jquery' ),
63
			'1.1',
64
			true);
65
66
		// alert the infinite scroll renderer that it should try to load the script
67
		self::$add_script = true;
68
		$atts[0] = strip_tags( join( ' ', $atts ) );
69
		$src = ltrim( $atts[0], '=' );
70
71
		/**
72
		 * Set the audio player default colors.
73
		 *
74
		 * @module shortcodes
75
		 *
76
		 * @since 1.4.0
77
		 *
78
		 * @param array $ap_options {
79
		 *      The default colors for the audio player in hexidecimal format (e.g. 0x#F8F8F8).
80
		 *
81
		 *      @type string $bg              Background color.
82
		 *      @type string $leftbg          Left background color.
83
		 *      @type string $lefticon        Left icon color.
84
		 *      @type string $rightbg         Right background color.
85
		 *      @type string $rightbghover    Right background hover color.
86
		 *      @type string $righticon       Right icon color.
87
		 *      @type string $righticonhover  Right icon hover color.
88
		 *      @type string $text            Text color.
89
		 *      @type string $slider          Slider color.
90
		 *      @type string $track           Track color.
91
		 *      @type string $border          Border color.
92
		 *      @type string $loader          Loader color.
93
		 */
94
		$ap_options = apply_filters(
95
			'audio_player_default_colors',
96
			array(
97
				"bg"             => "0xF8F8F8",
98
				"leftbg"         => "0xEEEEEE",
99
				"lefticon"       => "0x666666",
100
				"rightbg"        => "0xCCCCCC",
101
				"rightbghover"   => "0x999999",
102
				"righticon"      => "0x666666",
103
				"righticonhover" => "0xFFFFFF",
104
				"text"           => "0x666666",
105
				"slider"         => "0x666666",
106
				"track"          => "0xFFFFFF",
107
				"border"         => "0x666666",
108
				"loader"         => "0x9FFFB8"
109
			) );
110
111
		if ( ! isset( $ap_playerID ) ) {
112
			$ap_playerID = 1;
113
		} else {
114
			$ap_playerID++;
115
		}
116
117
		if ( ! isset( $load_audio_script ) ) {
0 ignored issues
show
Bug introduced by
The variable $load_audio_script seems only to be defined at a later point. As such the call to isset() seems to always evaluate to false.

This check marks calls to isset(...) or empty(...) that are found before the variable itself is defined. These will always have the same result.

This is likely the result of code being shifted around. Consider removing these calls.

Loading history...
118
			$load_audio_script = true;
0 ignored issues
show
Unused Code introduced by
$load_audio_script 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...
119
		}
120
121
		// prep the audio files
122
		$src = trim( $src, ' "' );
123
		$options = array();
124
		$data = preg_split( "/\|/", $src );
125
		$sound_file = $data[0];
126
		$sound_files = explode( ',', $sound_file );
127
128
		if ( is_ssl() ) {
129
			for ( $i = 0; $i < count( $sound_files ); $i++ ) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
130
				$sound_files[ $i ] = preg_replace( '#^http://([^.]+).files.wordpress.com/#', 'https://$1.files.wordpress.com/', $sound_files[ $i ] );
131
			}
132
		}
133
134
		$sound_files = array_map( 'trim', $sound_files );
135
		$sound_files = array_map( array( $this, 'rawurlencode_spaces' ), $sound_files );
136
		$sound_files = array_map( 'esc_url_raw', $sound_files ); // Ensure each is a valid URL
137
		$num_files = count( $sound_files );
138
		$sound_types = array(
0 ignored issues
show
Unused Code introduced by
$sound_types 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...
139
			'mp3'  => 'mpeg',
140
			'wav'  => 'wav',
141
			'ogg'  => 'ogg',
142
			'oga'  => 'ogg',
143
			'm4a'  => 'mp4',
144
			'aac'  => 'mp4',
145
			'webm' => 'webm'
146
		);
147
148
		for ( $i = 1; $i < count( $data ); $i++ ) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function count() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
149
			$pair = explode( "=", $data[$i] );
150
			if ( strtolower( $pair[0] ) != 'autostart' ) {
151
				$options[$pair[0]] = $pair[1];
152
			}
153
		}
154
155
		// Merge runtime options to default colour options
156
		// (runtime options overwrite default options)
157
		foreach ( $ap_options as $key => $default ) {
158
			if ( isset( $options[$key] ) ) {
159
				if ( preg_match( '/^(0x)?[a-f0-9]{6}$/i', $default ) && !preg_match( '/^(0x)?[a-f0-9]{6}$/i', $options[$key] ) ) {
160
					// Default is a hex color, but input is not
161
					$options[$key] = $default;
162
				}
163
			} else {
164
				$options[$key] = $default;
165
			}
166
		}
167
		$options['soundFile'] = join( ',', $sound_files ); // Rebuild the option with our now sanitized data
168
		$flash_vars = array();
169
		foreach ( $options as $key => $value ) {
170
			$flash_vars[] = rawurlencode( $key ) . '=' . rawurlencode( $value );
171
		}
172
		$flash_vars = implode( '&amp;', $flash_vars );
173
		$flash_vars = esc_attr( $flash_vars );
174
175
		// extract some of the options to insert into the markup
176
		if ( isset( $options['bgcolor'] ) && preg_match( '/^(0x)?[a-f0-9]{6}$/i', $options['bgcolor'] ) ) {
177
			$bgcolor = preg_replace( '/^(0x)?/', '#', $options['bgcolor'] );
178
			$bgcolor = esc_attr( $bgcolor );
179
		} else {
180
			$bgcolor = '#FFFFFF';
181
		}
182
183
		if ( isset( $options['width'] ) ) {
184
			$width = intval( $options['width'] );
185
		} else {
186
			$width = 290;
187
		}
188
189
		$loop = '';
190
		$script_loop = 'false';
191
		if ( isset( $options['loop'] ) && 'yes' == $options['loop'] ) {
192
			$script_loop = 'true';
193
			if ( 1 == $num_files ) {
194
				$loop = 'loop';
195
			}
196
		}
197
198
		$volume = 0.6;
199
		if ( isset( $options['initialvolume'] ) &&
200
				0.0 < floatval( $options['initialvolume'] ) &&
201
				100.0 >= floatval( $options['initialvolume'] ) ) {
202
203
			$volume = floatval( $options['initialvolume'] )/100.0;
204
		}
205
206
		$file_artists = array_pad( array(), $num_files, '' );
207 View Code Duplication
		if ( isset( $options['artists'] ) ) {
208
			$artists = preg_split( '/,/', $options['artists'] );
209
			foreach ( $artists as $i => $artist ) {
210
				$file_artists[$i] = esc_html( $artist ) . ' - ';
211
			}
212
		}
213
214
		// generate default titles
215
		$file_titles = array();
216
		for ( $i = 0; $i < $num_files; $i++ ) {
217
			$file_titles[] = 'Track #' . ($i+1);
218
		}
219
220
		// replace with real titles if they exist
221 View Code Duplication
		if ( isset( $options['titles'] ) ) {
222
			$titles = preg_split( '/,/', $options['titles'] );
223
			foreach ( $titles as $i => $title ) {
224
				$file_titles[$i] = esc_html( $title );
225
			}
226
		}
227
228
		// fallback for the fallback, just a download link
229
		$not_supported = '';
230
		foreach ( $sound_files as $sfile ) {
231
			$not_supported .= sprintf(
232
				__( 'Download: <a href="%s">%s</a><br />', 'jetpack' ),
233
				esc_url( $sfile ),
234
				esc_html( basename( $sfile ) ) );
235
		}
236
237
		// HTML5 audio tag
238
		$html5_audio = '';
239
		$all_mp3 = true;
240
		$add_audio = true;
0 ignored issues
show
Unused Code introduced by
$add_audio 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...
241
		$num_good = 0;
242
		$to_remove = array();
243
		foreach ( $sound_files as $i => $sfile ) {
244
			$file_extension = pathinfo( $sfile, PATHINFO_EXTENSION );
245
			if ( ! preg_match( '/^(mp3|wav|ogg|oga|m4a|aac|webm)$/i', $file_extension ) ) {
246
				$html5_audio .= '<!-- Audio shortcode unsupported audio format -->';
247
				if ( 1 == $num_files ) {
248
					$html5_audio .= $not_supported;
249
				}
250
251
				$to_remove[] = $i; // make a note of the bad files
252
				$all_mp3 = false;
253
				continue;
254
			} elseif ( ! preg_match( '/^mp3$/i', $file_extension ) ) {
255
				$all_mp3 = false;
256
			}
257
258
			if ( 0 == $i ) { // only need one player
259
				$html5_audio .= <<<AUDIO
260
				<span id="wp-as-{$post_id}_{$ap_playerID}-container">
261
					<audio id='wp-as-{$post_id}_{$ap_playerID}' controls preload='none' $loop style='background-color:$bgcolor;width:{$width}px;'>
262
						<span id="wp-as-{$post_id}_{$ap_playerID}-nope">$not_supported</span>
263
					</audio>
264
				</span>
265
				<br />
266
AUDIO;
267
			}
268
			$num_good++;
269
		}
270
271
		// player controls, if needed
272
		if ( 1 < $num_files ) {
273
			$html5_audio .= <<<CONTROLS
274
				<span id='wp-as-{$post_id}_{$ap_playerID}-controls' style='display:none;'>
275
					<a id='wp-as-{$post_id}_{$ap_playerID}-prev'
276
						href='javascript:audioshortcode.prev_track( "{$post_id}_{$ap_playerID}" );'
277
						style='font-size:1.5em;'>&laquo;</a>
278
					|
279
					<a id='wp-as-{$post_id}_{$ap_playerID}-next'
280
						href='javascript:audioshortcode.next_track( "{$post_id}_{$ap_playerID}", true, $script_loop );'
281
						style='font-size:1.5em;'>&raquo;</a>
282
				</span>
283
CONTROLS;
284
		}
285
		$html5_audio .= "<span id='wp-as-{$post_id}_{$ap_playerID}-playing'></span>";
286
287
		/**
288
		 * Sets external resource URL.
289
		 *
290
		 * @module shortcodes
291
		 *
292
		 * @since 1.4.0
293
		 *
294
		 * @param string $args URL of external resource.
295
		 *
296
		 */
297
		$swfurl = apply_filters(
298
			'jetpack_static_url',
299
			set_url_scheme( "http://en.wordpress.com/wp-content/plugins/audio-player/player.swf" )
300
		 );
301
302
		// all the fancy javascript is causing Google Reader to break, just include flash in GReader
303
		// override html5 audio code w/ just not supported code
304
		if ( is_feed() ) {
305
			$html5_audio = $not_supported;
306
		}
307
308
		if ( $all_mp3 ) {
309
			// process regular flash player, inserting HTML5 tags into object as fallback
310
			$audio_tags = <<<FLASH
311
				<object id='wp-as-{$post_id}_{$ap_playerID}-flash' type='application/x-shockwave-flash' data='$swfurl' width='$width' height='24'>
312
					<param name='movie' value='$swfurl' />
313
					<param name='FlashVars' value='{$flash_vars}' />
314
					<param name='quality' value='high' />
315
					<param name='menu' value='false' />
316
					<param name='bgcolor' value='$bgcolor' />
317
					<param name='wmode' value='opaque' />
318
					$html5_audio
319
				</object>
320
FLASH;
321
		} else { // just HTML5 for non-mp3 versions
322
			$audio_tags = $html5_audio;
323
		}
324
325
		// strip out all the bad files before it reaches .js
326
		foreach ( $to_remove as $i ) {
327
			array_splice( $sound_files, $i, 1 );
328
			array_splice( $file_artists, $i, 1 );
329
			array_splice( $file_titles, $i, 1 );
330
		}
331
332
		// mashup the artist/titles for the script
333
		$script_titles = array();
334
		for ( $i = 0; $i < $num_files; $i++ ) {
335
			if ( isset( $file_artists[ $i ] ) && isset( $file_titles[ $i ] ) ) {
336
				$script_titles[] = $file_artists[ $i ] . $file_titles[ $i ];
337
			}
338
		}
339
340
		// javacript to control audio
341
		$script_files   = json_encode( $sound_files );
342
		$script_titles  = json_encode( $script_titles );
343
		$script = <<<SCRIPT
344
			<script type='text/javascript'>
345
			//<![CDATA[
346
			(function() {
347
				var prep = function() {
348
					if ( 'undefined' === typeof window.audioshortcode ) { return; }
349
					audioshortcode.prep(
350
						'{$post_id}_{$ap_playerID}',
351
						$script_files,
352
						$script_titles,
353
						$volume,
354
						$script_loop
355
					);
356
				};
357
				if ( 'undefined' === typeof jQuery ) {
358
					if ( document.addEventListener ) {
359
						window.addEventListener( 'load', prep, false );
360
					} else if ( document.attachEvent ) {
361
						window.attachEvent( 'onload', prep );
362
					}
363
				} else {
364
					jQuery(document).on( 'ready as-script-load', prep );
365
				}
366
			})();
367
			//]]>
368
			</script>
369
SCRIPT;
370
371
		// add the special javascript, if needed
372
		if ( 0 < $num_good && ! is_feed() ) {
373
			$audio_tags .= $script;
374
		}
375
376
		return "<span style='text-align:left;display:block;'><p>$audio_tags</p></span>";
377
	}
378
379
	/**
380
	 * If the theme uses infinite scroll, include jquery at the start
381
	 */
382
	function check_infinite() {
383
		if ( current_theme_supports( 'infinite-scroll' ) && class_exists( 'The_Neverending_Home_Page' ) && The_Neverending_Home_Page::archive_supports_infinity() )
384
			wp_enqueue_script( 'jquery' );
385
	}
386
387
388
	/**
389
	 * Dynamically load the .js, if needed
390
	 *
391
	 * This hooks in late (priority 11) to infinite_scroll_render to determine
392
	 * a posteriori if a shortcode has been called.
393
	 */
394
	function audio_shortcode_infinite() {
395
		// only try to load if a shortcode has been called
396
		if( self::$add_script ) {
397
			$script_url = json_encode( esc_url_raw( plugins_url( 'js/audio-shortcode.js', __FILE__ ) ) );
398
399
			// if the script hasn't been loaded, load it
400
			// if the script loads successfully, fire an 'as-script-load' event
401
			echo <<<SCRIPT
402
				<script type='text/javascript'>
403
				//<![CDATA[
404
				if ( typeof window.audioshortcode === 'undefined' ) {
405
					var wp_as_js = document.createElement( 'script' );
406
					wp_as_js.type = 'text/javascript';
407
					wp_as_js.src = $script_url;
408
					wp_as_js.async = true;
409
					wp_as_js.onload = function() {
410
						jQuery( document.body ).trigger( 'as-script-load' );
411
					};
412
					document.getElementsByTagName( 'head' )[0].appendChild( wp_as_js );
413
				} else {
414
					jQuery( document.body ).trigger( 'as-script-load' );
415
				}
416
				//]]>
417
				</script>
418
SCRIPT;
419
		}
420
	}
421
422
	/**
423
	 * Fixes URLs that have been pasted with spaces:
424
	 * [audio http://example.com/Some Cool Music.mp3]
425
	 *
426
	 * @param string $url
427
	 * @return string
428
	 */
429
	function rawurlencode_spaces( $url ) {
430
		return str_replace( ' ', rawurlencode( ' ' ), $url );
431
	}
432
}
433
434
// kick it all off
435
new AudioShortcode();
436