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