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