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