Completed
Push — master-stable ( 6129d5...f1df5b )
by
unknown
21:50 queued 12:42
created

modules/shortcodes/soundcloud.php (1 issue)

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
Plugin Name: SoundCloud Shortcode
4
Plugin URI: http://wordpress.org/extend/plugins/soundcloud-shortcode/
5
Description: Converts SoundCloud WordPress shortcodes to a SoundCloud widget. Example: [soundcloud]http://soundcloud.com/forss/flickermood[/soundcloud]
6
Version: 2.3
7
Author: SoundCloud Inc., simplified for Jetpack by Automattic, Inc.
8
Author URI: http://soundcloud.com
9
License: GPLv2
10
11
Original version: Johannes Wagener <[email protected]>
12
Options support: Tiffany Conroy <[email protected]>
13
HTML5 & oEmbed support: Tim Bormans <[email protected]>
14
*/
15
16
/*
17
A8C: Taken from http://plugins.svn.wordpress.org/soundcloud-shortcode/trunk/
18
at revision 664386.
19
20
Commenting out (instead of removing) and replacing code with custom modifs
21
so it's eqsy to see what differs from the standard DOTORG version.
22
23
All custom modifs are annoted with "A8C" keyword in comment.
24
*/
25
26
/**
27
 * Register oEmbed provider
28
 */
29
30
wp_oembed_add_provider( '#https?://(?:api\.)?soundcloud\.com/.*#i', 'http://soundcloud.com/oembed', true );
31
32
33
/**
34
 * Register SoundCloud shortcode
35
 */
36
37
add_shortcode( 'soundcloud', 'soundcloud_shortcode' );
38
39
/**
40
 * SoundCloud shortcode handler
41
 *
42
 * @param  string|array $atts        The attributes passed to the shortcode like [soundcloud attr1="value" /].
43
 *                                   Is an empty string when no arguments are given.
44
 * @param  string       $content     The content between non-self closing [soundcloud]...[/soundcloud] tags.
0 ignored issues
show
Should the type for parameter $content not be string|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
45
 *
46
 * @return string                  Widget embed code HTML
47
 */
48
function soundcloud_shortcode( $atts, $content = null ) {
49
50
	// Custom shortcode options
51
	$shortcode_options = array_merge( array( 'url' => trim( $content ) ), is_array( $atts ) ? $atts : array() );
52
53
	// Turn shortcode option "param" (param=value&param2=value) into array
54
	$shortcode_params = array();
55
	if ( isset( $shortcode_options['params'] ) ) {
56
		parse_str( html_entity_decode( $shortcode_options['params'] ), $shortcode_params );
57
	}
58
	$shortcode_options['params'] = $shortcode_params;
59
60
	$player_type = soundcloud_get_option( 'player_type', 'visual' );
61
	$isIframe    = $player_type !== 'flash';
62
	$isVisual    = ! $player_type || $player_type === 'visual' || $shortcode_options['visual'];
63
64
	// User preference options
65
	$plugin_options = array_filter(
66
		array(
67
			'iframe' => $isIframe,
68
			'width'  => soundcloud_get_option( 'player_width' ),
69
			'height' => soundcloud_url_has_tracklist( $shortcode_options['url'] ) ? soundcloud_get_option( 'player_height_multi' ) : soundcloud_get_option( 'player_height' ),
70
			'params' => array_filter(
71
				array(
72
					'auto_play'     => soundcloud_get_option( 'auto_play' ),
73
					'show_comments' => soundcloud_get_option( 'show_comments' ),
74
					'color'         => soundcloud_get_option( 'color' ),
75
					'visual'        => ( $isVisual ? 'true' : 'false' ),
76
				)
77
			),
78
		)
79
	);
80
81
	// Needs to be an array
82
	if ( ! isset( $plugin_options['params'] ) ) {
83
		$plugin_options['params'] = array();
84
	}
85
86
	// plugin options < shortcode options
87
	$options = array_merge(
88
		$plugin_options,
89
		$shortcode_options
90
	);
91
92
	// plugin params < shortcode params
93
	$options['params'] = array_merge(
94
		$plugin_options['params'],
95
		$shortcode_options['params']
96
	);
97
98
	// The "url" option is required
99
	if ( ! isset( $options['url'] ) ) {
100
		return '';
101
	} else {
102
		$options['url'] = trim( $options['url'] );
103
	}
104
105
	// Both "width" and "height" need to be integers
106
	if ( isset( $options['width'] ) && ! preg_match( '/^\d+$/', $options['width'] ) ) {
107
		// set to 0 so oEmbed will use the default 100% and WordPress themes will leave it alone
108
		$options['width'] = 0;
109
	}
110
	if ( isset( $options['height'] ) && ! preg_match( '/^\d+$/', $options['height'] ) ) {
111
		unset( $options['height'] );
112
	}
113
114
	// The "iframe" option must be true to load the iframe widget
115
	$iframe = soundcloud_booleanize( $options['iframe'] );
116
117
	// Remove visual parameter from Flash widget, when it's false because that's the default, or when displaying the smallest player
118
	if ( $options['params']['visual'] && ( ! $iframe || ! soundcloud_booleanize( $options['params']['visual'] ) || ( isset( $options['height'] ) && '20' == $options['height'] ) ) ) {
119
		unset( $options['params']['visual'] );
120
	}
121
122
	// Merge in "url" value
123
	$options['params'] = array_merge(
124
		array(
125
			'url' => $options['url'],
126
		), $options['params']
127
	);
128
129
	// Return html embed code
130
	if ( $iframe ) {
131
		return soundcloud_iframe_widget( $options );
132
	} else {
133
		return soundcloud_flash_widget( $options );
134
	}
135
}
136
137
/**
138
 * Plugin options getter
139
 *
140
 * @param  string|array $option  Option name
141
 * @param  mixed        $default Default value
142
 *
143
 * @return mixed                   Option value
144
 */
