PluginProbe ʕ •ᴥ•ʔ
Music Player for WooCommerce / 1.2.5
Music Player for WooCommerce v1.2.5
1.8.3 1.8.2 1.8.1 1.1.10 1.1.11 1.1.2 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 1.1.8 1.1.9 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 1.3.0 1.3.1 1.3.10 1.3.11 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.5.0 1.5.1 1.6.0 1.6.1 1.6.2 1.6.3 1.7.0 1.7.1 1.7.2 1.7.3 1.7.4 1.7.5 1.7.6 1.7.7 1.7.8 1.7.9 1.8.0 trunk 1.0.173 1.0.174 1.0.175 1.0.176 1.0.177 1.0.178 1.0.179 1.0.180 1.0.181 1.0.182 1.0.183 1.0.184 1.0.185 1.0.186 1.0.187 1.0.188 1.0.189 1.0.190 1.0.191 1.0.192 1.0.193 1.0.194 1.0.195 1.0.196 1.0.197 1.1.0 1.1.1
music-player-for-woocommerce / wcmp.php
music-player-for-woocommerce Last commit date
addons 2 years ago css 2 years ago feedback 2 years ago js 2 years ago languages 2 years ago pagebuilders 2 years ago vendors 2 years ago views 2 years ago widgets 2 years ago banner.php 2 years ago readme.txt 2 years ago wcmp.php 2 years ago
wcmp.php
1990 lines
1 <?php
2 /*
3 Plugin Name: Music Player for WooCommerce
4 Plugin URI: https://wcmp.dwbooster.com
5 Version: 1.2.5
6 Text Domain: music-player-for-woocommerce
7 Author: CodePeople
8 Author URI: https://wcmp.dwbooster.com
9 Description: Music Player for WooCommerce includes the MediaElement.js music player in the pages of the products with audio files associated, and in the store's pages, furthermore, the plugin allows selecting between multiple skins.
10 License: GPLv2 or later
11 License URI: http://www.gnu.org/licenses/gpl-2.0.html
12 */
13
14 require_once 'banner.php';
15 $codepeople_promote_banner_plugins['codepeople-music-player-for-woocommerce'] = array(
16 'plugin_name' => 'Music Player for WooCommerce',
17 'plugin_url' => 'https://wordpress.org/support/plugin/music-player-for-woocommerce/reviews/#new-post',
18 );
19
20 // Feedback system
21 require_once 'feedback/cp-feedback.php';
22 new WCMP_FEEDBACK( 'music-player-for-woocommerce', __FILE__, 'https://wcmp.dwbooster.com/contact-us' );
23
24 // CONSTANTS
25
26 define( 'WCMP_WEBSITE_URL', get_home_url( get_current_blog_id(), '', is_ssl() ? 'https' : 'http' ) );
27 define( 'WCMP_PLUGIN_URL', plugins_url( '', __FILE__ ) );
28 define( 'WCMP_DEFAULT_PLAYER_LAYOUT', 'mejs-classic' );
29 define( 'WCMP_DEFAULT_SINGLE_PLAYER', 0 );
30 define( 'WCMP_DEFAULT_PLAYER_VOLUME', 1 );
31 define( 'WCMP_DEFAULT_PLAYER_CONTROLS', 'default' );
32 define( 'WCMP_DEFAULT_PlAYER_TITLE', 1 );
33 define( 'WCMP_REMOTE_TIMEOUT', 120 );
34 define( 'WCMP_VERSION', '1.2.5' );
35
36 // Load widgets
37 require_once 'widgets/playlist_widget.php';
38
39 add_filter( 'option_sbp_settings', array( 'WooCommerceMusicPlayer', 'troubleshoot' ) );
40 if ( ! class_exists( 'WooCommerceMusicPlayer' ) ) {
41 class WooCommerceMusicPlayer {
42
43 // ******************** ATTRIBUTES ************************
44
45 private $_products_attrs = array();
46 private $_global_attrs = array();
47 private $_player_layouts = array( 'mejs-classic', 'mejs-ted', 'mejs-wmp' );
48 private $_player_controls = array( 'button', 'all', 'default' );
49 private $_files_directory_path;
50 private $_files_directory_url;
51 private $_enqueued_resources = false;
52 private $_inserted_player = false;
53 private $_insert_player = true;
54
55 private $_insert_main_player = true;
56 private $_insert_all_players = true;
57
58 private $_force_hook_title = 0;
59
60 private $_current_user_downloads = array();
61
62 private $_preload_times = 0; // Multiple preloads with demo generators can affect the server performance
63
64 private $_hooks = array();
65
66 /**
67 * WCMP constructor
68 *
69 * @access public
70 * @return void
71 */
72 public function __construct() {
73
74 // Initialize $_hooks list
75 $this->_hooks = array(
76 'main_player' => array(),
77 'all_players' => array(
78 // 'woocommerce_before_single_product_summary' => 1,
79 'woocommerce_single_product_summary' => 1,
80 'woocommerce_after_single_product_summary' => 1,
81 'woocommerce_before_add_to_cart_form' => 1,
82 'woocommerce_after_add_to_cart_form' => 1,
83 )
84 );
85
86 $this->_createDir();
87 register_activation_hook( __FILE__, array( &$this, 'activation' ) );
88 register_deactivation_hook( __FILE__, array( &$this, 'deactivation' ) );
89
90 add_action( 'plugins_loaded', array( &$this, 'plugins_loaded' ) );
91 add_action( 'init', array( &$this, 'init' ) );
92 add_action( 'admin_init', array( &$this, 'admin_init' ), 99 );
93
94 // EXPORT / IMPORT PRODUCTS
95
96 add_filter( 'woocommerce_product_export_meta_value', function( $value, $meta, $product, $row ){
97 if (
98 preg_match( '/^' . preg_quote( '_wcmp_' ) . '/i', $meta->key ) &&
99 ! is_scalar( $value )
100 ) {
101 $value = serialize( $value );
102 }
103 return $value;
104 }, 10, 4 );
105
106 add_filter( 'woocommerce_product_importer_pre_expand_data', function( $data ){
107 foreach ( $data as $_key => $_value ) {
108 if (
109 preg_match( '/^' . preg_quote( 'meta:_wcmp_' ) . '/i', $_key ) &&
110 function_exists( 'is_serialized' ) &&
111 is_serialized( $_value )
112 ) {
113 try {
114 $data[ $_key ] = unserialize( $_value );
115 } catch ( Exception $err ) {
116 $data[ $_key ] = $_value;
117 } catch ( Error $err ) {
118 $data[ $_key ] = $_value;
119 }
120 }
121 }
122 return $data;
123 }, 10 );
124
125 /** WooCommerce Product Table by Barn2 Plugins integration **/
126 add_filter( 'wc_product_table_data_name', function( $title, $product ) {
127 return ( false === stripos( $title, '<audio' ) ? $this->include_main_player( $product, false ) : '' ) . $title;
128 }, 10, 2 );
129
130 add_action( 'wc_product_table_before_get_data', function( $table ) {
131 $GLOBALS['_insert_all_players_BK'] = $this->_insert_all_players;
132 $this->_insert_all_players = false;
133 }, 10 );
134
135 add_action( 'wc_product_table_after_get_data', function( $table ) {
136 if ( isset( $GLOBALS['_insert_all_players_BK'] ) ) {
137 $this->_insert_all_players = $GLOBALS['_insert_all_players_BK'];
138 unset( $GLOBALS['_insert_all_players_BK'] );
139 } else {
140 $this->_insert_all_players = true;
141 }
142 }, 10 );
143
144 add_filter( 'pre_do_shortcode_tag', function( $output, $tag, $attr, $m ){
145 if( strtolower( $tag ) == 'product_table' ) {
146 $this->enqueue_resources();
147 }
148 return $output;
149 }, 10, 4 );
150
151 } // End __constructor
152
153 public function activation() {
154 $this->_clearDir( $this->_files_directory_path );
155 $this->_createDir();
156 }
157
158 public function deactivation() {
159 $this->_clearDir( $this->_files_directory_path );
160 }
161
162 public function plugins_loaded() {
163 if ( ! class_exists( 'woocommerce' ) ) {
164 return;
165 }
166 load_plugin_textdomain( 'music-player-for-woocommerce', false, basename( dirname( __FILE__ ) ) . '/languages/' );
167
168 add_filter( 'the_title', array( &$this, 'include_main_player_filter' ), 11, 2 );
169 $this->init_force_in_title();
170 $this->_load_addons();
171
172 // Integration with the content editors
173 require_once dirname( __FILE__ ) . '/pagebuilders/builders.php';
174 WCMP_BUILDERS::run();
175 }
176
177 public function get_product_attr( $product_id, $attr, $default = false ) {
178 if ( ! isset( $this->_products_attrs[ $product_id ] ) ) {
179 $this->_products_attrs[ $product_id ] = array();
180 }
181 if ( ! isset( $this->_products_attrs[ $product_id ][ $attr ] ) ) {
182 if ( metadata_exists( 'post', $product_id, $attr ) ) {
183 $this->_products_attrs[ $product_id ][ $attr ] = get_post_meta( $product_id, $attr, true );
184 } else {
185 $this->_products_attrs[ $product_id ][ $attr ] = $this->get_global_attr( $attr, $default );
186 }
187 }
188 return apply_filters( 'wcmp_product_attr', $this->_products_attrs[ $product_id ][ $attr ], $product_id, $attr );
189
190 } // End get_product_attr
191
192 public function get_global_attr( $attr, $default = false ) {
193 if ( empty( $this->_global_attrs ) ) {
194 $this->_global_attrs = get_option( 'wcmp_global_settings', array() );
195 }
196 if ( ! isset( $this->_global_attrs[ $attr ] ) ) {
197 $this->_global_attrs[ $attr ] = $default;
198 }
199 return apply_filters( 'wcmp_global_attr', $this->_global_attrs[ $attr ], $attr );
200
201 } // End get_global_attr
202
203 // ******************** WordPress ACTIONS **************************
204
205 public function init() {
206 // Check if WooCommerce is installed or not
207 if ( ! class_exists( 'woocommerce' ) ) {
208 add_shortcode(
209 'wcmp-playlist',
210 function( $atts ) {
211 return '';
212 }
213 );
214 return; }
215 $_current_user_id = get_current_user_id();
216 if (
217 $this->get_global_attr( '_wcmp_registered_only', 0 ) &&
218 0 == $_current_user_id
219 ) {
220 $this->_insert_player = false;
221 }
222
223 if ( ! is_admin() ) {
224 add_filter( 'wcmp_preload', array( $this, 'preload' ), 10, 2 );
225
226 // Define the shortcode for the playlist_widget
227 add_shortcode( 'wcmp-playlist', array( &$this, 'replace_playlist_shortcode' ) );
228 $this->_preview();
229 if ( isset( $_REQUEST['wcmp-action'] ) && 'play' == $_REQUEST['wcmp-action'] ) {
230 if ( isset( $_REQUEST['wcmp-product'] ) ) {
231 $product_id = @intval( $_REQUEST['wcmp-product'] );
232 if ( ! empty( $product_id ) ) {
233 $product = wc_get_product( $product_id );
234 if ( false !== $product ){
235 $this->update_playback_counter( $product_id );
236 if ( isset( $_REQUEST['wcmp-file'] ) ) {
237 $files = $this->_get_product_files(
238 array(
239 'product' => $product,
240 'file_id' => sanitize_key( $_REQUEST['wcmp-file'] ),
241 )
242 );
243
244 if ( ! empty( $files ) ) {
245 $file_url = $files[ sanitize_key( $_REQUEST['wcmp-file'] ) ]['file'];
246 $this->_tracking_play_event( $product_id, $file_url );
247 $this->_output_file( array( 'url' => $file_url ) );
248 }
249 }
250 }
251 }
252 }
253 exit;
254 } else {
255 // To allow customize the hooks
256 $include_main_player_hook = preg_replace( '/[\t\s]/', '', $this->get_global_attr( '_wcmp_main_player_hook', '' ) );
257 $include_all_players_hook = preg_replace( '/[\t\s]/', '', $this->get_global_attr( '_wcmp_all_players_hook', '' ) );
258
259 if ( empty( $include_main_player_hook ) ) {
260 $include_main_player_hook = 'woocommerce_shop_loop_item_title';
261 }
262
263 if ( empty( $include_all_players_hook ) ) {
264 foreach ( $this->_hooks['all_players'] as $_hook_name => $_hook_data ) {
265 add_action( $_hook_name, array( $this, 'include_players' ), 10, $_hook_data );
266 }
267 } else {
268 $include_all_players_hook = explode( ',', $include_all_players_hook );
269 foreach ( $include_all_players_hook as $_hook_name ) {
270 if ( ! empty( $_hook_name ) ) {
271 add_action( $_hook_name, array( &$this, 'include_all_players' ), 11 );
272 }
273 }
274 }
275
276 if ( 0 == $this->_force_hook_title ) {
277 $include_main_player_hook = explode( ',', $include_main_player_hook );
278 foreach ( $include_main_player_hook as $_hook_name ) {
279 if ( ! empty( $_hook_name ) ) {
280 add_action( $_hook_name, array( &$this, 'include_main_player' ), 11 );
281 }
282 }
283 }
284
285 // Allows to call the players directly by themes
286 add_action( 'wcmp_main_player', array( &$this, 'include_main_player' ), 11 );
287 add_action( 'wcmp_all_players', array( &$this, 'include_all_players' ), 11 );
288
289 // Integration with woocommerce-product-table by barn2media
290 add_filter( 'wc_product_table_data_name', array( &$this, 'product_table_data_name' ), 11, 2 );
291
292 $players_in_cart = $this->get_global_attr( '_wcmp_players_in_cart', false );
293 if ( $players_in_cart ) {
294 add_action( 'woocommerce_after_cart_item_name', array( &$this, 'player_in_cart' ), 11, 2 );
295 }
296
297 // Add product id to audio tag
298 add_filter( 'wcmp_audio_tag', array( &$this, 'add_data_product' ), 99, 4 );
299
300 // Add class name to the feature image of product
301 add_filter( 'woocommerce_product_get_image', array( &$this, 'add_class_attachment' ), 99, 6 );
302 add_filter( 'woocommerce_single_product_image_thumbnail_html', array( &$this, 'add_class_single_product_image' ), 99, 2 );
303
304 // Include players with the titles
305 if (
306 $this->get_global_attr( '_wcmp_force_main_player_in_title', 1 ) &&
307 ! empty( $_SERVER['REQUEST_URI'] )
308 /*
309 ! empty( $_SERVER['REQUEST_URI'] ) &&
310 stripos( esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ), 'wc/store' ) !== false */
311 ) {
312 add_filter( 'woocommerce_product_title', array( &$this, 'woocommerce_product_title' ), 10, 2 );
313
314 add_filter( 'esc_html', array( &$this, 'esc_html' ), 10, 2 );
315 }
316
317 // For accepting the <source> tags
318 add_filter( 'wp_kses_allowed_html', array( &$this, 'allowed_html_tags' ), 10, 2 );
319 }
320 } else {
321 add_action( 'admin_menu', array( &$this, 'menu_links' ), 10 );
322 }
323
324 } // End init
325
326 public function admin_init() {
327 // Check if WooCommerce is installed or not
328 if ( ! class_exists( 'woocommerce' ) ) {
329 return;
330 }
331
332 $this->clear_expired_transients();
333
334 add_meta_box( 'wcmp_woocommerce_metabox', __( 'Music Player for WooCommerce', 'music-player-for-woocommerce' ), array( &$this, 'woocommerce_player_settings' ), $this->_get_post_types(), 'normal' );
335 add_action( 'save_post', array( &$this, 'save_post' ), 10, 3 );
336 add_action( 'delete_post', array( &$this, 'delete_post' ) );
337 add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), array( &$this, 'help_link' ) );
338
339 // Products list "Playback Counter"
340
341 $manage_product_posts_columns = function( $columns ) {
342 if ( $this->get_global_attr( '_wcmp_playback_counter_column', 1 ) ) {
343 wp_enqueue_style( 'wcmp-Playback-counter', plugin_dir_url( __FILE__ ) . 'css/style.admin.css', array(), '1.0.175' );
344 $columns = array_merge( $columns, [ 'wcmp_playback_counter' => __( 'Playback Counter', 'music-player-for-woocommerce' ) ] );
345 }
346 return $columns;
347 };
348 add_filter( 'manage_product_posts_columns', $manage_product_posts_columns );
349
350 $manage_product_posts_custom_column = function( $column_key, $product_id ) {
351 if (
352 $this->get_global_attr( '_wcmp_playback_counter_column', 1 ) &&
353 'wcmp_playback_counter' == $column_key
354 ) {
355 $counter = get_post_meta( $product_id, '_wcmp_playback_counter', true);
356 echo '<span class="wcmp-playback-counter">' . esc_html( ! empty( $counter ) ? $counter : '' ) . '</span>';
357 }
358 };
359 add_action( 'manage_product_posts_custom_column', $manage_product_posts_custom_column, 10, 2 );
360 } // End admin_init
361
362 public function help_link( $links ) {
363 array_unshift(
364 $links,
365 '<a href="https://wordpress.org/support/plugin/music-player-for-woocommerce/#new-post" target="_blank">' . __( 'Help' ) . '</a>'
366 );
367 return $links;
368 } // End help_link
369
370 public function menu_links() {
371 add_options_page( 'Music Player for WooCommerce', 'Music Player for WooCommerce', 'manage_options', 'music-player-for-woocommerce-settings', array( &$this, 'settings_page' ) );
372 } // End menu_links
373
374 public function settings_page() {
375 if (
376 isset( $_POST['wcmp_nonce'] ) &&
377 wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['wcmp_nonce'] ) ), 'wcmp_updating_plugin_settings' )
378 ) {
379 $_REQUEST = stripslashes_deep( $_REQUEST );
380 // Save the player settings
381 $registered_only = ( isset( $_REQUEST['_wcmp_registered_only'] ) ) ? 1 : 0;
382 $fade_out = ( isset( $_REQUEST['_wcmp_fade_out'] ) ) ? 1 : 0;
383 $purchased_times_text = sanitize_text_field( isset( $_REQUEST['_wcmp_purchased_times_text'] ) ? wp_unslash( $_REQUEST['_wcmp_purchased_times_text'] ) : '' );
384 $troubleshoot_default_extension = ( isset( $_REQUEST['_wcmp_default_extension'] ) ) ? true : false;
385 $force_main_player_in_title = ( isset( $_REQUEST['_wcmp_force_main_player_in_title'] ) ) ? 1 : 0;
386 $ios_controls = ( isset( $_REQUEST['_wcmp_ios_controls'] ) ) ? true : false;
387 $troubleshoot_onload = ( isset( $_REQUEST['_wcmp_onload'] ) ) ? true : false;
388 $include_main_player_hook = ( isset( $_REQUEST['_wcmp_main_player_hook'] ) ) ? sanitize_text_field( wp_unslash( $_REQUEST['_wcmp_main_player_hook'] ) ) : '';
389 $main_player_hook_title = ( isset( $_REQUEST['_wcmp_main_player_hook_title'] ) ) ? 1 : 0;
390 $disable_302 = ( isset( $_REQUEST['_wcmp_disable_302'] ) ) ? 1 : 0;
391 $include_all_players_hook = ( isset( $_REQUEST['_wcmp_all_players_hook'] ) ) ? sanitize_text_field( wp_unslash( $_REQUEST['_wcmp_all_players_hook'] ) ) : '';
392
393 $enable_player = ( isset( $_REQUEST['_wcmp_enable_player'] ) ) ? 1 : 0;
394 $show_in = ( isset( $_REQUEST['_wcmp_show_in'] ) && in_array( $_REQUEST['_wcmp_show_in'], array( 'single', 'multiple' ) ) ) ? sanitize_text_field( wp_unslash( $_REQUEST['_wcmp_show_in'] ) ) : 'all';
395 $players_in_cart = ( isset( $_REQUEST['_wcmp_players_in_cart'] ) ) ? true : false;
396 $player_style = (
397 isset( $_REQUEST['_wcmp_player_layout'] ) &&
398 in_array( $_REQUEST['_wcmp_player_layout'], $this->_player_layouts )
399 ) ? sanitize_text_field( wp_unslash( $_REQUEST['_wcmp_player_layout'] ) ) : WCMP_DEFAULT_PLAYER_LAYOUT;
400 $single_player = ( isset( $_REQUEST['_wcmp_single_player'] ) ) ? 1 : 0;
401 $player_controls = (
402 isset( $_REQUEST['_wcmp_player_controls'] ) &&
403 in_array( $_REQUEST['_wcmp_player_controls'], $this->_player_controls )
404 ) ? sanitize_text_field( wp_unslash( $_REQUEST['_wcmp_player_controls'] ) ) : WCMP_DEFAULT_PLAYER_CONTROLS;
405
406 $on_cover = ( ( 'button' == $player_controls || 'default' == $player_controls ) && isset( $_REQUEST['_wcmp_player_on_cover'] ) ) ? 1 : 0;
407
408 $player_title = ( isset( $_REQUEST['_wcmp_player_title'] ) ) ? 1 : 0;
409 $merge_grouped = ( isset( $_REQUEST['_wcmp_merge_in_grouped'] ) ) ? 1 : 0;
410 $play_all = ( isset( $_REQUEST['_wcmp_play_all'] ) ) ? 1 : 0;
411 $loop = ( isset( $_REQUEST['_wcmp_loop'] ) ) ? 1 : 0;
412 $play_simultaneously = ( isset( $_REQUEST['_wcmp_play_simultaneously'] ) ) ? 1 : 0;
413 $volume = ( isset( $_REQUEST['_wcmp_player_volume'] ) && is_numeric( $_REQUEST['_wcmp_player_volume'] ) ) ? floatval( $_REQUEST['_wcmp_player_volume'] ) : 1;
414 $preload = (
415 isset( $_REQUEST['_wcmp_preload'] ) &&
416 in_array( $_REQUEST['_wcmp_preload'], array( 'none', 'metadata', 'auto' ) )
417 ) ? sanitize_text_field( wp_unslash( $_REQUEST['_wcmp_preload'] ) ) : 'none';
418
419 $apply_to_all_players = ( isset( $_REQUEST['_wcmp_apply_to_all_players'] ) ) ? 1 : 0;
420
421 $global_settings = array(
422 '_wcmp_registered_only' => $registered_only,
423 '_wcmp_fade_out' => $fade_out,
424 '_wcmp_purchased_times_text' => $purchased_times_text,
425 '_wcmp_enable_player' => $enable_player,
426 '_wcmp_show_in' => $show_in,
427 '_wcmp_players_in_cart' => $players_in_cart,
428 '_wcmp_player_layout' => $player_style,
429 '_wcmp_player_volume' => $volume,
430 '_wcmp_single_player' => $single_player,
431 '_wcmp_player_controls' => $player_controls,
432 '_wcmp_player_title' => $player_title,
433 '_wcmp_merge_in_grouped' => $merge_grouped,
434 '_wcmp_play_all' => $play_all,
435 '_wcmp_loop' => $loop,
436 '_wcmp_play_simultaneously' => $play_simultaneously,
437 '_wcmp_preload' => $preload,
438 '_wcmp_on_cover' => $on_cover,
439 '_wcmp_default_extension' => $troubleshoot_default_extension,
440 '_wcmp_force_main_player_in_title' => $force_main_player_in_title,
441 '_wcmp_ios_controls' => $ios_controls,
442 '_wcmp_onload' => $troubleshoot_onload,
443 '_wcmp_main_player_hook' => $include_main_player_hook,
444 '_wcmp_main_player_hook_title' => $main_player_hook_title,
445 '_wcmp_disable_302' => $disable_302,
446 '_wcmp_all_players_hook' => $include_all_players_hook,
447 '_wcmp_playback_counter_column' => ( isset( $_REQUEST['_wcmp_playback_counter_column'] ) ) ? sanitize_text_field( wp_unslash( $_REQUEST['_wcmp_playback_counter_column'] ) ) : 0,
448 '_wcmp_analytics_integration' => ( isset( $_REQUEST['_wcmp_analytics_integration'] ) ) ? sanitize_text_field( wp_unslash( $_REQUEST['_wcmp_analytics_integration'] ) ) : 'ua',
449 '_wcmp_analytics_property' => ( isset( $_REQUEST['_wcmp_analytics_property'] ) ) ? sanitize_text_field( wp_unslash( $_REQUEST['_wcmp_analytics_property'] ) ) : '',
450 '_wcmp_analytics_api_secret' => ( isset( $_REQUEST['_wcmp_analytics_api_secret'] ) ) ? sanitize_text_field( wp_unslash( $_REQUEST['_wcmp_analytics_api_secret'] ) ) : '',
451 '_wcmp_apply_to_all_players' => $apply_to_all_players,
452 );
453
454 if ( $apply_to_all_players ) {
455 $this->_clearDir( $this->_files_directory_path );
456
457 $products_ids = array(
458 'post_type' => $this->_get_post_types(),
459 'numberposts' => -1,
460 'post_status' => array( 'publish', 'pending', 'draft', 'future' ),
461 'fields' => 'ids',
462 'cache_results' => false,
463 );
464
465 $products = get_posts( $products_ids );
466 foreach ( $products as $product_id ) {
467 update_post_meta( $product_id, '_wcmp_enable_player', $enable_player );
468 update_post_meta( $product_id, '_wcmp_show_in', $show_in );
469 update_post_meta( $product_id, '_wcmp_player_layout', $player_style );
470 update_post_meta( $product_id, '_wcmp_single_player', $single_player );
471 update_post_meta( $product_id, '_wcmp_player_controls', $player_controls );
472 update_post_meta( $product_id, '_wcmp_player_volume', $volume );
473 update_post_meta( $product_id, '_wcmp_player_title', $player_title );
474 update_post_meta( $product_id, '_wcmp_merge_in_grouped', $merge_grouped );
475 update_post_meta( $product_id, '_wcmp_play_all', $play_all );
476 update_post_meta( $product_id, '_wcmp_loop', $loop );
477 update_post_meta( $product_id, '_wcmp_preload', $preload );
478 update_post_meta( $product_id, '_wcmp_on_cover', $on_cover );
479 }
480 }
481
482 update_option( 'wcmp_global_settings', $global_settings );
483 $this->_global_attrs = $global_settings;
484 do_action( 'wcmp_save_setting' );
485 } // Save settings
486
487 print '<div class="wrap">'; // Open Wrap
488 include_once dirname( __FILE__ ) . '/views/global_options.php';
489 print '</div>'; // Close Wrap
490 } // End settings_page
491
492 public function save_post( $post_id, $post, $update ) {
493 if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
494 return;
495 }
496 if ( empty( $_POST['wcmp_nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['wcmp_nonce'] ) ), 'wcmp_updating_product' ) ) {
497 return;
498 }
499 $post_types = $this->_get_post_types();
500 if ( ! isset( $post ) || ! in_array( $post->post_type, $post_types ) || ! current_user_can( 'edit_post', $post_id ) ) {
501 return;
502 }
503
504 $this->delete_post( $post_id );
505
506 // Save the player options
507 $enable_player = ( isset( $_REQUEST['_wcmp_enable_player'] ) ) ? 1 : 0;
508 $show_in = ( isset( $_REQUEST['_wcmp_show_in'] ) && in_array( $_REQUEST['_wcmp_show_in'], array( 'single', 'multiple' ) ) ) ? sanitize_text_field( wp_unslash( $_REQUEST['_wcmp_show_in'] ) ) : 'all';
509 $player_style = (
510 isset( $_REQUEST['_wcmp_player_layout'] ) &&
511 in_array( $_REQUEST['_wcmp_player_layout'], $this->_player_layouts )
512 ) ? sanitize_text_field( wp_unslash( $_REQUEST['_wcmp_player_layout'] ) ) : WCMP_DEFAULT_PLAYER_LAYOUT;
513
514 $single_player = ( isset( $_DATA['_wcmp_single_player'] ) ) ? 1 : 0;
515 $player_controls = (
516 isset( $_REQUEST['_wcmp_player_controls'] ) &&
517 in_array( $_REQUEST['_wcmp_player_controls'], $this->_player_controls )
518 ) ? sanitize_text_field( wp_unslash( $_REQUEST['_wcmp_player_controls'] ) ) : WCMP_DEFAULT_PLAYER_CONTROLS;
519
520 $player_title = ( isset( $_REQUEST['_wcmp_player_title'] ) ) ? 1 : 0;
521 $merge_grouped = ( isset( $_REQUEST['_wcmp_merge_in_grouped'] ) ) ? 1 : 0;
522 $play_all = ( isset( $_REQUEST['_wcmp_play_all'] ) ) ? 1 : 0;
523 $loop = ( isset( $_REQUEST['_wcmp_loop'] ) ) ? 1 : 0;
524 $volume = ( isset( $_REQUEST['_wcmp_player_volume'] ) && is_numeric( $_REQUEST['_wcmp_player_volume'] ) ) ? floatval( $_REQUEST['_wcmp_player_volume'] ) : 1;
525 $preload = (
526 isset( $_REQUEST['_wcmp_preload'] ) &&
527 in_array( $_REQUEST['_wcmp_preload'], array( 'none', 'metadata', 'auto' ) )
528 ) ? sanitize_text_field( wp_unslash( $_REQUEST['_wcmp_preload'] ) ) : 'none';
529
530 $on_cover = ( ( 'button' == $player_controls || 'default' == $player_controls ) && isset( $_REQUEST['_wcmp_player_on_cover'] ) ) ? 1 : 0;
531
532 add_post_meta( $post_id, '_wcmp_enable_player', $enable_player, true );
533 add_post_meta( $post_id, '_wcmp_show_in', $show_in, true );
534 add_post_meta( $post_id, '_wcmp_player_layout', $player_style, true );
535 add_post_meta( $post_id, '_wcmp_player_volume', $volume, true );
536 add_post_meta( $post_id, '_wcmp_single_player', $single_player, true );
537 add_post_meta( $post_id, '_wcmp_player_controls', $player_controls, true );
538 add_post_meta( $post_id, '_wcmp_player_title', $player_title, true );
539 add_post_meta( $post_id, '_wcmp_merge_in_grouped', $merge_grouped, true );
540 add_post_meta( $post_id, '_wcmp_preload', $preload, true );
541 add_post_meta( $post_id, '_wcmp_play_all', $play_all, true );
542 add_post_meta( $post_id, '_wcmp_loop', $loop, true );
543 add_post_meta( $post_id, '_wcmp_on_cover', $on_cover, true );
544 } // End save_post
545
546 public function delete_post( $post_id ) {
547 $post = get_post( $post_id );
548 $post_types = $this->_get_post_types();
549 if ( ! isset( $post ) || ! in_array( $post->post_type, $post_types ) || ! current_user_can( 'edit_post', $post_id ) ) {
550 return;
551 }
552
553 // Delete truncated version of the audio file
554 $this->_delete_truncated_files( $post_id );
555
556 delete_post_meta( $post_id, '_wcmp_enable_player' );
557 delete_post_meta( $post_id, '_wcmp_show_in' );
558 delete_post_meta( $post_id, '_wcmp_merge_in_grouped' );
559 delete_post_meta( $post_id, '_wcmp_player_layout' );
560 delete_post_meta( $post_id, '_wcmp_player_volume' );
561 delete_post_meta( $post_id, '_wcmp_single_player' );
562 delete_post_meta( $post_id, '_wcmp_player_controls' );
563 delete_post_meta( $post_id, '_wcmp_player_title' );
564 delete_post_meta( $post_id, '_wcmp_preload' );
565 delete_post_meta( $post_id, '_wcmp_play_all' );
566 delete_post_meta( $post_id, '_wcmp_loop' );
567 delete_post_meta( $post_id, '_wcmp_on_cover' );
568
569 delete_post_meta( $post_id, '_wcmp_playback_counter' );
570 } // End delete_post
571
572 public function esc_html( $safe_text, $text ) {
573 if ( strpos( $safe_text, 'wcmp-player-container' ) !== false ) {
574 return $text;
575 }
576 return $safe_text;
577 } // End esc_html
578
579 public function enqueue_resources() {
580 if ( $this->_enqueued_resources ) {
581 return;
582 }
583 $this->_enqueued_resources = true;
584
585 if ( function_exists( 'wp_add_inline_script' ) ) {
586 wp_add_inline_script( 'wp-mediaelement', 'try{if(mejs && mejs.i18n && "undefined" == typeof mejs.i18n.locale) mejs.i18n.locale={};}catch(mejs_err){if(console) console.log(mejs_err);};' );
587 }
588
589 // Registering resources
590 wp_enqueue_style( 'wp-mediaelement' );
591 wp_enqueue_style( 'wp-mediaelement-skins', plugin_dir_url( __FILE__ ) . 'vendors/mejs-skins/mejs-skins.min.css', array(), WCMP_VERSION );
592 wp_enqueue_style( 'wcmp-style', plugin_dir_url( __FILE__ ) . 'css/style.css', array(), WCMP_VERSION );
593 wp_enqueue_script( 'jquery' );
594 wp_enqueue_script( 'wp-mediaelement' );
595 wp_enqueue_script( 'wcmp-script', plugin_dir_url( __FILE__ ) . 'js/public.js', array( 'jquery', 'wp-mediaelement' ), WCMP_VERSION );
596
597 $play_all = $GLOBALS['WooCommerceMusicPlayer']->get_global_attr(
598 '_wcmp_play_all',
599 // This option is only for compatibility with versions previous to 1.0.28
600 $GLOBALS['WooCommerceMusicPlayer']->get_global_attr( 'play_all', 0 )
601 );
602
603 $play_simultaneously = $GLOBALS['WooCommerceMusicPlayer']->get_global_attr( '_wcmp_play_simultaneously', 0 );
604
605 if ( function_exists( 'is_product' ) && is_product() ) {
606 global $post;
607 $post_types = $this->_get_post_types();
608 if ( ! empty( $post ) && in_array( $post->post_type, $post_types ) ) {
609 $play_all = $GLOBALS['WooCommerceMusicPlayer']->get_product_attr(
610 $post->ID,
611 '_wcmp_play_all',
612 // This option is only for compatibility with versions previous to 1.0.28
613 $GLOBALS['WooCommerceMusicPlayer']->get_product_attr(
614 $post->ID,
615 'play_all',
616 $play_all
617 )
618 );
619 }
620 }
621
622 wp_localize_script(
623 'wcmp-script',
624 'wcmp_global_settings',
625 array(
626 'fade_out' => $GLOBALS['WooCommerceMusicPlayer']->get_global_attr( '_wcmp_fade_out', 1 ),
627 'play_all' => intval( $play_all ),
628 'play_simultaneously' => intval( $play_simultaneously ),
629 'ios_controls' => $GLOBALS['WooCommerceMusicPlayer']->get_global_attr( '_wcmp_ios_controls', false ),
630 'onload' => $GLOBALS['WooCommerceMusicPlayer']->get_global_attr( '_wcmp_onload', false ),
631 )
632 );
633 } // End enqueue_resources
634
635 /**
636 * Replace the shortcode to display a playlist with all songs.
637 */
638 public function replace_playlist_shortcode( $atts ) {
639 if ( ! class_exists( 'woocommerce' ) ) {
640 return '';
641 }
642
643 $get_times = function( $product_id, $products_list ) {
644 if ( ! empty( $products_list ) ) {
645 foreach ( $products_list as $product ) {
646 if ( $product->product_id == $product_id ) {
647 return $product->times;
648 }
649 }
650 }
651 return 0;
652 };
653
654 global $post;
655
656 $output = '';
657 if ( ! $this->_insert_player ) {
658 return $output;
659 }
660
661 if ( ! is_array( $atts ) ) {
662 $atts = array();
663 }
664 $post_types = $this->_get_post_types();
665 if (
666 empty( $atts['products_ids'] ) &&
667 empty( $atts['purchased_products'] ) &&
668 ! empty( $post ) &&
669 in_array( $post->post_type, $post_types )
670 ) {
671 try {
672 ob_start();
673 $this->include_all_players( $post->ID );
674 $output = ob_get_contents();
675 ob_end_clean();
676
677 $class = esc_attr( isset( $atts['class'] ) ? $atts['class'] : '' );
678
679 return strpos( $output, 'wcmp-player-list' ) !== false ?
680 str_replace( 'wcmp-player-list', $class . ' wcmp-player-list', $output ) :
681 str_replace( 'wcmp-player-container', $class . ' wcmp-player-container', $output );
682 } catch ( Exception $err ) {
683 $atts['products_ids'] = $post->ID;
684 }
685 }
686
687 $atts = shortcode_atts(
688 array(
689 'products_ids' => '*',
690 'purchased_products' => 0,
691 'highlight_current_product' => 0,
692 'continue_playing' => 0,
693 'player_style' => WCMP_DEFAULT_PLAYER_LAYOUT,
694 'controls' => 'track',
695 'layout' => 'new',
696 'cover' => 0,
697 'volume' => 1,
698 'hide_purchase_buttons' => 0,
699 'class' => '',
700 'loop' => 0,
701 'purchased_times' => 0,
702 'download_links' => 0,
703 ),
704 $atts
705 );
706
707 $products_ids = $atts['products_ids'];
708 $purchased_products = $atts['purchased_products'];
709 $highlight_current_product = $atts['highlight_current_product'];
710 $continue_playing = $atts['continue_playing'];
711 $player_style = $atts['player_style'];
712 $controls = $atts['controls'];
713 $layout = $atts['layout'];
714 $cover = $atts['cover'];
715 $volume = $atts['volume'];
716 $hide_purchase_buttons = $atts['hide_purchase_buttons'];
717 $class = $atts['class'];
718 $loop = $atts['loop'];
719 $purchased_times = $atts['purchased_times'];
720 $download_links_flag = $atts['download_links'];
721
722 // Typecasting variables.
723 $cover = is_numeric( $cover ) ? intval( $cover ) : 0;
724 $volume = is_numeric( $volume ) ? floatval( $volume ) : 0;
725 $purchased_products = is_numeric( $purchased_products ) ? intval( $purchased_products ) : 0;
726 $highlight_current_product = is_numeric( $highlight_current_product ) ? intval( $highlight_current_product ) : 0;
727 $continue_playing = is_numeric( $continue_playing ) ? intval( $continue_playing ) : 0;
728 $hide_purchase_buttons = is_numeric( $hide_purchase_buttons ) ? intval( $hide_purchase_buttons ) : 0;
729 $loop = is_numeric( $loop ) ? intval( $loop ) : 0;
730 $purchased_times = is_numeric( $purchased_times ) ? intval( $purchased_times ) : 0;
731
732 // get the produts ids
733 $products_ids = preg_replace( '/[^\d\,\*]/', '', $products_ids );
734 $products_ids = preg_replace( '/(\,\,)+/', '', $products_ids );
735 $products_ids = trim( $products_ids, ',' );
736
737 if ( strlen( $products_ids ) == 0 ) {
738 return $output;
739 }
740
741 // MAIN CODE GOES HERE
742 global $wpdb, $post;
743
744 $current_post_id = ! empty( $post ) ? ( is_int( $post ) ? $post : $post->ID ) : -1;
745
746 $query = 'SELECT posts.ID, posts.post_title FROM ' . $wpdb->posts . ' AS posts, ' . $wpdb->postmeta . ' as postmeta WHERE posts.post_status="publish" AND posts.post_type IN (' . $this->_get_post_types( true ) . ') AND posts.ID = postmeta.post_id AND postmeta.meta_key="_wcmp_enable_player" AND (postmeta.meta_value="yes" OR postmeta.meta_value="1")';
747
748 if ( ! empty( $purchased_products ) ) {
749 // Hide the purchase buttons
750 $hide_purchase_buttons = 1;
751
752 // Getting the list of purchased products
753 $_current_user_id = get_current_user_id();
754 if ( 0 == $_current_user_id ) {
755 return $output;
756 }
757
758 // GET USER ORDERS (COMPLETED + PROCESSING)
759 $customer_orders = get_posts(
760 array(
761 'numberposts' => -1,
762 'meta_key' => '_customer_user',
763 'meta_value' => $_current_user_id,
764 'post_type' => wc_get_order_types(),
765 'post_status' => array_keys( wc_get_is_paid_statuses() ),
766 )
767 );
768
769 if ( empty( $customer_orders ) ) {
770 return $output;
771 }
772
773 // LOOP THROUGH ORDERS AND GET PRODUCT IDS
774 $products_ids = array();
775
776 foreach ( $customer_orders as $customer_order ) {
777 $order = wc_get_order( $customer_order->ID );
778 $items = $order->get_items();
779 foreach ( $items as $item ) {
780 $product_id = $item->get_product_id();
781 $products_ids[] = $product_id;
782 }
783 }
784 $products_ids = array_unique( $products_ids );
785 $products_ids_str = implode( ',', $products_ids );
786
787 $query .= ' AND posts.ID IN (' . $products_ids_str . ')';
788 $query .= ' ORDER BY FIELD(posts.ID,' . $products_ids_str . ')';
789 } else {
790 if ( strpos( '*', $products_ids ) === false ) {
791 $query .= ' AND posts.ID IN (' . $products_ids . ')';
792 $query .= ' ORDER BY FIELD(posts.ID,' . $products_ids . ')';
793 } else {
794 $query .= ' ORDER BY posts.post_title ASC';
795 }
796 }
797
798 $products = $wpdb->get_results( $query ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
799
800 if ( ! empty( $products ) ) {
801 $product_purchased_times = array();
802 if ( $purchased_times ) {
803 $products_ids_str = ( is_array( $products_ids ) ) ? implode( ',', $products_ids ) : $products_ids;
804
805 $product_purchased_times = $wpdb->get_results( 'SELECT order_itemmeta.meta_value product_id, COUNT(order_itemmeta.meta_value) as times FROM ' . $wpdb->prefix . 'posts as orders INNER JOIN ' . $wpdb->prefix . 'woocommerce_order_items as order_items ON (orders.ID=order_items.order_id) INNER JOIN ' . $wpdb->prefix . 'woocommerce_order_itemmeta as order_itemmeta ON (order_items.order_item_id=order_itemmeta.order_item_id) WHERE orders.post_type="shop_order" AND orders.post_status="wc-completed" AND order_itemmeta.meta_key="_product_id" ' . ( strlen( $products_ids_str ) && false === strpos( '*', $products_ids_str ) ? ' AND order_itemmeta.meta_value IN (' . $products_ids_str . ')' : '' ) . ' GROUP BY order_itemmeta.meta_value' ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
806 }
807
808 // Enqueue resources
809
810 $this->enqueue_resources();
811 wp_enqueue_style( 'wcmp-playlist-widget-style', plugin_dir_url( __FILE__ ) . 'widgets/playlist_widget/css/style.css', array(), WCMP_VERSION );
812 wp_enqueue_script( 'wcmp-playlist-widget-script', plugin_dir_url( __FILE__ ) . 'widgets/playlist_widget/js/public.js', array(), WCMP_VERSION );
813 wp_localize_script(
814 'wcmp-playlist-widget-script',
815 'wcmp_widget_settings',
816 array( 'continue_playing' => $continue_playing )
817 );
818 $counter = 0;
819 $output .= '<div data-loop="' . ( $loop ? 1 : 0 ) . '">';
820 foreach ( $products as $product ) {
821 $product_obj = wc_get_product( $product->ID );
822
823 $counter++;
824 $preload = $this->get_product_attr( $product->ID, '_wcmp_preload', '' );
825 $row_class = 'wcmp-even-product';
826 if ( 1 == $counter % 2 ) {
827 $row_class = 'wcmp-odd-product';
828 }
829
830 $audio_files = $this->get_product_files( $product->ID );
831 if ( ! is_array( $audio_files ) ) {
832 continue;
833 }
834
835 if ( $cover ) {
836 $featured_image = get_the_post_thumbnail_url( $product->ID );
837 }
838
839 // Download files links
840 $download_links = '';
841
842 if ( $download_links_flag ) {
843 $download_links = $this->woocommerce_user_download( $product->ID );
844 if ( ! empty( $download_links ) ) {
845 $download_links = '<span class="wcmp-download-links">(' . $download_links . ')</span>';
846 }
847 }
848
849 if ( 'new' == $layout ) {
850 $price = $product_obj->get_price();
851 $output .= '
852 <div class="wcmp-new-layout wcmp-widget-product controls-' . esc_attr( $controls ) . ' ' . esc_attr( $class ) . ' ' . esc_attr( $row_class ) . ' ' . esc_attr( ( $product->ID == $current_post_id && $highlight_current_product ) ? 'wcmp-current-product' : '' ) . '">
853 <div class="wcmp-widget-product-header">
854 <div class="wcmp-widget-product-title">
855 <a href="' . esc_url( get_permalink( $product->ID ) ) . '">' . $product_obj->get_name() . '</a>' .
856 (
857 $purchased_times ?
858 '<span class="wcmp-purchased-times">' .
859 sprintf(
860 /* translators: %d: purchased times */
861 __( $this->get_global_attr( '_wcmp_purchased_times_text', '- purchased %d time(s)' ), 'music-player-for-woocommerce' ), // phpcs:ignore WordPress.WP.I18n.NonSingularStringLiteralText
862 $get_times( $product->ID, $product_purchased_times )
863 ) . '</span>' : ''
864 ) .
865 $download_links .
866 '</div><!-- product title -->
867 ';
868
869 if ( 0 != @floatval( $price ) && 0 == $hide_purchase_buttons ) {
870 $product_id_for_add_to_cart = $product->ID;
871 if( $product_obj->is_type( 'variable' ) ){
872 $variations = $product_obj->get_available_variations();
873 $variations_id = wp_list_pluck( $variations, 'variation_id' );
874 if( ! empty( $variations_id ) ) $product_id_for_add_to_cart = $variations_id[0];
875 } elseif ( $product_obj->is_type( 'grouped' ) ) {
876 $children = $product_obj->get_children();
877 if( ! empty( $children ) ) $product_id_for_add_to_cart = $children[0];
878 }
879
880 $output .= '<div class="wcmp-widget-product-purchase">
881 ' . wc_price( $product_obj->get_price(), '' ) . ' <a href="?add-to-cart=' . $product_id_for_add_to_cart . '"></a>
882 </div><!-- product purchase -->
883 ';
884 }
885 $output .= '</div>
886 <div class="wcmp-widget-product-files">
887 ';
888
889 if ( ! empty( $featured_image ) ) {
890 $output .= '<img src="' . esc_attr( $featured_image ) . '" class="wcmp-widget-feature-image" /><div class="wcmp-widget-product-files-list">';
891 }
892
893 foreach ( $audio_files as $index => $file ) {
894 $audio_url = $this->generate_audio_url( $product->ID, $index, $file );
895 $duration = $this->_get_duration_by_url( $file['file'] );
896 $audio_tag = apply_filters(
897 'wcmp_widget_audio_tag',
898 $this->get_player(
899 $audio_url,
900 array(
901 'player_controls' => $controls,
902 'player_style' => $player_style,
903 'media_type' => $file['media_type'],
904 'id' => $index,
905 'duration' => $duration,
906 'preload' => $preload,
907 'volume' => $volume,
908 )
909 ),
910 $product->ID,
911 $index,
912 $audio_url
913 );
914 $file_title = esc_html( apply_filters( 'wcmp_widget_file_name', $file['name'], $product->ID, $index ) );
915 $output .= '
916 <div class="wcmp-widget-product-file">
917 ' . $audio_tag . '' . $file_title . '<div style="clear:both;"></div>
918 </div><!--product file -->
919 ';
920 }
921
922 if ( ! empty( $featured_image ) ) {
923 $output .= '</div>';
924 }
925
926 $output .= '
927 </div><!-- product-files -->
928 </div><!-- product -->
929 ';
930 } else // Load the previous playlist layout
931 {
932 $output .= '<ul class="wcmp-widget-playlist wcmp-classic-layout controls-' . esc_attr( $controls ) . ' ' . esc_attr( $class ) . ' ' . esc_attr( $row_class ) . ' ' . esc_attr( ( $product->ID == $current_post_id && $highlight_current_product ) ? 'wcmp-current-product' : '' ) . '">';
933
934 if ( ! empty( $featured_image ) ) {
935 $output .= '<li style="display:table-row;"><img src="' . esc_attr( $featured_image ) . '" class="wcmp-widget-feature-image" /><div class="wcmp-widget-product-files-list"><ul>';
936 }
937
938 foreach ( $audio_files as $index => $file ) {
939 $audio_url = $this->generate_audio_url( $product->ID, $index, $file );
940 $duration = $this->_get_duration_by_url( $file['file'] );
941 $audio_tag = apply_filters(
942 'wcmp_widget_audio_tag',
943 $this->get_player(
944 $audio_url,
945 array(
946 'player_controls' => $controls,
947 'player_style' => $player_style,
948 'media_type' => $file['media_type'],
949 'id' => $index,
950 'duration' => $duration,
951 'preload' => $preload,
952 'volume' => $volume,
953 )
954 ),
955 $product->ID,
956 $index,
957 $audio_url
958 );
959 $file_title = esc_html( apply_filters( 'wcmp_widget_file_name', ( ( ! empty( $file['name'] ) ) ? $file['name'] : $product->post_title ), $product->ID, $index ) );
960
961 $output .= '<li class="wcmp-widget-playlist-item">' . $audio_tag . '<a href="' . esc_url( get_permalink( $product->ID ) ) . '">' . $file_title . '</a>' .
962 (
963 $purchased_times ?
964 '<span class="wcmp-purchased-times">' .
965 sprintf(
966 /* translators: %d: purchased times */
967 __( $this->get_global_attr( '_wcmp_purchased_times_text', '- purchased %d time(s)' ), 'music-player-for-woocommerce' ), // phpcs:ignore WordPress.WP.I18n.NonSingularStringLiteralText
968 $get_times( $product->ID, $product_purchased_times )
969 ) . '</span>' : ''
970 )
971 . '<div style="clear:both;"/></li>';
972 }
973 if ( ! empty( $featured_image ) ) {
974 $output .= '</ul></div></li>';
975 }
976
977 $output .= $download_links; // Download links
978
979 $output .= '</ul>';
980 }
981 }
982 $output .= '</div>';
983 }
984 return $output;
985 } // End replace_playlist_shortcode
986
987 /**
988 * Used for accepting the <source> tags
989 */
990 public function allowed_html_tags( $allowedposttags, $context ) {
991 if ( ! in_array( 'source', $allowedposttags ) ) {
992 $allowedposttags['source'] = array(
993 'src' => true,
994 'type' => true,
995 );
996 }
997 return $allowedposttags;
998 } // End allowed_html_tags
999
1000 public function preload( $preload, $audio_url ) {
1001 $result = $preload;
1002 if ( strpos( $audio_url, 'wcmp-action=play' ) !== false ) {
1003 if ( $this->_preload_times ) {
1004 $result = 'none';
1005 }
1006 $this->_preload_times++;
1007 }
1008 return $result;
1009 } // End preload
1010
1011 // ******************** WOOCOMMERCE ACTIONS ************************
1012
1013 public function woocommerce_user_download( $product_id ) {
1014 $download_links = '';
1015 if ( is_user_logged_in() ) {
1016 if ( empty( $this->_current_user_downloads ) && function_exists( 'wc_get_customer_available_downloads' ) ) {
1017 $current_user = wp_get_current_user();
1018 $this->_current_user_downloads = wc_get_customer_available_downloads( $current_user->ID );
1019 }
1020 $separator = '';
1021 foreach ( $this->_current_user_downloads as $download ) {
1022 if ( $download['product_id'] == $product_id ) {
1023 $download_links .= $separator . '<a href="' . $download['download_url'] . '" target="_blank" class="wcmp-download-link">' . esc_html__( 'download', 'music-player-for-woocommerce' ) . '</a>';
1024 $separator = ', ';
1025 }
1026 }
1027 }
1028
1029 return $download_links;
1030
1031 }
1032
1033 public function woocommerce_product_title( $title, $product ) {
1034 global $wp;
1035 if ( ! empty( $wp->query_vars['wcfm-products-manage'] )) {
1036 return $title;
1037 }
1038 $player = '';
1039 if ( false === stripos( $title, '<audio' ) ) {
1040 $player .= $this->include_main_player( $product, false );
1041 }
1042 return $player . $title;
1043 } // End woocommerce_product_title
1044
1045 /**
1046 * Load the additional attributes to select the player layout
1047 */
1048 public function woocommerce_player_settings() {
1049 include_once 'views/player_options.php';
1050 } // End woocommerce_player_settings
1051
1052 public function get_player(
1053 $audio_url,
1054 $args = array()
1055 ) {
1056 $default_args = array(
1057 'media_type' => 'mp3',
1058 'player_style' => WCMP_DEFAULT_PLAYER_LAYOUT,
1059 'player_controls' => WCMP_DEFAULT_PLAYER_CONTROLS,
1060 'duration' => false,
1061 'volume' => 1,
1062 );
1063
1064 $args = array_merge( $default_args, $args );
1065 $id = ( ! empty( $args['id'] ) ) ? 'id="' . esc_attr( $args['id'] ) . '"' : '';
1066
1067 $preload = ( ! empty( $args['preload'] ) ) ? $args['preload'] : $GLOBALS['WooCommerceMusicPlayer']->get_global_attr(
1068 '_wcmp_preload',
1069 // This option is only for compatibility with versions previous to 1.0.28
1070 $GLOBALS['WooCommerceMusicPlayer']->get_global_attr( 'preload', 'none' )
1071 );
1072 $preload = apply_filters( 'wcmp_preload', $preload, $audio_url );
1073
1074 return '<audio ' . (
1075 (
1076 isset( $args['volume'] ) &&
1077 is_numeric( $args['volume'] ) &&
1078 0 <= $args['volume'] * 1 &&
1079 $args['volume'] * 1 <= 1
1080 ) ? 'volume="' . esc_attr( $args['volume'] ) . '"' : ''
1081 ) . ' ' . $id . ' preload="none" data-lazyloading="' . esc_attr( $preload ) . '" class="wcmp-player ' . esc_attr( $args['player_controls'] ) . ' ' . esc_attr( $args['player_style'] ) . '" ' . ( ( ! empty( $args['duration'] ) ) ? 'data-duration="' . esc_attr( $args['duration'] ) . '"' : '' ) . '><source src="' . esc_url( $audio_url ) . '" type="audio/' . esc_attr( $args['media_type'] ) . '" /></audio>';
1082
1083 } // End get_player
1084
1085 public function get_product_files( $id ) {
1086 $product = wc_get_product( $id );
1087 if ( ! empty( $product ) ) {
1088 return $this->_get_product_files(
1089 array(
1090 'product' => $product,
1091 'all' => 1,
1092 )
1093 );
1094 }
1095 return array();
1096 }
1097
1098 public function generate_audio_url( $product_id, $file_id, $file_data = array() ) {
1099 return $this->_generate_audio_url( $product_id, $file_id, $file_data );
1100 }
1101
1102 public function include_main_player_filter( $value, $id ) {
1103 global $wp;
1104 if (
1105 $this->_force_hook_title &&
1106 did_action('woocommerce_init') &&
1107 false === stripos( $value, '<audio' )
1108 ) {
1109 try {
1110 if (
1111 ( wp_doing_ajax() || ! is_admin() ) &&
1112 (
1113 ! function_exists( 'is_product' ) ||
1114 ! is_product() ||
1115 ( is_product() && get_queried_object_id() != $id )
1116 ) &&
1117 ! is_cart() &&
1118 ! is_page( 'cart' ) &&
1119 ! is_checkout() &&
1120 is_int( $id ) &&
1121 empty( $_REQUEST['wcmp_nonce'] ) &&
1122 empty( $wp->query_vars['wcfm-products-manage'] )
1123 ) {
1124 $p = wc_get_product( $id );
1125 if ( ! empty( $p ) ) {
1126 add_filter( 'esc_html', array( &$this, 'esc_html' ), 10, 2 );
1127
1128 $player = '';
1129 $player = $this->include_main_player( $p, false );
1130 $value = $player . $value;
1131 }
1132 }
1133 } catch ( Exception $err ) {
1134 error_log( $err->getMessage() );
1135 }
1136 }
1137 return $value;
1138 }
1139
1140 public function include_players( ...$args ) {
1141 if ( ! $this->_inserted_player ) {
1142 $this->_inserted_player = true;
1143 if ( ! empty( $args ) ) {
1144 $this->include_all_players( $args[0] );
1145 } else {
1146 $this->include_all_players();
1147 }
1148 }
1149
1150 if ( ! empty( $args ) ) {
1151 return $args[0];
1152 }
1153 } // End include_players
1154
1155 public function include_main_player( $product = '', $_echo = true ) {
1156 $output = '';
1157 if ( ! $this->_insert_player || ! $this->_insert_main_player ) {
1158 return $output;
1159 }
1160 if ( is_numeric( $product ) ) {
1161 $product = wc_get_product( $product );
1162 }
1163 if ( ! is_object( $product ) ) {
1164 $product = wc_get_product();
1165 }
1166
1167 if ( empty( $product ) ) {
1168 return '';
1169 }
1170
1171 $files = $this->_get_product_files(
1172 array(
1173 'product' => $product,
1174 'first' => true,
1175 )
1176 );
1177 if ( ! empty( $files ) ) {
1178 $id = $product->get_id();
1179
1180 $show_in = $this->get_product_attr( $id, '_wcmp_show_in', 'all' );
1181 if (
1182 ( 'single' == $show_in && ( ! function_exists( 'is_product' ) || ! is_product() ) ) ||
1183 ( 'multiple' == $show_in && ( function_exists( 'is_product' ) && is_product() ) && get_queried_object_id() == $id )
1184 ) {
1185 return $output;
1186 }
1187 $preload = $this->get_product_attr( $id, '_wcmp_preload', '' );
1188 $this->enqueue_resources();
1189
1190 $player_style = $this->get_product_attr( $id, '_wcmp_player_layout', WCMP_DEFAULT_PLAYER_LAYOUT );
1191 $player_controls = ( $this->get_product_attr( $id, '_wcmp_player_controls', WCMP_DEFAULT_PLAYER_CONTROLS ) != 'all' ) ? 'track' : '';
1192 $volume = @floatval( $this->get_product_attr( $id, '_wcmp_player_volume', WCMP_DEFAULT_PLAYER_VOLUME ) );
1193
1194 $file = reset( $files );
1195 $index = key( $files );
1196 $audio_url = $this->_generate_audio_url( $id, $index, $file );
1197 $duration = $this->_get_duration_by_url( $file['file'] );
1198 $audio_tag = apply_filters(
1199 'wcmp_audio_tag',
1200 $this->get_player(
1201 $audio_url,
1202 array(
1203 'player_controls' => $player_controls,
1204 'player_style' => $player_style,
1205 'media_type' => $file['media_type'],
1206 'duration' => $duration,
1207 'preload' => $preload,
1208 'volume' => $volume,
1209 )
1210 ),
1211 $id,
1212 $index,
1213 $audio_url
1214 );
1215
1216 do_action( 'wcmp_before_player_shop_page', $id );
1217
1218 $output = '<div class="wcmp-player-container product-' . esc_attr( $file['product'] ) . '">' . $audio_tag . '</div>';
1219 if ( $_echo ) {
1220 print $output; // phpcs:ignore WordPress.Security.EscapeOutput
1221 }
1222
1223 do_action( 'wcmp_after_player_shop_page', $id );
1224
1225 return $output; // phpcs:ignore WordPress.Security.EscapeOutput
1226 }
1227 } // End include_main_player
1228
1229 public function include_all_players( $product = '' ) {
1230 if ( ! $this->_insert_player || ! $this->_insert_all_players ) {
1231 return;
1232 }
1233
1234 if ( ! is_object( $product ) ) {
1235 $product = wc_get_product();
1236 }
1237
1238 if ( empty( $product ) ) {
1239 return;
1240 }
1241
1242 $files = $this->_get_product_files(
1243 array(
1244 'product' => $product,
1245 'all' => true,
1246 )
1247 );
1248 if ( ! empty( $files ) ) {
1249 $id = $product->get_id();
1250
1251 $show_in = $this->get_product_attr( $id, '_wcmp_show_in', 'all' );
1252 if (
1253 ( 'single' == $show_in && ! is_singular() ) ||
1254 ( 'multiple' == $show_in && is_singular() )
1255 ) {
1256 return;
1257 }
1258 $preload = $this->get_product_attr( $id, '_wcmp_preload', '' );
1259 $this->enqueue_resources();
1260 $player_style = $this->get_product_attr( $id, '_wcmp_player_layout', WCMP_DEFAULT_PLAYER_LAYOUT );
1261 $volume = @floatval( $this->get_product_attr( $id, '_wcmp_player_volume', WCMP_DEFAULT_PLAYER_VOLUME ) );
1262 $player_controls = $this->get_product_attr( $id, '_wcmp_player_controls', WCMP_DEFAULT_PLAYER_CONTROLS );
1263 $player_title = intval( $this->get_product_attr( $id, '_wcmp_player_title', WCMP_DEFAULT_PlAYER_TITLE ) );
1264 $loop = intval( $this->get_product_attr( $id, '_wcmp_loop', 0 ) );
1265 $merge_grouped = intval( $this->get_product_attr( $id, '_wcmp_merge_in_grouped', 0 ) );
1266 $merge_grouped_clss = ( $merge_grouped ) ? 'merge_in_grouped_products' : '';
1267
1268 $counter = count( $files );
1269
1270 do_action( 'wcmp_before_players_product_page', $id );
1271 if ( 1 == $counter ) {
1272 $player_controls = ( 'button' == $player_controls ) ? 'track' : '';
1273 $file = reset( $files );
1274 $index = key( $files );
1275 $audio_url = $this->_generate_audio_url( $id, $index, $file );
1276 $duration = $this->_get_duration_by_url( $file['file'] );
1277 $audio_tag = apply_filters(
1278 'wcmp_audio_tag',
1279 $this->get_player(
1280 $audio_url,
1281 array(
1282 'player_controls' => $player_controls,
1283 'player_style' => $player_style,
1284 'media_type' => $file['media_type'],
1285 'duration' => $duration,
1286 'preload' => $preload,
1287 'volume' => $volume,
1288 )
1289 ),
1290 $id,
1291 $index,
1292 $audio_url
1293 );
1294 $title = esc_html( ( $player_title ) ? apply_filters( 'wcmp_file_name', $file['name'], $id, $index ) : '' );
1295 print '<div class="wcmp-player-container ' . esc_attr( $merge_grouped_clss ) . ' product-' . esc_attr( $file['product'] ) . '" ' . ( $loop ? 'data-loop="1"' : '' ) . '>' . $audio_tag . '</div><div class="wcmp-player-title" data-audio-url="' . esc_attr( $audio_url ) . '">' . wp_kses_post( $title ) . '</div><div style="clear:both;"></div>'; // phpcs:ignore WordPress.Security.EscapeOutput
1296 } elseif ( $counter > 1 ) {
1297
1298 $single_player = intval( $this->get_product_attr( $id, '_wcmp_single_player', WCMP_DEFAULT_SINGLE_PLAYER ) );
1299
1300 $before = '<table class="wcmp-player-list ' . $merge_grouped_clss . ( $single_player ? ' wcmp-single-player ' : '' ) . '" ' . ( $loop ? 'data-loop="1"' : '' ) . '>';
1301 $first_player_class = 'wcmp-first-player';
1302 $after = '';
1303 foreach ( $files as $index => $file ) {
1304 $evenOdd = ( 1 == $counter % 2 ) ? 'wcmp-odd-row' : 'wcmp-even-row';
1305 $counter--;
1306 $audio_url = $this->_generate_audio_url( $id, $index, $file );
1307 $duration = $this->_get_duration_by_url( $file['file'] );
1308 $audio_tag = apply_filters(
1309 'wcmp_audio_tag',
1310 $this->get_player(
1311 $audio_url,
1312 array(
1313 'player_style' => $player_style,
1314 'player_controls' => ( 'all' != $player_controls ) ? 'track' : '',
1315 'media_type' => $file['media_type'],
1316 'duration' => $duration,
1317 'preload' => $preload,
1318 'volume' => $volume,
1319 )
1320 ),
1321 $id,
1322 $index,
1323 $audio_url
1324 );
1325 $title = esc_html( ( $player_title ) ? apply_filters( 'wcmp_file_name', $file['name'], $id, $index ) : '' );
1326
1327 print $before; // phpcs:ignore WordPress.Security.EscapeOutput
1328 $before = '';
1329 $after = '</table>';
1330 if ( 'all' != $player_controls ) {
1331 print '<tr class="' . esc_attr( $evenOdd ) . ' product-' . esc_attr( $file['product'] ) . '"><td class="wcmp-column-player-' . esc_attr( $player_style ) . '"><div class="wcmp-player-container ' . $first_player_class . '" data-wcfm-pair="' . esc_attr( $counter ) . '">' . $audio_tag . '</div></td><td class="wcmp-player-title wcmp-column-player-title" data-wcfm-pair="' . esc_attr( $counter ) . '">' . wp_kses_post( $title ) . '</td></tr>'; // phpcs:ignore WordPress.Security.EscapeOutput
1332 } else {
1333 print '<tr class="' . esc_attr( $evenOdd ) . ' product-' . esc_attr( $file['product'] ) . '"><td><div class="wcmp-player-container ' . $first_player_class . '" data-wcfm-pair="' . esc_attr( $counter ) . '">' . $audio_tag . '</div><div class="wcmp-player-title wcmp-column-player-title" data-wcfm-pair="' . esc_attr( $counter ) . '">' . wp_kses_post( $title ) . '</div></td></tr>'; // phpcs:ignore WordPress.Security.EscapeOutput
1334 }
1335 $first_player_class = '';
1336 }
1337 print $after; // phpcs:ignore WordPress.Security.EscapeOutput
1338 }
1339 do_action( 'wcmp_after_players_product_page', $id );
1340 }
1341 } // End include_all_players
1342
1343 public function player_in_cart( $cart_item, $cart_item_key ) {
1344 $product = wc_get_product( $cart_item['product_id'] );
1345 $this->include_all_players( $product );
1346 } // player_in_cart
1347
1348 // Integration with woocommerce-product-table by barn2media
1349 public function product_table_data_name( $name, $product ) {
1350 if ( false === stripos( $name, '<audio' ) ) {
1351 $player = $this->include_main_player( $product, false );
1352 $player = str_replace( '<div ', '<div style="display:inline-block" ', $player );
1353 $name = $player . $name;
1354 }
1355 return $name;
1356 } // product_table_data_name
1357
1358 public function add_data_product( $player, $product_id, $index, $url ) {
1359 $player = preg_replace( '/<audio\b/i', '<audio controlslist="nodownload" data-product="' . esc_attr( $product_id ) . '" ', $player );
1360 return $player;
1361 } // End add_data_product
1362
1363 public function add_class_attachment( $html, $product, $size, $attr, $placeholder, $image ) {
1364 $id = $product->get_id();
1365 $html = $this->_add_class( $html, $product );
1366 return $html;
1367 } // End add_class_attachment
1368
1369 public function add_class_single_product_image( $html, $post_thumbnail_id ) {
1370 global $product;
1371
1372 if ( ! empty( $product ) ) {
1373 $html = $this->_add_class( $html, $product );
1374 }
1375 return $html;
1376 } // add_class_single_product_image
1377
1378 public function init_force_in_title( $v = null ) {
1379 if ( is_numeric( $v ) ) {
1380 $this->_force_hook_title = intval( $v );
1381 return;
1382 }
1383
1384 $this->_force_hook_title = $this->get_global_attr( '_wcmp_main_player_hook_title', 1 );
1385
1386 // Integration with "WOOF – Products Filter for WooCommerce" by realmag777
1387 if ( isset( $_REQUEST['action'] ) && 'woof_draw_products' == $_REQUEST['action'] ) {
1388 $this->_force_hook_title = 1;
1389 }
1390
1391 } // End init_force_in_title
1392
1393 // ******************** PRIVATE METHODS ************************
1394
1395 private function get_ip_address() {
1396 if( ! empty( $_SERVER['HTTP_CLIENT_IP'] ) ) { //whether ip is from the share internet
1397 $ip = $_SERVER['HTTP_CLIENT_IP'];
1398 } elseif (! empty( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) { //whether ip is from the proxy
1399 $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
1400 } else{ //whether ip is from the remote address
1401 $ip = $_SERVER['REMOTE_ADDR'];
1402 }
1403 return $ip;
1404 } // End update_playback_counter
1405
1406 private function clear_expired_transients() {
1407 $transient = get_transient( 'wcmp_clear_expired_transients' );
1408 if( ! $transient || 24 * 60 * 60 <= time() - intval( $transient ) ) {
1409 set_transient( 'wcmp_clear_expired_transients', time() );
1410 delete_expired_transients();
1411 }
1412 } // End clear_expired_transients
1413
1414 private function update_playback_counter( $product_id ) {
1415
1416 $ip = $this->get_ip_address();
1417 $transient_name = 'wcmp-playback-record-' . md5( $ip ) . '-' . $product_id;
1418 $transient = get_transient( $transient_name );
1419 if ( ! get_transient( $transient_name ) ) {
1420 set_transient( $transient_name, 1, 12 * 60 * 60 );
1421
1422 $counter = get_post_meta( $product_id, '_wcmp_playback_counter', true );
1423
1424 if ( is_numeric( $counter ) ) $counter = intval( $counter );
1425 else $counter = 0;
1426
1427 $counter++;
1428 update_post_meta( $product_id, '_wcmp_playback_counter', $counter );
1429 }
1430 } // End update_playback_counter
1431
1432 private function _get_post_types( $mysql_in = false ) {
1433 $post_types = array( 'product' );
1434 if ( ! empty( $GLOBALS['wcmp_post_types'] ) && is_array( $GLOBALS['wcmp_post_types'] ) ) {
1435 $post_types = $GLOBALS['wcmp_post_types'];
1436 }
1437 if ( $mysql_in ) {
1438 return '"' . implode( '","', $post_types ) . '"';
1439 }
1440 return $post_types;
1441 } // End _get_post_types
1442
1443 private function _load_addons() {
1444 $path = __DIR__ . '/addons';
1445 $wcmp = $this;
1446
1447 if ( file_exists( $path ) ) {
1448 $addons = dir( $path );
1449 while ( false !== ( $entry = $addons->read() ) ) {
1450 if ( strlen( $entry ) > 3 && strtolower( pathinfo( $entry, PATHINFO_EXTENSION ) ) == 'php' ) {
1451 include_once $addons->path . '/' . $entry;
1452 }
1453 }
1454 }
1455 } // End _load_addons
1456
1457 private function _preview() {
1458 $user = wp_get_current_user();
1459 $allowed_roles = array( 'editor', 'administrator', 'author' );
1460
1461 if ( array_intersect( $allowed_roles, $user->roles ) ) {
1462 if ( ! empty( $_REQUEST['wcmp-preview'] ) ) {
1463 // Sanitizing variable
1464 $preview = sanitize_text_field( wp_unslash( $_REQUEST['wcmp-preview'] ) );
1465
1466 // Remove every shortcode that is not in the plugin
1467 remove_all_shortcodes();
1468 add_shortcode( 'wcmp-playlist', array( &$this, 'replace_playlist_shortcode' ) );
1469
1470 if ( has_shortcode( $preview, 'wcmp-playlist' ) ) {
1471 print '<!DOCTYPE html>';
1472 $if_empty = __( 'There are no products that satisfy the block\'s settings', 'music-player-for-woocommerce' );
1473 wp_enqueue_script( 'jquery' );
1474 $output = do_shortcode( $preview );
1475 if ( preg_match( '/^\s*$/', $output ) ) {
1476 $output = '<div>' . $if_empty . '</div>';
1477 }
1478
1479 // Deregister all scripts and styles for loading only the plugin styles.
1480 global $wp_styles, $wp_scripts;
1481 if ( ! empty( $wp_scripts ) ) {
1482 $wp_scripts->reset();
1483 }
1484 $this->enqueue_resources();
1485 if ( ! empty( $wp_styles ) ) {
1486 $wp_styles->do_items();
1487 }
1488 if ( ! empty( $wp_scripts ) ) {
1489 $wp_scripts->do_items();
1490 }
1491
1492 print '<div class="wcmp-preview-container">' . $output . '</div>'; // phpcs:ignore WordPress.Security.EscapeOutput
1493 print '<script type="text/javascript">jQuery(window).on("load", function(){ var frameEl = window.frameElement; if(frameEl) frameEl.height = jQuery(".wcmp-preview-container").outerHeight(true)+25; });</script>';
1494 exit;
1495 }
1496 }
1497 }
1498 } // End _preview
1499
1500 private function _createDir() {
1501 // Generate upload dir
1502 $_files_directory = wp_upload_dir();
1503 $this->_files_directory_path = rtrim( $_files_directory['basedir'], '/' ) . '/wcmp/';
1504 $this->_files_directory_url = rtrim( $_files_directory['baseurl'], '/' ) . '/wcmp/';
1505 $this->_files_directory_url = preg_replace( '/^http(s)?:\/\//', '//', $this->_files_directory_url );
1506 if ( ! file_exists( $this->_files_directory_path ) ) {
1507 @mkdir( $this->_files_directory_path, 0755 );
1508 }
1509 } // End _createDir
1510
1511 private function _clearDir( $dirPath ) {
1512 try {
1513 if ( empty( $dirPath ) || ! file_exists( $dirPath ) || ! is_dir( $dirPath ) ) {
1514 return;
1515 }
1516 $dirPath = rtrim( $dirPath, '\\/' ) . '/';
1517 $files = glob( $dirPath . '*', GLOB_MARK );
1518 foreach ( $files as $file ) {
1519 if ( is_dir( $file ) ) {
1520 $this->_clearDir( $file );
1521 } else {
1522 unlink( $file );
1523 }
1524 }
1525 } catch ( Exception $err ) {
1526 return;
1527 }
1528 } // End _clearDir
1529
1530 private function _get_duration_by_url( $url ) {
1531 global $wpdb;
1532 try {
1533 $attachment = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE guid RLIKE %s;", $url ) );
1534 if ( empty( $attachment ) ) {
1535 $uploads_dir = wp_upload_dir();
1536 $uploads_url = $uploads_dir['baseurl'];
1537 $parsed_url = explode( parse_url( $uploads_url, PHP_URL_PATH ), $url );
1538 $this_host = str_ireplace( 'www.', '', parse_url( home_url(), PHP_URL_HOST ) );
1539 $file_host = str_ireplace( 'www.', '', parse_url( $url, PHP_URL_HOST ) );
1540 if ( ! isset( $parsed_url[1] ) || empty( $parsed_url[1] ) || ( $this_host != $file_host ) ) {
1541 return false;
1542 }
1543 $file = trim( $parsed_url[1], '/' );
1544 $attachment = $wpdb->get_col( $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key='_wp_attached_file' AND meta_value RLIKE %s;", $file ) );
1545 }
1546 if ( ! empty( $attachment ) && ! empty( $attachment[0] ) ) {
1547 $metadata = wp_get_attachment_metadata( $attachment[0] );
1548 if ( false !== $metadata && ! empty( $metadata['length_formatted'] ) ) {
1549 return $metadata['length_formatted'];
1550 }
1551 }
1552 } catch ( Exception $err ) {
1553 error_log( $err->getMessage() );
1554 }
1555 return false;
1556 } // End _get_duration_by_url
1557
1558 private function _generate_audio_url( $product_id, $file_index, $file_data = array() ) {
1559 if ( ! empty( $file_data['file'] ) ) {
1560 $file_url = $file_data['file'];
1561 if ( ! empty( $file_data['play_src'] ) || $this->_is_playlist( $file_url ) ) {
1562 return $file_url; // Play src audio file, without copying or truncate it.
1563 }
1564
1565 // If the playback of music are tracked with Google Analytics, should not be loaded directly the audio files.
1566 $_wcmp_analytics_property = trim( $this->get_global_attr( '_wcmp_analytics_property', '' ) );
1567 if ( '' == $_wcmp_analytics_property ) {
1568 $file_name = $this->_demo_file_name( $file_url );
1569
1570 $file_path = $this->_files_directory_path . $file_name;
1571
1572 if ( $this->_valid_demo( $file_path ) ) {
1573 return 'http' . ( ( is_ssl() ) ? 's:' : ':' ) . $this->_files_directory_url . $file_name;
1574 }
1575 }
1576 }
1577 $url = WCMP_WEBSITE_URL; //isset( $_SERVER['REQUEST_URI'] ) ? esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : '';
1578 $url .= ( ( strpos( $url, '?' ) === false ) ? '?' : '&' ) . 'wcmp-action=play&wcmp-product=' . $product_id . '&wcmp-file=' . $file_index;
1579 return $url;
1580 } // End _generate_audio_url
1581
1582 private function _delete_truncated_files( $product_id ) {
1583 $files_arr = get_post_meta( $product_id, '_downloadable_files', true );
1584 if ( ! empty( $files_arr ) && is_array( $files_arr ) ) {
1585 foreach ( $files_arr as $file ) {
1586 if ( is_array( $file ) && ! empty( $file['file'] ) ) {
1587 $ext = pathinfo( $file['file'], PATHINFO_EXTENSION );
1588 $file_name = md5( $file['file'] ) . ( ( ! empty( $ext ) ) ? '.' . $ext : '' );
1589 if ( file_exists( $this->_files_directory_path . $file_name ) ) {
1590 @unlink( $this->_files_directory_path . $file_name );
1591 }
1592 }
1593 }
1594 }
1595
1596 } // End _delete_truncated_files
1597
1598 /**
1599 * Check if the file is an m3u or m3u8 playlist
1600 */
1601 private function _is_playlist( $file_path ) {
1602 return preg_match( '/\.(m3u|m3u8)$/i', $file_path );
1603 } // End _is_playlist
1604
1605 /**
1606 * Check if the file is an audio file and return its type or false
1607 */
1608 private function _is_audio( $file_path ) {
1609 if ( preg_match( '/\.(mp3|ogg|oga|wav|wma|mp4)$/i', $file_path, $match ) ) {
1610 return $match[1];
1611 }
1612 if ( preg_match( '/\.m4a$/i', $file_path ) ) {
1613 return 'mp4';
1614 }
1615 if ( $this->_is_playlist( $file_path ) ) {
1616 return 'hls';
1617 }
1618
1619 // From troubleshoot
1620 $extension = pathinfo( $file_path, PATHINFO_EXTENSION );
1621 $troubleshoot_default_extension = $GLOBALS['WooCommerceMusicPlayer']->get_global_attr( '_wcmp_default_extension', false );
1622 if ( ( empty( $extension ) || ! preg_match( '/^[a-z\d]{3,4}$/i', $extension ) ) && $troubleshoot_default_extension ) {
1623 return 'mp3';
1624 }
1625
1626 return false;
1627 } // End _is_audio
1628
1629 private function _sort_list( $product_a, $product_b ) {
1630 if (
1631 ! is_object( $product_a ) || ! method_exists( $product_a, 'get_menu_order' ) ||
1632 ! is_object( $product_b ) || ! method_exists( $product_b, 'get_menu_order' )
1633 ) {
1634 return 0;
1635 }
1636
1637 $menu_order_a = $product_a->get_menu_order();
1638 $menu_order_b = $product_b->get_menu_order();
1639 if ( $menu_order_a == $menu_order_b ) {
1640 if (
1641 ! method_exists( $product_a, 'get_name' ) ||
1642 ! method_exists( $product_b, 'get_name' )
1643 ) {
1644 return 0;
1645 }
1646
1647 $name_a = $product_a->get_name();
1648 $name_b = $product_b->get_name();
1649 if ( $name_a == $name_b ) {
1650 return 0;
1651 }
1652 return ( $name_a < $name_b ) ? -1 : 1;
1653 }
1654 return ( $menu_order_a < $menu_order_b ) ? -1 : 1;
1655 } // End _sort_list
1656
1657 private function _edit_files_array( $product_id, $files, $play_src = 0 ) {
1658 $p_files = array();
1659 foreach ( $files as $key => $file ) {
1660 $p_key = $key . '_' . $product_id;
1661 if ( gettype( $file ) == 'object' ) {
1662 $file = (array) $file->get_data();
1663 }
1664 $file['product'] = $product_id;
1665 $file['play_src'] = $play_src;
1666 $p_files[ $p_key ] = $file;
1667 }
1668 return $p_files;
1669 } // end _edit_files_array
1670
1671 private function _get_recursive_product_files( $product, $files_arr ) {
1672 if ( ! is_object( $product ) || ! method_exists( $product, 'get_type' ) ) {
1673 return $files_arr;
1674 }
1675
1676 $product_type = $product->get_type();
1677 $id = $product->get_id();
1678
1679 if ( 'variation' == $product_type ) {
1680 // $_files = $product->get_files();
1681 $_files = $product->get_downloads();
1682 $_files = $this->_edit_files_array( $id, $_files );
1683 $files_arr = array_merge( $files_arr, $_files );
1684 } else {
1685
1686 if ( ! $this->get_product_attr( $id, '_wcmp_enable_player', false ) ) {
1687 return $files_arr;
1688 }
1689
1690 switch ( $product_type ) {
1691 case 'variable':
1692 case 'grouped':
1693 $children = $product->get_children();
1694
1695 foreach ( $children as $key => $child_id ) {
1696 $children[ $key ] = wc_get_product( $child_id );
1697 }
1698
1699 uasort( $children, array( &$this, '_sort_list' ) );
1700
1701 foreach ( $children as $child_obj ) {
1702 $files_arr = $this->_get_recursive_product_files( $child_obj, $files_arr );
1703 }
1704 break;
1705 default:
1706 $_files = $product->get_downloads();
1707 $_files = $this->_edit_files_array( $id, $_files );
1708 $files_arr = array_merge( $files_arr, $_files );
1709 break;
1710 }
1711 }
1712 return $files_arr;
1713 } // End _get_recursive_product_files
1714
1715 private function _get_product_files( $args ) {
1716 if ( empty( $args['product'] ) ) {
1717 return false;
1718 }
1719
1720 $product = $args['product'];
1721 $files = $this->_get_recursive_product_files( $product, array() );
1722
1723 if ( empty( $files ) ) {
1724 return false;
1725 }
1726
1727 $audio_files = array();
1728 foreach ( $files as $index => $file ) {
1729 if ( ! empty( $file['file'] ) && false !== ( $media_type = $this->_is_audio( $file['file'] ) ) ) { // phpcs:ignore Squiz.PHP.DisallowMultipleAssignments
1730 $file['media_type'] = $media_type;
1731
1732 if ( ! empty( $args['file_id'] ) ) {
1733 if ( $args['file_id'] == $index ) {
1734 $audio_files[ $index ] = $file;
1735 return $audio_files;
1736 }
1737 } elseif ( ! empty( $args['first'] ) ) {
1738 $audio_files[ $index ] = $file;
1739 return $audio_files;
1740 } elseif ( ! empty( $args['all'] ) ) {
1741 $audio_files[ $index ] = $file;
1742 }
1743 }
1744 }
1745
1746 return $audio_files;
1747 } // End _get_product_files
1748
1749 private function _demo_file_name( $url ) {
1750 $file_extension = pathinfo( $url, PATHINFO_EXTENSION );
1751 $file_name = md5( $url ) . ( ( ! empty( $file_extension ) && preg_match( '/^[a-z\d]{3,4}$/i', $file_extension ) ) ? '.' . $file_extension : '.mp3' );
1752 return $file_name;
1753 } // End _demo_file_name
1754
1755 private function _valid_demo( $file_path ) {
1756 if ( ! file_exists( $file_path ) || filesize( $file_path ) == 0 ) {
1757 return false;
1758 }
1759 if ( function_exists( 'finfo_open' ) ) {
1760 $finfo = finfo_open( FILEINFO_MIME );
1761 return substr( finfo_file( $finfo, $file_path ), 0, 4 ) !== 'text';
1762 }
1763 return true;
1764 } // End _valid_demo
1765
1766 /**
1767 * Create a temporal file and redirect to the new file
1768 */
1769 private function _output_file( $args ) {
1770 if ( empty( $args['url'] ) ) {
1771 return;
1772 }
1773 $url = $args['url'];
1774 $url = do_shortcode( $url );
1775
1776 if ( file_exists( $url ) ) {
1777 $url_fixed = $url;
1778 } elseif ( strpos( $url, '//' ) === 0 ) {
1779 $url_fixed = 'http' . ( is_ssl() ? 's:' : ':' ) . $url;
1780 } elseif ( strpos( $url, '/' ) === 0 ) {
1781 $url_fixed = rtrim( WCMP_WEBSITE_URL, '/' ) . $url;
1782 } else {
1783 $url_fixed = $url;
1784 }
1785
1786 $file_name = $this->_demo_file_name( $url );
1787 $text = 'The requested URL was not found on this server';
1788 $file_path = $this->_files_directory_path . $file_name;
1789
1790 if ( $this->_valid_demo( $file_path ) ) {
1791 header( 'location: http' . ( ( is_ssl() ) ? 's:' : ':' ) . $this->_files_directory_url . $file_name );
1792 exit;
1793 } else {
1794 try {
1795 $c = false;
1796 if ( ( $path = $this->_is_local( $url_fixed ) ) !== false ) { // phpcs:ignore Squiz.PHP.DisallowMultipleAssignments
1797 $c = copy( $path, $file_path );
1798 } else {
1799 $response = wp_remote_get(
1800 $url_fixed,
1801 array(
1802 'timeout' => WCMP_REMOTE_TIMEOUT,
1803 'stream' => true,
1804 'filename' => $file_path,
1805 )
1806 );
1807 if ( ! is_wp_error( $response ) && 200 == $response['response']['code'] ) {
1808 $c = true;
1809 }
1810 }
1811
1812 if ( true === $c ) {
1813
1814 if ( ! function_exists( 'mime_content_type' ) || false === ( $mime_type = mime_content_type( $file_path ) ) ) $mime_type = 'audio/mpeg';
1815
1816 if ( ! headers_sent() ) {
1817 if ( ! $this->get_global_attr( '_wcmp_disable_302', 0 ) ) {
1818 header( "location: " . $this->_files_directory_url . $file_name, true, 302 );
1819 exit;
1820 }
1821
1822 header( "Content-Type: " . $mime_type );
1823 header( "Content-length: " . filesize( $file_path ) );
1824 header( 'Content-Disposition: filename="' . $file_name . '"' );
1825 header( "Accept-Ranges: " . ( stripos( $mime_type, 'wav' ) ? 'none' : 'bytes' ) );
1826 header( "Content-Transfer-Encoding: binary" );
1827 }
1828
1829 readfile($file_path);
1830 exit;
1831 }
1832 } catch ( Exception $err ) {
1833 error_log( $err->getMessage() );
1834 }
1835 $text = 'It is not possible to generate the file for demo. Possible causes are: - the amount of memory allocated to the php script on the web server is not enough, - the execution time is too short, - or the "uploads/wcmp" directory does not have write permissions.';
1836 }
1837 $this->_print_page_not_found( $text );
1838 } // End _output_file
1839
1840 /**
1841 * Add the class name: product-<product id> to cover images associated to the products.
1842 *
1843 * @param $html, a html piece of code that includes the <img> tag.
1844 * @param $product, the product object.
1845 */
1846 private function _add_class( $html, $product ) {
1847 if ( preg_match( '/<img\b[^>]*>/i', $html, $image ) ) {
1848 $id = $product->get_id();
1849 if ( $GLOBALS['WooCommerceMusicPlayer']->get_product_attr( $id, '_wcmp_on_cover', 0 ) ) {
1850 if ( preg_match( '/\bclass\s*=/i', $image[0] ) ) {
1851 $tmp_image = preg_replace( '/\bclass\s*=\s*[\'"]/i', "$0product-$id ", $image[0] );
1852 } else {
1853 $tmp_image = preg_replace( '/<img\b/i', "<img $0 class=\"product-$id\" ", $image[0] );
1854 }
1855
1856 $html = str_replace( $image[0], $tmp_image, $html );
1857 }
1858 }
1859
1860 return $html;
1861 } // End _add_class
1862
1863 /**
1864 * Print not found page if file it is not accessible
1865 */
1866 private function _print_page_not_found( $text = 'The requested URL was not found on this server' ) {
1867 header( 'Status: 404 Not Found' );
1868 echo '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
1869 <HTML><HEAD>
1870 <TITLE>404 Not Found</TITLE>
1871 </HEAD><BODY>
1872 <H1>Not Found</H1>
1873 <P>' . esc_html( $text ) . '</P>
1874 </BODY></HTML>
1875 ';
1876 } // End _print_page_not_found
1877
1878 private function _is_local( $url ) {
1879 $file_path = false;
1880 if ( file_exists( $url ) ) {
1881 $file_path = $url;
1882 }
1883
1884 if ( false === $file_path ) {
1885 $attachment_id = attachment_url_to_postid( $url );
1886 if ( $attachment_id ) {
1887 $attachment_path = get_attached_file( $attachment_id );
1888 if ( $attachment_path && file_exists( $attachment_path ) ) {
1889 $file_path = $attachment_path;
1890 }
1891 }
1892 }
1893
1894 if ( false === $file_path && defined( 'ABSPATH' ) ) {
1895 $path_component = parse_url( $url, PHP_URL_PATH );
1896 $path = rtrim( ABSPATH, '/' ) . '/' . ltrim( $path_component, '/' );
1897 if ( file_exists( $path ) ) {
1898 $file_path = $path;
1899 }
1900
1901 if ( false === $file_path ) {
1902 $site_url = get_site_url( get_current_blog_id() );
1903 $file_path = str_ireplace( $site_url . '/', ABSPATH, $url );
1904 if ( ! file_exists( $file_path ) ) {
1905 $file_path = false;
1906 }
1907 }
1908 }
1909
1910 return apply_filters( 'wcmp_is_local', $file_path, $url );
1911 } // End _is_local
1912
1913 private function _tracking_play_event( $product_id, $file_url ) {
1914 $_wcmp_analytics_integration = $this->get_global_attr( '_wcmp_analytics_integration', 'ua' );
1915 $_wcmp_analytics_property = trim( $this->get_global_attr( '_wcmp_analytics_property', '' ) );
1916 $_wcmp_analytics_api_secret = trim( $this->get_global_attr( '_wcmp_analytics_api_secret', '' ) );
1917 if ( ! empty( $_wcmp_analytics_property ) ) {
1918 $cid = isset( $_SERVER['REMOTE_ADDR'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) ) : 555;
1919 try {
1920 if ( isset( $_COOKIE['_ga'] ) ) {
1921 $cid_parts = explode( '.', sanitize_text_field( wp_unslash( $_COOKIE['_ga'] ) ), 3 );
1922 $cid = $cid_parts[2];
1923 }
1924 } catch ( Exception $err ) {
1925 error_log( $err->getMessage() );
1926 }
1927
1928 if ( 'ua' == $_wcmp_analytics_integration ) {
1929 $_response = wp_remote_post(
1930 'http://www.google-analytics.com/collect',
1931 array(
1932 'body' => array(
1933 'v' => 1,
1934 'tid' => $_wcmp_analytics_property,
1935 'cid' => $cid,
1936 't' => 'event',
1937 'ec' => 'Music Player for WooCommerce',
1938 'ea' => 'play',
1939 'el' => $file_url,
1940 'ev' => $product_id,
1941 ),
1942 )
1943 );
1944 } else {
1945 $_response = wp_remote_post(
1946 'https://www.google-analytics.com/mp/collect?api_secret=' . $_wcmp_analytics_api_secret . '&measurement_id=' . $_wcmp_analytics_property,
1947 array(
1948 'sslverify' => true,
1949 'headers' => array(
1950 'Content-Type' => 'application/json',
1951 ),
1952 'body' => json_encode(
1953 array(
1954 'client_id' => $cid,
1955 'events' => array(
1956 array(
1957 'name' => 'play',
1958 'params' => array(
1959 'event_category' => 'Music Player for WooCommerce',
1960 'event_label' => $file_url,
1961 'event_value' => $product_id,
1962 ),
1963 ),
1964 ),
1965 )
1966 ),
1967 )
1968 );
1969 }
1970
1971 if ( is_wp_error( $_response ) ) {
1972 error_log( $_response->get_error_message() );
1973 }
1974 }
1975 } // _tracking_play_event
1976
1977 public static function troubleshoot( $option ) {
1978 if ( ! is_admin() ) {
1979 // Solves a conflict caused by the "Speed Booster Pack" plugin
1980 if ( is_array( $option ) && isset( $option['jquery_to_footer'] ) ) {
1981 unset( $option['jquery_to_footer'] );
1982 }
1983 }
1984 return $option;
1985 } // End troubleshoot
1986 } // End Class WooCommerceMusicPlayer
1987
1988 $GLOBALS['WooCommerceMusicPlayer'] = new WooCommerceMusicPlayer();
1989 }
1990