PluginProbe
WpStream – Live Streaming, Video on Demand, Pay Per View / 4.8.2
WpStream – Live Streaming, Video on Demand, Pay Per View v4.8.2
4.14.1 4.14.0 4.13.2 4.13.1 4.13 4.12.5 4.12.4 4.12.3 4.12.2 4.12.1 4.12 4.4.4 4.4.5 4.4.6 4.4.7 4.4.8 4.4.9 4.5 4.5.1 4.5.11 4.5.11.1 4.5.11.2 4.5.11.4 4.5.11.5 4.5.11.6 All 181 releases
← All changes | includes/class-wpstream-player.php +1314 -444 4.14.14.8.2 View file →
@@ -1,59 +1,28 @@
1 1 <?php
2 2
3 +/*
4 + * To change this license header, choose License Headers in Project Properties.
5 + * To change this template file, choose Tools | Templates
6 + * and open the template in the editor.
7 + */
8 +
9 +
3 10 /**
4 - * Front-end video player for WpStream live channels and video-on-demand.
11 + * Description of class-wpstream-player
5 12 *
6 - * This class is the WordPress and backwards-compatibility facade: it hooks
7 - * the_content, decides whether the current user is entitled to watch, preserves
8 - * the established public renderer methods, and exposes the status-poll AJAX
9 - * endpoint. Wpstream_Playback_Presentation owns source resolution, engine
10 - * selection, assets, and viewer-facing player markup.
11 - *
12 - * Live status is fetched from the WpStream cloud API and cached in a 45-second
13 - * transient so repeated polls do not hammer the remote service.
14 - *
15 - * @package Wpstream
16 - * @subpackage Wpstream/includes
17 - * @author cretu
13 + * @author cretu
18 14 */
19 -
20 -// Exit if accessed directly.
21 -if ( ! defined( 'ABSPATH' ) ) {
22 - exit;
23 -}
24 -
25 15 class Wpstream_Player{
26 - /** @var object Main plugin instance; exposes shared services (live connection, quota manager). */
27 16 public $main;
28 -
29 - /**
30 - * @var Wpstream_Playback_Session Helper that issues/validates playback sessions for encrypted streams.
31 - */
32 - public $playback_session;
33 -
34 - /**
35 - * Wire up the player: keep a handle on the plugin, load the playback-session
36 - * helper, and register the content filter, purchase check, and status-poll
37 - * AJAX endpoints (both logged-in and nopriv).
38 - *
39 - * @param object $plugin_main Main plugin instance passed in by the loader.
40 - */
17 +
41 18 public function __construct($plugin_main) {
42 - // Keep a reference to the main plugin so we can reach its services later.
43 19 $this->main = $plugin_main;
44 -
45 - // Instantiate the playback-session helper (used for encrypted streams).
46 - $this->playback_session = new Wpstream_Playback_Session();
47 -
48 - // Inject the player markup into single wpstream product/VOD pages.
20 +
49 21 add_filter( 'the_content',array($this, 'wpstream_filter_the_title') );
50 - // On a WooCommerce single product, render the player only if the visitor already bought it.
51 22 add_action( 'woocommerce_before_single_product', array($this,'wpstream_user_logged_in_product_already_bought') );
52 -
53 - // Front-end status poll endpoint for logged-in users.
54 - add_action( 'wp_ajax_wpstream_player_check_status', array($this,'wpstream_player_check_status') );
55 - // Same endpoint for logged-out visitors (nopriv) so public streams can poll too.
23 +
24 + add_action( 'wp_ajax_wpstream_player_check_status', array($this,'wpstream_player_check_status') );
56 25 add_action('wp_ajax_nopriv_wpstream_player_check_status', array($this,'wpstream_player_check_status'));
57 26
58 27 }
59 28
@@ -62,249 +31,125 @@
62 31
63 32
64 33
65 34 /**
66 - * AJAX endpoint: report whether a channel is currently live and, if so, its
67 - * playback/stats/chat URLs. Called repeatedly by the front-end player JS.
68 - *
69 - * The posted id must be a published streaming channel or it is rejected
70 - * before any work. Reads the channel status from a 45-second transient; on
71 - * a cache miss it calls the WpStream cloud API and refreshes the transient.
72 - * Liveness is public, but the playback/stats/chat URLs are returned only to
73 - * callers who pass the player-render entitlement check; the response always
74 - * carries exactly the five keys the player JS reads. Echoes a JSON payload
75 - * and dies. No nonce check on purpose (see inline note) because the hosting
76 - * page may be cached, which would invalidate the nonce.
77 - *
35 + *
78 36 * edited 4.0
79 - *
80 - * @return void Outputs JSON and terminates the request.
81 - * @author cretu
82 - */
37 + *
38 + * check player status
39 + *
40 + * @author cretu
41 + */
42 +
83 43 public function wpstream_player_check_status(){
84 - // did not add a nonce check here because this is a call done from the frontend
85 - // and the page might be cached, so the nonce would not be valid
86 - // Which channel/post the caller is asking about.
87 - $channel_id = intval($_POST['channel_id']);
88 -
89 - // Reject anything that is not a published streaming channel BEFORE any
90 - // cache read, remote API call or meta write: the id must be a wpstream
91 - // live/VOD post, or a WooCommerce product carrying one of the wpstream
92 - // product types. This stops arbitrary-id probing from reaching the API
93 - // or touching unrelated posts' meta.
94 - $channel_post = get_post( $channel_id );
95 - $is_valid_channel = false;
96 - if ( $channel_post instanceof WP_Post && 'publish' === $channel_post->post_status ) {
97 - if ( in_array( $channel_post->post_type, array( 'wpstream_product', 'wpstream_product_vod' ), true ) ) {
98 - $is_valid_channel = true;
99 - } elseif ( 'product' === $channel_post->post_type
100 - && has_term( array( 'live_stream', 'video_on_demand', 'subscription' ), 'product_type', $channel_post ) ) {
101 - $is_valid_channel = true;
102 - }
44 + $channel_id = intval($_POST['channel_id']);
45 +
46 +
47 + $transient_name = 'event_data_to_return_'. $channel_id;
48 + $event_data_for_transient = get_transient( $transient_name );
49 +
50 +
51 + $usefull_info =' get cache from transiet';
52 + if ( false === $event_data_for_transient || $event_data_for_transient=='' ) { //ws || $hls_to_return==''
53 + $notes = 'wpstream_player_check_status_note_from_js';
54 + $event_status = $this->main->wpstream_live_connection->wpstream_check_event_status_api_call($channel_id,$notes);
55 + $event_data_for_transient = $event_status;
56 + $usefull_info =' no cache found';
57 + set_transient($transient_name,$event_data_for_transient,45);
103 58 }
104 - if ( ! $is_valid_channel ) {
105 - ob_end_clean();
106 - wp_send_json_error( array( 'message' => esc_html__( 'Invalid channel.', 'wpstream' ) ), 400 );
107 - }
108 -
109 - // Channel state (cache, Baker fetch on miss, fresh-data meta sync) is
110 - // owned by Wpstream_Channel_State — the poll only asks questions of it.
111 - $state = Wpstream_Channel_State::for_channel( $channel_id, 'wpstream_player_check_status_note_from_js' );
112 -
113 - // Live means playable: upstream status active AND a playback URL present.
114 - if ( $state->is_live() ) {
115 -
116 - // Entitlement gate: playback/stats/chat URLs go only to
117 - // callers who pass the same check that decides whether the player
118 - // renders at all (free wpstream post types for anyone; WooCommerce
119 - // products only for buyers / active subscribers / bundle owners).
120 - // Liveness itself stays visible so a paywall page can reflect it.
121 - $viewer_is_entitled = wpstream_user_entitled_for_product( $channel_id );
122 -
59 +
60 +
61 + if( isset($event_data_for_transient['hls_playback_url']) && $event_data_for_transient['hls_playback_url']!=''){
123 62 // cleanup any previous echo before sending json
124 63 ob_end_clean();
125 - // Both branches return exactly the keys the player JS reads —
126 - // never the raw upstream payload or any debug field.
127 - if ( $viewer_is_entitled ) {
128 - echo json_encode( array(
129 - 'started' => 'yes',
130 - 'channel_id' => $channel_id,
131 - 'event_uri' => $state->playback_url(),
132 - 'live_conect_views' => $state->stats_url(),
133 - 'chat_url' => $state->chat_url(),
134 - ));
135 - } else {
136 - // Unentitled caller: same JSON shape, real liveness, but every
137 - // URL field empty.
138 - echo json_encode( array(
139 - 'started' => 'yes',
140 - 'channel_id' => $channel_id,
141 - 'event_uri' => '',
142 - 'live_conect_views' => '',
143 - 'chat_url' => '',
144 - ));
145 - }
64 + echo json_encode( array(
65 +
66 + 'started' => 'yes',
67 + 'usefull_info' => $usefull_info,
68 + 'channel_id' => $channel_id,
69 + 'event_uri' => $event_data_for_transient['hls_playback_url'],
70 + 'live_conect_views' => $event_data_for_transient['stats_url'],
71 + 'chat_url' => $event_data_for_transient['chat_url'],
72 + '$event_data_for_transient'=>$event_data_for_transient
73 +
74 +
75 + ));
76 + $usedfull_info =' ';
77 + update_post_meta($channel_id,'stream_name',$event_data_for_transient['stream_name']);
78 + update_post_meta($channel_id,'hls_key_retrieval_url',$event_data_for_transient['hls_key_retrieval_url']);
79 + delete_transient( 'free_event_streamName_'.$event_data_for_transient['stream_name']);
146 80
147 81 }else{
148 - // Channel is not live: return a "started: no" payload with empty
149 - // URLs, in the same five-key shape as the live branch.
150 82 // cleanup any previous echo before sending json
151 83 ob_end_clean();
152 84 echo json_encode( array(
153 85 'started' => 'no',
86 + 'usefull_info' => $usefull_info,
87 + 'server_id' => '',
154 88 'channel_id' => $channel_id,
155 89 'event_uri' => '',
156 90 'live_conect_views' => '',
157 91 'chat_url' => '',
92 +
93 +
158 94 ));
159 -
95 +
160 96 }
161 -
162 - // AJAX response is complete; stop execution so nothing else is appended.
97 +
163 98 die();
164 99 }
165 -
166 -
167 -
100 +
101 +
102 +
168 103 /**
169 - * the_content filter: prepend the player markup to single live/VOD product pages.
104 + * Insert player in page
170 105 *
171 - * @param string $content The post content WordPress is about to render.
172 - * @return string Content with the player div prepended, or unchanged.
173 106 * @author cretu
174 107 */
175 108 public function wpstream_filter_the_title( $content ) {
176 - // Only inject on single WpStream live-product or VOD-product pages.
109 + if(function_exists('wpstream_remove_wpstream_filter')){
110 + return $content;
111 + }
112 +
177 113 if( is_singular('wpstream_product') || is_singular('wpstream_product_vod') ){
178 114 global $post;
179 - // The theme may own the player placement and switch the injection off.
180 - if ( ! $this->auto_insert_enabled( intval( $post->ID ), 'the_content' ) ) {
181 - return $content;
182 - }
183 - // Build the player HTML for the current post and prepend it to the content.
184 115 $args=array('id'=>$post->ID);
185 116 $custom_content = $this->wpstream_insert_player_inpage($args);
186 117 $content = '<div class="wpestream_inserted_player">'.$custom_content.'</div>'.$content;
187 118 return $content;
188 119 }else{
189 - // Not a player page: return content untouched.
190 120 return $content;
191 121 }
192 122 }
193 123
194 124 /**
195 - * Decide whether the plugin injects its player automatically into a page.
196 - *
197 - * Themes that render the player in their own templates switch this off.
198 - * Replaces the `wpstream_remove_wpstream_filter()` function-name sniff,
199 - * which is honoured as the default for one more release.
200 - *
201 - * @param int $post_id Post the page is about.
202 - * @param string $context `the_content` or `woocommerce_before_single_product`.
203 - * @return bool
204 - */
205 - private function auto_insert_enabled( $post_id, $context ) {
206 - // One-release shim: a theme defining the legacy opt-out function still opts out.
207 - $enabled = ! function_exists( 'wpstream_remove_wpstream_filter' );
208 -
209 - /**
210 - * Filter whether the plugin inserts its player into the page automatically.
211 - *
212 - * Only the automatic placements (post content, WooCommerce single product)
213 - * are affected; shortcodes and builder widgets always render.
214 - *
215 - * @since 4.14.0
216 - *
217 - * @param bool $enabled Whether to insert the player.
218 - * @param int $post_id Post the page is about.
219 - * @param string $context `the_content` or `woocommerce_before_single_product`.
220 - */
221 - return (bool) apply_filters( 'wpstream_player_auto_insert', $enabled, $post_id, $context );
222 - }
223 -
224 - /**
225 - * Build the access notice shown in place of the player.
226 - *
227 - * @param string $reason `nobuy`, `nolog` or `sub_active`.
228 - * @param int $product_id Product the notice is about.
229 - * @param string $message Configured wording for the reason.
230 - * @param string $wrapper_class Extra class on the outer wrapper (shortcode placement).
231 - * @param string $notice_style Inline style kept by the shortcode placement.
232 - * @return string Notice markup.
233 - */
234 - private function not_entitled_notice( $reason, $product_id, $message, $wrapper_class = '', $notice_style = '' ) {
235 - /**
236 - * Filter the wording of the access notice shown in place of the player.
237 - *
238 - * @since 4.14.0
239 - *
240 - * @param string $message Plain-text message (not yet escaped).
241 - * @param int $product_id Product the notice is about.
242 - * @param string $reason `nobuy`, `nolog` or `sub_active` — the entitlement path,
243 - * not the wording (global-subscription sites show the
244 - * "not subscribed" text under `nobuy`).
245 - */
246 - $message = (string) apply_filters( 'wpstream_player_not_entitled_message', $message, $product_id, $reason );
247 -
248 - // Assemble the block with the message escaped; the style is a plugin constant.
249 - $style = '' !== $notice_style ? ' style="' . esc_attr( $notice_style ) . '"' : '';
250 - $html = '<div class="wpstream_player_wrapper ' . esc_attr( trim( $wrapper_class . ' no_buy' ) ) . '"><div class="wpstream_player_container">'
251 - . '<div class="wpstream_notice"' . $style . '>' . esc_html( $message ) . '</div>'
252 - . '</div></div>';
253 -
254 - /**
255 - * Filter the whole access notice block shown in place of the player.
256 - *
257 - * The default markup is already escaped; callbacks own the escaping of
258 - * anything they add. This decides presentation only — entitlement was
259 - * refused before this point and is not revisited.
260 - *
261 - * @since 4.14.0
262 - *
263 - * @param string $html Notice markup.
264 - * @param int $product_id Product the notice is about.
265 - * @param string $reason `nobuy`, `nolog` or `sub_active` (the entitlement path).
266 - */
267 - return (string) apply_filters( 'wpstream_player_not_entitled_html', $html, $product_id, $reason );
268 - }
269 -
270 - /**
271 - * Build the player HTML for a shortcode/embed and return it as a string.
125 + * Insert player in page
272 126 *
273 - * Buffers the echoed player markup so it can be returned instead of printed.
274 - *
275 - * @param array $attributes Shortcode attributes; 'id' selects the product.
276 - * @param string|null $content Unused enclosed shortcode content.
277 - * @return string The captured player markup.
278 127 * @author cretu
279 128 */
129 +
280 130 public function wpstream_insert_player_inpage($attributes, $content = null){
281 131 $product_id = '';
282 132 $return_string = '';
283 - // Normalise the incoming attributes against the supported defaults.
284 - $attributes = shortcode_atts(
133 + $attributes = shortcode_atts(
285 134 array(
286 135 'id' => 0,
287 136 ), $attributes) ;
288 137
289 138
290 - // Take the product id from the attributes when present.
291 139 if ( isset($attributes['id']) ){
292 140 $product_id=$attributes['id'];
293 141 }
294 -
295 - // No explicit id: fall back to the first available product id. The
296 - // lookup lives on the main plugin class, not on this player service.
142 +
297 143 if(intval($product_id)==0){
298 - $product_id= $this->main->wpstream_player_retrieve_first_id();
144 + $product_id= $this->wpstream_player_retrive_first_id();
299 145 }
300 146
301 - // Capture everything the shortcode renderer echoes into a string.
302 147 ob_start();
303 -
148 +
304 149 $this->wpstream_video_player_shortcode($product_id);
305 150 $return_string= ob_get_contents();
306 - ob_end_clean();
151 + ob_end_clean();
307 152
308 153 return $return_string;
309 154 }
310 155
@@ -311,70 +156,86 @@
311 156
312 157
313 158
314 159 /**
315 - * Render the player for a product, gated by login and purchase entitlement.
160 + * Video Player shortcode
316 161 *
317 - * Picks the live or VOD renderer based on product type / taxonomy term, and
318 - * shows a "not purchased" / "must log in" notice when the visitor is not
319 - * entitled to watch.
320 - *
321 - * @param string|int $from_sh_id Product/post id to render.
322 - * @return void Echoes the player markup or an access notice.
323 162 * @author cretu
324 163 */
164 +
325 165 public function wpstream_video_player_shortcode($from_sh_id='') {
326 - // disable cache in order to be able to check the nonce
327 - if ( !defined( 'DONOTCACHEPAGE' ) ) {
328 - define( 'DONOTCACHEPAGE', true );
329 - }
330 166
331 - $product_id = intval( $from_sh_id );
332 - $product_post = get_post( $product_id );
333 - if ( ! $product_post instanceof WP_Post
334 - || ( 'publish' !== $product_post->post_status && ! current_user_can( 'read_post', $product_id ) ) ) {
335 - return;
336 - }
167 + wp_enqueue_script('video.min');
168 + wp_enqueue_script('wpstream-player');
337 169
338 - // Player depends on Video.js plus the WpStream player glue script (+styles).
339 - wpstream_enqueue_player_assets();
170 + if ( is_user_logged_in() ) {
171 + global $product;
172 + $current_user = wp_get_current_user();
173 + $product_id = intval($from_sh_id);
174 + $term_list = wp_get_post_terms($product_id, 'product_type');
175 + $possible_bundle = get_post_meta($product_id, 'wpstream_part_of_bundle', true);
176 +
340 177
341 - if ( is_user_logged_in() ) {
342 - // Logged-in branch: gather the identifier needed to check entitlement.
343 - // Entitlement gate: the single shared rule (free type / purchase /
344 - // active subscription / bundle / Netflix mode).
345 - if ( wpstream_user_entitled_for_product( $product_id ) ){
346 - // Open the player wrapper markup.
178 +
179 +
180 + if (
181 +
182 + ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) && wc_customer_bought_product( $current_user->user_email, $current_user->ID, $product_id) ) ||
183 + ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) && (intval($possible_bundle)!=0) && wc_customer_bought_product( $current_user->user_email, $current_user->ID, $possible_bundle) ) ||
184 + get_post_type($product_id)=='wpstream_product' ||
185 + get_post_type($product_id)=='wpstream_product_vod' ){
186 + global $product;
347 187 echo '<div class="wpstream_player_wrapper wpstream_player_shortcode"><div class="wpstream_player_container">';
348 - echo $this->main->playback_presentation->render( $product_id, 'auto' );
349 - // Close the player wrapper markup.
188 +
189 +
190 + if( get_post_type($product_id) == 'wpstream_product' ){
191 + $this->wpstream_live_event_player($product_id);
192 + }else if( get_post_type($product_id) == 'wpstream_product_vod' ){
193 + $this->wpstream_video_on_demand_player($product_id);
194 + }else{
195 +
196 + $is_subscription_live_event = esc_html(get_post_meta($product_id,'_subscript_live_event',true));
197 +
198 + if( $term_list[0]->name=='live_stream' || ( $term_list[0]->name=='subscription' && $is_subscription_live_event=='yes' ) ){
199 + $this->wpstream_live_event_player($product_id);
200 + }else if( $term_list[0]->name=='video_on_demand' || ($term_list[0]->name=='subscription' && $is_subscription_live_event=='no' ) ){
201 + $this->wpstream_video_on_demand_player($product_id);
202 + }
203 + }
204 +
205 +
350 206 echo '</div></div>';
351 207 }else{
352 - // Logged in but not entitled: show a "not purchased" notice for paid products.
208 +
353 209 if( get_post_type($product_id) == 'product' ){
354 - $message = (string) get_option( 'wpstream_product_not_bought', 'You did not yet purchase this item.' );
355 - echo $this->not_entitled_notice( 'nobuy', $product_id, $message, 'wpstream_player_shortcode', 'background:#e16767;' );
210 + echo '<div class="wpstream_player_wrapper wpstream_player_shortcode no_buy"><div class="wpstream_player_container">';
211 + $message =esc_html( get_option('wpstream_product_not_bought','You did not yet purchase this item.')) ;
212 + echo '<div class="wpstream_notice" style="background:#e16767;">'.esc_html($message).'</div>';
213 + echo '</div></div>';
356 214 }
357 215 }
358 216
217 +
218 + }else{
219 +
220 + $product_id = intval($from_sh_id);
221 + $term_list = wp_get_post_terms($product_id, 'product_type');
222 +
223 + if( get_post_type($product_id) == 'product' && ($term_list[0]->name=='live_stream' || $term_list[0]->name=='video_on_demand') ){
224 +
225 + echo '<div class="wpstream_player_wrapper wpstream_player_shortcode no_buy"><div class="wpstream_player_container">';
226 + $message= esc_html( get_option('wpstream_product_not_login','You must be logged in to watch this video.')) ;
359 227
360 - }else{
361 - // Logged-out branch. Stable type slug is '' when the product has no term.
362 - $product_type_slug = wpstream_get_product_type_slug($product_id);
363 228
364 - if( get_post_type($product_id) == 'product' && ($product_type_slug=='live_stream' || $product_type_slug=='video_on_demand') ){
365 - // Paid live/VOD product requires login: show a "must log in" notice.
366 - $message = (string) get_option( 'wpstream_product_not_login', 'You must be logged in to watch this video.' );
367 - echo $this->not_entitled_notice( 'nolog', $product_id, $message, 'wpstream_player_shortcode', 'background:#e16767;' );
229 + echo '<div class="wpstream_notice" style="background:#e16767;">'.esc_html($message).'</div>';
230 + echo '</div></div>';
368 231 }elseif( get_post_type($product_id) == 'wpstream_product' ){
369 - // Free live product is watchable without login.
370 - echo '<div class="wpstream_player_wrapper wpstream_player_shortcode"><div class="wpstream_player_container">';
371 - echo $this->main->playback_presentation->render( $product_id, 'auto' );
232 + echo '<div class="wpstream_player_wrapper wpstream_player_shortcode"><div class="wpstream_player_container">';
233 + $this->wpstream_live_event_player($product_id);
372 234 echo '</div></div>';
373 235 } else if( get_post_type($product_id) == 'wpstream_product_vod' ){
374 - // Free VOD product is watchable without login.
375 - echo '<div class="wpstream_player_wrapper wpstream_player_shortcode"><div class="wpstream_player_container">';
376 - echo $this->main->playback_presentation->render( $product_id, 'auto' );
236 + echo '<div class="wpstream_player_wrapper wpstream_player_shortcode"><div class="wpstream_player_container">';
237 + $this->wpstream_video_on_demand_player($product_id);
377 238 echo '</div></div>';
378 239 }
379 240 }
380 241 }
@@ -381,107 +242,584 @@
381 242
382 243
383 244
384 245 /**
385 - * Strip a leading http:// or https:// scheme from a URL.
246 + * Video Player shortcode - low latency
386 247 *
387 - * @param string $url URL to normalise.
388 - * @return string URL without its leading scheme, or unchanged if none matched.
389 248 * @author cretu
390 249 */
391 - function remove_http($url) { return $this->main->playback_presentation->remove_http( $url ); }
392 250
251 + public function wpstream_video_player_shortcode_low_latency($from_sh_id='') {
252 + wp_enqueue_script('video.min');
253 + wp_enqueue_script('wpstream-player');
254 +
255 +
256 + if ( is_user_logged_in() ) {
257 + global $product;
258 + $current_user = wp_get_current_user();
259 + $product_id = intval($from_sh_id);
260 +
261 +
262 + if ( ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) && wc_customer_bought_product( $current_user->user_email, $current_user->ID, $product_id) ) || get_post_type($product_id)=='wpstream_product' ){
263 + global $product;
264 + echo '<div class="wpstream_player_wrapper wpstream_player_shortcode"><div class="wpstream_player_container">';
265 +
266 +
267 + if( get_post_type($product_id) == 'wpstream_product' ){
268 + $this->wpstream_live_event_player_low_latency($product_id);
269 + }else{
270 + $term_list = wp_get_post_terms($product_id, 'product_type');
271 + $is_subscription_live_event = esc_html(get_post_meta($product_id,'_subscript_live_event',true));
272 +
273 + if( $term_list[0]->name=='live_stream' || ( $term_list[0]->name=='subscription' && $is_subscription_live_event=='yes' ) ){
274 + $this->wpstream_live_event_player_low_latency($product_id);
275 + }
276 + }
277 +
278 +
279 + echo '</div></div>';
280 + }else{
281 +
282 + if( get_post_type($product_id) == 'product' ){
283 + echo '<div class="wpstream_player_wrapper wpstream_player_shortcode no_buy"><div class="wpstream_player_container">';
284 +
285 + $message =esc_html( get_option('wpstream_product_not_bought','You did not yet purchase this item.')) ;
286 + echo '<div class="wpstream_notice" style="background:#e16767;">'.$message.'</div>';
287 + echo '</div></div>';
288 + }
289 + }
290 +
291 +
292 + }else{
293 + $product_id = intval($from_sh_id);
294 + if( get_post_type($product_id) == 'wpstream_product' ){
295 + $this->wpstream_live_event_player_low_latency($product_id);
296 + }
297 + }
298 + }
299 +
300 +
301 +
302 +
303 +
393 304 /**
394 - * Derive the "live connect" stats URI from an event-status payload.
305 + * Live Event Player
395 306 *
396 - * @deprecated Kept because separately-installed themes may call it; the
397 - * derivation now lives in Wpstream_Channel_State.
398 - * @param array $event_status Status data from the cloud API.
399 - * @return string The stats URL, a host derived from the playback URL, or ''.
307 + * @author cretu
400 308 */
401 - function wpstream_get_live_connect_uri($event_status) {
402 - return Wpstream_Channel_State::derive_stats_url( $event_status );
309 + function remove_http($url) {
310 + $disallowed = array('http://', 'https://');
311 + foreach($disallowed as $d) {
312 + if(strpos($url, $d) === 0) {
313 + return str_replace($d, '', $url);
314 + }
315 + }
316 + return $url;
403 317 }
404 318
405 319 /**
406 - * Resolve the effective event settings for a product: per-event options when
407 - * enabled, otherwise the site-wide global channel options.
320 + * Get event settings
408 321 *
409 - * @param int $product_id Product/channel id.
410 - * @return mixed The per-event options array, or the global options.
411 322 * @author cretu
412 323 */
413 - function wpstream_return_event_settings($product_id){ return $this->main->playback_presentation->wpstream_return_event_settings( $product_id ); }
324 +
325 + function wpestream_return_event_settings($product_id){
326 +
327 + $local_event_options = get_post_meta( $product_id, 'local_event_options', true);
328 + $use_global_event_options = get_post_meta($product_id, 'use_global_event_options',true);
329 + $is_local_event_options_enabled = is_array( $local_event_options ) || intval( $use_global_event_options ) === 1;
414 330
331 + if( !$is_local_event_options_enabled ) {
332 + $local_event_options = get_option('wpstream_user_streaming_global_channel_options') ;
333 + }
334 +
335 + return $local_event_options;
336 + }
337 +
338 +
339 +
415 340 /**
416 - * Deprecated misspelled alias of wpstream_return_event_settings().
341 + * edited in 4.0
342 + *
343 + * Live Event Player
417 344 *
418 - * Kept because the method is public and may be called by external code.
419 - *
420 - * @deprecated 4.13.4 Use wpstream_return_event_settings() instead.
345 + * @author cretu
421 346 */
422 - function wpestream_return_event_settings($product_id){ return $this->wpstream_return_event_settings( $product_id ); }
347 +
348 + function wpstream_live_event_player($channel_id,$poster_show='',$use_chat=''){
349 + wp_enqueue_script('video.min');
350 + wp_enqueue_script('wpstream-player');
423 351
352 +
353 + $player_theme = $this->wpstream_get_player_theme();
354 + $now = time().rand(0,1000000);
355 + $overlay_video_div_id = "random_id_".$now;
356 + // print '<div id="'.esc_attr($overlay_video_div_id).'" class="vjs-title-overlay wpstream-video-title-overlay">'.esc_html__('Playing:','wpstream').' '.get_the_title($channel_id).'</div>';
357 +
358 +
359 + $thumb_id = get_post_thumbnail_id($channel_id);
360 + $thumb = wp_get_attachment_image_src($thumb_id,'small');
361 + $usernamestream = esc_html ( get_option('wpstream_api_username','') );
362 + $autoplay = true;
363 +
364 + $event_settings = $this->wpestream_return_event_settings($channel_id);
365 +
366 + $transient_name = 'event_data_to_return_'. $channel_id;
367 + $event_status = get_transient( $transient_name );
368 +
369 + if ( false === $event_status || $event_status=='' ) {
370 + $notes = 'wpstream_live_event_player_note';
371 + $event_status = $this->main->wpstream_live_connection-> wpstream_check_event_status_api_call($channel_id,$notes);
372 + set_transient($transient_name, $event_status, 45);
373 + }
374 +
375 + $hls_playback_url = '';
376 + $live_conect_views = '';
377 +
378 + if(isset($event_status['status']) && $event_status['status']=='active'){
379 + //live event
380 + if(isset($event_status['hls_playback_url'])){
381 + $hls_playback_url = $event_status['hls_playback_url'];
382 +
383 + update_post_meta($channel_id,'stream_name',$event_status['stream_name']);
384 + update_post_meta($channel_id,'hls_key_retrieval_url',$event_status['hls_key_retrieval_url']);
385 + delete_transient( 'free_event_streamName_'.$event_status['stream_name']);
386 +
387 + $live_conect_array = explode('live.streamer.wpstream.net',$hls_playback_url);
388 + $live_conect_views = $live_conect_array[0].'live.streamer.wpstream.net';
389 + $live_conect_views = $this->remove_http($live_conect_views);
390 +
391 + }
392 + if(isset($event_status['chat_url'])){
393 + $chat_url = $event_status['chat_url'];
394 + }
395 +
396 + }else{
397 + // event not live
398 + }
399 +
400 + if(isset($event_settings['autoplay']) && intval($event_settings['autoplay'])==0){
401 + $autoplay=false;
402 + }
403 +
404 +
405 +
406 + echo '<div class="wpstream_live_player_wrapper function_wpstream_live_event_player" data-now="'.$now.'" data-me="'.esc_attr($usernamestream).'" data-product-id="'.$channel_id.'" id="wpstream_live_player_wrapper'.$now.'" > ';
407 +
408 + $show_viewer_count = (
409 + ( isset($event_settings['view_count']) && intval($event_settings['view_count']) == 1 )
410 + || !isset($event_settings['view_count'])
411 + );
412 +
413 + echo '<div id="wpestream_live_counting" class="wpestream_live_counting" data-showviewercount="' . ($show_viewer_count ? '1' : '0') . '"></div>';
414 +
415 + $show_wpstream_not_live_mess=' style="display:none;" ';
416 + if(trim($hls_playback_url) ==''){
417 +
418 + $show_wpstream_not_live_mess='';
419 + }
420 +
421 + $message_show= esc_html( get_option('wpstream_you_are_not_live','We are not live at this moment')) ;
422 +
423 + if( function_exists('wpstream_theme_not_live_section' ) ) {
424 + print wpstream_theme_not_live_section( $channel_id );
425 + } else {
426 + print '<div class="wpstream_not_live_mess" '.$show_wpstream_not_live_mess.' style="display: none">
427 + <div class="wpstream_not_live_mess_back"></div>
428 + <div class="wpstream_not_live_mess_mess">'.esc_html($message_show).'</div>
429 + </div>';
430 + }
431 +
432 +
433 + $poster_data='';
434 + if(isset($thumb[0])){
435 + $poster_data=' poster="'.$thumb[0].'" ';
436 + }
437 + if($poster_show=='no'){
438 + $poster_data='';
439 + }
440 +
441 + $is_muted=false;
442 + if( isset($event_settings['mute']) && intval($event_settings['mute'])==1){
443 + $is_muted=true;
444 + }
445 + // override $is_muted and $autoplay here - for testing
446 + // $autoplay = true;
447 + // $is_muted = false;
448 +
449 + $autoplay_str = $autoplay ? 'autoplay' : '';
450 + $is_muted_str = $is_muted ? 'muted' : '';
451 +
452 + $video_trailer = '';
453 + $trailer_attachment_id = intval (get_post_meta( $channel_id, 'video_trailer', true ));
454 + $video_trailer = '';
455 + $video_trailer_type = '';
456 + $has_trailer_class = '';
457 + if($trailer_attachment_id!=0) {
458 + $video_trailer = wp_get_attachment_url( $trailer_attachment_id );
459 + $attachment_metadata = wp_get_attachment_metadata($trailer_attachment_id);
460 + if( isset ($attachment_metadata['mime_type']) ) {
461 + $video_trailer_type = $attachment_metadata['mime_type'];
462 + }
463 + $poster_data=''; // cancel poster for theme
464 + $has_trailer_class='wpstream_theme_player_has_trailer';
465 + }
466 +
467 + // override trailer url here - for testing
468 + // $video_trailer = '';
469 + // $video_trailer = '/wp-content/uploads/2023/10/production-ID_4608975.mp4';
470 + // $video_trailer = '/wp-content/uploads/2023/10/ultrawide.mp4';
471 +
472 +
473 +
474 + $player_logo_position = get_option('wpstream_player_logo_position');
475 + $player_logo_position_class = '';
476 + if( $player_logo_position && $player_logo_position != '' ){
477 + $player_logo_position_class = 'logo-' . explode( '-', $player_logo_position )[0];
478 + }
479 + echo'
480 + <video id="wpstream-video'.$now.'" '.$poster_data.' class="video-js vjs-default-skin vjs-fluid vjs-wpstream ' . esc_attr($has_trailer_class) . ' ' . $player_theme . ' ' . $player_logo_position_class .'" playsinline="true" '.$is_muted_str." ".$autoplay_str.'>
481 +
482 + </video>';
483 + if ($video_trailer){
484 + print '<div class="wpstream_theme_trailer_wrapper">';
485 + print '<div id="wpstream_live_video_play_trailer_btn_' . $now . '" style="display: none;" class="wpstream_video_on_demand_play_trailer">
486 + <svg width="30" height="24" viewBox="0 0 30 24" fill="none" xmlns="http://www.w3.org/2000/svg">
487 + <path fill-rule="evenodd" clip-rule="evenodd" d="M26.6667 1.5H3.33337C2.50495 1.5 1.83337 2.17157 1.83337 3V21C1.83337 21.8284 2.50495 22.5 3.33338 22.5H26.6667C27.4951 22.5 28.1667 21.8284 28.1667 21V3C28.1667 2.17157 27.4951 1.5 26.6667 1.5ZM3.33337 0C1.67652 0 0.333374 1.34315 0.333374 3V21C0.333374 22.6569 1.67652 24 3.33338 24H26.6667C28.3236 24 29.6667 22.6569 29.6667 21V3C29.6667 1.34315 28.3236 0 26.6667 0H3.33337ZM4.83337 4C4.55723 4 4.33337 4.22386 4.33337 4.5V6.16667C4.33337 6.44281 4.55723 6.66667 4.83337 6.66667H6.50004C6.77618 6.66667 7.00004 6.44281 7.00004 6.16667V4.5C7.00004 4.22386 6.77618 4 6.50004 4H4.83337ZM23.5 4C23.2239 4 23 4.22386 23 4.5V6.16667C23 6.44281 23.2239 6.66667 23.5 6.66667H25.1667C25.4428 6.66667 25.6667 6.44281 25.6667 6.16667V4.5C25.6667 4.22386 25.4428 4 25.1667 4H23.5ZM4.33337 11.167C4.33337 10.8909 4.55723 10.667 4.83337 10.667H6.50004C6.77618 10.667 7.00004 10.8909 7.00004 11.167V12.8337C7.00004 13.1098 6.77618 13.3337 6.50004 13.3337H4.83337C4.55723 13.3337 4.33337 13.1098 4.33337 12.8337V11.167ZM23.5001 10.667C23.224 10.667 23.0001 10.8909 23.0001 11.167V12.8337C23.0001 13.1098 23.224 13.3337 23.5001 13.3337H25.1668C25.4429 13.3337 25.6668 13.1098 25.6668 12.8337V11.167C25.6668 10.8909 25.4429 10.667 25.1668 10.667H23.5001ZM4.33337 17.833C4.33337 17.5569 4.55723 17.333 4.83337 17.333H6.50004C6.77618 17.333 7.00004 17.5569 7.00004 17.833V19.4997C7.00004 19.7758 6.77618 19.9997 6.50004 19.9997H4.83337C4.55723 19.9997 4.33337 19.7758 4.33337 19.4997V17.833ZM23.5001 17.333C23.224 17.333 23.0001 17.5569 23.0001 17.833V19.4997C23.0001 19.7758 23.224 19.9997 23.5001 19.9997H25.1668C25.4429 19.9997 25.6668 19.7758 25.6668 19.4997V17.833C25.6668 17.5569 25.4429 17.333 25.1668 17.333H23.5001ZM19.0677 13.0997L13.4077 16.5087C13.0434 16.7281 12.6092 16.7094 12.2661 16.5091C11.9218 16.3081 11.6666 15.9224 11.6666 15.4086V8.59072C11.6666 8.07698 11.9218 7.69125 12.2661 7.49026C12.6092 7.28999 13.0434 7.27126 13.4077 7.49064L19.0677 10.8996C19.8663 11.3805 19.8663 12.6188 19.0677 13.0997Z"/>
488 + </svg>
489 + '.esc_html__('Play Trailer', 'wpstream').'</div>';
490 + print '<div id="wpstream_live_video_mute_trailer_btn_' . $now . '" style="display: none;" class="wpstream_video_on_demand_mute_trailer">
491 + <svg width="37" height="36" viewBox="0 0 37 36" fill="none" xmlns="http://www.w3.org/2000/svg">
492 + <path fill-rule="evenodd" clip-rule="evenodd" d="M1.32143 10.0789H8.69499L18.8964 0L21.1428 0.921053V35.1316L18.8964 36L8.69499 25.8684H1.32143L0 24.5526V11.3947L1.32143 10.0789ZM10.175 23.6842L18.5 31.9474V4.10526L10.175 12.3158L9.24999 12.7105H2.64286V23.2368H9.24999L10.175 23.6842ZM37 17.9737C37.0069 22.2216 35.5329 26.3401 32.8295 29.6263L30.9478 27.7579C33.1613 24.9734 34.3629 21.5249 34.3571 17.9737C34.3571 14.2895 33.0885 10.8974 30.9637 8.21053L32.8454 6.34211C35.5382 9.62494 37.0062 13.735 37 17.9737ZM31.7143 17.9737C31.7193 20.8255 30.7895 23.6011 29.0661 25.8789L27.1738 23.9947C28.4127 22.2295 29.0752 20.1272 29.0714 17.9737C29.0751 15.8287 28.4174 13.7344 27.1871 11.9737L29.0793 10.0895C30.7338 12.2868 31.7143 15.0158 31.7143 17.9737ZM26.4286 17.9737C26.4286 19.4842 26.0057 20.8947 25.2657 22.0947L23.3126 20.1526C23.6249 19.4729 23.7876 18.7345 23.7899 17.9869C23.7922 17.2394 23.634 16.5001 23.3258 15.8184L25.2789 13.8737C26.0083 15.0684 26.4286 16.4737 26.4286 17.9737Z" fill="white"/>
493 + </svg>
494 +
495 + </div>';
496 + print '<div id="wpstream_live_video_unmute_trailer_btn_' . $now . '" style="display: none;" class="wpstream_video_on_demand_unmute_trailer">
497 + <svg width="33" height="32" viewBox="0 0 33 32" fill="none" xmlns="http://www.w3.org/2000/svg">
498 + <path fill-rule="evenodd" clip-rule="evenodd" d="M1.15625 8.85688H7.60813L16.5344 0L18.5 0.809375V30.8719L16.5344 31.635L7.60813 22.7319H1.15625L0 21.5756V10.0131L1.15625 8.85688ZM8.90313 20.8125L16.1875 28.0738V3.6075L8.90313 10.8225L8.09375 11.1694H2.3125V20.4194H8.09375L8.90313 20.8125ZM30.5967 11.3127L32.2316 12.9477L28.2287 16.9506L32.2316 20.9559L30.5967 22.5908L26.5938 18.5856L22.5885 22.5908L20.9536 20.9559L24.9588 16.9506L20.9513 12.95L22.5862 11.3151L26.5938 15.3157L30.5967 11.3127Z" fill="white"/>
499 + </svg>
500 + </div>';
501 + print '</div>';
502 + }
503 + print '<script type="text/javascript">
504 + //<![CDATA[
505 + jQuery(document).ready(function(){
506 + wpstream_player_initialize({
507 + titleOverlayElementId:"'.$overlay_video_div_id.'",
508 + videoElementId: "'.$now.'",
509 + trailerUrl: "'.$video_trailer.'",
510 + contentUrl: "'.$hls_playback_url.'",
511 + statsUri: "'.$live_conect_views.'",
512 + autoplay: '.var_export($autoplay, true).',
513 + muted: '.var_export($is_muted, true).',
514 + playTrailerButtonElementId: "wpstream_live_video_play_trailer_btn_'.$now.'",
515 + muteTrailerButtonElementId: "wpstream_live_video_mute_trailer_btn_'.$now.'",
516 + unmuteTrailerButtonElementId: "wpstream_live_video_unmute_trailer_btn_'.$now.'",
517 + });
518 + });
519 + //]]>
520 + </script>';
521 + print '</div>';
522 +
523 +
524 + if(trim($hls_playback_url) ==''){
525 + // $show_wpstream_not_live_mess='';
526 + }else{
527 + print '<script type="text/javascript">
528 + //<![CDATA[
529 + jQuery(document).ready(function(){
530 + var player_wrapper = jQuery(".wpstream_live_player_wrapper");
531 + wpstream_read_websocket_info("'.$channel_id.'","wpstream_live_player_wrapper'.$now.'", player_wrapper ,"'.$chat_url.'", "'.$hls_playback_url.'");
532 + });
533 + //]]>
534 + </script>';
535 + }
536 +
537 +
538 + if($use_chat=="yes"){
539 + $this->wpstream_connect_to_chat($channel_id);
540 + }
541 +
542 + usleep (10000);
543 +
544 + }
545 +
546 +
547 +
548 +
549 +
424 550 /**
425 - * Render the live event player for a channel.
551 + *
552 + * Edited in 4.0
553 + *
554 + *
555 + * Live Event Player
426 556 *
427 - * Fetches channel status from the cloud API (cached 45s in a transient),
428 - * then renders either the legacy Video.js markup or, when the channel has an
429 - * embedUrl, the newer iframe-based player with a minted embed key.
430 - *
431 - * edited in 4.0
432 - *
433 - * @param int $channel_id Channel/post id.
434 - * @param string $poster_show Pass 'no' to suppress the poster image.
435 - * @return void Echoes the player markup.
436 557 * @author cretu
437 558 */
438 - function wpstream_live_event_player($channel_id,$poster_show=''){ $this->main->playback_presentation->wpstream_live_event_player( $channel_id, $poster_show ); }
559 +
560 + function wpstream_live_event_player_low_latency($channel_id,$poster_show='',$use_chat=''){
561 + $usernamestream = esc_html ( get_option('wpstream_api_username','') );
562 + $thumb_id = get_post_thumbnail_id($channel_id);
563 + $thumb = wp_get_attachment_image_src($thumb_id,'small');
564 +
565 + $event_settings = $this->wpestream_return_event_settings($channel_id);
566 + $notes = 'wpstream_live_event_player_low_latency_note';
567 + $event_status = $this->main->wpstream_live_connection-> wpstream_check_event_status_api_call($channel_id,$notes);
568 + $hls_playback_url = '';
569 + $live_conect_views = '';
570 + $now = time().rand(0,10);
571 +
572 +
439 573
574 + if(isset($event_status['status']) && $event_status['status']=='active'){
575 + //live event
576 + if(isset($event_status['sldp_playback_url'])){
577 + $hls_playback_url = $event_status['sldp_playback_url'];
578 +
579 + $live_conect_array = explode('live.streamer.wpstream.net',$hls_playback_url);
580 + $live_conect_views = $live_conect_array[0].'live.streamer.wpstream.net';
581 + $live_conect_views = $this->remove_http($live_conect_views);
582 +
583 + }
584 + if(isset($event_status['chat_url'])){
585 + $chat_url =$event_status['chat_url'];
586 + }
587 +
588 + }else{
589 + // event not live
590 + }
591 +
592 +
593 +
594 +
595 + echo '<div class="wpstream_live_player_wrapper function_wpstream_live_event_player_low_latency wpstream_low_latency" data-now="'.$now.'" data-me="'.esc_attr($usernamestream).'" data-product-id="'.$channel_id.'" id="wpstream_live_player_wrapper'.$now.'" > ';
596 +
597 +
598 + if( ( isset($event_settings['view_count'] ) && intval($event_settings['view_count'])==1 ) || !isset($event_settings['view_count']) ){
599 + echo '<div id="wpestream_live_counting" class="wpestream_live_counting"></div>';
600 + }
601 +
602 + $show_wpstream_not_live_mess=' style="display:none;" ';
603 + if(trim($hls_playback_url) ==''){
604 + $show_wpstream_not_live_mess='';
605 + }
606 +
607 + $message_show= esc_html( get_option('wpstream_you_are_not_live','We are not live at this moment')) ;
608 + print '<div class="wpstream_not_live_mess " '.$show_wpstream_not_live_mess.' ><div class="wpstream_not_live_mess_back"></div><div class="wpstream_not_live_mess_mess">'. $message_show.'</div></div>';
609 +
610 +
611 + $poster_data=' poster="'.$thumb[0].'" ';
612 + if($poster_show=='no'){
613 + $poster_data='';
614 + }
615 +
616 +
617 + $is_muted='';
618 + if( isset($event_settings['mute']) && intval($event_settings['mute'])==1){
619 + $is_muted=' muted ';
620 + }
621 +
622 +
623 + $autoplay='autoplay';
624 + if(isset($event_settings['autoplay']) && intval($event_settings['autoplay'])==0){
625 + $autoplay='';
626 + }
627 +
628 + echo'
629 + <div iccd="player" id="wpstream-video'.$now.'" '.$poster_data.' '.$is_muted.' class="" >
630 + </div>';
631 +
632 + print '<script type="text/javascript">
633 + //<![CDATA[
634 + jQuery(document).ready(function(){
635 + var low_latencyid="wpstream-video'.$now.'";
636 + document.addEventListener("DOMContentLoaded", initPlayer(low_latencyid, "'.$hls_playback_url.'","'.$is_muted.'","'.$autoplay.'" ) ); ';
637 + print'});
638 + //]]>
639 + </script>';
640 +
641 +
642 +
643 + if(trim($hls_playback_url) ==''){
644 + // $show_wpstream_not_live_mess='';
645 + }else{
646 + print '<script type="text/javascript">
647 + //<![CDATA[
648 + jQuery(document).ready(function(){
649 + var player_wrapper = jQuery(".wpstream_live_player_wrapper");
650 + wpstream_read_websocket_info("'.$channel_id.'","wpstream_live_player_wrapper'.$now.'", player_wrapper ,"'.$chat_url.'", "'.$hls_playback_url.'");
651 + });
652 + //]]>
653 + </script>';
654 + }
655 +
656 +
657 + if($use_chat=="yes"){
658 + $this->wpstream_connect_to_chat($channel_id);
659 + }
660 +
661 + usleep (10000);
662 +
663 + }
664 +
665 +
440 666
667 +
668 +
441 669 /*
442 - * Ask the cloud API for a VOD's HLS manifest URL (and DRM keys/embed data).
443 - *
444 - * Persists a 5-minute transient of the HLS URL and stores decryption keys /
445 - * embed metadata as post meta. Note: the transient read is immediately
446 - * overwritten with false below, so the API is currently queried every call.
447 - *
448 - * @param string $video_name Remote video name/identifier.
449 - * @param int $product_id Product/post to store the resulting meta on.
450 - * @return string HLS URL on success, '' on failure.
670 + *
671 + * Request HLS player
672 + *
673 + *
674 + *
451 675 */
452 - public function wpstream_request_video_on_demand_hls_player($video_name,$product_id){ return $this->main->playback_presentation->wpstream_request_video_on_demand_hls_player( $video_name, $product_id ); }
676 + public function wpstream_request_video_on_demand_hls_player($video_name,$product_id){
677 + if($video_name==''){
678 + return '';
679 + }
680 +
681 + $transient_name = 'wpstream_video_on_demand_'.$video_name;
682 + $hls_to_return = get_transient( $transient_name );
683 + $hls_to_return = false;
453 684
454 - /**
455 - * Resolve the CSS class for the configured Video.js theme/skin.
456 - *
457 - * Enqueues the theme stylesheet as a side effect. Streamify users get no theme.
458 - *
459 - * @param int|null $channel_id Channel/product id (used for the streamify check).
460 - * @return string A 'vjs-theme-*' class, or '' when no theme applies.
461 - */
462 - function wpstream_get_player_theme( $channel_id = null ) { return $this->main->playback_presentation->wpstream_get_player_theme( $channel_id ); }
685 +
686 + if($hls_to_return==false){
687 +
688 + $access_token = $this->main->wpstream_live_connection->wpstream_get_token();
689 + $url = 'video/info';
463 690
464 - /**
465 - * Enqueue the bundled Video.js theme stylesheet for the selected skin.
466 - *
467 - * @param string $player_theme Theme slug (skips the built-in 'default').
468 - * @return void
469 - */
470 - function wpstream_enqueue_player_theme_style( $player_theme ) { $this->main->playback_presentation->wpstream_enqueue_player_theme_style( $player_theme ); }
691 + //corsorigin de check
692 + $local_event_options = get_option('wpstream_user_streaming_global_channel_options') ;
693 + $domain = parse_url ( get_site_url() );
694 + $domain_scheme = 'http';
695 + if(is_ssl()){
696 + $domain_scheme='https';
697 + }
471 698
699 +
700 + $wpstream_vod_domain_lock = intval( get_option('wpstream_vod_domain_lock','') ) ;
701 + $corsorigin='*';
702 + if($wpstream_vod_domain_lock !== 0 ){
703 + $corsorigin=$domain_scheme.'://'.$domain['host'];
704 + }
705 +
706 +
707 + $is_encrypt="false";
708 + $wpstream_vod_encrypt = intval( get_option('wpstream_vod_encrypt','') ) ;
709 + if( intval( $wpstream_vod_encrypt ) ==1 ){
710 + $is_encrypt="true";
711 + }
712 +
713 + $hlsKeysUrlPrefix = get_site_url().'?wpstream_voddrm=';
714 + $encrypt = $is_encrypt;
715 + $debugDrm = false;
716 +
717 + $curl_post_fields=array(
718 + 'access_token' => $access_token,
719 + 'name' => $video_name,
720 + 'corsOrigin' => $corsorigin,
721 + 'encryptHls' => $encrypt,
722 + 'hlsKeysUrlPrefix' => $hlsKeysUrlPrefix,
723 + 'debugDrm' => $debugDrm,
724 + );
725 +
726 +
727 + $curl_response = $this->main->wpstream_live_connection->wpstream_baker_do_curl_base($url,$curl_post_fields);
728 + $curl_response_decoded = json_decode($curl_response,JSON_OBJECT_AS_ARRAY);
729 +
730 + if($curl_response_decoded['success']){
731 + set_transient( $transient_name, $curl_response_decoded['hlsUrl'] ,300);
732 + $hls_to_return = $curl_response_decoded['hlsUrl'];
733 + if( isset($curl_response_decoded['hlsDecryptionKey']) && isset($curl_response_decoded['hlsDecryptionKeyIndex']) ){
734 + update_post_meta($product_id,'hlsDecryptionKey',$curl_response_decoded['hlsDecryptionKey']);
735 + update_post_meta($product_id,'hlsDecryptionKeyIndex',$curl_response_decoded['hlsDecryptionKeyIndex']);
736 + }else{
737 + delete_post_meta($product_id,'hlsDecryptionKey');
738 + delete_post_meta($product_id,'hlsDecryptionKeyIndex');
739 + }
740 +
741 + }else{
742 + return '';
743 + }
744 +
745 + }
746 +
747 + return $hls_to_return;
748 +
749 + }
750 +
751 + function wpstream_get_player_theme() {
752 + $player_theme = get_option('wpstream_video_player_theme');
753 + $is_streamify_user = $this->wpstream_is_streamify_user();
754 + if ( !empty($player_theme) && !$is_streamify_user ) {
755 + $this->wpstream_enqueue_player_theme_style( $player_theme );
756 + return 'vjs-theme-' . $player_theme;
757 + }
758 +
759 + return '';
760 + }
761 +
762 + function wpstream_enqueue_player_theme_style( $player_theme ) {
763 + if ( $player_theme != 'default' ) {
764 + wp_enqueue_style('videojs-theme-' . $player_theme, 'https://cdn.jsdelivr.net/npm/@videojs/themes@1/dist/' . $player_theme . '/index.min.css', array(), '1.0.0');
765 +
766 + }
767 + }
768 +
769 +
770 +
472 771 /**
473 - * Resolve the VOD source URL and type for a product.
772 + * VODPlayer uri details
474 773 *
475 - * Encrypted VODs (and WooCommerce products) get an HLS manifest fetched
476 - * from the cloud API; unencrypted VODs use the stored external/local URL.
477 - *
478 - * @param int $product_id Product/post id.
479 - * @return array Keys: video_path_final, wpstream_data_setup, video_type,
480 - * free_video_type, post_type.
481 774 * @author cretu
482 775 */
483 - public function wpstream_video_on_demand_player_uri_request($product_id){ return $this->main->playback_presentation->resolve_vod_source( $product_id ); }
776 + public function wpstream_video_on_demand_player_uri_request($product_id){
777 +
778 + $wpstream_data_setup = ' data-setup="{}" ';
779 +
780 + /* free_video_type
781 + * 1 - free live channel
782 + * 2 - free video encrypted
783 + * 3 - free video -not encrypted
784 + */
785 +
786 + $post_type = get_post_type($product_id);
787 + $free_video_type = intval( get_post_meta($product_id, 'wpstream_product_type', true));
788 + if( ( $post_type =='wpstream_product_vod' && $free_video_type==2 ) || get_post_type($product_id)=='product' ){
789 +
790 + /*
791 + * IF vide is encrypted- readed from vod,streaner
792 + *
793 + */
794 +
795 +
796 + $video_type = 'application/x-mpegURL';
797 + $video_path = get_post_meta($product_id,'_movie_url',true);
798 + if(get_post_type($product_id)=='wpstream_product_vod'){
799 + $video_path = esc_html(get_post_meta($product_id, 'wpstream_free_video', true));
800 + }
801 + $video_path_final = $this->wpstream_request_video_on_demand_hls_player($video_path,$product_id);
802 +
803 +
804 + }else if( $post_type =='wpstream_product_vod' && $free_video_type==3 ){
805 +
806 + /* Video is unecrypted - read from local or youtube / vimeo
807 + */
808 +
809 + $video_type = 'video/mp4';
810 + $video_path_final=esc_html(get_post_meta($product_id, 'wpstream_free_video_external', true));
811 + wp_enqueue_script('youtube.min');
812 + }
813 +
814 + $return_array = array();
815 + $return_array['video_path_final'] = $video_path_final;
816 + $return_array['wpstream_data_setup']= $wpstream_data_setup;
817 + $return_array['video_type'] = $video_type;
818 + $return_array['free_video_type'] = $free_video_type;
819 + $return_array['post_type'] = $post_type ;
820 + return $return_array;
821 + }
484 822
485 823
486 824
487 825 /**
@@ -489,73 +827,493 @@
489 827 *
490 828 * @author cretu
491 829 */
492 830
493 - public function wpstream_video_on_demand_player($product_id){ $this->main->playback_presentation->wpstream_video_on_demand_player( $product_id ); }
831 + public function wpstream_video_on_demand_player($product_id){
832 + wp_enqueue_script('video.min');
833 + wp_enqueue_script('wpstream-player');
494 834
835 + $player_theme = $this->wpstream_get_player_theme();
495 836
837 + $uri_details = $this->wpstream_video_on_demand_player_uri_request($product_id);
838 + $video_path_final = $uri_details['video_path_final'];
839 + $wpstream_data_setup = $uri_details['wpstream_data_setup'];
840 + $video_type = $uri_details['video_type'];
841 + $now = time().rand(0,1000000);
842 +
843 + $overlay_video_div_id = "random_id_".$now;
844 + print '<div id="'.esc_attr($overlay_video_div_id).'" class="vjs-title-overlay wpstream-video-title-overlay">'.esc_html__('Playing:','wpstream').' '.get_the_title($product_id).'</div>';
845 +
846 + $thumb_id = get_post_thumbnail_id($product_id);
847 + $thumb = wp_get_attachment_image_src($thumb_id,'small');
848 + $usernamestream = esc_html ( get_option('wpstream_api_username','') );
849 +
850 + $poster_thumb = '';
851 + if(isset($thumb[0])){
852 + $poster_thumb=$thumb[0];
853 + }
854 +
855 + $hlsDecryptionKey = get_post_meta($product_id,'hlsDecryptionKey',true);
856 + $hlsDecryptionKeyIndex = get_post_meta($product_id,'hlsDecryptionKeyIndex',true);
857 +
858 +
859 + $pack = $this->main->wpstream_live_connection->wpstream_request_pack_data_per_user('wpstream_video_on_demand_player');
860 +
861 +
862 +
863 + $trailer_attachment_id = intval (get_post_meta( $product_id, 'video_trailer', true ));
864 + $video_trailer = '';
865 + $video_trailer_type = '';
866 + if($trailer_attachment_id!=0) {
867 + $video_trailer = wp_get_attachment_url( $trailer_attachment_id );
868 + $attachment_metadata = wp_get_attachment_metadata($trailer_attachment_id);
869 + if( isset ($attachment_metadata['mime_type']) ) {
870 + $video_trailer_type = $attachment_metadata['mime_type'];
871 + }
872 + }
873 +
874 + // override trailer setup here (for testing)
875 + // $trailer_attachment_id = 1;
876 + // $video_trailer = '/wp-content/uploads/2023/10/production-ID_4608975.mp4';
877 + // $video_trailer = '/wp-content/uploads/2023/10/ultrawide.mp4';
878 +
879 + // If the video is self hosted or external, we should let the user see it
880 + $video_type = intval( get_post_meta($product_id, 'wpstream_product_type', true));
881 +
882 +
883 + if ( (isset($pack['available_data_mb']) && $pack['available_data_mb']>0) || $video_type === 3 ) {
884 +
885 + if($video_path_final==''){
886 + if( $uri_details['post_type']=='wpstream_product_vod' && $uri_details['free_video_type']==3 ){
887 + }else{
888 + print '<div class="wpstream_vod_notice">This video does not exist or it has been deleted!</div>';
889 + }
890 +
891 + }
892 +
893 + // TODO (crerem) populate these from VOD settings
894 + $autoplay = false;
895 + $muted = false;
896 +
897 + $wpstream_vod_start_muted = intval ( get_option('wpstream_vod_start_muted','') );
898 + if($wpstream_vod_start_muted===1){
899 + $muted=true;
900 + }
901 + $wpstream_vod_autoplay = intval ( get_option('wpstream_vod_autoplay','') );
902 + if($wpstream_vod_autoplay===1){
903 + $autoplay=true;
904 + }
905 +
906 + $poster_data = 'poster="'.esc_url($poster_thumb).'"';
907 + $has_trailer_class='';
908 + if($trailer_attachment_id !=0){
909 + $poster_data=''; // cancel poster for theme
910 + $has_trailer_class='wpstream_theme_player_has_trailer';
911 + }
912 +
913 + $player_logo_position = get_option('wpstream_player_logo_position');
914 + $player_logo_position_class = '';
915 + if( $player_logo_position && $player_logo_position!='' ){
916 + $player_logo_position_class = 'logo-' . explode( '-', $player_logo_position )[0];
917 + }
918 +
919 + echo '<video id="wpstream-video-vod-'.$now.'" class="'.esc_attr($has_trailer_class).' video-js vjs-default-skin vjs-fluid kuk wpstream_video_on_demand vjs-wpstream ' . $player_theme .' ' . $player_logo_position_class . '" data-me="'.esc_attr($usernamestream).'" data-product-id="'.$product_id.'" playsinline preload="auto"
920 + '. $poster_data.' '.$wpstream_data_setup.'>
921 + <p class="vjs-no-js">
922 + To view this video please enable JavaScript, and consider upgrading to a web browser that
923 + <a href="http://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
924 + </p>
925 + </video>';
926 +
927 + if($trailer_attachment_id !=0){
928 + print '<div class="wpstream_theme_trailer_wrapper">';
929 + print '<div id="wpstream_video_on_demand_play_trailer_btn_' . $now . '" class="wpstream_video_on_demand_play_trailer">
930 + <svg width="30" height="24" viewBox="0 0 30 24" fill="none" xmlns="http://www.w3.org/2000/svg">
931 + <path fill-rule="evenodd" clip-rule="evenodd" d="M26.6667 1.5H3.33337C2.50495 1.5 1.83337 2.17157 1.83337 3V21C1.83337 21.8284 2.50495 22.5 3.33338 22.5H26.6667C27.4951 22.5 28.1667 21.8284 28.1667 21V3C28.1667 2.17157 27.4951 1.5 26.6667 1.5ZM3.33337 0C1.67652 0 0.333374 1.34315 0.333374 3V21C0.333374 22.6569 1.67652 24 3.33338 24H26.6667C28.3236 24 29.6667 22.6569 29.6667 21V3C29.6667 1.34315 28.3236 0 26.6667 0H3.33337ZM4.83337 4C4.55723 4 4.33337 4.22386 4.33337 4.5V6.16667C4.33337 6.44281 4.55723 6.66667 4.83337 6.66667H6.50004C6.77618 6.66667 7.00004 6.44281 7.00004 6.16667V4.5C7.00004 4.22386 6.77618 4 6.50004 4H4.83337ZM23.5 4C23.2239 4 23 4.22386 23 4.5V6.16667C23 6.44281 23.2239 6.66667 23.5 6.66667H25.1667C25.4428 6.66667 25.6667 6.44281 25.6667 6.16667V4.5C25.6667 4.22386 25.4428 4 25.1667 4H23.5ZM4.33337 11.167C4.33337 10.8909 4.55723 10.667 4.83337 10.667H6.50004C6.77618 10.667 7.00004 10.8909 7.00004 11.167V12.8337C7.00004 13.1098 6.77618 13.3337 6.50004 13.3337H4.83337C4.55723 13.3337 4.33337 13.1098 4.33337 12.8337V11.167ZM23.5001 10.667C23.224 10.667 23.0001 10.8909 23.0001 11.167V12.8337C23.0001 13.1098 23.224 13.3337 23.5001 13.3337H25.1668C25.4429 13.3337 25.6668 13.1098 25.6668 12.8337V11.167C25.6668 10.8909 25.4429 10.667 25.1668 10.667H23.5001ZM4.33337 17.833C4.33337 17.5569 4.55723 17.333 4.83337 17.333H6.50004C6.77618 17.333 7.00004 17.5569 7.00004 17.833V19.4997C7.00004 19.7758 6.77618 19.9997 6.50004 19.9997H4.83337C4.55723 19.9997 4.33337 19.7758 4.33337 19.4997V17.833ZM23.5001 17.333C23.224 17.333 23.0001 17.5569 23.0001 17.833V19.4997C23.0001 19.7758 23.224 19.9997 23.5001 19.9997H25.1668C25.4429 19.9997 25.6668 19.7758 25.6668 19.4997V17.833C25.6668 17.5569 25.4429 17.333 25.1668 17.333H23.5001ZM19.0677 13.0997L13.4077 16.5087C13.0434 16.7281 12.6092 16.7094 12.2661 16.5091C11.9218 16.3081 11.6666 15.9224 11.6666 15.4086V8.59072C11.6666 8.07698 11.9218 7.69125 12.2661 7.49026C12.6092 7.28999 13.0434 7.27126 13.4077 7.49064L19.0677 10.8996C19.8663 11.3805 19.8663 12.6188 19.0677 13.0997Z"/>
932 + </svg>
933 + '.esc_html__('Play Trailer','wpstream').'</div>';
934 +
935 + print '<div class="wpstream_video_on_demand_play_video_wrapper" id="wpstream_video_on_demand_play_video_btn_' . $now . '" >
936 + <div class="wpstream_video_on_demand_play_video">
937 + <svg width="29" height="30" viewBox="0 0 29 30" fill="none" xmlns="http://www.w3.org/2000/svg">
938 + <path fill-rule="evenodd" clip-rule="evenodd" d="M6.1808 28.9035L26.274 18.1652C29.1087 16.6503 29.1087 12.7497 26.274 11.2348L6.1808 0.496557C4.88769 -0.194506 3.34623 -0.1355 2.1283 0.495357C0.906043 1.12846 1.0095e-06 2.34351 9.38766e-07 3.96179L0 25.4382C-7.07369e-08 27.0565 0.906042 28.2715 2.1283 28.9046C3.34622 29.5355 4.88769 29.5945 6.1808 28.9035ZM24.8221 13.8026C25.5742 14.2045 25.5742 15.1955 24.8221 15.5974L4.72891 26.3356C3.94628 26.7539 3.01386 26.2165 3.01386 25.4382L3.01386 3.96179C3.01386 3.18347 3.94628 2.6461 4.72891 3.06436L24.8221 13.8026Z" fill="#F1F1F1"/>
939 + </svg>
940 + </div>
941 + '.esc_html__('Play Video','wpstream').'
942 + </div>';
943 +
944 +
945 +
946 + print '<div id="wpstream_video_on_demand_mute_trailer_btn_' . $now . '" class="wpstream_video_on_demand_mute_trailer">
947 +
948 + <svg width="37" height="36" viewBox="0 0 37 36" fill="none" xmlns="http://www.w3.org/2000/svg">
949 + <path fill-rule="evenodd" clip-rule="evenodd" d="M1.32143 10.0789H8.69499L18.8964 0L21.1428 0.921053V35.1316L18.8964 36L8.69499 25.8684H1.32143L0 24.5526V11.3947L1.32143 10.0789ZM10.175 23.6842L18.5 31.9474V4.10526L10.175 12.3158L9.24999 12.7105H2.64286V23.2368H9.24999L10.175 23.6842ZM37 17.9737C37.0069 22.2216 35.5329 26.3401 32.8295 29.6263L30.9478 27.7579C33.1613 24.9734 34.3629 21.5249 34.3571 17.9737C34.3571 14.2895 33.0885 10.8974 30.9637 8.21053L32.8454 6.34211C35.5382 9.62494 37.0062 13.735 37 17.9737ZM31.7143 17.9737C31.7193 20.8255 30.7895 23.6011 29.0661 25.8789L27.1738 23.9947C28.4127 22.2295 29.0752 20.1272 29.0714 17.9737C29.0751 15.8287 28.4174 13.7344 27.1871 11.9737L29.0793 10.0895C30.7338 12.2868 31.7143 15.0158 31.7143 17.9737ZM26.4286 17.9737C26.4286 19.4842 26.0057 20.8947 25.2657 22.0947L23.3126 20.1526C23.6249 19.4729 23.7876 18.7345 23.7899 17.9869C23.7922 17.2394 23.634 16.5001 23.3258 15.8184L25.2789 13.8737C26.0083 15.0684 26.4286 16.4737 26.4286 17.9737Z" fill="white"/>
950 + </svg>
951 + </div>';
952 + print '<div id="wpstream_video_on_demand_unmute_trailer_btn_' . $now . '" class="wpstream_video_on_demand_unmute_trailer">
953 + <svg width="33" height="32" viewBox="0 0 33 32" fill="none" xmlns="http://www.w3.org/2000/svg">
954 + <path fill-rule="evenodd" clip-rule="evenodd" d="M1.15625 8.85688H7.60813L16.5344 0L18.5 0.809375V30.8719L16.5344 31.635L7.60813 22.7319H1.15625L0 21.5756V10.0131L1.15625 8.85688ZM8.90313 20.8125L16.1875 28.0738V3.6075L8.90313 10.8225L8.09375 11.1694H2.3125V20.4194H8.09375L8.90313 20.8125ZM30.5967 11.3127L32.2316 12.9477L28.2287 16.9506L32.2316 20.9559L30.5967 22.5908L26.5938 18.5856L22.5885 22.5908L20.9536 20.9559L24.9588 16.9506L20.9513 12.95L22.5862 11.3151L26.5938 15.3157L30.5967 11.3127Z" fill="white"/>
955 + </svg>
956 +
957 + </div>';
958 + print '<script type="text/javascript">
959 + //<![CDATA[
960 + jQuery(document).ready(function(){
961 + console.log("wpstream_video_on_demand_player 886");
962 + wpstream_player_initialize_vod({
963 + titleOverlayElementId:"'.$overlay_video_div_id.'",
964 + videoElementId: "wpstream-video-vod-'.$now.'",
965 + trailerUrl: "'.$video_trailer.'",
966 + videoUrl: "'.$video_path_final.'",
967 + autoplay: '.var_export($autoplay, true).',
968 + muted: '.var_export($muted, true).',
969 + playTrailerButtonElementId: "wpstream_video_on_demand_play_trailer_btn_'.$now.'",
970 + muteTrailerButtonElementId: "wpstream_video_on_demand_mute_trailer_btn_'.$now.'",
971 + unmuteTrailerButtonElementId: "wpstream_video_on_demand_unmute_trailer_btn_'.$now.'",
972 + playVideoButtonElementId: "wpstream_video_on_demand_play_video_btn_'.$now.'",
973 + playerLogoSettings: {
974 + image: "'. $this->wpstream_get_video_player_logo() . '",
975 + position: "' . esc_html( get_option('wpstream_player_logo_position','top-right') ) . '",
976 + opacity: ' . ( intval ( esc_html( get_option('wpstream_player_logo_opacity','100') ) ) / 100 ) . ',
977 + width: 100,
978 + height: "auto",
979 + padding: 10,
980 + },
981 + });
982 + });
983 + //]]>
984 + </script>';
985 + print '</div>';
986 + }
987 + else {
988 + print '<script type="text/javascript">
989 + //<![CDATA[
990 + jQuery(document).ready(function(){
991 +
992 + console.log("wpstream_video_on_demand_player 907");
993 +
994 + wpstream_player_initialize_vod({
995 + titleOverlayElementId:"'.$overlay_video_div_id.'",
996 + videoElementId: "wpstream-video-vod-'.$now.'",
997 + videoUrl: "'.$video_path_final.'",
998 + autoplay: '.var_export($autoplay, true).',
999 + muted: '.var_export($muted, true).',
1000 + playerLogoSettings: {
1001 + image: "'. $this->wpstream_get_video_player_logo() . '",
1002 + position: "' . esc_html( get_option('wpstream_player_logo_position','top-right') ) . '",
1003 + opacity: ' . ( intval ( esc_html( get_option('wpstream_player_logo_opacity','100') ) ) / 100 ) . ',
1004 + width: 100,
1005 + height: "auto",
1006 + padding: 10,
1007 + }
1008 + });
1009 + });
1010 + //]]>
1011 + </script>';
1012 + }
1013 + }else{
1014 + print '<div class="wpstream_insuficent_res">'.esc_html__('Insufficient resources to stream this title','wpstream').'</div>';
1015 + }
1016 +
1017 + }
1018 +
1019 +
496 1020
497 1021 /**
498 - * Render a VOD player that shows only the trailer (used by the theme).
1022 + * VODPlayer url - only trailer - used in theme
499 1023 *
500 - * No main video source is set; playback is limited to the trailer plus
501 - * its play/mute/unmute controls.
1024 + * @author cretu
1025 + */
1026 + public function wpstream_video_on_demand_player_only_trailer($product_id){
1027 + wp_enqueue_script('video.min');
1028 + wp_enqueue_script('wpstream-player');
1029 +
1030 +
1031 + $player_theme = $this->wpstream_get_player_theme();
1032 + $now = time().rand(0,1000000);
1033 + $overlay_video_div_id = "random_id_".$now;
1034 + print '<div id="'.esc_attr($overlay_video_div_id).'" class="vjs-title-overlay wpstream-video-title-overlay">'.esc_html__('Playing:','wpstream').' '.get_the_title($product_id).'</div>';
1035 +
1036 +
1037 +
1038 + $thumb_id = get_post_thumbnail_id($product_id);
1039 + $thumb = wp_get_attachment_image_src($thumb_id,'small');
1040 + $usernamestream = esc_html ( get_option('wpstream_api_username','') );
1041 +
1042 + $poster_thumb = '';
1043 + if(isset($thumb[0])){
1044 + $poster_thumb=$thumb[0];
1045 + }
1046 +
1047 +
1048 + $trailer_attachment_id = intval (get_post_meta( $product_id, 'video_trailer', true ));
1049 + $video_trailer = '';
1050 + $video_trailer_type = '';
1051 + if($trailer_attachment_id!=0) {
1052 + $video_trailer = wp_get_attachment_url( $trailer_attachment_id );
1053 + $attachment_metadata = wp_get_attachment_metadata($trailer_attachment_id);
1054 + if(isset($attachment_metadata['mime_type'])){
1055 + $video_trailer_type = $attachment_metadata['mime_type'];
1056 + }
1057 +
1058 + }
1059 +
1060 +
1061 + $autoplay = false;
1062 + $muted = false;
1063 +
1064 + if( intval ( get_option('wpstream_vod_start_muted','') ) === 1){
1065 + $muted = true;
1066 + }
1067 + if( intval ( get_option('wpstream_vod_autoplay','') ) === 1 ){
1068 + $autoplay = true;
1069 + }
1070 + $video_path_final='';
1071 + $has_trailer_class='wpstream_theme_player_has_trailer';
1072 +
1073 + echo '<video id="wpstream-video-vod-'.$now.'" class="video-js vjs-default-skin vjs-fluid kuk wpstream_video_on_demand vjs-wpstream '.esc_attr( $has_trailer_class ).' ' . $player_theme . '" data-me="'.esc_attr($usernamestream).'" data-product-id="'.$product_id.'" playsinline preload="auto"
1074 + >
1075 + <p class="vjs-no-js">
1076 + To view this video please enable JavaScript, and consider upgrading to a web browser that
1077 + <a href="http://videojs.com/html5-video-support/" target="_blank">supports HTML5 video</a>
1078 + </p>
1079 + </video>';
1080 +
1081 + if($trailer_attachment_id !=0){
1082 + print '<div class="wpstream_theme_trailer_wrapper">';
1083 + print '<div id="wpstream_video_on_demand_play_trailer_btn_' . $now . '" class="wpstream_video_on_demand_play_trailer">
1084 + <svg width="30" height="24" viewBox="0 0 30 24" fill="none" xmlns="http://www.w3.org/2000/svg">
1085 + <path fill-rule="evenodd" clip-rule="evenodd" d="M26.6667 1.5H3.33337C2.50495 1.5 1.83337 2.17157 1.83337 3V21C1.83337 21.8284 2.50495 22.5 3.33338 22.5H26.6667C27.4951 22.5 28.1667 21.8284 28.1667 21V3C28.1667 2.17157 27.4951 1.5 26.6667 1.5ZM3.33337 0C1.67652 0 0.333374 1.34315 0.333374 3V21C0.333374 22.6569 1.67652 24 3.33338 24H26.6667C28.3236 24 29.6667 22.6569 29.6667 21V3C29.6667 1.34315 28.3236 0 26.6667 0H3.33337ZM4.83337 4C4.55723 4 4.33337 4.22386 4.33337 4.5V6.16667C4.33337 6.44281 4.55723 6.66667 4.83337 6.66667H6.50004C6.77618 6.66667 7.00004 6.44281 7.00004 6.16667V4.5C7.00004 4.22386 6.77618 4 6.50004 4H4.83337ZM23.5 4C23.2239 4 23 4.22386 23 4.5V6.16667C23 6.44281 23.2239 6.66667 23.5 6.66667H25.1667C25.4428 6.66667 25.6667 6.44281 25.6667 6.16667V4.5C25.6667 4.22386 25.4428 4 25.1667 4H23.5ZM4.33337 11.167C4.33337 10.8909 4.55723 10.667 4.83337 10.667H6.50004C6.77618 10.667 7.00004 10.8909 7.00004 11.167V12.8337C7.00004 13.1098 6.77618 13.3337 6.50004 13.3337H4.83337C4.55723 13.3337 4.33337 13.1098 4.33337 12.8337V11.167ZM23.5001 10.667C23.224 10.667 23.0001 10.8909 23.0001 11.167V12.8337C23.0001 13.1098 23.224 13.3337 23.5001 13.3337H25.1668C25.4429 13.3337 25.6668 13.1098 25.6668 12.8337V11.167C25.6668 10.8909 25.4429 10.667 25.1668 10.667H23.5001ZM4.33337 17.833C4.33337 17.5569 4.55723 17.333 4.83337 17.333H6.50004C6.77618 17.333 7.00004 17.5569 7.00004 17.833V19.4997C7.00004 19.7758 6.77618 19.9997 6.50004 19.9997H4.83337C4.55723 19.9997 4.33337 19.7758 4.33337 19.4997V17.833ZM23.5001 17.333C23.224 17.333 23.0001 17.5569 23.0001 17.833V19.4997C23.0001 19.7758 23.224 19.9997 23.5001 19.9997H25.1668C25.4429 19.9997 25.6668 19.7758 25.6668 19.4997V17.833C25.6668 17.5569 25.4429 17.333 25.1668 17.333H23.5001ZM19.0677 13.0997L13.4077 16.5087C13.0434 16.7281 12.6092 16.7094 12.2661 16.5091C11.9218 16.3081 11.6666 15.9224 11.6666 15.4086V8.59072C11.6666 8.07698 11.9218 7.69125 12.2661 7.49026C12.6092 7.28999 13.0434 7.27126 13.4077 7.49064L19.0677 10.8996C19.8663 11.3805 19.8663 12.6188 19.0677 13.0997Z"/>
1086 + </svg>
1087 + '.esc_html__('Play Trailer','wpstream').'
1088 + </div>';
1089 + print '<div id="wpstream_video_on_demand_mute_trailer_btn_' . $now . '" class="wpstream_video_on_demand_mute_trailer">
1090 + <svg width="37" height="36" viewBox="0 0 37 36" fill="none" xmlns="http://www.w3.org/2000/svg">
1091 + <path fill-rule="evenodd" clip-rule="evenodd" d="M1.32143 10.0789H8.69499L18.8964 0L21.1428 0.921053V35.1316L18.8964 36L8.69499 25.8684H1.32143L0 24.5526V11.3947L1.32143 10.0789ZM10.175 23.6842L18.5 31.9474V4.10526L10.175 12.3158L9.24999 12.7105H2.64286V23.2368H9.24999L10.175 23.6842ZM37 17.9737C37.0069 22.2216 35.5329 26.3401 32.8295 29.6263L30.9478 27.7579C33.1613 24.9734 34.3629 21.5249 34.3571 17.9737C34.3571 14.2895 33.0885 10.8974 30.9637 8.21053L32.8454 6.34211C35.5382 9.62494 37.0062 13.735 37 17.9737ZM31.7143 17.9737C31.7193 20.8255 30.7895 23.6011 29.0661 25.8789L27.1738 23.9947C28.4127 22.2295 29.0752 20.1272 29.0714 17.9737C29.0751 15.8287 28.4174 13.7344 27.1871 11.9737L29.0793 10.0895C30.7338 12.2868 31.7143 15.0158 31.7143 17.9737ZM26.4286 17.9737C26.4286 19.4842 26.0057 20.8947 25.2657 22.0947L23.3126 20.1526C23.6249 19.4729 23.7876 18.7345 23.7899 17.9869C23.7922 17.2394 23.634 16.5001 23.3258 15.8184L25.2789 13.8737C26.0083 15.0684 26.4286 16.4737 26.4286 17.9737Z" fill="white"/>
1092 + </svg>
1093 +
1094 +
1095 + </div>';
1096 + print '<div id="wpstream_video_on_demand_unmute_trailer_btn_' . $now . '" class="wpstream_video_on_demand_unmute_trailer">
1097 + <svg width="33" height="32" viewBox="0 0 33 32" fill="none" xmlns="http://www.w3.org/2000/svg">
1098 + <path fill-rule="evenodd" clip-rule="evenodd" d="M1.15625 8.85688H7.60813L16.5344 0L18.5 0.809375V30.8719L16.5344 31.635L7.60813 22.7319H1.15625L0 21.5756V10.0131L1.15625 8.85688ZM8.90313 20.8125L16.1875 28.0738V3.6075L8.90313 10.8225L8.09375 11.1694H2.3125V20.4194H8.09375L8.90313 20.8125ZM30.5967 11.3127L32.2316 12.9477L28.2287 16.9506L32.2316 20.9559L30.5967 22.5908L26.5938 18.5856L22.5885 22.5908L20.9536 20.9559L24.9588 16.9506L20.9513 12.95L22.5862 11.3151L26.5938 15.3157L30.5967 11.3127Z" fill="white"/>
1099 + </svg>
1100 +
1101 + </div>';
1102 + print '<script type="text/javascript">
1103 + //<![CDATA[
1104 + jQuery(document).ready(function(){
1105 +
1106 + console.log("wpstream_video_on_demand_player trailer 995");
1107 +
1108 + wpstream_player_initialize_vod({
1109 + titleOverlayElementId:"'.$overlay_video_div_id.'",
1110 + videoElementId: "wpstream-video-vod-'.$now.'",
1111 + trailerUrl: "'.$video_trailer.'",
1112 + autoplay: '.var_export($autoplay, true).',
1113 + muted: '.var_export($muted, true).',
1114 + playTrailerButtonElementId: "wpstream_video_on_demand_play_trailer_btn_'.$now.'",
1115 + muteTrailerButtonElementId: "wpstream_video_on_demand_mute_trailer_btn_'.$now.'",
1116 + unmuteTrailerButtonElementId: "wpstream_video_on_demand_unmute_trailer_btn_'.$now.'",
1117 + playerLogoSettings: {
1118 + image: "'. $this->wpstream_get_video_player_logo() . '",
1119 + position: "' . esc_html( get_option('wpstream_player_logo_position','top-right') ) . '",
1120 + opacity: ' . ( intval ( esc_html( get_option('wpstream_player_logo_opacity','100') ) ) / 100 ) . ',
1121 + width: 100,
1122 + height: "auto",
1123 + padding: 10,
1124 + },
1125 + });
1126 + });
1127 + //]]>
1128 + </script>';
1129 + print '</div>';
1130 + }
1131 + else {
1132 + //just show the poster or don't show anything; no player needed
1133 + }
1134 +
1135 + }
1136 +
1137 +
1138 +
1139 + /**
1140 + *
1141 + * edited 4.0
1142 + *
1143 + * Retreive username for vod path
502 1144 *
503 - * @param int $product_id Product/post id.
504 - * @return void Echoes the trailer-only player markup.
505 1145 * @author cretu
506 1146 */
507 - public function wpstream_video_on_demand_player_only_trailer($product_id){ $this->main->playback_presentation->wpstream_video_on_demand_player_only_trailer( $product_id ); }
508 -
1147 + private function wpstream_retrive_username(){
1148 +
1149 + return get_option('wpstream_api_username_from_token');
1150 + }
1151 +
509 1152 /**
510 - * Decide whether the current user may watch the given product.
1153 + * check if the we can add display the player
511 1154 *
512 - * @deprecated Kept as a compatibility shim for separately-installed themes
513 - * that call it; the rule itself lives in wpstream_user_entitled_for_product()
514 - * (includes/Helpers/wpstream-entitlement.php). New code calls the helper.
515 - *
516 - * @param int $product_id Product id.
517 - * @return bool True when the user is entitled to watch.
518 1155 * @since 3.12
1156 + * returns html of the player
519 1157 */
1158 +
520 1159 public function wpstream_check_if_player_can_dsplay($product_id){
521 - // Delegate to the single entitlement rule.
522 - return wpstream_user_entitled_for_product( $product_id );
1160 + if ( is_user_logged_in() ) {
1161 +
1162 + $term_list = wp_get_post_terms($product_id, 'product_type');
1163 + $current_user = wp_get_current_user();
1164 + $subscription_model = intval( get_option('wpstream_global_sub','')) ;
1165 +
1166 + $product = wc_get_product($product_id);
1167 + $product_type = $product->get_type();
1168 +
1169 +
1170 + if($subscription_model==1){ // if we have Neflix mode
1171 + if( $product_type=='subscription' ){ // if the product loaded is a subscription and we are on netflix mode
1172 + return false;
1173 + }
1174 + if($this->wpstream_in_plugin_check_global_subscription_model($product_id)){
1175 + return true;
1176 + }
1177 + }else{
1178 + // ppv mode
1179 +
1180 + if( $product_type=='subscription' ){
1181 +
1182 +// $user_subscriptions = wcs_get_users_subscriptions($current_user->ID );
1183 +// foreach ($user_subscriptions as $subscription) {
1184 +// $subscription_status = $subscription->get_status();
1185 +// echo "</br>*** Subscription ID $subscription->ID for User ID $current_user->ID has status: $subscription_status";
1186 +// }
1187 +
1188 +
1189 + if( wcs_user_has_subscription( $current_user->ID, $product_id ,'active') ) {
1190 + // user has active subcription
1191 + return true;
1192 + }
1193 +
1194 + }else{
1195 + if( wc_customer_bought_product( $current_user->user_email, $current_user->ID, $product_id)){
1196 + return true;
1197 + }
1198 + }
1199 +
1200 +
1201 + }
1202 + return false;
1203 +
1204 + }
1205 + return false;
1206 +
523 1207 }
1208 +
1209 +
524 1210
525 -
526 -
527 1211 /**
528 - * Theme variant of the entitlement check.
1212 + * check if the we can add display the player - theme variant
529 1213 *
530 - * @deprecated Kept as a compatibility shim for separately-installed themes
531 - * that call it; the rule itself lives in wpstream_user_entitled_for_product()
532 - * (includes/Helpers/wpstream-entitlement.php). New code calls the helper.
533 - *
534 - * @param int $product_id Product/post id.
535 - * @return bool True when the player may be displayed.
536 1214 * @since 3.12
1215 + * returns html of the player
537 1216 */
538 1217 public function wpstream_check_if_player_can_dsplay_theme($product_id){
539 - // Delegate to the single entitlement rule.
540 - return wpstream_user_entitled_for_product( $product_id );
541 - }
1218 +
1219 + $post_type= get_post_type($product_id);
1220 +
542 1221
1222 +
1223 + if($post_type=='wpstream_product_vod' || $post_type=='wpstream_product'){
1224 + return true; // if we have free vod or live
1225 + }
543 1226
1227 +
1228 +
1229 + if ( is_user_logged_in() && $post_type==='product' ) {
1230 +
1231 + $product = wc_get_product( $product_id );
1232 + $product_type = $product->get_type();
1233 + $possible_bundle = get_post_meta($product_id, 'wpstream_part_of_bundle',true);
1234 +
1235 +
1236 +
1237 +
1238 +
1239 + $current_user = wp_get_current_user();
1240 + $subscription_model = intval( get_option('wpstream_global_sub','')) ;
1241 + // print 'subscription model '.$subscription_model.'</br>';
1242 +
1243 + if($subscription_model==1){ // if we have Neflix mode
1244 + if( $product_type=='subscription' ){ // if the product loaded is a subscription and we are on netflix mode
1245 + return false;
1246 + }
1247 + if($this->wpstream_in_plugin_check_global_subscription_model($product_id)){
1248 + return true;
1249 + }
1250 + }else{
1251 + // ppv mode
1252 + if ( wc_customer_bought_product( $current_user->user_email, $current_user->ID, $product_id) ){
1253 + return true; //simple product bought
1254 + }else if (function_exists('wcs_user_has_subscription') && wcs_user_has_subscription( $current_user->ID, $product_id ,'active') ){
1255 + return true; // subscription boght
1256 + }else if( get_post_type($product_id) =='product' &&
1257 + intval($possible_bundle )!=0 &&
1258 + wc_customer_bought_product( $current_user->user_email, $current_user->ID, $possible_bundle)
1259 + ){
1260 + return true; // part of a boght bundle
1261 + }
1262 + }
1263 + // print ' fac return false </br>';
1264 + return false;
1265 +
1266 + }
1267 + return false;
1268 +
1269 + }
1270 +
1271 +
544 1272 /**
545 - * Check the global-subscription entitlement for a product (Netflix mode).
1273 + * in plugin - check if global subscription model is enabled
546 1274 *
547 - * @deprecated Logic moved to wpstream_user_has_qualifying_global_subscription()
548 - * (includes/Helpers/wpstream-entitlement.php); kept as a compatibility shim
549 - * for external callers.
550 - *
551 - * @param int $product_id Product id.
552 - * @return bool True when the user has a qualifying active subscription.
553 1275 * @since 3.12
1276 + *
554 1277 */
555 - public function wpstream_in_plugin_check_global_subscription_model($product_id) {
556 - // Delegate to the moved Netflix-mode leg of the entitlement rule.
557 - return wpstream_user_has_qualifying_global_subscription( $product_id );
1278 + public function wpstream_in_plugin_check_global_subscription_model($product_id) {
1279 +
1280 + // $selected_sub= get_post_meta($post->ID,'_wpstream_parent_sub',true);
1281 + if( is_user_logged_in() && function_exists('wcs_user_has_subscription') ){
1282 +
1283 + global $woocommerce;
1284 + $current_user = wp_get_current_user();
1285 +
1286 + $subscription_model = intval( get_option('wpstream_global_sub','')) ;
1287 + $main_subscription = intval( get_option('wpstream_global_sub_id',''));
1288 +
1289 + if($subscription_model==1){
1290 + $selected_sub= get_post_meta($product_id,'_wpstream_parent_sub',true) ;
1291 +
1292 + if( is_array($selected_sub) ){
1293 +
1294 + // we have per product sub
1295 + foreach($selected_sub as $key=>$subscrition_id ):
1296 + if( wcs_user_has_subscription( $current_user->ID, $subscrition_id ,'active') ) {
1297 + return true;
1298 + }
1299 + endforeach;
1300 +
1301 + } else if($main_subscription!=0){
1302 +
1303 + // if we have one main subscription
1304 + if( wcs_user_has_subscription( $current_user->ID, $main_subscription ,'active') ) {
1305 + return true;
1306 + }
1307 + }
1308 +
1309 +
1310 + }
1311 + return false;
1312 +
1313 + }
1314 + // there is no woo subscription or user not logged in
1315 + return false;
558 1316 }
559 1317
560 1318
561 1319
@@ -580,53 +1338,55 @@
580 1338 *
581 1339 *
582 1340 */
583 1341 public function wpstream_user_logged_in_product_already_bought($from_sh_id='') {
584 - // Work against the current WooCommerce product on the page.
585 - global $product;
586 - if ( ! $product instanceof WC_Product ) {
1342 + if(function_exists('wpstream_remove_wpstream_filter')){
587 1343 return;
588 1344 }
589 - $product_id = $product->get_id();
590 - $current_user = wp_get_current_user();
591 - // The theme may own the player placement and switch the injection off.
592 - if ( ! $this->auto_insert_enabled( intval( $product_id ), 'woocommerce_before_single_product' ) ) {
593 - return;
594 - }
595 - // Stable type slug is '' when the product has no term (never a crash).
596 - $product_type_slug = wpstream_get_product_type_slug($product_id);
1345 + global $product;
1346 + $product_id = $product->get_id();
1347 + $current_user = wp_get_current_user();
597 1348
598 - // A "simple subscription" (neither live nor VOD) has no player here.
599 - $is_simple_subscription = get_post_meta($product_id, '_subscript_live_event');
600 - if ( $product_type_slug == 'subscription' && ! empty( $is_simple_subscription ) && $is_simple_subscription[0] == 'none' ) {
601 - return;
602 - }
603 -
604 1349 if ( is_user_logged_in() ) {
605 - if( wpstream_user_entitled_for_product($product_id) ){
606 - // Entitled: the presentation module classifies live vs VOD
607 - // (product term or subscription flag) and renders.
1350 +
1351 +
1352 + if($this->wpstream_check_if_player_can_dsplay($product_id) ){
1353 +
608 1354 echo '<div class="wpstream_player_wrapper "><div class="wpstream_player_container">';
609 - echo $this->main->playback_presentation->render( $product_id, 'auto' );
1355 +
1356 + $is_subscription_live_event = esc_html(get_post_meta($product_id,'_subscript_live_event',true));
1357 + $term_list = wp_get_post_terms($product_id, 'product_type');
1358 +
1359 +
1360 + if( $term_list[0]->name=='live_stream' || ($term_list[0]->name=='subscription' && $is_subscription_live_event=='yes' ) ){
1361 + $this->wpstream_live_event_player($product_id);
1362 + }else if( $term_list[0]->name=='video_on_demand' || ($term_list[0]->name=='subscription' && $is_subscription_live_event=='no' ) ){
1363 +
1364 + $this->wpstream_video_on_demand_player($product_id);
1365 + }
610 1366 echo '</div></div>';
611 - } else {
612 - // Not entitled: show the appropriate "no buy" message.
613 - if( $product_type_slug=='subscription' ){
614 - // For subscriptions, only prompt when there is no active subscription.
1367 + }else{
1368 +
1369 +
1370 + $term_list = wp_get_post_terms($product_id, 'product_type');
1371 +
1372 + if( $term_list[0]->name=='subscription' ){
1373 +
615 1374 if( !wcs_user_has_subscription( $current_user->ID, $product_id ,'active') ) {
616 1375 $this->wpstream_display_no_buy_message('nobuy',$product_id);
617 1376 }
618 -
1377 +
619 1378 }else{
620 1379 $this->wpstream_display_no_buy_message('nobuy',$product_id);
621 1380 }
622 -
623 -
1381 +
1382 +
1383 +
624 1384 }
625 1385
626 -
1386 +
627 1387 }else{
628 - // Logged out: prompt the visitor to log in.
1388 +
629 1389 $this->wpstream_display_no_buy_message('nolog',$product_id);
630 1390 }
631 1391 }
632 1392
@@ -634,74 +1394,184 @@
634 1394
635 1395
636 1396
637 1397 /**
1398 + *
1399 + *
1400 + * check if the user bought the product and display the player - TO REDo
1401 + *
1402 + * @since 3.0.1
1403 + * returns html of the player
1404 + */
1405 +
1406 + public function wpstream_chat_wrapper($product_id){
1407 + require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/templates/wpstream_chat_template.php';
1408 + }
1409 +
1410 +
1411 +
1412 +
1413 +
1414 +
1415 +
1416 +
1417 + /**
1418 + * coonect to chat
1419 + *
1420 + * @since 1.12.2
1421 + *
1422 + */
1423 +
1424 +
1425 +
1426 + public function wpstream_connect_to_chat($product_id){
1427 + $current_user = wp_get_current_user();
1428 + $userID = $current_user->ID;
1429 + $user_login = $current_user->user_login;
1430 +
1431 + $key='';
1432 +
1433 + $chat_url = get_post_meta($product_id,'chat_url',true);
1434 +
1435 +
1436 + wp_enqueue_script( 'sockjs-0.3.min' );
1437 + wp_enqueue_script( 'emojione.min.js' );
1438 + wp_enqueue_script( "jquery-effects-core");
1439 + wp_enqueue_script( 'jquery.linkify.min.js');
1440 + wp_enqueue_script( 'ripples.min.js');
1441 + wp_enqueue_script( 'material.min.js');
1442 + wp_enqueue_script( 'chat.js');
1443 +
1444 +
1445 +
1446 + wp_enqueue_style( 'chat.css');
1447 + wp_enqueue_style( 'ripples.css');
1448 + wp_enqueue_style( 'emojione.min.css');
1449 +
1450 +
1451 +
1452 +
1453 + if(!is_user_logged_in()){
1454 + $user_login='';
1455 + $chat_url='';
1456 + }
1457 +
1458 +
1459 + print '<script type="text/javascript">
1460 + //<![CDATA[
1461 + jQuery(document).ready(function(){
1462 + username = "'.$user_login.'";
1463 + key="'.$key.'";
1464 +
1465 + });
1466 + //]]>
1467 + </script>';
1468 +
1469 + }
1470 +
1471 +
1472 + /**
638 1473 * display no buy Message
639 - * Render the appropriate access notice ("must log in" / "not purchased" /
640 - * "not subscribed" / "subscription active") for a product.
641 1474 *
642 - * @param string $log Which case to show: 'sub_active', 'nolog', or other (nobuy).
643 - * @param int $product_id Product/post id.
644 - * @return void Echoes the notice markup.
645 1475 * @since 3.12.2
1476 + *
646 1477 */
647 1478 public function wpstream_display_no_buy_message($log,$product_id) {
648 - // Special case: subscription already active -> confirmation notice and return early.
1479 +
649 1480 if($log=='sub_active'){
650 - $message = (string) get_option( 'wpstream_subscription_active', 'Your Subscription is Active.' );
651 - echo $this->not_entitled_notice( 'sub_active', $product_id, $message );
1481 + $message= esc_html( get_option('wpstream_subscription_active','Your Subscription is Active.')) ;
1482 + echo '<div class="wpstream_player_wrapper no_buy"><div class="wpstream_player_container">';
1483 + echo '<div class="wpstream_notice"> '.$message.'</div>';
1484 + echo '</div></div>';
652 1485 return;
653 -
1486 +
654 1487 }else if($log=='nolog'){
655 - // Visitor is logged out.
656 - $reason = 'nolog';
657 - $message = (string) get_option( 'wpstream_product_not_login', 'You must be logged in to watch this video.' );
1488 + $message= esc_html( get_option('wpstream_product_not_login','You must be logged in to watch this video.')) ;
658 1489 }else{
659 - // Default: logged in but has not purchased.
660 - $reason = 'nobuy';
661 - $message = (string) get_option( 'wpstream_product_not_bought', 'You did not yet purchase this item.' );
1490 + $message =esc_html( get_option('wpstream_product_not_bought','You did not yet purchase this item.')) ;
662 1491 }
663 - // In subscription mode, swap in the "not subscribed" wording.
664 1492 $subscription_model = intval( get_option('wpstream_global_sub','')) ;
665 1493 if($subscription_model==1){
666 - $message = (string) get_option( 'wpstream_product_not_subscribe', 'You did not yet subscribe to this item.' );
1494 + $message =esc_html( get_option('wpstream_product_not_subscribe','You did not yet subscribe to this item.'));
667 1495 }
668 -
669 -
1496 +
1497 +
670 1498 if( get_post_type($product_id) == 'product' && $subscription_model==0 ){
671 - // PPV mode: only show the notice for live/VOD/subscription product types.
672 1499 $product = wc_get_product($product_id);
673 - $product_type_slug = wpstream_get_product_type_slug($product_id);
1500 + $term_list = wp_get_post_terms($product_id, 'product_type');
674 1501 $product_type = $product->get_type();
675 1502 $is_subscription_live_event = esc_html(get_post_meta($product_id,'_subscript_live_event',true));
676 1503
1504 +
677 1505
678 -
679 - if( $product_type_slug=='video_on_demand' || $product_type_slug=='live_stream' || $product_type=='subscription'){
680 - echo $this->not_entitled_notice( $reason, $product_id, $message );
1506 + if( $term_list[0]->name=='video_on_demand' || $term_list[0]->name=='live_stream' || $product_type=='subscription'){
1507 +
1508 + echo '<div class="wpstream_player_wrapper no_buy"><div class="wpstream_player_container">';
1509 + echo '<div class="wpstream_notice">'.$message.'</div>';
1510 + echo '</div></div>';
1511 +
681 1512 }
682 -
1513 +
683 1514 }else if( get_post_type($product_id) == 'product' && $subscription_model==1 ){
684 - // Subscription mode: show the notice for any non-simple product.
685 - // '' (no term) counts as non-simple, matching the pre-guard intent.
686 - if( wpstream_get_product_type_slug($product_id)!=='simple'){
687 - echo $this->not_entitled_notice( $reason, $product_id, $message );
1515 + $term_list = wp_get_post_terms($product_id, 'product_type');
1516 + if( $term_list[0]->name!=='simple'){
1517 + echo '<div class="wpstream_player_wrapper no_buy"><div class="wpstream_player_container">';
1518 + echo '<div class="wpstream_notice"> '.$message.'</div>';
1519 + echo '</div></div>';
688 1520 }
689 1521 }
1522 +
1523 +
1524 +
1525 +
1526 +
1527 +
690 1528 }
691 1529
692 1530 /**
693 1531 * Get the video player logo URL.
694 1532 *
695 - * @param int $product_id Product ID.
696 - * @return mixed|string Logo URL, the WpStream symbol for streamify users, or ''.
1533 + * @return mixed|string
697 1534 */
698 - public function wpstream_get_video_player_logo( $product_id ) { return $this->main->playback_presentation->wpstream_get_video_player_logo( $product_id ); }
1535 + public function wpstream_get_video_player_logo() {
1536 + if ( $this->wpstream_is_streamify_user() ) {
1537 + return WPSTREAM_PLUGIN_DIR_URL . 'img/default_300.png';
1538 + }
699 1539
700 - /*
701 - * Check whether a channel/product is on a basic (streamify) subscription.
1540 + $logo = get_option( 'wpstream_player_logo', '' );
1541 + if ( ! empty( $logo ) ) {
1542 + return $logo;
1543 + }
1544 + }
1545 +
1546 + /**
1547 + * Get cached pack data or request fresh pack data
702 1548 *
703 - * @param int $channel_id Channel ID
704 - * @return bool True when the 'basicStreaming' meta equals '1'.
1549 + * @param bool $force_refresh Force a refresh of the cached data
1550 + * @return array Pack data
705 1551 */
706 - public function wpstream_is_streamify_user( $channel_id ) { return $this->main->playback_presentation->wpstream_is_streamify_user( $channel_id ); }
1552 + private function wpstream_get_cached_pack_data( $force_refresh = false ) {
1553 + $cached_data = get_transient( 'wpstream_user_pack_data' );
1554 +
1555 + if ( $force_refresh || $cached_data === false ) {
1556 + $fresh_data = $this->main->wpstream_live_connection->wpstream_request_pack_data_per_user('wpstream_get_cached_pack_data');
1557 + set_transient( 'wpstream_user_pack_data', $fresh_data, 60);
1558 +
1559 + return $fresh_data;
1560 + }
1561 +
1562 + return $cached_data;
1563 + }
1564 +
1565 + public function wpstream_is_streamify_user() {
1566 + return false;
1567 +// $pack_details = $this->wpstream_get_cached_pack_data();
1568 +//
1569 +// if ( isset( $pack_details['total_data'] ) && $pack_details['total_data'] === 500 &&
1570 +// isset( $pack_details['total_storage_mb'] ) && $pack_details['total_storage_mb'] === 100 &&
1571 +// isset( $pack_details['available_data'] ) && $pack_details['available_data'] <= 0
1572 +// ) {
1573 +// return true;
1574 +// }
1575 +// return false;
1576 + }
707 1577 }