145
function soundcloud_get_option( $option, $default = false ) {
146
	$value = get_option( 'soundcloud_' . $option );
147
148
	return $value === '' ? $default : $value;
149
}
150
151
/**
152
 * Booleanize a value
153
 *
154
 * @param  boolean|string $value
155
 *
156
 * @return boolean
157
 */
158
function soundcloud_booleanize( $value ) {
159
	return is_bool( $value ) ? $value : $value === 'true' ? true : false;
160
}
161
162
/**
163
 * Decide if a url has a tracklist
164
 *
165
 * @param  string $url
166
 *
167
 * @return boolean
168
 */
169
function soundcloud_url_has_tracklist( $url ) {
170
	return preg_match( '/^(.+?)\/(sets|groups|playlists)\/(.+?)$/', $url );
171
}
172
173
/**
174
 * Parameterize url
175
 *
176
 * @param  array $match Matched regex
177
 *
178
 * @return string          Parameterized url
179
 */
180
function soundcloud_oembed_params_callback( $match ) {
181
	global $soundcloud_oembed_params;
182
183
	// Convert URL to array
184
	$url = parse_url( urldecode( $match[1] ) );
185
	// Convert URL query to array
186
	parse_str( $url['query'], $query_array );
187
	// Build new query string
188
	$query = http_build_query( array_merge( $query_array, $soundcloud_oembed_params ) );
189
190
	return 'src="' . $url['scheme'] . '://' . $url['host'] . $url['path'] . '?' . $query;
191
}
192
193
/**
194
 * Iframe widget embed code
195
 *
196
 * @param  array $options Parameters
197
 *
198
 * @return string            Iframe embed code
199
 */
200
function soundcloud_iframe_widget( $options ) {
201
202
	// Build URL
203
	$url = set_url_scheme( 'https://w.soundcloud.com/player/?' . http_build_query( $options['params'] ) );
204
	// Set default width if not defined
205
	$width = isset( $options['width'] ) && $options['width'] !== 0 ? $options['width'] : '100%';
206
	// Set default height if not defined
207
	$height = isset( $options['height'] ) && $options['height'] !== 0
208
		? $options['height']
209
		: ( soundcloud_url_has_tracklist( $options['url'] ) || ( isset( $options['params']['visual'] ) && soundcloud_booleanize( $options['params']['visual'] ) ) ? '450' : '166' );
210
211
	return sprintf( '<iframe width="%s" height="%s" scrolling="no" frameborder="no" src="%s"></iframe>', $width, $height, $url );
212
}
213
214
/**
215
 * Legacy Flash widget embed code
216
 *
217
 * @param array $options Parameters
218
 *
219
 * @return string            Flash embed code
220
 */
