PluginProbe ʕ •ᴥ•ʔ
Music Player for WooCommerce / 1.1.4
Music Player for WooCommerce v1.1.4
1.8.3 1.8.2 1.8.1 1.1.10 1.1.11 1.1.2 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 1.1.8 1.1.9 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 1.3.0 1.3.1 1.3.10 1.3.11 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.5.0 1.5.1 1.6.0 1.6.1 1.6.2 1.6.3 1.7.0 1.7.1 1.7.2 1.7.3 1.7.4 1.7.5 1.7.6 1.7.7 1.7.8 1.7.9 1.8.0 trunk 1.0.173 1.0.174 1.0.175 1.0.176 1.0.177 1.0.178 1.0.179 1.0.180 1.0.181 1.0.182 1.0.183 1.0.184 1.0.185 1.0.186 1.0.187 1.0.188 1.0.189 1.0.190 1.0.191 1.0.192 1.0.193 1.0.194 1.0.195 1.0.196 1.0.197 1.1.0 1.1.1
music-player-for-woocommerce / wcmp.php
music-player-for-woocommerce Last commit date
addons 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
1803 lines
1 <?php
2 /*
3 Plugin Name: Music Player for WooCommerce
4 Plugin URI: https://wcmp.dwbooster.com
5 Version: 1.1.4
6 Text Domain: music-player-for-woocommerce
7 Author: CodePeople
8 Author URI: https://wcmp.dwbooster.com
9 Description: Music Player for WooCommerce includes the MediaElement.js music player in the pages of the products with audio files associated, and in the store's pages, furthermore, the plugin allows selecting between multiple skins.
10 License: GPLv2 or later
11 License URI: http://www.gnu.org/licenses/gpl-2.0.html
12 */
13
14 require_once 'banner.php';
15 $codepeople_promote_banner_plugins['codepeople-music-player-for-woocommerce'] = array(
16 'plugin_name' => 'Music Player for WooCommerce',
17 'plugin_url' => 'https://wordpress.org/support/plugin/music-player-for-woocommerce/reviews/#new-post',
18 );
19
20 // Feedback system
21 require_once 'feedback/cp-feedback.php';
22 new WCMP_FEEDBACK( 'music-player-for-woocommerce', __FILE__, 'https://wcmp.dwbooster.com/contact-us' );
23
24 // CONSTANTS
25
26 define( 'WCMP_WEBSITE_URL', get_home_url( get_current_blog_id(), '', is_ssl() ? 'https' : 'http' ) );
27 define( 'WCMP_PLUGIN_URL', plugins_url( '', __FILE__ ) );
28 define( 'WCMP_DEFAULT_PLAYER_LAYOUT', 'mejs-classic' );
29 define( 'WCMP_DEFAULT_SINGLE_PLAYER', 0 );
30 define( 'WCMP_DEFAULT_PLAYER_VOLUME', 1 );
31 define( 'WCMP_DEFAULT_PLAYER_CONTROLS', 'default' );
32 define( 'WCMP_DEFAULT_PlAYER_TITLE', 1 );
33 define( 'WCMP_REMOTE_TIMEOUT', 120 );
34 define( 'WCMP_VERSION', '1.1.4' );
35
36 // Load widgets
37 require_once 'widgets/playlist_widget.php';
38
39 add_filter( 'option_sbp_settings', array( 'WooCommerceMusicPlayer', 'troubleshoot' ) );
40 if ( ! class_exists( 'WooCommerceMusicPlayer' ) ) {
41 class WooCommerceMusicPlayer {
42
43 // ******************** ATTRIBUTES ************************
44
45 private $_products_attrs = array();
46 private $_global_attrs = array();
47 private $_player_layouts = array( 'mejs-classic', 'mejs-ted', 'mejs-wmp' );
48 private $_player_controls = array( 'button', 'all', 'default' );
49 private $_files_directory_path;
50 private $_files_directory_url;
51 private $_enqueued_resources = false;
52 private $_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 $player .= $this->include_main_player( $product, false );
930 return $player . $title;
931 } // End woocommerce_product_title
932
933 /**
934 * Load the additional attributes to select the player layout
935 */
936 public function woocommerce_player_settings() {
937 include_once 'views/player_options.php';
938 } // End woocommerce_player_settings
939
940 public function get_player(
941 $audio_url,
942 $args = array()
943 ) {
944 $default_args = array(
945 'media_type' => 'mp3',
946 'player_style' => WCMP_DEFAULT_PLAYER_LAYOUT,
947 'player_controls' => WCMP_DEFAULT_PLAYER_CONTROLS,
948 'duration' => false,
949 'volume' => 1,
950 );
951
952 $args = array_merge( $default_args, $args );
953 $id = ( ! empty( $args['id'] ) ) ? 'id="' . esc_attr( $args['id'] ) . '"' : '';
954
955 $preload = ( ! empty( $args['preload'] ) ) ? $args['preload'] : $GLOBALS['WooCommerceMusicPlayer']->get_global_attr(
956 '_wcmp_preload',
957 // This option is only for compatibility with versions previous to 1.0.28
958 $GLOBALS['WooCommerceMusicPlayer']->get_global_attr( 'preload', 'none' )
959 );
960 $preload = apply_filters( 'wcmp_preload', $preload, $audio_url );
961
962 return '<audio ' . (
963 (
964 isset( $args['volume'] ) &&
965 is_numeric( $args['volume'] ) &&
966 0 <= $args['volume'] * 1 &&
967 $args['volume'] * 1 <= 1
968 ) ? 'volume="' . esc_attr( $args['volume'] ) . '"' : ''
969 ) . ' ' . $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>';
970
971 } // End get_player
972
973 public function get_product_files( $id ) {
974 $product = wc_get_product( $id );
975 if ( ! empty( $product ) ) {
976 return $this->_get_product_files(
977 array(
978 'product' => $product,
979 'all' => 1,
980 )
981 );
982 }
983 return array();
984 }
985
986 public function generate_audio_url( $product_id, $file_id, $file_data = array() ) {
987 return $this->_generate_audio_url( $product_id, $file_id, $file_data );
988 }
989
990 public function include_main_player_filter( $value, $id ) {
991 global $wp;
992 if ( $this->_force_hook_title ) {
993 try {
994 if (
995 ( wp_doing_ajax() || ! is_admin() ) &&
996 (
997 ! function_exists( 'is_product' ) ||
998 ! is_product() ||
999 ( is_product() && get_queried_object_id() != $id )
1000 ) &&
1001 ! is_cart() &&
1002 ! is_page( 'cart' ) &&
1003 ! is_checkout() &&
1004 is_int( $id ) &&
1005 empty( $_REQUEST['wcmp_nonce'] ) &&
1006 empty( $wp->query_vars['wcfm-products-manage'] )
1007 ) {
1008 $p = wc_get_product( $id );
1009 if ( ! empty( $p ) ) {
1010 add_filter( 'esc_html', array( &$this, 'esc_html' ), 10, 2 );
1011
1012 $player = '';
1013 $player = $this->include_main_player( $p, false );
1014 $value = $player . $value;
1015 }
1016 }
1017 } catch ( Exception $err ) {
1018 error_log( $err->getMessage() );
1019 }
1020 }
1021 return $value;
1022 }
1023
1024 public function include_main_player( $product = '', $_echo = true ) {
1025 $output = '';
1026 if ( ! $this->_insert_player ) {
1027 return $output;
1028 }
1029 if ( is_numeric( $product ) ) {
1030 $product = wc_get_product( $product );
1031 }
1032 if ( ! is_object( $product ) ) {
1033 $product = wc_get_product();
1034 }
1035 $files = $this->_get_product_files(
1036 array(
1037 'product' => $product,
1038 'first' => true,
1039 )
1040 );
1041 if ( ! empty( $files ) ) {
1042 $id = $product->get_id();
1043
1044 $show_in = $this->get_product_attr( $id, '_wcmp_show_in', 'all' );
1045 if (
1046 ( 'single' == $show_in && ( ! function_exists( 'is_product' ) || ! is_product() ) ) ||
1047 ( 'multiple' == $show_in && ( function_exists( 'is_product' ) && is_product() ) && get_queried_object_id() == $id )
1048 ) {
1049 return $output;
1050 }
1051 $preload = $this->get_product_attr( $id, '_wcmp_preload', '' );
1052 $this->enqueue_resources();
1053
1054 $player_style = $this->get_product_attr( $id, '_wcmp_player_layout', WCMP_DEFAULT_PLAYER_LAYOUT );
1055 $player_controls = ( $this->get_product_attr( $id, '_wcmp_player_controls', WCMP_DEFAULT_PLAYER_CONTROLS ) != 'all' ) ? 'track' : '';
1056 $volume = @floatval( $this->get_product_attr( $id, '_wcmp_player_volume', WCMP_DEFAULT_PLAYER_VOLUME ) );
1057
1058 $file = reset( $files );
1059 $index = key( $files );
1060 $audio_url = $this->_generate_audio_url( $id, $index, $file );
1061 $duration = $this->_get_duration_by_url( $file['file'] );
1062 $audio_tag = apply_filters(
1063 'wcmp_audio_tag',
1064 $this->get_player(
1065 $audio_url,
1066 array(
1067 'player_controls' => $player_controls,
1068 'player_style' => $player_style,
1069 'media_type' => $file['media_type'],
1070 'duration' => $duration,
1071 'preload' => $preload,
1072 'volume' => $volume,
1073 )
1074 ),
1075 $id,
1076 $index,
1077 $audio_url
1078 );
1079
1080 do_action( 'wcmp_before_player_shop_page', $id );
1081
1082 $output = '<div class="wcmp-player-container product-' . esc_attr( $file['product'] ) . '">' . $audio_tag . '</div>';
1083 if ( $_echo ) {
1084 print $output; // phpcs:ignore WordPress.Security.EscapeOutput
1085 }
1086
1087 do_action( 'wcmp_after_player_shop_page', $id );
1088
1089 return $output; // phpcs:ignore WordPress.Security.EscapeOutput
1090 }
1091 } // End include_main_player
1092
1093 public function include_all_players( $product = '' ) {
1094 if ( ! $this->_insert_player ) {
1095 return;
1096 }
1097 if ( ! is_object( $product ) ) {
1098 $product = wc_get_product();
1099 }
1100 $files = $this->_get_product_files(
1101 array(
1102 'product' => $product,
1103 'all' => true,
1104 )
1105 );
1106 if ( ! empty( $files ) ) {
1107 $id = $product->get_id();
1108
1109 $show_in = $this->get_product_attr( $id, '_wcmp_show_in', 'all' );
1110 if (
1111 ( 'single' == $show_in && ! is_singular() ) ||
1112 ( 'multiple' == $show_in && is_singular() )
1113 ) {
1114 return;
1115 }
1116 $preload = $this->get_product_attr( $id, '_wcmp_preload', '' );
1117 $this->enqueue_resources();
1118 $player_style = $this->get_product_attr( $id, '_wcmp_player_layout', WCMP_DEFAULT_PLAYER_LAYOUT );
1119 $volume = @floatval( $this->get_product_attr( $id, '_wcmp_player_volume', WCMP_DEFAULT_PLAYER_VOLUME ) );
1120 $player_controls = $this->get_product_attr( $id, '_wcmp_player_controls', WCMP_DEFAULT_PLAYER_CONTROLS );
1121 $player_title = intval( $this->get_product_attr( $id, '_wcmp_player_title', WCMP_DEFAULT_PlAYER_TITLE ) );
1122 $loop = intval( $this->get_product_attr( $id, '_wcmp_loop', 0 ) );
1123 $merge_grouped = intval( $this->get_product_attr( $id, '_wcmp_merge_in_grouped', 0 ) );
1124 $merge_grouped_clss = ( $merge_grouped ) ? 'merge_in_grouped_products' : '';
1125
1126 $counter = count( $files );
1127
1128 do_action( 'wcmp_before_players_product_page', $id );
1129 if ( 1 == $counter ) {
1130 $player_controls = ( 'button' == $player_controls ) ? 'track' : '';
1131 $file = reset( $files );
1132 $index = key( $files );
1133 $audio_url = $this->_generate_audio_url( $id, $index, $file );
1134 $duration = $this->_get_duration_by_url( $file['file'] );
1135 $audio_tag = apply_filters(
1136 'wcmp_audio_tag',
1137 $this->get_player(
1138 $audio_url,
1139 array(
1140 'player_controls' => $player_controls,
1141 'player_style' => $player_style,
1142 'media_type' => $file['media_type'],
1143 'duration' => $duration,
1144 'preload' => $preload,
1145 'volume' => $volume,
1146 )
1147 ),
1148 $id,
1149 $index,
1150 $audio_url
1151 );
1152 $title = esc_html( ( $player_title ) ? apply_filters( 'wcmp_file_name', $file['name'], $id, $index ) : '' );
1153 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
1154 } elseif ( $counter > 1 ) {
1155
1156 $single_player = intval( $this->get_product_attr( $id, '_wcmp_single_player', WCMP_DEFAULT_SINGLE_PLAYER ) );
1157
1158 $before = '<table class="wcmp-player-list ' . $merge_grouped_clss . ( $single_player ? ' wcmp-single-player ' : '' ) . '" ' . ( $loop ? 'data-loop="1"' : '' ) . '>';
1159 $first_player_class = 'wcmp-first-player';
1160 $after = '';
1161 foreach ( $files as $index => $file ) {
1162 $evenOdd = ( 1 == $counter % 2 ) ? 'wcmp-odd-row' : 'wcmp-even-row';
1163 $counter--;
1164 $audio_url = $this->_generate_audio_url( $id, $index, $file );
1165 $duration = $this->_get_duration_by_url( $file['file'] );
1166 $audio_tag = apply_filters(
1167 'wcmp_audio_tag',
1168 $this->get_player(
1169 $audio_url,
1170 array(
1171 'player_style' => $player_style,
1172 'player_controls' => ( 'all' != $player_controls ) ? 'track' : '',
1173 'media_type' => $file['media_type'],
1174 'duration' => $duration,
1175 'preload' => $preload,
1176 'volume' => $volume,
1177 )
1178 ),
1179 $id,
1180 $index,
1181 $audio_url
1182 );
1183 $title = esc_html( ( $player_title ) ? apply_filters( 'wcmp_file_name', $file['name'], $id, $index ) : '' );
1184
1185 print $before; // phpcs:ignore WordPress.Security.EscapeOutput
1186 $before = '';
1187 $after = '</table>';
1188 if ( 'all' != $player_controls ) {
1189 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
1190 } else {
1191 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
1192 }
1193 $first_player_class = '';
1194 }
1195 print $after; // phpcs:ignore WordPress.Security.EscapeOutput
1196 }
1197 do_action( 'wcmp_after_players_product_page', $id );
1198 }
1199 } // End include_all_players
1200
1201 public function player_in_cart( $cart_item, $cart_item_key ) {
1202 $product = wc_get_product( $cart_item['product_id'] );
1203 $this->include_all_players( $product );
1204 } // player_in_cart
1205
1206 // Integration with woocommerce-product-table by barn2media
1207 public function product_table_data_name( $name, $product ) {
1208 $player = $this->include_main_player( $product, false );
1209 $player = str_replace( '<div ', '<div style="display:inline-block" ', $player );
1210 return $player . $name;
1211 } // product_table_data_name
1212
1213 public function add_data_product( $player, $product_id, $index, $url ) {
1214 $player = preg_replace( '/<audio\b/i', '<audio controlslist="nodownload" data-product="' . esc_attr( $product_id ) . '" ', $player );
1215 return $player;
1216 } // End add_data_product
1217
1218 public function add_class_attachment( $html, $product, $size, $attr, $placeholder, $image ) {
1219 $id = $product->get_id();
1220 $html = $this->_add_class( $html, $product );
1221 return $html;
1222 } // End add_class_attachment
1223
1224 public function add_class_single_product_image( $html, $post_thumbnail_id ) {
1225 global $product;
1226
1227 if ( ! empty( $product ) ) {
1228 $html = $this->_add_class( $html, $product );
1229 }
1230 return $html;
1231 } // add_class_single_product_image
1232
1233 public function init_force_in_title( $v = null ) {
1234 if ( is_numeric( $v ) ) {
1235 $this->_force_hook_title = intval( $v );
1236 return;
1237 }
1238
1239 $this->_force_hook_title = $this->get_global_attr( '_wcmp_main_player_hook_title', 1 );
1240
1241 // Integration with "WOOF – Products Filter for WooCommerce" by realmag777
1242 if ( isset( $_REQUEST['action'] ) && 'woof_draw_products' == $_REQUEST['action'] ) {
1243 $this->_force_hook_title = 1;
1244 }
1245
1246 } // End init_force_in_title
1247
1248 // ******************** PRIVATE METHODS ************************
1249
1250 private function _get_post_types( $mysql_in = false ) {
1251 $post_types = array( 'product' );
1252 if ( ! empty( $GLOBALS['wcmp_post_types'] ) && is_array( $GLOBALS['wcmp_post_types'] ) ) {
1253 $post_types = $GLOBALS['wcmp_post_types'];
1254 }
1255 if ( $mysql_in ) {
1256 return '"' . implode( '","', $post_types ) . '"';
1257 }
1258 return $post_types;
1259 } // End _get_post_types
1260
1261 private function _load_addons() {
1262 $path = __DIR__ . '/addons';
1263 $wcmp = $this;
1264
1265 if ( file_exists( $path ) ) {
1266 $addons = dir( $path );
1267 while ( false !== ( $entry = $addons->read() ) ) {
1268 if ( strlen( $entry ) > 3 && strtolower( pathinfo( $entry, PATHINFO_EXTENSION ) ) == 'php' ) {
1269 include_once $addons->path . '/' . $entry;
1270 }
1271 }
1272 }
1273 } // End _load_addons
1274
1275 private function _preview() {
1276 $user = wp_get_current_user();
1277 $allowed_roles = array( 'editor', 'administrator', 'author' );
1278
1279 if ( array_intersect( $allowed_roles, $user->roles ) ) {
1280 if ( ! empty( $_REQUEST['wcmp-preview'] ) ) {
1281 // Sanitizing variable
1282 $preview = sanitize_text_field( wp_unslash( $_REQUEST['wcmp-preview'] ) );
1283
1284 // Remove every shortcode that is not in the plugin
1285 remove_all_shortcodes();
1286 add_shortcode( 'wcmp-playlist', array( &$this, 'replace_playlist_shortcode' ) );
1287
1288 if ( has_shortcode( $preview, 'wcmp-playlist' ) ) {
1289 print '<!DOCTYPE html>';
1290 $if_empty = __( 'There are no products that satisfy the block\'s settings', 'music-player-for-woocommerce' );
1291 wp_enqueue_script( 'jquery' );
1292 $output = do_shortcode( $preview );
1293 if ( preg_match( '/^\s*$/', $output ) ) {
1294 $output = '<div>' . $if_empty . '</div>';
1295 }
1296
1297 // Deregister all scripts and styles for loading only the plugin styles.
1298 global $wp_styles, $wp_scripts;
1299 if ( ! empty( $wp_scripts ) ) {
1300 $wp_scripts->reset();
1301 }
1302 $this->enqueue_resources();
1303 if ( ! empty( $wp_styles ) ) {
1304 $wp_styles->do_items();
1305 }
1306 if ( ! empty( $wp_scripts ) ) {
1307 $wp_scripts->do_items();
1308 }
1309
1310 print '<div class="wcmp-preview-container">' . $output . '</div>'; // phpcs:ignore WordPress.Security.EscapeOutput
1311 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>';
1312 exit;
1313 }
1314 }
1315 }
1316 } // End _preview
1317
1318 private function _createDir() {
1319 // Generate upload dir
1320 $_files_directory = wp_upload_dir();
1321 $this->_files_directory_path = rtrim( $_files_directory['basedir'], '/' ) . '/wcmp/';
1322 $this->_files_directory_url = rtrim( $_files_directory['baseurl'], '/' ) . '/wcmp/';
1323 $this->_files_directory_url = preg_replace( '/^http(s)?:\/\//', '//', $this->_files_directory_url );
1324 if ( ! file_exists( $this->_files_directory_path ) ) {
1325 @mkdir( $this->_files_directory_path, 0755 );
1326 }
1327 } // End _createDir
1328
1329 private function _deleteDir( $dirPath ) {
1330 try {
1331 if ( ! is_dir( $dirPath ) ) {
1332 return;
1333 }
1334 if ( substr( $dirPath, strlen( $dirPath ) - 1, 1 ) != '/' ) {
1335 $dirPath .= '/';
1336 }
1337 $files = glob( $dirPath . '*', GLOB_MARK );
1338 foreach ( $files as $file ) {
1339 if ( is_dir( $file ) ) {
1340 $this->_deleteDir( $file );
1341 } else {
1342 unlink( $file );
1343 }
1344 }
1345 rmdir( $dirPath );
1346 } catch ( Exception $err ) {
1347 return;
1348 }
1349 } // End _deleteDir
1350
1351 private function _get_duration_by_url( $url ) {
1352 global $wpdb;
1353 try {
1354 $attachment = $wpdb->get_col( $wpdb->prepare( "SELECT ID FROM $wpdb->posts WHERE guid RLIKE %s;", $url ) );
1355 if ( empty( $attachment ) ) {
1356 $uploads_dir = wp_upload_dir();
1357 $uploads_url = $uploads_dir['baseurl'];
1358 $parsed_url = explode( parse_url( $uploads_url, PHP_URL_PATH ), $url );
1359 $this_host = str_ireplace( 'www.', '', parse_url( home_url(), PHP_URL_HOST ) );
1360 $file_host = str_ireplace( 'www.', '', parse_url( $url, PHP_URL_HOST ) );
1361 if ( ! isset( $parsed_url[1] ) || empty( $parsed_url[1] ) || ( $this_host != $file_host ) ) {
1362 return false;
1363 }
1364 $file = trim( $parsed_url[1], '/' );
1365 $attachment = $wpdb->get_col( $wpdb->prepare( "SELECT post_id FROM $wpdb->postmeta WHERE meta_key='_wp_attached_file' AND meta_value RLIKE %s;", $file ) );
1366 }
1367 if ( ! empty( $attachment ) ) {
1368 $metadata = wp_get_attachment_metadata( $attachment[0] );
1369 if ( false !== $metadata && ! empty( $metadata['length_formatted'] ) ) {
1370 return $metadata['length_formatted'];
1371 }
1372 }
1373 } catch ( Exception $err ) {
1374 error_log( $err->getMessage() );
1375 }
1376 return false;
1377 } // End _get_duration_by_url
1378
1379 private function _generate_audio_url( $product_id, $file_index, $file_data = array() ) {
1380 if ( ! empty( $file_data['file'] ) ) {
1381 $file_url = $file_data['file'];
1382 if ( ! empty( $file_data['play_src'] ) || $this->_is_playlist( $file_url ) ) {
1383 return $file_url; // Play src audio file, without copying or truncate it.
1384 }
1385
1386 // If the playback of music are tracked with Google Analytics, should not be loaded directly the audio files.
1387 $_wcmp_analytics_property = trim( $this->get_global_attr( '_wcmp_analytics_property', '' ) );
1388 if ( '' == $_wcmp_analytics_property ) {
1389 $file_name = $this->_demo_file_name( $file_url );
1390
1391 $file_path = $this->_files_directory_path . $file_name;
1392
1393 if ( $this->_valid_demo( $file_path ) ) {
1394 return 'http' . ( ( is_ssl() ) ? 's:' : ':' ) . $this->_files_directory_url . $file_name;
1395 }
1396 }
1397 }
1398 $url = isset( $_SERVER['REQUEST_URI'] ) ? esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : '';
1399 $url .= ( ( strpos( $url, '?' ) === false ) ? '?' : '&' ) . 'wcmp-action=play&wcmp-product=' . $product_id . '&wcmp-file=' . $file_index;
1400 return $url;
1401 } // End _generate_audio_url
1402
1403 private function _delete_truncated_files( $product_id ) {
1404 $files_arr = get_post_meta( $product_id, '_downloadable_files', true );
1405 if ( ! empty( $files_arr ) && is_array( $files_arr ) ) {
1406 foreach ( $files_arr as $file ) {
1407 if ( is_array( $file ) && ! empty( $file['file'] ) ) {
1408 $ext = pathinfo( $file['file'], PATHINFO_EXTENSION );
1409 $file_name = md5( $file['file'] ) . ( ( ! empty( $ext ) ) ? '.' . $ext : '' );
1410 if ( file_exists( $this->_files_directory_path . $file_name ) ) {
1411 @unlink( $this->_files_directory_path . $file_name );
1412 }
1413 }
1414 }
1415 }
1416
1417 } // End _delete_truncated_files
1418
1419 /**
1420 * Check if the file is an m3u or m3u8 playlist
1421 */
1422 private function _is_playlist( $file_path ) {
1423 return preg_match( '/\.(m3u|m3u8)$/i', $file_path );
1424 } // End _is_playlist
1425
1426 /**
1427 * Check if the file is an audio file and return its type or false
1428 */
1429 private function _is_audio( $file_path ) {
1430 if ( preg_match( '/\.(mp3|ogg|oga|wav|wma|mp4)$/i', $file_path, $match ) ) {
1431 return $match[1];
1432 }
1433 if ( preg_match( '/\.m4a$/i', $file_path ) ) {
1434 return 'mp4';
1435 }
1436 if ( $this->_is_playlist( $file_path ) ) {
1437 return 'hls';
1438 }
1439
1440 // From troubleshoot
1441 $extension = pathinfo( $file_path, PATHINFO_EXTENSION );
1442 $troubleshoot_default_extension = $GLOBALS['WooCommerceMusicPlayer']->get_global_attr( '_wcmp_default_extension', false );
1443 if ( ( empty( $extension ) || ! preg_match( '/^[a-z\d]{3,4}$/i', $extension ) ) && $troubleshoot_default_extension ) {
1444 return 'mp3';
1445 }
1446
1447 return false;
1448 } // End _is_audio
1449
1450 private function _sort_list( $product_a, $product_b ) {
1451 if (
1452 ! is_object( $product_a ) || ! method_exists( $product_a, 'get_menu_order' ) ||
1453 ! is_object( $product_b ) || ! method_exists( $product_b, 'get_menu_order' )
1454 ) {
1455 return 0;
1456 }
1457
1458 $menu_order_a = $product_a->get_menu_order();
1459 $menu_order_b = $product_b->get_menu_order();
1460 if ( $menu_order_a == $menu_order_b ) {
1461 if (
1462 ! method_exists( $product_a, 'get_name' ) ||
1463 ! method_exists( $product_b, 'get_name' )
1464 ) {
1465 return 0;
1466 }
1467
1468 $name_a = $product_a->get_name();
1469 $name_b = $product_b->get_name();
1470 if ( $name_a == $name_b ) {
1471 return 0;
1472 }
1473 return ( $name_a < $name_b ) ? -1 : 1;
1474 }
1475 return ( $menu_order_a < $menu_order_b ) ? -1 : 1;
1476 } // End _sort_list
1477
1478 private function _edit_files_array( $product_id, $files, $play_src = 0 ) {
1479 $p_files = array();
1480 foreach ( $files as $key => $file ) {
1481 $p_key = $key . '_' . $product_id;
1482 if ( gettype( $file ) == 'object' ) {
1483 $file = (array) $file->get_data();
1484 }
1485 $file['product'] = $product_id;
1486 $file['play_src'] = $play_src;
1487 $p_files[ $p_key ] = $file;
1488 }
1489 return $p_files;
1490 } // end _edit_files_array
1491
1492 private function _get_recursive_product_files( $product, $files_arr ) {
1493 if ( ! is_object( $product ) || ! method_exists( $product, 'get_type' ) ) {
1494 return $files_arr;
1495 }
1496
1497 $product_type = $product->get_type();
1498 $id = $product->get_id();
1499
1500 if ( 'variation' == $product_type ) {
1501 // $_files = $product->get_files();
1502 $_files = $product->get_downloads();
1503 $_files = $this->_edit_files_array( $id, $_files );
1504 $files_arr = array_merge( $files_arr, $_files );
1505 } else {
1506
1507 if ( ! $this->get_product_attr( $id, '_wcmp_enable_player', false ) ) {
1508 return $files_arr;
1509 }
1510
1511 switch ( $product_type ) {
1512 case 'variable':
1513 case 'grouped':
1514 $children = $product->get_children();
1515
1516 foreach ( $children as $key => $child_id ) {
1517 $children[ $key ] = wc_get_product( $child_id );
1518 }
1519
1520 uasort( $children, array( &$this, '_sort_list' ) );
1521
1522 foreach ( $children as $child_obj ) {
1523 $files_arr = $this->_get_recursive_product_files( $child_obj, $files_arr );
1524 }
1525 break;
1526 default:
1527 $_files = $product->get_downloads();
1528 $_files = $this->_edit_files_array( $id, $_files );
1529 $files_arr = array_merge( $files_arr, $_files );
1530 break;
1531 }
1532 }
1533 return $files_arr;
1534 } // End _get_recursive_product_files
1535
1536 private function _get_product_files( $args ) {
1537 if ( empty( $args['product'] ) ) {
1538 return false;
1539 }
1540
1541 $product = $args['product'];
1542 $files = $this->_get_recursive_product_files( $product, array() );
1543
1544 if ( empty( $files ) ) {
1545 return false;
1546 }
1547
1548 $audio_files = array();
1549 foreach ( $files as $index => $file ) {
1550 if ( ! empty( $file['file'] ) && false !== ( $media_type = $this->_is_audio( $file['file'] ) ) ) { // phpcs:ignore Squiz.PHP.DisallowMultipleAssignments
1551 $file['media_type'] = $media_type;
1552
1553 if ( ! empty( $args['file_id'] ) ) {
1554 if ( $args['file_id'] == $index ) {
1555 $audio_files[ $index ] = $file;
1556 return $audio_files;
1557 }
1558 } elseif ( ! empty( $args['first'] ) ) {
1559 $audio_files[ $index ] = $file;
1560 return $audio_files;
1561 } elseif ( ! empty( $args['all'] ) ) {
1562 $audio_files[ $index ] = $file;
1563 }
1564 }
1565 }
1566
1567 return $audio_files;
1568 } // End _get_product_files
1569
1570 private function _demo_file_name( $url ) {
1571 $file_extension = pathinfo( $url, PATHINFO_EXTENSION );
1572 $file_name = md5( $url ) . ( ( ! empty( $file_extension ) && preg_match( '/^[a-z\d]{3,4}$/i', $file_extension ) ) ? '.' . $file_extension : '.mp3' );
1573 return $file_name;
1574 } // End _demo_file_name
1575
1576 private function _valid_demo( $file_path ) {
1577 if ( ! file_exists( $file_path ) || filesize( $file_path ) == 0 ) {
1578 return false;
1579 }
1580 if ( function_exists( 'finfo_open' ) ) {
1581 $finfo = finfo_open( FILEINFO_MIME );
1582 return substr( finfo_file( $finfo, $file_path ), 0, 4 ) !== 'text';
1583 }
1584 return true;
1585 } // End _valid_demo
1586
1587 /**
1588 * Create a temporal file and redirect to the new file
1589 */
1590 private function _output_file( $args ) {
1591 if ( empty( $args['url'] ) ) {
1592 return;
1593 }
1594 $url = $args['url'];
1595 $url = do_shortcode( $url );
1596
1597 if ( file_exists( $url ) ) {
1598 $url_fixed = $url;
1599 } elseif ( strpos( $url, '//' ) === 0 ) {
1600 $url_fixed = 'http' . ( is_ssl() ? 's:' : ':' ) . $url;
1601 } elseif ( strpos( $url, '/' ) === 0 ) {
1602 $url_fixed = rtrim( WCMP_WEBSITE_URL, '/' ) . $url;
1603 } else {
1604 $url_fixed = $url;
1605 }
1606
1607 $file_name = $this->_demo_file_name( $url );
1608 $text = 'The requested URL was not found on this server';
1609 $file_path = $this->_files_directory_path . $file_name;
1610
1611 if ( $this->_valid_demo( $file_path ) ) {
1612 header( 'location: http' . ( ( is_ssl() ) ? 's:' : ':' ) . $this->_files_directory_url . $file_name );
1613 exit;
1614 } else {
1615 try {
1616 $c = false;
1617 if ( ( $path = $this->_is_local( $url_fixed ) ) !== false ) { // phpcs:ignore Squiz.PHP.DisallowMultipleAssignments
1618 $c = copy( $path, $file_path );
1619 } else {
1620 $response = wp_remote_get(
1621 $url_fixed,
1622 array(
1623 'timeout' => WCMP_REMOTE_TIMEOUT,
1624 'stream' => true,
1625 'filename' => $file_path,
1626 )
1627 );
1628 if ( ! is_wp_error( $response ) && 200 == $response['response']['code'] ) {
1629 $c = true;
1630 }
1631 }
1632
1633 if ( true === $c ) {
1634
1635 if ( ! function_exists( 'mime_content_type' ) || false === ( $mime_type = mime_content_type( $file_path ) ) ) $mime_type = 'audio/mpeg';
1636
1637 if ( ! headers_sent() ) {
1638 if ( ! $this->get_global_attr( '_wcmp_disable_302', 0 ) ) {
1639 header( "location: " . $this->_files_directory_url . $file_name, true, 302 );
1640 exit;
1641 }
1642
1643 header( "Content-Type: " . $mime_type );
1644 header( "Content-length: " . filesize( $file_path ) );
1645 header( 'Content-Disposition: filename="' . $file_name . '"' );
1646 header( "Accept-Ranges: " . ( stripos( $mime_type, 'wav' ) ? 'none' : 'bytes' ) );
1647 header( "Content-Transfer-Encoding: binary" );
1648 }
1649
1650 readfile($file_path);
1651 exit;
1652 }
1653 } catch ( Exception $err ) {
1654 error_log( $err->getMessage() );
1655 }
1656 $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.';
1657 }
1658 $this->_print_page_not_found( $text );
1659 } // End _output_file
1660
1661 /**
1662 * Add the class name: product-<product id> to cover images associated to the products.
1663 *
1664 * @param $html, a html piece of code that includes the <img> tag.
1665 * @param $product, the product object.
1666 */
1667 private function _add_class( $html, $product ) {
1668 if ( preg_match( '/<img\b[^>]*>/i', $html, $image ) ) {
1669 $id = $product->get_id();
1670 if ( $GLOBALS['WooCommerceMusicPlayer']->get_product_attr( $id, '_wcmp_on_cover', 0 ) ) {
1671 if ( preg_match( '/\bclass\s*=/i', $image[0] ) ) {
1672 $tmp_image = preg_replace( '/\bclass\s*=\s*[\'"]/i', "$0product-$id ", $image[0] );
1673 } else {
1674 $tmp_image = preg_replace( '/<img\b/i', "<img $0 class=\"product-$id\" ", $image[0] );
1675 }
1676
1677 $html = str_replace( $image[0], $tmp_image, $html );
1678 }
1679 }
1680
1681 return $html;
1682 } // End _add_class
1683
1684 /**
1685 * Print not found page if file it is not accessible
1686 */
1687 private function _print_page_not_found( $text = 'The requested URL was not found on this server' ) {
1688 header( 'Status: 404 Not Found' );
1689 echo '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
1690 <HTML><HEAD>
1691 <TITLE>404 Not Found</TITLE>
1692 </HEAD><BODY>
1693 <H1>Not Found</H1>
1694 <P>' . esc_html( $text ) . '</P>
1695 </BODY></HTML>
1696 ';
1697 } // End _print_page_not_found
1698
1699 private function _is_local( $url ) {
1700 $file_path = false;
1701 if ( file_exists( $url ) ) {
1702 $file_path = $url;
1703 }
1704
1705 if ( false === $file_path ) {
1706 $attachment_id = attachment_url_to_postid( $url );
1707 if ( $attachment_id ) {
1708 $attachment_path = get_attached_file( $attachment_id );
1709 if ( $attachment_path && file_exists( $attachment_path ) ) {
1710 $file_path = $attachment_path;
1711 }
1712 }
1713 }
1714
1715 if ( false === $file_path && defined( 'ABSPATH' ) ) {
1716 $site_url = get_site_url( get_current_blog_id() );
1717 $file_path = str_ireplace( $site_url . '/', ABSPATH, $url );
1718 if ( ! file_exists( $file_path ) ) {
1719 $file_path = false;
1720 }
1721 }
1722
1723 return apply_filters( 'wcmp_is_local', $file_path, $url );
1724 } // End _is_local
1725
1726 private function _tracking_play_event( $product_id, $file_url ) {
1727 $_wcmp_analytics_integration = $this->get_global_attr( '_wcmp_analytics_integration', 'ua' );
1728 $_wcmp_analytics_property = trim( $this->get_global_attr( '_wcmp_analytics_property', '' ) );
1729 $_wcmp_analytics_api_secret = trim( $this->get_global_attr( '_wcmp_analytics_api_secret', '' ) );
1730 if ( ! empty( $_wcmp_analytics_property ) ) {
1731 $cid = isset( $_SERVER['REMOTE_ADDR'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) ) : 555;
1732 try {
1733 if ( isset( $_COOKIE['_ga'] ) ) {
1734 $cid_parts = explode( '.', sanitize_text_field( wp_unslash( $_COOKIE['_ga'] ) ), 3 );
1735 $cid = $cid_parts[2];
1736 }
1737 } catch ( Exception $err ) {
1738 error_log( $err->getMessage() );
1739 }
1740
1741 if ( 'ua' == $_wcmp_analytics_integration ) {
1742 $_response = wp_remote_post(
1743 'http://www.google-analytics.com/collect',
1744 array(
1745 'body' => array(
1746 'v' => 1,
1747 'tid' => $_wcmp_analytics_property,
1748 'cid' => $cid,
1749 't' => 'event',
1750 'ec' => 'Music Player for WooCommerce',
1751 'ea' => 'play',
1752 'el' => $file_url,
1753 'ev' => $product_id,
1754 ),
1755 )
1756 );
1757 } else {
1758 $_response = wp_remote_post(
1759 'https://www.google-analytics.com/mp/collect?api_secret=' . $_wcmp_analytics_api_secret . '&measurement_id=' . $_wcmp_analytics_property,
1760 array(
1761 'sslverify' => true,
1762 'headers' => array(
1763 'Content-Type' => 'application/json',
1764 ),
1765 'body' => json_encode(
1766 array(
1767 'client_id' => $cid,
1768 'events' => array(
1769 array(
1770 'name' => 'play',
1771 'params' => array(
1772 'event_category' => 'Music Player for WooCommerce',
1773 'event_label' => $file_url,
1774 'event_value' => $product_id,
1775 ),
1776 ),
1777 ),
1778 )
1779 ),
1780 )
1781 );
1782 }
1783
1784 if ( is_wp_error( $_response ) ) {
1785 error_log( $_response->get_error_message() );
1786 }
1787 }
1788 } // _tracking_play_event
1789
1790 public static function troubleshoot( $option ) {
1791 if ( ! is_admin() ) {
1792 // Solves a conflict caused by the "Speed Booster Pack" plugin
1793 if ( is_array( $option ) && isset( $option['jquery_to_footer'] ) ) {
1794 unset( $option['jquery_to_footer'] );
1795 }
1796 }
1797 return $option;
1798 } // End troubleshoot
1799 } // End Class WooCommerceMusicPlayer
1800
1801 $GLOBALS['WooCommerceMusicPlayer'] = new WooCommerceMusicPlayer();
1802 }
1803