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