221
function soundcloud_flash_widget( $options ) {
222
	// Build URL
223
	$url = set_url_scheme( 'https://player.soundcloud.com/player.swf?' . http_build_query( $options['params'] ) );
224
	// Set default width if not defined
225
	$width = isset( $options['width'] ) && $options['width'] !== 0 ? $options['width'] : '100%';
226
	// Set default height if not defined
227
	$height = isset( $options['height'] ) && $options['height'] !== 0 ? $options['height'] : ( soundcloud_url_has_tracklist( $options['url'] ) ? '255' : '81' );
228
229
	return preg_replace(
230
		'/\s\s+/', '', sprintf(
231
			'<object width="%s" height="%s">
232
				<param name="movie" value="%s" />
233
				<param name="allowscriptaccess" value="always" />
234
				<embed width="%s" height="%s" src="%s" allowscriptaccess="always" type="application/x-shockwave-flash"></embed>
235
			</object>', $width, $height, $url, $width, $height, $url
236
		)
237
	);
238
}
239
240
/**
241
 * SoundCloud Embed Reversal
242
 *
243
 * Converts a generic HTML embed code from SoundClound into a
244
 * WordPress.com-compatibly shortcode.
245
 *
246
 * @param string $content HTML content.
247
 *
248
 * @return string Parsed content.
249
 */
250
function jetpack_soundcloud_embed_reversal( $content ) {
251
	if ( false === stripos( $content, 'w.soundcloud.com/player' ) ) {
252
		return $content;
253
	}
254
255
	/* Sample embed code:
256
257
		<iframe width="100%" height="450" scrolling="no" frameborder="no" src="https://w.soundcloud.com/player/?url=https%3A//api.soundcloud.com/tracks/150745932&amp;auto_play=false&amp;hide_related=false&amp;show_comments=true&amp;show_user=true&amp;show_reposts=false&amp;visual=true"></iframe>
258
	*/
259
260
	$regexes = array();
261
262
	$regexes[] = '#<iframe[^>]+?src="((?:https?:)?//w\.soundcloud\.com/player/[^"\']++)"[^>]*+>\s*?</iframe>#i';
263
	$regexes[] = '#&lt;iframe(?:[^&]|&(?!gt;))+?src="((?:https?:)?//w\.soundcloud\.com/player/[^"\']++)"(?:[^&]|&(?!gt;))*+&gt;\s*?&lt;/iframe&gt;#i';
264
265
	foreach ( $regexes as $regex ) {
266
		if ( ! preg_match_all( $regex, $content, $matches, PREG_SET_ORDER ) ) {
267
			continue;
268
		}
269
270
		foreach ( $matches as $match ) {
271
272
			// if pasted from the visual editor - prevent double encoding
273
			$match[1] = str_replace( '&amp;amp;', '&amp;', $match[1] );
274
275
			$args = parse_url( html_entity_decode( $match[1] ), PHP_URL_QUERY );
276
			$args = wp_parse_args( $args );
277
278
			if ( ! preg_match( '#^(?:https?:)?//api\.soundcloud\.com/.+$#i', $args['url'], $url_matches ) ) {
279
				continue;
280
			}
281
282
			if ( ! preg_match( '#height="(\d+)"#i', $match[0], $hmatch ) ) {
283
				$height = '';
284
			} else {
285
				$height = ' height="' . intval( $hmatch[1] ) . '"';
286
			}
287
288
			unset( $args['url'] );
289
			$params = 'params="';
290
			if ( count( $args ) > 0 ) {
291
				foreach ( $args as $key => $value ) {
292
					$params .= esc_html( $key ) . '=' . esc_html( $value ) . '&amp;';
293
				}
294
				$params = substr( $params, 0, -5 );
295
			}
296
			$params .= '"';
297
298
			$shortcode = '[soundcloud url="' . esc_url( $url_matches[0] ) . '" ' . $params . ' width="100%"' . $height . ' iframe="true" /]';
299
300
			$replace_regex = sprintf( '#\s*%s\s*#', preg_quote( $match[0], '#' ) );
301
			$content       = preg_replace( $replace_regex, sprintf( "\n\n%s\n\n", $shortcode ), $content );
302
			/** This action is documented in modules/shortcodes/youtube.php */
303
			do_action( 'jetpack_embed_to_shortcode', 'soundcloud', $url_matches[0] );
304
		}
305
	}
306
307
	return $content;
308
}
309
310
add_filter( 'pre_kses', 'jetpack_soundcloud_embed_reversal' );
311