PluginProbe ʕ •ᴥ•ʔ
Music Player for WooCommerce / 1.3.4
Music Player for WooCommerce v1.3.4
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
2022 lines
1 <?php
2 /*
3 Plugin Name: Music Player for WooCommerce
4 Plugin URI: https://wcmp.dwbooster.com
5 Version: 1.3.4
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.4' );
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 . '' . $file_title . '<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 . '<div style="clear:both;"/></li>';
996 }
997 if ( ! empty( $featured_image ) ) {
998 $output .= '</ul></div></li>';
999 }
1000
1001 $output .= $download_links; // Download links
1002
1003 $output .= '</ul>';
1004 }
1005 }
1006 $output .= '</div>';
1007 }
1008 return $output;
1009 } // End replace_playlist_shortcode
1010
1011 /**
1012 * Used for accepting the <source> tags
1013 */
1014 public function allowed_html_tags( $allowedposttags, $context ) {
1015 if ( ! in_array( 'source', $allowedposttags ) ) {
1016 $allowedposttags['source'] = array(
1017 'src' => true,
1018 'type' => true,
1019 );
1020 }
1021 return $allowedposttags;
1022 } // End allowed_html_tags
1023
1024 public function preload( $preload, $audio_url ) {
1025 $result = $preload;
1026 if ( strpos( $audio_url, 'wcmp-action=play' ) !== false ) {
1027 if ( $this->_preload_times ) {
1028 $result = 'none';
1029 }
1030 $this->_preload_times++;
1031 }
1032 return $result;
1033 } // End preload
1034
1035 // ******************** WOOCOMMERCE ACTIONS ************************
1036
1037 public function woocommerce_user_download( $product_id ) {
1038 $download_links = '';
1039 if ( is_user_logged_in() ) {
1040 if ( empty( $this->_current_user_downloads ) && function_exists( 'wc_get_customer_available_downloads' ) ) {
1041 $current_user = wp_get_current_user();
1042 $this->_current_user_downloads = wc_get_customer_available_downloads( $current_user->ID );
1043 }
1044 foreach ( $this->_current_user_downloads as $download ) {
1045 if ( $download['product_id'] == $product_id ) {
1046 $download_links = '<a href="' . $download['download_url'] . '" target="_blank" class="wcmp-download-link">' . esc_html__( 'download', 'music-player-for-woocommerce' ) . '</a>';
1047 break;
1048 }
1049 }
1050 }
1051
1052 return $download_links;
1053
1054 }
1055
1056 public function woocommerce_product_title( $title, $product ) {
1057 global $wp;
1058 if ( ! empty( $wp->query_vars['wcfm-products-manage'] )) {
1059 return $title;
1060 }
1061 $player = '';
1062 if ( false === stripos( $title, '<audio' ) ) {
1063 $player .= $this->include_main_player( $product, false );
1064 }
1065 return $player . $title;
1066 } // End woocommerce_product_title
1067
1068 /**
1069 * Load the additional attributes to select the player layout
1070 */
1071 public function woocommerce_player_settings() {
1072 include_once 'views/player_options.php';
1073 } // End woocommerce_player_settings
1074
1075 public function get_player(
1076 $audio_url,
1077 $args = array()
1078 ) {
1079 $default_args = array(
1080 'media_type' => 'mp3',
1081 'player_style' => WCMP_DEFAULT_PLAYER_LAYOUT,
1082 'player_controls' => WCMP_DEFAULT_PLAYER_CONTROLS,
1083 'duration' => false,
1084 'volume' => 1,
1085 );
1086
1087 $args = array_merge( $default_args, $args );
1088 $id = ( ! empty( $args['id'] ) ) ? 'id="' . esc_attr( $args['id'] ) . '"' : '';
1089
1090 $preload = ( ! empty( $args['preload'] ) ) ? $args['preload'] : $GLOBALS['WooCommerceMusicPlayer']->get_global_attr(
1091 '_wcmp_preload',
1092 // This option is only for compatibility with versions previous to 1.0.28
1093 $GLOBALS['WooCommerceMusicPlayer']->get_global_attr( 'preload', 'none' )
1094 );
1095 $preload = apply_filters( 'wcmp_preload', $preload, $audio_url );
1096
1097 return '<audio ' . (
1098 (
1099 isset( $args['volume'] ) &&
1100 is_numeric( $args['volume'] ) &&
1101 0 <= $args['volume'] * 1 &&
1102 $args['volume'] * 1 <= 1
1103 ) ? 'volume="' . esc_attr( $args['volume'] ) . '"' : ''
1104 ) . ' ' . $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>';
1105
1106 } // End get_player
1107
1108 public function get_product_files( $id ) {
1109 $product = wc_get_product( $id );
1110 if ( ! empty( $product ) ) {
1111 return $this->_get_product_files(
1112 array(
1113 'product' => $product,
1114 'all' => 1,
1115 )
1116 );
1117 }
1118 return array();
1119 }
1120
1121 public function generate_audio_url( $product_id, $file_id, $file_data = array() ) {
1122 return $this->_generate_audio_url( $product_id, $file_id, $file_data );
1123 }
1124
1125 public function include_main_player_filter( $value, $id ) {
1126 global $wp;
1127 if (
1128 $this->_force_hook_title &&
1129 did_action('woocommerce_init') &&
1130 false === stripos( $value, '<audio' )
1131 ) {
1132 try {
1133 if (
1134 ( wp_doing_ajax() || ! is_admin() ) &&
1135 (
1136 ! function_exists( 'is_product' ) ||
1137 ! is_product() ||
1138 ( is_product() && get_queried_object_id() != $id )
1139 ) &&
1140 ! is_cart() &&
1141 ! is_page( 'cart' ) &&
1142 ! is_checkout() &&
1143 is_int( $id ) &&
1144 empty( $_REQUEST['wcmp_nonce'] ) &&
1145 empty( $wp->query_vars['wcfm-products-manage'] )
1146 ) {
1147 $p = wc_get_product( $id );
1148 if ( ! empty( $p ) ) {
1149 add_filter( 'esc_html', array( &$this, 'esc_html' ), 10, 2 );
1150
1151 $player = '';
1152 $player = $this->include_main_player( $p, false );
1153 $value = $player . $value;
1154 }
1155 }
1156 } catch ( Exception $err ) {
1157 error_log( $err->getMessage() );
1158 }
1159 }
1160 return $value;
1161 }
1162
1163 public function include_players( ...$args ) {
1164 if ( ! $this->_inserted_player ) {
1165 $this->_inserted_player = true;
1166 if ( ! empty( $args ) ) {
1167 $this->include_all_players( $args[0] );
1168 } else {
1169 $this->include_all_players();
1170 }
1171 }
1172
1173 if ( ! empty( $args ) ) {
1174 return $args[0];
1175 }
1176 } // End include_players
1177
1178 public function include_main_player( $product = '', $_echo = true ) {
1179 $output = '';
1180
1181 if ( is_admin() ) return $output;
1182
1183 if ( ! $this->_insert_player || ! $this->_insert_main_player ) {
1184 return $output;
1185 }
1186 if ( is_numeric( $product ) ) {
1187 $product = wc_get_product( $product );
1188 }
1189 if ( ! is_object( $product ) ) {
1190 $product = wc_get_product();
1191 }
1192
1193 if ( empty( $product ) ) {
1194 return '';
1195 }
1196
1197 $files = $this->_get_product_files(
1198 array(
1199 'product' => $product,
1200 'first' => true,
1201 )
1202 );
1203 if ( ! empty( $files ) ) {
1204 $id = $product->get_id();
1205
1206 $show_in = $this->get_product_attr( $id, '_wcmp_show_in', 'all' );
1207 if (
1208 ( 'single' == $show_in && ( ! function_exists( 'is_product' ) || ! is_product() ) ) ||
1209 ( 'multiple' == $show_in && ( function_exists( 'is_product' ) && is_product() ) && get_queried_object_id() == $id )
1210 ) {
1211 return $output;
1212 }
1213 $preload = $this->get_product_attr( $id, '_wcmp_preload', '' );
1214 $this->enqueue_resources();
1215
1216 $player_style = $this->get_product_attr( $id, '_wcmp_player_layout', WCMP_DEFAULT_PLAYER_LAYOUT );
1217 $player_controls = ( $this->get_product_attr( $id, '_wcmp_player_controls', WCMP_DEFAULT_PLAYER_CONTROLS ) != 'all' ) ? 'track' : '';
1218 $volume = @floatval( $this->get_product_attr( $id, '_wcmp_player_volume', WCMP_DEFAULT_PLAYER_VOLUME ) );
1219
1220 $file = reset( $files );
1221 $index = key( $files );
1222 $audio_url = $this->_generate_audio_url( $id, $index, $file );
1223 $duration = $this->_get_duration_by_url( $file['file'] );
1224 $audio_tag = apply_filters(
1225 'wcmp_audio_tag',
1226 $this->get_player(
1227 $audio_url,
1228 array(
1229 'player_controls' => $player_controls,
1230 'player_style' => $player_style,
1231 'media_type' => $file['media_type'],
1232 'duration' => $duration,
1233 'preload' => $preload,
1234 'volume' => $volume,
1235 )
1236 ),
1237 $id,
1238 $index,
1239 $audio_url
1240 );
1241
1242 do_action( 'wcmp_before_player_shop_page', $id );
1243
1244 $output = '<div class="wcmp-player-container product-' . esc_attr( $file['product'] ) . '">' . $audio_tag . '</div>';
1245 if ( $_echo ) {
1246 print $output; // phpcs:ignore WordPress.Security.EscapeOutput
1247 }
1248
1249 do_action( 'wcmp_after_player_shop_page', $id );
1250
1251 return $output; // phpcs:ignore WordPress.Security.EscapeOutput
1252 }
1253 } // End include_main_player
1254
1255 public function include_all_players( $product = '' ) {
1256
1257 if ( ! $this->_insert_player || ! $this->_insert_all_players || is_admin() ) {
1258 return;
1259 }
1260
1261 if ( ! is_object( $product ) ) {
1262 $product = wc_get_product();
1263 }
1264
1265 if ( empty( $product ) ) {
1266 return;
1267 }
1268
1269 $files = $this->_get_product_files(
1270 array(
1271 'product' => $product,
1272 'all' => true,
1273 )
1274 );
1275 if ( ! empty( $files ) ) {
1276 $id = $product->get_id();
1277
1278 $show_in = $this->get_product_attr( $id, '_wcmp_show_in', 'all' );
1279 if (
1280 ( 'single' == $show_in && ! is_singular() ) ||
1281 ( 'multiple' == $show_in && is_singular() )
1282 ) {
1283 return;
1284 }
1285 $preload = $this->get_product_attr( $id, '_wcmp_preload', '' );
1286 $this->enqueue_resources();
1287 $player_style = $this->get_product_attr( $id, '_wcmp_player_layout', WCMP_DEFAULT_PLAYER_LAYOUT );
1288 $volume = @floatval( $this->get_product_attr( $id, '_wcmp_player_volume', WCMP_DEFAULT_PLAYER_VOLUME ) );
1289 $player_controls = $this->get_product_attr( $id, '_wcmp_player_controls', WCMP_DEFAULT_PLAYER_CONTROLS );
1290 $player_title = intval( $this->get_product_attr( $id, '_wcmp_player_title', WCMP_DEFAULT_PlAYER_TITLE ) );
1291 $loop = intval( $this->get_product_attr( $id, '_wcmp_loop', 0 ) );
1292 $merge_grouped = intval( $this->get_product_attr( $id, '_wcmp_merge_in_grouped', 0 ) );
1293 $merge_grouped_clss = ( $merge_grouped ) ? 'merge_in_grouped_products' : '';
1294
1295 $counter = count( $files );
1296
1297 do_action( 'wcmp_before_players_product_page', $id );
1298 if ( 1 == $counter ) {
1299 $player_controls = ( 'button' == $player_controls ) ? 'track' : '';
1300 $file = reset( $files );
1301 $index = key( $files );
1302 $audio_url = $this->_generate_audio_url( $id, $index, $file );
1303 $duration = $this->_get_duration_by_url( $file['file'] );
1304 $audio_tag = apply_filters(
1305 'wcmp_audio_tag',
1306 $this->get_player(
1307 $audio_url,
1308 array(
1309 'player_controls' => $player_controls,
1310 'player_style' => $player_style,
1311 'media_type' => $file['media_type'],
1312 'duration' => $duration,
1313 'preload' => $preload,
1314 'volume' => $volume,
1315 )
1316 ),
1317 $id,
1318 $index,
1319 $audio_url
1320 );
1321 $title = esc_html( ( $player_title ) ? apply_filters( 'wcmp_file_name', $file['name'], $id, $index ) : '' );
1322 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
1323 } elseif ( $counter > 1 ) {
1324
1325 $single_player = intval( $this->get_product_attr( $id, '_wcmp_single_player', WCMP_DEFAULT_SINGLE_PLAYER ) );
1326
1327 $before = '<table class="wcmp-player-list ' . $merge_grouped_clss . ( $single_player ? ' wcmp-single-player ' : '' ) . '" ' . ( $loop ? 'data-loop="1"' : '' ) . '>';
1328 $first_player_class = 'wcmp-first-player';
1329 $after = '';
1330 foreach ( $files as $index => $file ) {
1331 $evenOdd = ( 1 == $counter % 2 ) ? 'wcmp-odd-row' : 'wcmp-even-row';
1332 $counter--;
1333 $audio_url = $this->_generate_audio_url( $id, $index, $file );
1334 $duration = $this->_get_duration_by_url( $file['file'] );
1335 $audio_tag = apply_filters(
1336 'wcmp_audio_tag',
1337 $this->get_player(
1338 $audio_url,
1339 array(
1340 'player_style' => $player_style,
1341 'player_controls' => ( 'all' != $player_controls ) ? 'track' : '',
1342 'media_type' => $file['media_type'],
1343 'duration' => $duration,
1344 'preload' => $preload,
1345 'volume' => $volume,
1346 )
1347 ),
1348 $id,
1349 $index,
1350 $audio_url
1351 );
1352 $title = esc_html( ( $player_title ) ? apply_filters( 'wcmp_file_name', $file['name'], $id, $index ) : '' );
1353
1354 print $before; // phpcs:ignore WordPress.Security.EscapeOutput
1355 $before = '';
1356 $after = '</table>';
1357 if ( 'all' != $player_controls ) {
1358 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
1359 } else {
1360 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
1361 }
1362 $first_player_class = '';
1363 }
1364 print $after; // phpcs:ignore WordPress.Security.EscapeOutput
1365 }
1366 do_action( 'wcmp_after_players_product_page', $id );
1367 }
1368 } // End include_all_players
1369
1370 public function player_in_cart( $cart_item, $cart_item_key ) {
1371 $product = wc_get_product( $cart_item['product_id'] );
1372 $this->include_all_players( $product );
1373 } // player_in_cart
1374
1375 // Integration with woocommerce-product-table by barn2media
1376 public function product_table_data_name( $name, $product ) {
1377 if ( false === stripos( $name, '<audio' ) ) {
1378 $player = $this->include_main_player( $product, false );
1379 $player = str_replace( '<div ', '<div style="display:inline-block" ', $player );
1380 $name = $player . $name;
1381 }
1382 return $name;
1383 } // product_table_data_name
1384
1385 public function add_data_product( $player, $product_id, $index, $url ) {
1386 $player = preg_replace( '/<audio\b/i', '<audio controlslist="nodownload" data-product="' . esc_attr( $product_id ) . '" ', $player );
1387 return $player;
1388 } // End add_data_product
1389
1390 public function add_class_attachment( $html, $product, $size, $attr, $placeholder, $image ) {
1391 $id = $product->get_id();
1392 $html = $this->_add_class( $html, $product );
1393 return $html;
1394 } // End add_class_attachment
1395
1396 public function add_class_single_product_image( $html, $post_thumbnail_id ) {
1397 global $product;
1398
1399 if ( ! empty( $product ) ) {
1400 $html = $this->_add_class( $html, $product );
1401 }
1402 return $html;
1403 } // add_class_single_product_image
1404
1405 public function init_force_in_title( $v = null ) {
1406 if ( is_admin() ) {
1407 $this->_force_hook_title = 0;
1408 return;
1409 }
1410
1411 if ( is_numeric( $v ) ) {
1412 $this->_force_hook_title = intval( $v );
1413 return;
1414 }
1415
1416 $this->_force_hook_title = $this->get_global_attr( '_wcmp_main_player_hook_title', 1 );
1417
1418 // Integration with "WOOF – Products Filter for WooCommerce" by realmag777
1419 if ( isset( $_REQUEST['action'] ) && 'woof_draw_products' == $_REQUEST['action'] ) {
1420 $this->_force_hook_title = 1;
1421 }
1422
1423 } // End init_force_in_title
1424
1425 // ******************** PRIVATE METHODS ************************
1426
1427 private function get_ip_address() {
1428 if( ! empty( $_SERVER['HTTP_CLIENT_IP'] ) ) { //whether ip is from the share internet
1429 $ip = $_SERVER['HTTP_CLIENT_IP'];
1430 } elseif (! empty( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) { //whether ip is from the proxy
1431 $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
1432 } else{ //whether ip is from the remote address
1433 $ip = $_SERVER['REMOTE_ADDR'];
1434 }
1435 return $ip;
1436 } // End update_playback_counter
1437
1438 private function clear_expired_transients() {
1439 $transient = get_transient( 'wcmp_clear_expired_transients' );
1440 if( ! $transient || 24 * 60 * 60 <= time() - intval( $transient ) ) {
1441 set_transient( 'wcmp_clear_expired_transients', time() );
1442 delete_expired_transients();
1443 }
1444 } // End clear_expired_transients
1445
1446 private function update_playback_counter( $product_id ) {
1447
1448 $ip = $this->get_ip_address();
1449 $transient_name = 'wcmp-playback-record-' . md5( $ip ) . '-' . $product_id;
1450 $transient = get_transient( $transient_name );
1451 if ( ! get_transient( $transient_name ) ) {
1452 set_transient( $transient_name, 1, 12 * 60 * 60 );
1453
1454 $counter = get_post_meta( $product_id, '_wcmp_playback_counter', true );
1455
1456 if ( is_numeric( $counter ) ) $counter = intval( $counter );
1457 else $counter = 0;
1458
1459 $counter++;
1460 update_post_meta( $product_id, '_wcmp_playback_counter', $counter );
1461 }
1462 } // End update_playback_counter
1463
1464 private function _get_post_types( $mysql_in = false ) {
1465 $post_types = array( 'product' );
1466 if ( ! empty( $GLOBALS['wcmp_post_types'] ) && is_array( $GLOBALS['wcmp_post_types'] ) ) {
1467 $post_types = $GLOBALS['wcmp_post_types'];
1468 }
1469 if ( $mysql_in ) {
1470 return '"' . implode( '","', $post_types ) . '"';
1471 }
1472 return $post_types;
1473 } // End _get_post_types
1474
1475 private function _load_addons() {
1476 $path = __DIR__ . '/addons';
1477 $wcmp = $this;
1478
1479 if ( file_exists( $path ) ) {
1480 $addons = dir( $path );
1481 while ( false !== ( $entry = $addons->read() ) ) {
1482 if ( strlen( $entry ) > 3 && strtolower( pathinfo( $entry, PATHINFO_EXTENSION ) ) == 'php' ) {
1483 include_once $addons->path . '/' . $entry;
1484 }
1485 }
1486 }
1487 } // End _load_addons
1488
1489 private function _preview() {
1490 $user = wp_get_current_user();
1491 $allowed_roles = array( 'editor', 'administrator', 'author' );
1492
1493 if ( array_intersect( $allowed_roles, $user->roles ) ) {
1494 if ( ! empty( $_REQUEST['wcmp-preview'] ) ) {
1495 // Sanitizing variable
1496 $preview = sanitize_text_field( wp_unslash( $_REQUEST['wcmp-preview'] ) );
1497
1498 // Remove every shortcode that is not in the plugin
1499 remove_all_shortcodes();
1500 add_shortcode( 'wcmp-playlist', array( &$this, 'replace_playlist_shortcode' ) );
1501
1502 if ( has_shortcode( $preview, 'wcmp-playlist' ) ) {
1503 print '<!DOCTYPE html>';
1504 $if_empty = __( 'There are no products that satisfy the block\'s settings', 'music-player-for-woocommerce' );
1505 wp_enqueue_script( 'jquery' );
1506 $output = do_shortcode( $preview );
1507 if ( preg_match( '/^\s*$/', $output ) ) {
1508 $output = '<div>' . $if_empty . '</div>';
1509 }
1510
1511 // Deregister all scripts and styles for loading only the plugin styles.
1512 global $wp_styles, $wp_scripts;
1513 if ( ! empty( $wp_scripts ) ) {
1514 $wp_scripts->reset();
1515 }
1516 $this->enqueue_resources();
1517 if ( ! empty( $wp_styles ) ) {
1518 $wp_styles->do_items();
1519 }
1520 if ( ! empty( $wp_scripts ) ) {
1521 $wp_scripts->do_items();
1522 }
1523
1524 print '<div class="wcmp-preview-container">' . $output . '</div>'; // phpcs:ignore WordPress.Security.EscapeOutput
1525 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>';
1526 exit;
1527 }
1528 }
1529 }
1530 } // End _preview
1531
1532 private function _createDir() {
1533 // Generate upload dir
1534 $_files_directory = wp_upload_dir();
1535 $this->_files_directory_path = rtrim( $_files_directory['basedir'], '/' ) . '/wcmp/';
1536 $this->_files_directory_url = rtrim( $_files_directory['baseurl'], '/' ) . '/wcmp/';
1537 $this->_files_directory_url = preg_replace( '/^http(s)?:\/\//', '//', $this->_files_directory_url );
1538 if ( ! file_exists( $this->_files_directory_path ) ) {
1539 @mkdir( $this->_files_directory_path, 0755 );
1540 }
1541 } // End _createDir
1542
1543 private function _clearDir( $dirPath ) {
1544 try {
1545 if ( empty( $dirPath ) || ! file_exists( $dirPath ) || ! is_dir( $dirPath ) ) {
1546 return;
1547 }
1548 $dirPath = rtrim( $dirPath, '\\/' ) . '/';
1549 $files = glob( $dirPath . '*', GLOB_MARK );
1550 foreach ( $files as $file ) {
1551 if ( is_dir( $file ) ) {
1552 $this->_clearDir( $file );
1553 } else {
1554 unlink( $file );
1555 }
1556 }
1557 } catch ( Exception $err ) {
1558 return;
1559 }
1560 } // End _clearDir
1561
1562 private function _get_duration_by_url( $url ) {
1563 global $wpdb;
1564 try {
1565 $attachment = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE guid RLIKE %s;", $url ) );
1566 if ( empty( $attachment ) ) {
1567 $uploads_dir = wp_upload_dir();
1568 $uploads_url = $uploads_dir['baseurl'];
1569 $parsed_url = explode( parse_url( $uploads_url, PHP_URL_PATH ), $url );
1570 $this_host = str_ireplace( 'www.', '', parse_url( home_url(), PHP_URL_HOST ) );
1571 $file_host = str_ireplace( 'www.', '', parse_url( $url, PHP_URL_HOST ) );
1572 if ( ! isset( $parsed_url[1] ) || empty( $parsed_url[1] ) || ( $this_host != $file_host ) ) {
1573 return false;
1574 }
1575 $file = trim( $parsed_url[1], '/' );
1576 $attachment = $wpdb->get_col( $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key='_wp_attached_file' AND meta_value RLIKE %s;", $file ) );
1577 }
1578 if ( ! empty( $attachment ) && ! empty( $attachment[0] ) ) {
1579 $metadata = wp_get_attachment_metadata( $attachment[0] );
1580 if ( false !== $metadata && ! empty( $metadata['length_formatted'] ) ) {
1581 return $metadata['length_formatted'];
1582 }
1583 }
1584 } catch ( Exception $err ) {
1585 error_log( $err->getMessage() );
1586 }
1587 return false;
1588 } // End _get_duration_by_url
1589
1590 private function _generate_audio_url( $product_id, $file_index, $file_data = array() ) {
1591 if ( ! empty( $file_data['file'] ) ) {
1592 $file_url = $file_data['file'];
1593 if ( ! empty( $file_data['play_src'] ) || $this->_is_playlist( $file_url ) ) {
1594 return $file_url; // Play src audio file, without copying or truncate it.
1595 }
1596
1597 // If the playback of music are tracked with Google Analytics, should not be loaded directly the audio files.
1598 $_wcmp_analytics_property = trim( $this->get_global_attr( '_wcmp_analytics_property', '' ) );
1599 if ( '' == $_wcmp_analytics_property ) {
1600 $file_name = $this->_demo_file_name( $file_url );
1601
1602 $file_path = $this->_files_directory_path . $file_name;
1603
1604 if ( $this->_valid_demo( $file_path ) ) {
1605 return 'http' . ( ( is_ssl() ) ? 's:' : ':' ) . $this->_files_directory_url . $file_name;
1606 }
1607 }
1608 }
1609 $url = WCMP_WEBSITE_URL; //isset( $_SERVER['REQUEST_URI'] ) ? esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : '';
1610 $url .= ( ( strpos( $url, '?' ) === false ) ? '?' : '&' ) . 'wcmp-action=play&wcmp-product=' . $product_id . '&wcmp-file=' . $file_index;
1611 return $url;
1612 } // End _generate_audio_url
1613
1614 private function _delete_truncated_files( $product_id ) {
1615 $files_arr = get_post_meta( $product_id, '_downloadable_files', true );
1616 if ( ! empty( $files_arr ) && is_array( $files_arr ) ) {
1617 foreach ( $files_arr as $file ) {
1618 if ( is_array( $file ) && ! empty( $file['file'] ) ) {
1619 $ext = pathinfo( $file['file'], PATHINFO_EXTENSION );
1620 $file_name = md5( $file['file'] ) . ( ( ! empty( $ext ) ) ? '.' . $ext : '' );
1621 if ( file_exists( $this->_files_directory_path . $file_name ) ) {
1622 @unlink( $this->_files_directory_path . $file_name );
1623 }
1624 }
1625 }
1626 }
1627
1628 } // End _delete_truncated_files
1629
1630 /**
1631 * Check if the file is an m3u or m3u8 playlist
1632 */
1633 private function _is_playlist( $file_path ) {
1634 return preg_match( '/\.(m3u|m3u8)$/i', $file_path );
1635 } // End _is_playlist
1636
1637 /**
1638 * Check if the file is an audio file and return its type or false
1639 */
1640 private function _is_audio( $file_path ) {
1641 if ( preg_match( '/\.(mp3|ogg|oga|wav|wma|mp4)$/i', $file_path, $match ) ) {
1642 return $match[1];
1643 }
1644 if ( preg_match( '/\.m4a$/i', $file_path ) ) {
1645 return 'mp4';
1646 }
1647 if ( $this->_is_playlist( $file_path ) ) {
1648 return 'hls';
1649 }
1650
1651 // From troubleshoot
1652 $extension = pathinfo( $file_path, PATHINFO_EXTENSION );
1653 $troubleshoot_default_extension = $GLOBALS['WooCommerceMusicPlayer']->get_global_attr( '_wcmp_default_extension', false );
1654 if ( ( empty( $extension ) || ! preg_match( '/^[a-z\d]{3,4}$/i', $extension ) ) && $troubleshoot_default_extension ) {
1655 return 'mp3';
1656 }
1657
1658 return false;
1659 } // End _is_audio
1660
1661 private function _sort_list( $product_a, $product_b ) {
1662 if (
1663 ! is_object( $product_a ) || ! method_exists( $product_a, 'get_menu_order' ) ||
1664 ! is_object( $product_b ) || ! method_exists( $product_b, 'get_menu_order' )
1665 ) {
1666 return 0;
1667 }
1668
1669 $menu_order_a = $product_a->get_menu_order();
1670 $menu_order_b = $product_b->get_menu_order();
1671 if ( $menu_order_a == $menu_order_b ) {
1672 if (
1673 ! method_exists( $product_a, 'get_name' ) ||
1674 ! method_exists( $product_b, 'get_name' )
1675 ) {
1676 return 0;
1677 }
1678
1679 $name_a = $product_a->get_name();
1680 $name_b = $product_b->get_name();
1681 if ( $name_a == $name_b ) {
1682 return 0;
1683 }
1684 return ( $name_a < $name_b ) ? -1 : 1;
1685 }
1686 return ( $menu_order_a < $menu_order_b ) ? -1 : 1;
1687 } // End _sort_list
1688
1689 private function _edit_files_array( $product_id, $files, $play_src = 0 ) {
1690 $p_files = array();
1691 foreach ( $files as $key => $file ) {
1692 $p_key = $key . '_' . $product_id;
1693 if ( gettype( $file ) == 'object' ) {
1694 $file = (array) $file->get_data();
1695 }
1696 $file['product'] = $product_id;
1697 $file['play_src'] = $play_src;
1698 $p_files[ $p_key ] = $file;
1699 }
1700 return $p_files;
1701 } // end _edit_files_array
1702
1703 private function _get_recursive_product_files( $product, $files_arr ) {
1704 if ( ! is_object( $product ) || ! method_exists( $product, 'get_type' ) ) {
1705 return $files_arr;
1706 }
1707
1708 $product_type = $product->get_type();
1709 $id = $product->get_id();
1710
1711 if ( 'variation' == $product_type ) {
1712 // $_files = $product->get_files();
1713 $_files = $product->get_downloads();
1714 $_files = $this->_edit_files_array( $id, $_files );
1715 $files_arr = array_merge( $files_arr, $_files );
1716 } else {
1717
1718 if ( ! $this->get_product_attr( $id, '_wcmp_enable_player', false ) ) {
1719 return $files_arr;
1720 }
1721
1722 switch ( $product_type ) {
1723 case 'variable':
1724 case 'grouped':
1725 $children = $product->get_children();
1726
1727 foreach ( $children as $key => $child_id ) {
1728 $children[ $key ] = wc_get_product( $child_id );
1729 }
1730
1731 uasort( $children, array( &$this, '_sort_list' ) );
1732
1733 foreach ( $children as $child_obj ) {
1734 $files_arr = $this->_get_recursive_product_files( $child_obj, $files_arr );
1735 }
1736 break;
1737 default:
1738 $_files = $product->get_downloads();
1739 $_files = $this->_edit_files_array( $id, $_files );
1740 $files_arr = array_merge( $files_arr, $_files );
1741 break;
1742 }
1743 }
1744 return $files_arr;
1745 } // End _get_recursive_product_files
1746
1747 private function _get_product_files( $args ) {
1748 if ( empty( $args['product'] ) ) {
1749 return false;
1750 }
1751
1752 $product = $args['product'];
1753 $files = $this->_get_recursive_product_files( $product, array() );
1754
1755 if ( empty( $files ) ) {
1756 return false;
1757 }
1758
1759 $audio_files = array();
1760 foreach ( $files as $index => $file ) {
1761 if ( ! empty( $file['file'] ) && false !== ( $media_type = $this->_is_audio( $file['file'] ) ) ) { // phpcs:ignore Squiz.PHP.DisallowMultipleAssignments
1762 $file['media_type'] = $media_type;
1763
1764 if ( ! empty( $args['file_id'] ) ) {
1765 if ( $args['file_id'] == $index ) {
1766 $audio_files[ $index ] = $file;
1767 return $audio_files;
1768 }
1769 } elseif ( ! empty( $args['first'] ) ) {
1770 $audio_files[ $index ] = $file;
1771 return $audio_files;
1772 } elseif ( ! empty( $args['all'] ) ) {
1773 $audio_files[ $index ] = $file;
1774 }
1775 }
1776 }
1777
1778 return $audio_files;
1779 } // End _get_product_files
1780
1781 private function _demo_file_name( $url ) {
1782 $file_extension = pathinfo( $url, PATHINFO_EXTENSION );
1783 $file_name = md5( $url ) . ( ( ! empty( $file_extension ) && preg_match( '/^[a-z\d]{3,4}$/i', $file_extension ) ) ? '.' . $file_extension : '.mp3' );
1784 return $file_name;
1785 } // End _demo_file_name
1786
1787 private function _valid_demo( $file_path ) {
1788 if ( ! file_exists( $file_path ) || filesize( $file_path ) == 0 ) {
1789 return false;
1790 }
1791 if ( function_exists( 'finfo_open' ) ) {
1792 $finfo = finfo_open( FILEINFO_MIME );
1793 return substr( finfo_file( $finfo, $file_path ), 0, 4 ) !== 'text';
1794 }
1795 return true;
1796 } // End _valid_demo
1797
1798 /**
1799 * Create a temporal file and redirect to the new file
1800 */
1801 private function _output_file( $args ) {
1802 if ( empty( $args['url'] ) ) {
1803 return;
1804 }
1805 $url = $args['url'];
1806 $url = do_shortcode( $url );
1807
1808 if ( file_exists( $url ) ) {
1809 $url_fixed = $url;
1810 } elseif ( strpos( $url, '//' ) === 0 ) {
1811 $url_fixed = 'http' . ( is_ssl() ? 's:' : ':' ) . $url;
1812 } elseif ( strpos( $url, '/' ) === 0 ) {
1813 $url_fixed = rtrim( WCMP_WEBSITE_URL, '/' ) . $url;
1814 } else {
1815 $url_fixed = $url;
1816 }
1817
1818 $file_name = $this->_demo_file_name( $url );
1819 $text = 'The requested URL was not found on this server';
1820 $file_path = $this->_files_directory_path . $file_name;
1821
1822 if ( $this->_valid_demo( $file_path ) ) {
1823 header( 'location: http' . ( ( is_ssl() ) ? 's:' : ':' ) . $this->_files_directory_url . $file_name );
1824 exit;
1825 } else {
1826 try {
1827 $c = false;
1828 if ( ( $path = $this->_is_local( $url_fixed ) ) !== false ) { // phpcs:ignore Squiz.PHP.DisallowMultipleAssignments
1829 $c = copy( $path, $file_path );
1830 } else {
1831 $response = wp_remote_get(
1832 $url_fixed,
1833 array(
1834 'timeout' => WCMP_REMOTE_TIMEOUT,
1835 'stream' => true,
1836 'filename' => $file_path,
1837 )
1838 );
1839 if ( ! is_wp_error( $response ) && 200 == $response['response']['code'] ) {
1840 $c = true;
1841 }
1842 }
1843
1844 if ( true === $c ) {
1845
1846 if ( ! function_exists( 'mime_content_type' ) || false === ( $mime_type = mime_content_type( $file_path ) ) ) $mime_type = 'audio/mpeg';
1847
1848 if ( ! headers_sent() ) {
1849 if ( ! $this->get_global_attr( '_wcmp_disable_302', 0 ) ) {
1850 header( "location: " . $this->_files_directory_url . $file_name, true, 302 );
1851 exit;
1852 }
1853
1854 header( "Content-Type: " . $mime_type );
1855 header( "Content-length: " . filesize( $file_path ) );
1856 header( 'Content-Disposition: filename="' . $file_name . '"' );
1857 header( "Accept-Ranges: " . ( stripos( $mime_type, 'wav' ) ? 'none' : 'bytes' ) );
1858 header( "Content-Transfer-Encoding: binary" );
1859 }
1860
1861 readfile($file_path);
1862 exit;
1863 }
1864 } catch ( Exception $err ) {
1865 error_log( $err->getMessage() );
1866 }
1867 $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.';
1868 }
1869 $this->_print_page_not_found( $text );
1870 } // End _output_file
1871
1872 /**
1873 * Add the class name: product-<product id> to cover images associated to the products.
1874 *
1875 * @param $html, a html piece of code that includes the <img> tag.
1876 * @param $product, the product object.
1877 */
1878 private function _add_class( $html, $product ) {
1879 if ( preg_match( '/<img\b[^>]*>/i', $html, $image ) ) {
1880 $id = $product->get_id();
1881 if ( $GLOBALS['WooCommerceMusicPlayer']->get_product_attr( $id, '_wcmp_on_cover', 0 ) ) {
1882 if ( preg_match( '/\bclass\s*=/i', $image[0] ) ) {
1883 $tmp_image = preg_replace( '/\bclass\s*=\s*[\'"]/i', "$0product-$id ", $image[0] );
1884 } else {
1885 $tmp_image = preg_replace( '/<img\b/i', "<img $0 class=\"product-$id\" ", $image[0] );
1886 }
1887
1888 $html = str_replace( $image[0], $tmp_image, $html );
1889 }
1890 }
1891
1892 return $html;
1893 } // End _add_class
1894
1895 /**
1896 * Print not found page if file it is not accessible
1897 */
1898 private function _print_page_not_found( $text = 'The requested URL was not found on this server' ) {
1899 header( 'Status: 404 Not Found' );
1900 echo '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
1901 <HTML><HEAD>
1902 <TITLE>404 Not Found</TITLE>
1903 </HEAD><BODY>
1904 <H1>Not Found</H1>
1905 <P>' . esc_html( $text ) . '</P>
1906 </BODY></HTML>
1907 ';
1908 } // End _print_page_not_found
1909
1910 private function _is_local( $url ) {
1911 $file_path = false;
1912 if ( file_exists( $url ) ) {
1913 $file_path = $url;
1914 }
1915
1916 if ( false === $file_path ) {
1917 $attachment_id = attachment_url_to_postid( $url );
1918 if ( $attachment_id ) {
1919 $attachment_path = get_attached_file( $attachment_id );
1920 if ( $attachment_path && file_exists( $attachment_path ) ) {
1921 $file_path = $attachment_path;
1922 }
1923 }
1924 }
1925
1926 if ( false === $file_path && defined( 'ABSPATH' ) ) {
1927 $path_component = parse_url( $url, PHP_URL_PATH );
1928 $path = rtrim( ABSPATH, '/' ) . '/' . ltrim( $path_component, '/' );
1929 if ( file_exists( $path ) ) {
1930 $file_path = $path;
1931 }
1932
1933 if ( false === $file_path ) {
1934 $site_url = get_site_url( get_current_blog_id() );
1935 $file_path = str_ireplace( $site_url . '/', ABSPATH, $url );
1936 if ( ! file_exists( $file_path ) ) {
1937 $file_path = false;
1938 }
1939 }
1940 }
1941
1942 return apply_filters( 'wcmp_is_local', $file_path, $url );
1943 } // End _is_local
1944
1945 private function _tracking_play_event( $product_id, $file_url ) {
1946 $_wcmp_analytics_integration = $this->get_global_attr( '_wcmp_analytics_integration', 'ua' );
1947 $_wcmp_analytics_property = trim( $this->get_global_attr( '_wcmp_analytics_property', '' ) );
1948 $_wcmp_analytics_api_secret = trim( $this->get_global_attr( '_wcmp_analytics_api_secret', '' ) );
1949 if ( ! empty( $_wcmp_analytics_property ) ) {
1950 $cid = isset( $_SERVER['REMOTE_ADDR'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) ) : 555;
1951 try {
1952 if ( isset( $_COOKIE['_ga'] ) ) {
1953 $cid_parts = explode( '.', sanitize_text_field( wp_unslash( $_COOKIE['_ga'] ) ), 3 );
1954 $cid = $cid_parts[2];
1955 }
1956 } catch ( Exception $err ) {
1957 error_log( $err->getMessage() );
1958 }
1959
1960 if ( 'ua' == $_wcmp_analytics_integration ) {
1961 $_response = wp_remote_post(
1962 'http://www.google-analytics.com/collect',
1963 array(
1964 'body' => array(
1965 'v' => 1,
1966 'tid' => $_wcmp_analytics_property,
1967 'cid' => $cid,
1968 't' => 'event',
1969 'ec' => 'Music Player for WooCommerce',
1970 'ea' => 'play',
1971 'el' => $file_url,
1972 'ev' => $product_id,
1973 ),
1974 )
1975 );
1976 } else {
1977 $_response = wp_remote_post(
1978 'https://www.google-analytics.com/mp/collect?api_secret=' . $_wcmp_analytics_api_secret . '&measurement_id=' . $_wcmp_analytics_property,
1979 array(
1980 'sslverify' => true,
1981 'headers' => array(
1982 'Content-Type' => 'application/json',
1983 ),
1984 'body' => json_encode(
1985 array(
1986 'client_id' => $cid,
1987 'events' => array(
1988 array(
1989 'name' => 'play',
1990 'params' => array(
1991 'event_category' => 'Music Player for WooCommerce',
1992 'event_label' => $file_url,
1993 'event_value' => $product_id,
1994 ),
1995 ),
1996 ),
1997 )
1998 ),
1999 )
2000 );
2001 }
2002
2003 if ( is_wp_error( $_response ) ) {
2004 error_log( $_response->get_error_message() );
2005 }
2006 }
2007 } // _tracking_play_event
2008
2009 public static function troubleshoot( $option ) {
2010 if ( ! is_admin() ) {
2011 // Solves a conflict caused by the "Speed Booster Pack" plugin
2012 if ( is_array( $option ) && isset( $option['jquery_to_footer'] ) ) {
2013 unset( $option['jquery_to_footer'] );
2014 }
2015 }
2016 return $option;
2017 } // End troubleshoot
2018 } // End Class WooCommerceMusicPlayer
2019
2020 $GLOBALS['WooCommerceMusicPlayer'] = new WooCommerceMusicPlayer();
2021 }
2022