PluginProbe
WpStream – Live Streaming, Video on Demand, Pay Per View / 3.7
WpStream – Live Streaming, Video on Demand, Pay Per View v3.7
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.php +313 -852 4.14.03.7 View file →
@@ -1,5 +1,6 @@
1 1 <?php
2 +
2 3 /**
3 4 * The file that defines the core plugin class
4 5 *
5 6 * A class definition that includes attributes and functions used across both the
@@ -11,14 +12,8 @@
11 12 * @package Wpstream
12 13 * @subpackage Wpstream/includes
13 14 */
14 15
15 -
16 -// Exit if accessed directly.
17 -if ( ! defined( 'ABSPATH' ) ) {
18 - exit;
19 -}
20 -
21 16 /**
22 17 * The core plugin class.
23 18 *
24 19 * This is used to define internationalization, admin-specific hooks, and
@@ -40,10 +35,8 @@
40 35 * @since 3.0.1
41 36 * @var object The main class.
42 37 */
43 38 public $main;
44 - /** @var Wpstream_Admin The admin-area controller instance. */
45 - public $admin;
46 39
47 40 /**
48 41 * The loader that's responsible for maintaining and registering all hooks that power
49 42 * the plugin.
@@ -81,484 +74,220 @@
81 74 *
82 75 * @since 3.0.1
83 76 */
84 77
85 - /** @var Wpstream_Live_Api_Connection Cloud API client for channels/quota. */
86 78 public $wpstream_live_connection;
87 - /** @var Wpstream_Player Player/rendering service. */
88 79 public $wpstream_player;
89 - /** @var Wpstream_Quota_Manager Quota cache manager. */
90 - public $quota_manager;
91 - /** @var Wpstream_Channel_Settings Deep Module for per-Channel streaming settings. */
92 - public $channel_settings;
93 - /** @var Wpstream_Streaming_Content_Creation Deep Module for Live Channel and VOD creation. */
94 - public $streaming_content_creation;
95 - /** @var Wpstream_Drm_Key_Delivery Deep Module for live and VOD DRM Key delivery. */
96 - public $drm_key_delivery;
97 - /** @var Wpstream_Media_List Deep Module for Channel and VOD lists. */
98 - public $media_list;
99 - /** @var Wpstream_Playback_Presentation Deep Module for approved player presentation. */
100 - public $playback_presentation;
101 - /** @var object User quota service resolved from the live connection. */
102 - public $user_quota_service;
103 - /** @var mixed Unused/reserved property. */
104 80 public $xtest;
105 - /** @var Wpstream_Admin Admin controller (also stored in $admin). */
106 81 public $plugin_admin;
107 - /** @var Wpstream_Onboarding|null Lazily-created onboarding workflow module. */
108 - private $onboarding;
109 - /** @var Wpstream_Live_Channel_Presentation|null Lazily-created Live Channel presentation module. */
110 - private $live_channel_presentation;
111 -
112 - /**
113 - * Bootstrap the plugin: resolve version/name, load dependencies, then wire
114 - * all admin, public, AJAX, template, and service objects together.
115 - */
82 +
116 83 public function __construct() {
117 - // Expose this instance as the shared "main" service locator.
118 - $this->main = $this;
119 -
120 - // Resolve the plugin version from the defined constant, else fall back.
121 - if ( defined( 'WPSTREAM_PLUGIN_VERSION' ) ) {
122 - $this->version = WPSTREAM_PLUGIN_VERSION;
84 + $this->main = $this;
85 + if ( defined( 'WPSTREAM_VERSION' ) ) {
86 + $this->version = WPSTREAM_VERSION;
123 87 } else {
124 - $this->version = '3.0.1';
88 + $this->version = '3.0.1';
125 89 }
126 -
127 - // Text-domain / unique plugin identifier.
128 90 $this->plugin_name = 'wpstream';
129 91
130 - // Require class files and instantiate the hook loader.
131 92 $this->load_dependencies();
132 - // Register admin-area hooks (menus, metaboxes, WooCommerce, onboarding).
93 + $this->set_locale();
133 94 $this->define_admin_hooks();
134 - // Register public-facing hooks (scripts, endpoints, shortcodes).
135 95 $this->define_public_hooks();
136 - // Register AJAX handlers.
137 - $this->define_ajax_hooks();
138 - // Register the front-end page/single template loader.
139 - $this->wpstream_load_page_templates();
140 - // Register the "theme update available" admin notice.
141 - $this->wpstream_load_theme_notice();
96 +
97 + $this->xtest = "this is test2";
98 + $this->wpstream_conection();
99 + $this->wpstream_player();
142 100
143 - // Instantiate the cloud API connection (and user quota service).
144 - $this->wpstream_connection();
145 - // Compose the deep Channel Settings Module with its WordPress and Baker Adapters.
146 - $this->channel_settings = new Wpstream_Channel_Settings(
147 - new Wpstream_WordPress_Channel_Settings_Storage(),
148 - new Wpstream_Baker_Channel_Settings_Adapter( $this->wpstream_live_connection )
149 - );
150 - $this->wpstream_live_connection->set_channel_settings( $this->channel_settings );
151 - $this->drm_key_delivery = new Wpstream_Drm_Key_Delivery(
152 - $this->channel_settings,
153 - new Wpstream_WordPress_Drm_Key_Remote_Fetch()
154 - );
155 - $this->media_list = new Wpstream_Media_List(
156 - new Wpstream_Baker_Media_List_Active_Catalog( $this->wpstream_live_connection )
157 - );
158 - $this->playback_presentation = new Wpstream_Playback_Presentation( $this );
159 - $this->streaming_content_creation = new Wpstream_Streaming_Content_Creation(
160 - $this,
161 - $this->channel_settings,
162 - new Wpstream_Baker_Streaming_Content_Provisioning( $this->wpstream_live_connection ),
163 - new Wpstream_Baker_Streaming_Content_Recording_Catalog( $this->wpstream_live_connection )
164 - );
165 - $this->wpstream_live_connection->set_streaming_content_creation( $this->streaming_content_creation );
166 - // Instantiate the player service.
167 - $this->wpstream_player();
168 - // Instantiate the quota cache manager.
169 - $this->wpstream_init_quota_manager();
170 -
171 101 }
172 102
173 -
174 -
175 -
176 -
177 - /**
178 - * Convert a quota figure from megabytes to gigabytes.
179 - *
180 - * @param float|int $megabytes Value in megabytes.
181 - * @return float Value in gigabytes, floored to two decimals.
182 - */
183 - public function wpstream_convert_band( $megabytes ) {
184 - // Quota payloads use binary megabytes. Never round remaining allowance up.
185 - return $this->wpstream_floor_decimals( (float) $megabytes / 1024, 2 );
103 +
104 +
105 +
106 +
107 + public function wpstream_convert_band($megabits){
108 + $gigabit = $megabits * 0.001;
109 + $gigabit = number_format($gigabit,2);
110 + return $gigabit;
186 111 }
187 112
188 - /**
189 - * Floor a number to a given number of decimal places.
190 - *
191 - * @param float $value The number to floor.
192 - * @param int $decimals Number of decimal places.
193 - * @return float
194 - */
195 - public function wpstream_floor_decimals( $value, $decimals = 2 ) {
196 - // Clamp decimals to a non-negative integer.
197 - $decimals = max( 0, (int) $decimals );
198 - // Scale factor for the requested precision.
199 - $factor = pow( 10, $decimals );
200 -
201 - // Multiply, floor, divide back, then format to fixed precision.
202 - return floatval( sprintf( '%.' . $decimals . 'f', floor( (float) $value * $factor ) / $factor ) );
203 - }
204 -
205 -
206 - /** @var WpStream_Ajax The AJAX handler service. */
207 - public $wpstream_ajax;
208 -
209 - /**
210 - * Load and instantiate the AJAX handler service.
211 - */
212 - private function define_ajax_hooks() {
213 - // Construct the AJAX service with the main instance (class autoloads).
214 - $this->wpstream_ajax = new WpStream_Ajax( $this->main );
215 - }
216 -
217 -
218 - /**
219 - * Load the cloud API connection and resolve the user quota service.
220 - */
221 - private function wpstream_connection(){
222 - // Instantiate the live/cloud API client (class autoloads).
113 +
114 +
115 +
116 +
117 + private function wpstream_conection(){
118 + require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-wpstream-live-api-connection.php';
223 119 $this->wpstream_live_connection = new Wpstream_Live_Api_Connection();
224 - // Cache the user quota service exposed by the connection.
225 - $this->user_quota_service = $this->wpstream_live_connection->get_user_quota_service();
226 120 }
227 -
228 -
229 - /**
230 - * Load and instantiate the player service.
231 - */
121 +
122 +
232 123 private function wpstream_player(){
233 - // Build the player service with the main instance (class autoloads).
124 + require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-wpstream-player.php';
234 125 $this->wpstream_player = new Wpstream_Player($this->main);
235 126 }
236 -
237 - /**
238 - * Load and instantiate the quota cache manager.
239 - */
240 - private function wpstream_init_quota_manager() {
241 - // Build the quota cache manager with this main instance (class autoloads).
242 - $this->quota_manager = new Wpstream_Quota_Manager( $this );
243 - }
244 -
245 -
246 - /**
247 - * Load and register the front-end template loader.
248 - */
249 - private function wpstream_load_page_templates() {
250 - // Register the template loader's hooks by constructing it (class autoloads).
251 - new WpStream_Template_Loader();
252 - }
253 -
254 - /**
255 - * Load and register the companion-theme update admin notice.
256 - */
257 - private function wpstream_load_theme_notice() {
258 - // Register the notice by constructing it (class autoloads).
259 - new WPStream_Theme_Notice();
260 - }
261 127
262 128
129 +
130 +
263 131 /**
264 - * Load the dependencies the classmap autoloader cannot serve.
132 + * Load the required dependencies for this plugin.
265 133 *
266 - * Plugin classes resolve through Wpstream_Autoloader on first use, so this
267 - * only requires what an autoloader can never load: the WooCommerce product
268 - * types (kept behind a WooCommerce guard because they extend WC_Product)
269 - * and the function-only helper files. It then creates the hook loader that
270 - * the define_*_hooks() methods populate.
134 + * Include the following files that make up the plugin:
271 135 *
136 + * - Wpstream_Loader. Orchestrates the hooks of the plugin.
137 + * - Wpstream_i18n. Defines internationalization functionality.
138 + * - Wpstream_Admin. Defines all hooks for the admin area.
139 + * - Wpstream_Public. Defines all hooks for the public side of the site.
140 + *
141 + * Create an instance of the loader which will be used to register the hooks
142 + * with WordPress.
143 + *
272 144 * @since 3.0.1
273 145 * @access private
274 146 */
275 147 private function load_dependencies() {
276 148
277 - // WooCommerce product-type classes extend WC_Product, so loading them
278 - // without WooCommerce active would fatal at class-link time; they stay
279 - // behind this guard instead of the classmap.
280 - if( class_exists( 'WooCommerce' ) ){
281 - // Paid live-stream product type.
282 - require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-wc-product-live-stream.php';
283 - // Paid video-on-demand product type.
284 - require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-wc-product-video-on-demand.php';
285 - }
149 + /**
150 + * The class responsible for orchestrating the actions and filters of the
151 + * core plugin.
152 + */
153 + require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-wpstream-loader.php';
286 154
287 - // Function-only helper files: no class inside, so the autoloader can
288 - // never serve them and they must be required eagerly.
155 + /**
156 + * The class responsible for defining internationalization functionality
157 + * of the plugin.
158 + */
159 + require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-wpstream-i18n.php';
289 160
290 - // Channel-ownership authorization helper (wpstream_can_manage_channel),
291 - // used by every live/broadcast handler to enforce per-channel ownership.
292 - require_once plugin_dir_path(__FILE__) . 'Helpers/wpstream-authorization.php';
161 + /**
162 + * The class responsible for defining all actions that occur in the admin area.
163 + */
164 + require_once plugin_dir_path( dirname( __FILE__ ) ) . 'admin/class-wpstream-admin.php';
293 165
294 - // Viewing-entitlement helper (wpstream_user_entitled_for_product),
295 - // the single rule every playback access gate must call.
296 - require_once plugin_dir_path(__FILE__) . 'Helpers/wpstream-entitlement.php';
166 + /**
167 + * The class responsible for defining all actions that occur in the public-facing
168 + * side of the site.
169 + */
170 + require_once plugin_dir_path( dirname( __FILE__ ) ) . 'public/class-wpstream-public.php';
171 +
172 + /**
173 + * The class responsible for custom post type
174 +
175 + */
176 + require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-wpstream_product.php';
177 + if( class_exists( 'WooCommerce' ) ){
178 + require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-wc_product_live_stream.php';
179 + require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-wc_product_video_on_demand.php';
180 + }
297 181
298 - // WpStream account credential accessors (constant override + options).
299 - require_once plugin_dir_path(__FILE__) . 'Helpers/wpstream-credentials.php';
300 -
301 - // Viewer-facing presentation strings (wpstream_not_live_message), shared by
302 - // the player, the public JS config and the bundled theme framework.
303 - require_once plugin_dir_path(__FILE__) . 'Helpers/wpstream-presentation.php';
304 -
305 - // My Account list collector (wpstream_account_list_products) shared by the
306 - // event-list and video-list templates.
307 - require_once plugin_dir_path(__FILE__) . 'Helpers/wpstream-account-lists.php';
308 -
309 - // Tunables (wpstream_tunable): cache TTLs, poll intervals and limits run
310 - // through their filter and are clamped in one place.
311 - require_once plugin_dir_path(__FILE__) . 'Helpers/wpstream-tunables.php';
312 -
313 - // Create the hook loader that other define_*_hooks() methods populate.
314 182 $this->loader = new Wpstream_Loader();
315 183
316 184 }
317 185
318 186 /**
319 - * Register all of the hooks related to the admin area functionality
320 - * of the plugin.
187 + * Define the locale for this plugin for internationalization.
321 188 *
189 + * Uses the Wpstream_i18n class in order to set the domain and to register the hook
190 + * with WordPress.
191 + *
322 192 * @since 3.0.1
323 193 * @access private
324 194 */
325 - /**
326 - * Whether a post edit route can present Live Channel controls.
327 - *
328 - * @param string $post_type Current post type.
329 - * @param WP_Post|null $post Current post, when one exists.
330 - * @return bool
331 - */
332 - private function is_live_channel_admin_post( $post_type, $post = null ) {
333 - if ( 'wpstream_product' === $post_type ) {
334 - return true;
335 - }
195 + private function set_locale() {
336 196
337 - if ( 'product' !== $post_type ) {
338 - return false;
339 - }
197 + $plugin_i18n = new Wpstream_i18n();
340 198
341 - $post_id = $post instanceof WP_Post ? intval( $post->ID ) : 0;
342 - if ( ! $post_id && isset( $_GET['post'] ) ) {
343 - $post_id = absint( wp_unslash( $_GET['post'] ) );
344 - }
199 + $this->loader->add_action( 'plugins_loaded', $plugin_i18n, 'load_plugin_textdomain' );
345 200
346 - if ( $post_id ) {
347 - $product_type = wpstream_get_product_type_slug( $post_id );
348 - return 'live_stream' === $product_type
349 - || ( 'subscription' === $product_type && 'yes' === get_post_meta( $post_id, '_subscript_live_event', true ) );
350 - }
351 -
352 - return isset( $_GET['new_stream'] ) && 'new' === sanitize_key( wp_unslash( $_GET['new_stream'] ) );
353 201 }
354 202
355 203 /**
356 - * Whether the current wp-admin screen presents Live Channel controls.
204 + * Register all of the hooks related to the admin area functionality
205 + * of the plugin.
357 206 *
358 - * @param WP_Screen|null $screen Current WordPress screen.
359 - * @return bool
207 + * @since 3.0.1
208 + * @access private
360 209 */
361 - private function is_live_channel_admin_screen( $screen ) {
362 - if ( ! $screen ) {
363 - return false;
364 - }
365 -
366 - if ( 'wpstream_page_wpstream_live_channels' === $screen->base ) {
367 - return true;
368 - }
369 -
370 - global $post;
371 - return $this->is_live_channel_admin_post( $screen->post_type, $post instanceof WP_Post ? $post : null );
372 - }
373 -
374 210 private function define_admin_hooks() {
375 211
376 - // Build the admin controller and keep a reference to it.
377 - $plugin_admin = new Wpstream_Admin( $this->get_plugin_name(), $this->get_version(), $this->main );
212 + $this->admin= $plugin_admin = new Wpstream_Admin( $this->get_plugin_name(), $this->get_version(), $this->main );
378 213
379 - $this->admin = $plugin_admin;
380 -
381 - // Admin CSS/JS and the plugin's admin menu (late priority).
382 - $this->loader->add_action( 'admin_enqueue_scripts', $plugin_admin, 'enqueue_styles' );
383 - $this->loader->add_action( 'admin_enqueue_scripts', $plugin_admin, 'enqueue_scripts' );
384 - add_action(
385 - 'admin_enqueue_scripts',
386 - function () {
387 - $screen = get_current_screen();
388 - if ( $this->is_live_channel_admin_screen( $screen ) ) {
389 - $this->get_live_channel_presentation()->enqueue_assets();
390 - }
391 - },
392 - 20
393 - );
214 +
215 +
216 + $this->loader->add_action( 'admin_enqueue_scripts', $plugin_admin, 'enqueue_styles' );
217 + $this->loader->add_action( 'admin_enqueue_scripts', $plugin_admin, 'enqueue_scripts' );
394 218 $this->loader->add_action( 'admin_menu', $plugin_admin, 'wpstream_manage_admin_menu',999);
395 -
396 - // "Chat Room" metabox: bind an existing Better Messages room to a channel.
397 - new Wpstream_Chat_Room_Binding();
398 -
399 - // Register the custom post types on init.
219 +
400 220 $plugin_post_types = new Wpstream_Product();
401 221 $this->loader->add_action( 'init', $plugin_post_types, 'create_custom_post_type', 999 );
402 -
222 +
403 223 // save and render metaboxed
404 - // Register product metaboxes; persist their values on save; and,
405 - // on publish, create the remote streaming channel.
406 - $this->loader->add_action( 'add_meta_boxes', $plugin_admin, 'add_wpstream_product_metaboxes' );
407 - $this->loader->add_action( 'save_post', $plugin_admin, 'wpstream_free_product_update_post',1,2 );
408 - $this->loader->add_action( 'publish_wpstream_product', $plugin_admin, 'wpstream_publish_wpstream_product',1,2 );
409 - $this->loader->add_action( 'publish_wpstream_product', $plugin_admin, 'wpstream_create_remote_channel_on_publish',20,2 );
410 - $this->loader->add_action( 'publish_wpstream_product_vod', $plugin_admin, 'wpstream_create_remote_channel_on_publish', 20, 2 );
411 - $this->loader->add_action( 'publish_product', $plugin_admin, 'wpstream_create_remote_channel_on_publish', 20, 2 );
412 - // Mirror of the publish hooks above: a permanently deleted Live
413 - // Channel is deleted at the service too (trash is untouched).
414 - $this->loader->add_action( 'before_delete_post', $plugin_admin, 'wpstream_delete_remote_channel_on_delete', 10, 2 );
415 - $this->loader->add_action( 'before_delete_post', $plugin_admin, 'wpstream_invalidate_vod_drm_on_delete', 5, 2 );
416 - $this->loader->add_action( 'transition_post_status', $plugin_admin, 'wpstream_invalidate_vod_drm_on_status_change', 10, 3 );
417 - // WooCommerce restores products to their previous published status.
418 - // Paid Live Channels follow the safer channel lifecycle instead:
419 - // restore as draft and require an explicit republish.
420 - $this->loader->add_filter( 'wp_untrash_post_status', $plugin_admin, 'wpstream_paid_live_untrash_status', 20, 3 );
421 -
422 -
423 -
224 + $this->loader->add_action( 'admin_init', $plugin_admin, 'add_wpstream_product_metaboxes' );
225 + $this->loader->add_action( 'save_post', $plugin_admin, 'wpstream_free_product_update_post',1,2 );
226 +
424 227 // make product virtual
425 228 $this->loader->add_action( 'save_post', $plugin_admin, 'wpstream_make_product_virtual', 99999, 2 );
426 -
427 -
428 -
429 - // Add Live Channel controls only on edit screens that can own them.
430 - add_action(
431 - 'add_meta_boxes',
432 - function ( $post_type, $post ) {
433 - if ( $this->is_live_channel_admin_post( $post_type, $post ) ) {
434 - $this->get_live_channel_presentation()->register_metaboxes();
435 - }
436 - },
437 - 10,
438 - 2
439 - );
440 -
441 - // Load onboarding only when its page assets or one of its AJAX routes runs.
442 - add_action(
443 - 'admin_enqueue_scripts',
444 - function () {
445 - $screen = get_current_screen();
446 - $is_quickstart = $screen && 'wpstream_page_wpstream_onboard' === $screen->base;
447 - $is_post_edit = isset( $_GET['onboard'] ) && 'yes' === $_GET['onboard'];
448 -
449 - if ( $is_quickstart || $is_post_edit ) {
450 - $this->get_onboarding()->enqueue_assets();
451 - }
452 - },
453 - 20
454 - );
455 -
456 - $onboarding_ajax_actions = array(
457 - 'wpstream_on_board_create_channel',
458 - 'wpstream_on_board_create_channel_ppv',
459 - 'wpstream_on_board_create_free_vod',
460 - 'wpstream_on_board_create_ppv_vod',
461 - 'wpstream_on_board_login',
462 - 'wpstream_on_board_register',
463 - 'wpstream_get_captcha_challenge',
464 - );
465 - foreach ( $onboarding_ajax_actions as $onboarding_ajax_action ) {
466 - add_action(
467 - 'wp_ajax_' . $onboarding_ajax_action,
468 - function () use ( $onboarding_ajax_action ) {
469 - return $this->get_onboarding()->handle_ajax( $onboarding_ajax_action );
470 - }
471 - );
472 - }
473 229
474 - // Register AJAX actions for multipart uploads
475 - $this->loader->add_action( 'wp_ajax_wpstream_initiate_multipart_upload', $plugin_admin, 'handle_initiate_multipart_upload' );
476 - $this->loader->add_action( 'wp_ajax_wpstream_complete_multipart_upload', $plugin_admin, 'handle_complete_multipart_upload' );
477 -
478 - // General and plugin-update admin notices.
479 - $this->loader->add_action( 'admin_notices', $plugin_admin,'wpstream_admin_notice' );
480 - $this->loader->add_action( 'admin_notices', $plugin_admin,'wpstream_plugin_update_available_notice' );
481 -
482 - // Dismiss-cache-notice AJAX endpoint.
483 - $this->loader->add_action( 'wp_ajax_wpstream_update_cache_notice', $plugin_admin,'wpstream_update_cache_notice' );
484 -// $this->loader->add_action( 'wp_ajax_wpstream_get_videos_list', $plugin_admin,'wpstream_get_videos_list' );
485 -
486 -
487 - // Settings-tab "update plugin" AJAX endpoint.
488 - $this->loader->add_action( 'wp_ajax_wpstream_settings_tab_update_plugin', $plugin_admin, 'wpstream_settings_tab_update_plugin' );
489 -
230 +
231 +
232 + // show streaming controls on sidebar
233 + $this->loader->add_action('add_meta_boxes', $plugin_admin, 'wpstream_startstreaming_sidebar_meta');
234 +
235 +
236 + $this->loader->add_action( 'admin_notices', $plugin_admin,'wpstream_admin_notice' );
237 + $this->loader->add_action( 'wp_ajax_wpstream_update_cache_notice', $plugin_admin,'wpstream_update_cache_notice' );
238 +
490 239 // add and save category extra fields
491 - // The same add/edit/create/save callbacks are shared across every taxonomy below.
492 240 $this->loader->add_action( 'category_edit_form_fields', $plugin_post_types, 'wpstream_category_callback_function', 10, 2);
493 - $this->loader->add_action( 'category_add_form_fields', $plugin_post_types, 'wpstream_category_callback_add_function' );
241 + $this->loader->add_action( 'category_add_form_fields', $plugin_post_types, 'wpstream_category_callback_add_function', 10, 2 );
494 242 $this->loader->add_action( 'created_category', $plugin_post_types, 'wpstream_category_save_extra_fields_callback', 10, 2);
495 243 $this->loader->add_action( 'edited_category', $plugin_post_types, 'wpstream_category_save_extra_fields_callback', 10, 2);
496 244
497 - // Same extra fields on the WooCommerce product category taxonomy.
498 245 $this->loader->add_action( 'product_cat_edit_form_fields', $plugin_post_types, 'wpstream_category_callback_function', 10, 2);
499 - $this->loader->add_action( 'product_cat_add_form_fields', $plugin_post_types, 'wpstream_category_callback_add_function' );
246 + $this->loader->add_action( 'product_cat_add_form_fields', $plugin_post_types, 'wpstream_category_callback_add_function', 10, 2 );
500 247 $this->loader->add_action( 'created_product_cat', $plugin_post_types, 'wpstream_category_save_extra_fields_callback', 10, 2);
501 248 $this->loader->add_action( 'edited_product_cat', $plugin_post_types, 'wpstream_category_save_extra_fields_callback', 10, 2);
502 249
503 250
504 - // Same extra fields on the plugin's own wpstream_category taxonomy.
505 251 $this->loader->add_action( 'wpstream_category_edit_form_fields', $plugin_post_types, 'wpstream_category_callback_function', 10, 2);
506 - $this->loader->add_action( 'wpstream_category_add_form_fields', $plugin_post_types, 'wpstream_category_callback_add_function' );
252 + $this->loader->add_action( 'wpstream_category_add_form_fields', $plugin_post_types, 'wpstream_category_callback_add_function', 10, 2 );
507 253 $this->loader->add_action( 'created_wpstream_category', $plugin_post_types, 'wpstream_category_save_extra_fields_callback', 10, 2);
508 254 $this->loader->add_action( 'edited_wpstream_category', $plugin_post_types, 'wpstream_category_save_extra_fields_callback', 10, 2);
509 255
510 256
511 - // Same extra fields on the wpstream_actors taxonomy.
512 257 $this->loader->add_action( 'wpstream_actors_edit_form_fields', $plugin_post_types, 'wpstream_category_callback_function', 10, 2);
513 - $this->loader->add_action( 'wpstream_actors_add_form_fields', $plugin_post_types, 'wpstream_category_callback_add_function' );
258 + $this->loader->add_action( 'wpstream_actors_add_form_fields', $plugin_post_types, 'wpstream_category_callback_add_function', 10, 2 );
514 259 $this->loader->add_action( 'created_wpstream_actors', $plugin_post_types, 'wpstream_category_save_extra_fields_callback', 10, 2);
515 260 $this->loader->add_action( 'edited_wpstream_actors', $plugin_post_types, 'wpstream_category_save_extra_fields_callback', 10, 2);
516 261
517 - // Same extra fields on the wpstream_movie_rating taxonomy.
518 262 $this->loader->add_action( 'wpstream_movie_rating_edit_form_fields', $plugin_post_types, 'wpstream_category_callback_function', 10, 2);
519 - $this->loader->add_action( 'wpstream_movie_rating_add_form_fields', $plugin_post_types, 'wpstream_category_callback_add_function' );
263 + $this->loader->add_action( 'wpstream_movie_rating_add_form_fields', $plugin_post_types, 'wpstream_category_callback_add_function', 10, 2 );
520 264 $this->loader->add_action( 'created_wpstream_movie_rating', $plugin_post_types, 'wpstream_category_save_extra_fields_callback', 10, 2);
521 265 $this->loader->add_action( 'edited_wpstream_movie_rating', $plugin_post_types, 'wpstream_category_save_extra_fields_callback', 10, 2);
266 +
267 +
522 268
523 269
524 - // WooCommerce-only admin hooks: register the custom product types,
525 - // their data tabs/fields, pricing visibility, and add-to-cart handling.
526 - // Deferred to plugins_loaded because WooCommerce may load after this
527 - // plugin, and detection uses class_exists (not the active_plugins
528 - // option) so network-activated WooCommerce on multisite is seen too.
529 - // Registered directly (not via the loader) because the loader runs
530 - // before plugins_loaded fires; every hook below fires later than
531 - // plugins_loaded, so nothing is missed by the deferral.
532 - add_action( 'plugins_loaded', function () use ( $plugin_admin ) {
533 - // Without WooCommerce none of these hooks have anything to do.
534 - if ( ! class_exists( 'WooCommerce' ) ) {
535 - return;
536 - }
270 + if ( in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) {
271 +
272 + $this->loader->add_filter( 'product_type_selector', $plugin_admin, 'wpstream_add_products' );
273 + $this->loader->add_action( 'admin_footer', $plugin_admin, 'wpstream_products_custom_js' );
274 + $this->loader->add_filter( 'woocommerce_product_data_tabs', $plugin_admin, 'wpstream_hide_attributes_data_panel',10,1 );
275 +
276 + $this->loader->add_filter( 'woocommerce_product_options_general_product_data',$plugin_admin, 'wpstream_add_custom_general_fields', 10,1);
277 + $this->loader->add_filter( 'woocommerce_process_product_meta',$plugin_admin, 'wpstream_add_custom_general_fields_save',10,1 );
278 + $this->loader->add_action( 'woocommerce_live_stream_add_to_cart', $plugin_admin, 'wpstream_add_to_cart',10,1);
279 + $this->loader->add_action( 'woocommerce_video_on_demand_add_to_cart', $plugin_admin, 'wpstream_add_to_cart',10,1);
280 + $this->loader->add_filter( 'woocommerce_loop_add_to_cart_link', $plugin_admin,'replacing_add_to_cart_button', 10, 2 );
281 + }
282 +
283 +
284 +
285 +
537 286
538 - // Register product types and map them to their PHP classes.
539 - add_action( 'init', array( $plugin_admin, 'wpstream_add_custom_wc_products' ) );
540 - add_filter( 'product_type_selector', array( $plugin_admin, 'wpstream_add_products' ) );
541 - add_filter( 'woocommerce_product_class', array( $plugin_admin, 'wpstream_add_products_class' ), 10, 2 );
542 - // Pricing-field visibility, tab hiding, and purchasability rules.
543 - add_action( 'admin_enqueue_scripts', array( $plugin_admin, 'wpstream_enqueue_wc_product_pricing_visibility' ), 20 );
544 - add_filter( 'woocommerce_product_data_tabs', array( $plugin_admin, 'wpstream_hide_attributes_data_panel' ), 10, 1 );
545 - add_filter( 'woocommerce_is_purchasable', array( $plugin_admin, 'wpstream_hide_buy_now_subscription_mode' ), 10, 2 );
546 287
547 - // Custom general-tab fields (render + save) and add-to-cart wiring.
548 - add_action( 'woocommerce_product_options_general_product_data', array( $plugin_admin, 'wpstream_add_custom_general_fields' ), 20 );
549 - add_filter( 'woocommerce_process_product_meta', array( $plugin_admin, 'wpstream_add_custom_general_fields_save' ), 10, 1 );
550 - add_action( 'woocommerce_process_product_meta', array( $plugin_admin, 'wpstream_initialize_paid_streaming_product' ), 30, 1 );
551 - add_action( 'woocommerce_live_stream_add_to_cart', array( $plugin_admin, 'wpstream_add_to_cart' ), 10, 1 );
552 - add_action( 'woocommerce_video_on_demand_add_to_cart', array( $plugin_admin, 'wpstream_add_to_cart' ), 10, 1 );
553 - add_filter( 'woocommerce_loop_add_to_cart_link', array( $plugin_admin, 'replacing_add_to_cart_button' ), 10, 2 );
554 - } );
555 288 }
556 289
557 -
558 -
559 -
560 -
561 290 /**
562 291 * Register all of the hooks related to the public-facing functionality
563 292 * of the plugin.
564 293 *
@@ -566,68 +295,38 @@
566 295 * @access private
567 296 */
568 297 private function define_public_hooks() {
569 298
570 - // Build the public-facing controller.
571 299 $plugin_public = new Wpstream_Public( $this->get_plugin_name(), $this->get_version(), $this->main );
572 300
573 - // Front-end styles.
574 301 $this->loader->add_action( 'wp_enqueue_scripts', $plugin_public, 'enqueue_styles' );
575 - // Registered on `wp` (not `wp_enqueue_scripts`/`wp_head`) because block themes render
576 - // the Post Content block - and thus our `the_content` filter that enqueues/localizes
577 - // these scripts - before `wp_head` ever fires, leaving the handles unregistered.
578 - $this->loader->add_action( 'wp', $plugin_public, 'enqueue_scripts' );
302 + $this->loader->add_action( 'wp_enqueue_scripts', $plugin_public, 'enqueue_scripts' );
303 +
304 + $this->loader->add_action( 'init', $plugin_public,'wpstream_my_custom_endpoints' );
305 + $this->loader->add_filter( 'query_vars',$plugin_public, 'wpstream_my_custom_query_vars', 0 );
306 +
307 + //live stream action
308 + $this->loader->add_action('init',$plugin_public,'wpstream_set_cookies',0);
309 + $this->loader->add_action('init',$plugin_public,'wpstream_live_streaming_key');
310 + $this->loader->add_action('init',$plugin_public,'wpstream_live_streaming_key_for_3rdparty');
311 + $this->loader->add_action('init',$plugin_public,'wpstream_live_streaming_key_vod');
312 + // woo action
313 +
314 + $this->loader->add_action( 'woocommerce_before_single_product', $plugin_public,'wpstream_non_image_content_wrapper_start', 20 );
315 + $this->loader->add_action( 'woocommerce_after_single_product', $plugin_public,'wpstream_non_image_content_wrapper_end', 20 );
316 +
317 + $this->loader->add_filter( 'woocommerce_account_menu_items', $plugin_public,'wpstream_custom_my_account_menu_items' );
318 + $this->loader->add_action( 'woocommerce_account_event-list_endpoint', $plugin_public,'wpstream_custom_endpoint_content_event_list' );
319 + $this->loader->add_action( 'woocommerce_account_video-list_endpoint', $plugin_public,'wpstream_custom_endpoint_video_list' );
320 +
579 321
580 - // Custom rewrite endpoints and their query vars.
581 - $this->loader->add_action( 'init', $plugin_public,'wpstream_my_custom_endpoints' );
582 - $this->loader->add_filter( 'query_vars',$plugin_public, 'wpstream_my_custom_query_vars', 0 );
583 -
584 - //live stream action
585 - // Streaming cookies plus the RTMP/3rd-party/VOD streaming-key handlers.
586 - $this->loader->add_action('init',$plugin_public,'wpstream_set_cookies',0);
587 - $this->loader->add_action('init',$plugin_public,'wpstream_live_streaming_key');
588 - $this->loader->add_action('init',$plugin_public,'wpstream_live_streaming_key_for_3rdparty');
589 - $this->loader->add_action('init',$plugin_public,'wpstream_live_streaming_key_vod',10);
590 -
591 - // woo action
592 - // Product-page content wrappers and order/email extras.
593 - $this->loader->add_action( 'woocommerce_before_single_product', $plugin_public,'wpstream_non_image_content_wrapper_start', 20 );
594 - $this->loader->add_action( 'woocommerce_after_single_product', $plugin_public,'wpstream_non_image_content_wrapper_end', 20 );
595 - $this->loader->add_action( 'woocommerce_thankyou_order_received_text', $plugin_public,'wpstream_thankyou_extra', 20,2 );
596 - $this->loader->add_action( 'woocommerce_email_order_details', $plugin_public,'wpstream_email_order_details', 20,4 );
597 -
598 - // My Account: add the Events/Videos menu items and their endpoint content.
599 - // Run after themes have built their account navigation so a theme that
600 - // replaces the menu cannot discard the plugin-owned Events/Videos links.
601 - $this->loader->add_filter( 'woocommerce_account_menu_items', $plugin_public, 'wpstream_custom_my_account_menu_items', 99 );
602 - $this->loader->add_action( 'woocommerce_account_event-list_endpoint', $plugin_public,'wpstream_custom_endpoint_content_event_list' );
603 - $this->loader->add_action( 'woocommerce_account_video-list_endpoint', $plugin_public,'wpstream_custom_endpoint_video_list' );
604 -
605 - // Flush rewrite rules on theme switch; register plugin and WPBakery shortcodes.
606 - $this->loader->add_action( 'after_switch_theme', $plugin_public,'wpstream_custom_flush_rewrite_rules' );
607 - $this->loader->add_action('init', $plugin_public,'wpstream_shortcodes');
608 - $this->loader->add_action('vc_before_init', $plugin_public,'wpstream_bakery_shortcodes');
609 -
610 - // CORS preflight check for the API (uses a plain function callback).
611 - $this->loader->add_action('wo_before_api', 'wpstream_cors_check_and_response',10,1);
612 -
613 - // Theme-integration filters/actions: search, sidebars, archives, and
614 - // author/episode/past-broadcast content resolution by post type.
615 - $this->loader->add_filter( 'wpstream_search_template_item_post_type', $plugin_public, 'wpstream_search_template_add_item_post_type' );
616 - $this->loader->add_filter( 'wpstream_sidebar_id_by_post_type', $plugin_public, 'wpstream_sidebar_id_by_post_type' );
617 - $this->loader->add_filter( 'wpstream_header_search_values', $plugin_public, 'wpstream_header_search_values' );
618 - $this->loader->add_filter( 'wpstream_extend_category_archive_query_filter', $plugin_public, 'wpstream_extend_category_archive_query_filter_callback' );
619 - $this->loader->add_filter( 'wpstream_archives_lists_taxonomy_labels', $plugin_public, 'wpstream_archives_lists_taxonomy_labels_callback' );
620 - $this->loader->add_filter( 'wpstream_author_archive_list_taxonomy_labels', $plugin_public, 'wpstream_author_archive_list_taxonomy_labels_callback' );
621 - $this->loader->add_action( 'wpstream_vod_attached_to_channel', $plugin_public, 'wpstream_vod_attached_to_channel' );
622 - $this->loader->add_action( 'wpstream_additional_content_post_type', $plugin_public, 'wpstream_additional_content_post_type_callback' );
623 - $this->loader->add_action( 'wpstream_post_author_content_post_type_list', $plugin_public, 'wpstream_post_author_content_post_type_list_callback' );
624 - $this->loader->add_action( 'wpstream_author_content_simple_post_type_message', $plugin_public, 'wpstream_author_content_simple_post_type_message_callback', 10, 2 );
625 - $this->loader->add_action( 'wpstream_author_content_post_type_message', $plugin_public, 'wpstream_author_content_post_type_message_callback', 10, 2 );
626 - $this->loader->add_action( 'wpstream_show_sidebar_for_post_type', $plugin_public, 'wpstream_show_sidebar_for_post_type_callback', 10, 2 );
627 - $this->loader->add_action( 'wpstream_video_episodes_post_type', $plugin_public, 'wpstream_video_episodes_post_type_callback' );
628 - $this->loader->add_action( 'wpstream_video_past_broadcast_post_type', $plugin_public, 'wpstream_video_past_broadcast_post_type_callback' );
629 - $this->loader->add_action( 'wpstream_additional_content_post_type_label', $plugin_public, 'wpstream_additional_content_post_type_label_callback', 10, 2 );
322 + $this->loader->add_action( 'after_switch_theme', $plugin_public,'wpstream_custom_flush_rewrite_rules' );
323 + $this->loader->add_action('init', $plugin_public,'wpstream_shortcodes');
324 +
325 + $this->loader->add_action('wo_before_api', 'wpstream_cors_check_and_response',10,1);
326 +
327 +
328 +
630 329 }
631 330
632 331 /**
633 332 * Run the loader to execute all of the hooks with WordPress.
@@ -634,9 +333,8 @@
634 333 *
635 334 * @since 3.0.1
636 335 */
637 336 public function run() {
638 - // Hand off to the loader, which calls add_action/add_filter for every hook.
639 337 $this->loader->run();
640 338 }
641 339
642 340 /**
@@ -646,9 +344,8 @@
646 344 * @since 3.0.1
647 345 * @return string The name of the plugin.
648 346 */
649 347 public function get_plugin_name() {
650 - // Return the stored text-domain / identifier string.
651 348 return $this->plugin_name;
652 349 }
653 350
654 351 /**
@@ -657,9 +354,8 @@
657 354 * @since 3.0.1
658 355 * @return Wpstream_Loader Orchestrates the hooks of the plugin.
659 356 */
660 357 public function get_loader() {
661 - // Return the hook loader instance.
662 358 return $this->loader;
663 359 }
664 360
665 361 /**
@@ -668,193 +364,40 @@
668 364 * @since 3.0.1
669 365 * @return string The version number of the plugin.
670 366 */
671 367 public function get_version() {
672 - // Return the resolved plugin version string.
673 368 return $this->version;
674 369 }
675 -
676 - /**
677 - * Return the onboarding workflow, creating it only when an onboarding route
678 - * actually needs it.
679 - *
680 - * @return Wpstream_Onboarding
681 - */
682 - public function get_onboarding() {
683 - if ( ! $this->onboarding ) {
684 - $this->onboarding = new Wpstream_Onboarding( $this );
685 - }
686 -
687 - return $this->onboarding;
688 - }
689 -
690 - /**
691 - * Return the Live Channel admin presentation, creating it only when a
692 - * relevant screen or shared go-live card needs it.
693 - *
694 - * @return Wpstream_Live_Channel_Presentation
695 - */
696 - public function get_live_channel_presentation() {
697 - if ( ! $this->live_channel_presentation ) {
698 - $this->live_channel_presentation = new Wpstream_Live_Channel_Presentation( $this );
699 - }
700 -
701 - return $this->live_channel_presentation;
702 - }
703 -
704 - /**
705 - * Whether WordPress currently reports a pending update for this plugin.
706 - *
707 - * @return bool True when an update is available in the update_plugins transient.
708 - */
709 - public function is_plugin_outdated(){
710 - // WordPress caches pending plugin updates in this site transient.
711 - $update_data = get_site_transient('update_plugins');
712 - // The plugin's basename key within that transient.
713 - $plugin_path = 'wpstream/wpstream.php';
714 -
715 - // Presence of a response entry means an update is offered.
716 - if (isset($update_data->response[$plugin_path])) {
717 - return true;
718 - }
719 -
720 - // No entry -> up to date.
721 - return false;
722 - }
723 -
724 -
370 +
371 +
725 372
726 - /**
727 - * Print the account resource summary (data/storage or hours) shown in the UI.
728 - *
729 - * @param array $pack_details Quota payload for the current account.
730 - */
731 373 public function show_user_data($pack_details){
732 - // Branch A: data/storage (megabyte) plans - when NOT using streaming hours.
733 - if ( ! isset( $pack_details['use_streaming_hours'] ) || $pack_details['use_streaming_hours'] !== true ) {
734 - // Only render when both data and storage figures are present.
735 - if ( isset( $pack_details['available_data_mb'] ) && isset( $pack_details['available_storage_mb'] ) ) {
736 - // Convert available data MB to GB, clamping negatives to zero.
737 - $wpstream_convert_band = $this->wpstream_convert_band( $pack_details['available_data_mb'] );
738 - if ( $wpstream_convert_band < 0 ) {
739 - $wpstream_convert_band = 0;
740 - }
374 + if( isset($pack_details['band']) && isset( $pack_details['storage']) ){
375 + $wpstream_convert_band = $this->wpstream_convert_band($pack_details['band']);
376 + if($wpstream_convert_band<0)$wpstream_convert_band=0;
377 +
378 + $wpstream_convert_storage = $this->wpstream_convert_band($pack_details['storage']);
379 + if($wpstream_convert_storage<0)$wpstream_convert_storage=0;
380 +
381 + print '<div class="pack_details_wrapper"><strong>'.__('Your account information: ','wpstream').'</strong> '.__('You have','wpstream').'<strong> '.$wpstream_convert_band.' Gb</strong> '.__('available streaming bandwidth and','wpstream').' <strong>'.$wpstream_convert_storage.' Gb</strong> '.__('available media storage','wpstream').'.</div>';
382 + print'<input type="hidden" id="wpstream_band" value="'.$pack_details['band'].'">';
383 + print'<input type="hidden" id="wpstream_storage" value="'.$pack_details['storage'].'">';
741 384
742 - // Convert available storage MB to GB, clamping negatives to zero.
743 - $wpstream_convert_storage = $this->wpstream_convert_band( $pack_details['available_storage_mb'] );
744 - if ( $wpstream_convert_storage < 0 ) {
745 - $wpstream_convert_storage = 0;
746 - }
747 -
748 - // Output the cloud data + storage summary line.
749 - print '<div class="pack_details_wrapper">'
750 - . '<strong>' . __( 'Your account information: ', 'wpstream' ) . '</strong> '
751 - . __( 'You have ', 'wpstream' ) . '<strong id="wpstream_available_data">' . abs( $wpstream_convert_band ) . ' GB</strong> '
752 - . __( 'available cloud data and ', 'wpstream' )
753 - . '<strong id="wpstream_available_storage">' . abs( $wpstream_convert_storage ) . ' GB</strong> '
754 - . __( 'available cloud storage', 'wpstream' ) . '.';
755 -
756 - // Upgrade link plus hidden inputs carrying the raw MB figures for JS.
757 - print '<a href="https://wpstream.net/pricing/" class="wpstream_upgrade_topbar" target="_blank">' . esc_html__( 'Upgrade Plan', 'wpstream' ) . '</a>';
758 - print '</div>';
759 - print '<input type="hidden" id="wpstream_band" value="' . esc_attr( $pack_details['available_data_mb'] ) . '">';
760 - print '<input type="hidden" id="wpstream_storage" value="' . esc_attr( $pack_details['available_storage_mb'] ) . '">';
761 - }
762 - } else {
763 - // Branch B: streaming-hours plans (viewer/broadcast/storage hours).
764 - if ( isset( $pack_details['available_viewer_hours'] ) && isset( $pack_details['available_broadcast_hours'] ) && isset( $pack_details['available_storage_hours'] ) ) {
765 - // Normalize viewer hours to a non-negative float.
766 - $available_viewer_hours = floatval( $pack_details['available_viewer_hours'] );
767 - if ( $available_viewer_hours < 0 ) {
768 - $available_viewer_hours = 0;
769 - }
770 -
771 - // Normalize broadcast hours to a non-negative float.
772 - $available_broadcast_hours = floatval( $pack_details['available_broadcast_hours'] );
773 - if ( $available_broadcast_hours < 0 ) {
774 - $available_broadcast_hours = 0;
775 - }
776 -
777 - // Normalize storage hours to a non-negative float.
778 - $available_storage_hours = floatval( $pack_details['available_storage_hours'] );
779 - if ( $available_storage_hours < 0 ) {
780 - $available_storage_hours = 0;
781 - }
782 -
783 - // Floor each figure to two decimals for display.
784 - $formatted_viewer_hours = $this->wpstream_floor_decimals( $available_viewer_hours, 2 );
785 - $formatted_broadcast_hours = $this->wpstream_floor_decimals( $available_broadcast_hours, 2 );
786 - $formatted_storage_hours = $this->wpstream_floor_decimals( $available_storage_hours, 2 );
787 -
788 - // Output the viewer/broadcast/storage hours summary line.
789 - print '<div class="pack_details_wrapper">'
790 - . __( 'Available streaming resources: ', 'wpstream' )
791 - . '<strong id="wpstream_available_viewer_hours">' . abs( $formatted_viewer_hours ) . ' viewer</strong> '
792 - . __( 'hours, ', 'wpstream' )
793 - . '<strong id="wpstream_available_broadcast_hours">' . abs( $formatted_broadcast_hours ) . ' broadcast</strong> '
794 - . __( 'hours, ', 'wpstream' )
795 - . '<strong id="wpstream_available_storage_hours">' . $formatted_storage_hours . ' storage</strong> '
796 - . __( 'hours', 'wpstream' ) . '.';
797 -
798 - // Upgrade link plus hidden inputs carrying the raw hour figures for JS.
799 - print '<a href="https://wpstream.net/pricing/" class="wpstream_upgrade_topbar" target="_blank">' . esc_html__( 'Upgrade Plan', 'wpstream' ) . '</a>';
800 - print '</div>';
801 - print '<input type="hidden" id="wpstream_viewer_hours" value="' . esc_attr( $pack_details['available_viewer_hours'] ) . '">';
802 - print '<input type="hidden" id="wpstream_broadcast_hours" value="' . esc_attr( $pack_details['available_broadcast_hours'] ) . '">';
803 - print '<input type="hidden" id="wpstream_storage_hours" value="' . esc_attr( $pack_details['available_storage_hours'] ) . '">';
804 - }
805 - }
806 - }
807 -
808 -
809 - /**
810 - * help function for media list elementor widget
811 - *
812 - * Compatibility delegate for customer themes that call the historical
813 - * renderer on the main plugin object.
814 - *
815 - * @since 3.0.1
816 - * @param array $attributes Widget attributes (counts, type, order, labels).
817 - * @param string|null $content Unused shortcode inner content.
818 - * @return string Rendered HTML markup for the media grid.
819 - */
820 -
821 - public function wpstream_media_list_elementor_function($attributes, $content = null){
822 - $kind = isset( $attributes['product_type'] ) && 2 === intval( $attributes['product_type'] )
823 - ? 'vod'
824 - : 'live_channel';
825 - return $this->media_list->render( $kind, is_array( $attributes ) ? $attributes : array() );
385 + }
826 386 }
827 387
828 388
829 -
830 -
831 -
832 -
833 -
834 -
835 -
836 -
837 -
838 -
839 -
840 389 /**
841 390 * help function for player elementr widget
842 391 *
843 - * Renders the standard video player for a given product id, or resolves the
844 - * author's first channel when only a user_id is supplied.
845 - *
846 392 * @since 3.0.1
847 - * @param array $attributes Widget attributes ('id', 'user_id').
848 - * @param string|null $content Unused shortcode inner content.
849 - * @return string Rendered player markup.
393 + * @return string
850 394 */
851 -
395 +
852 396 public function wpstream_insert_player_elementor($attributes, $content = null){
853 - // Normalize incoming attributes with defaults.
854 397 $product_id = '';
855 398 $return_string = '';
856 - $attributes = shortcode_atts(
399 + $attributes = shortcode_atts(
857 400 array(
858 401 'id' => 0,
859 402 'user_id' => 0,
860 403 ), $attributes) ;
@@ -859,129 +402,141 @@
859 402 'user_id' => 0,
860 403 ), $attributes) ;
861 404
862 405
863 - // Explicit product id, if provided.
864 406 if ( isset($attributes['id']) ){
865 407 $product_id=$attributes['id'];
866 408 }
867 - // Optional author id used to look up a channel.
868 409 if ( isset($attributes['user_id']) ){
869 410 $user_id = intval( $attributes['user_id'] );
870 411 }
871 -
872 - // No product id but a user id: resolve that author's first channel.
412 +
873 413 if(intval($product_id)==0 && $user_id!=0 ){
874 - $product_id= $this->wpstream_player_retrieve_first_id($user_id);
414 + $product_id= $this->wpstream_player_retrive_first_id($user_id);
875 415 }
416 +
417 +
418 +
419 +
420 + ob_start();
421 + $this->main->wpstream_player->wpstream_video_player_shortcode($product_id);
422 + $return_string= ob_get_contents();
423 + ob_end_clean();
876 424
425 + return $return_string;
426 + }
427 +
428 + /**
429 + * help function for player low latency elementor widget
430 + *
431 + * @since 3.0.1
432 + * @return string
433 + */
434 +
435 + public function wpstream_insert_player__low_latency_elementor($attributes, $content = null){
436 + $product_id = '';
437 + $return_string = '';
438 + $attributes = shortcode_atts(
439 + array(
440 + 'id' => 0,
441 + 'user_id' => 0,
442 + ), $attributes) ;
877 443
878 444
879 - // Buffer the player output so it can be returned as a string.
445 + if ( isset($attributes['id']) ){
446 + $product_id=$attributes['id'];
447 + }
448 +
449 + if ( isset($attributes['user_id']) ){
450 + $user_id = intval( $attributes['user_id'] );
451 + }
452 +
453 + if(intval($product_id)==0 && $user_id!=0){
454 + $product_id= $this->wpstream_player_retrive_first_id($user_id);
455 + }
456 +
457 +
880 458 ob_start();
881 - // Render the player shortcode inside the wrapper markup below.
882 - ?>
883 - <div class="wpstream_insert_player_elementor_wrapper">
884 - <?php
885 - $this->main->wpstream_player->wpstream_video_player_shortcode($product_id);
886 - ?>
887 - </div>
888 - <?php
889 - // Capture and return the buffered markup.
459 + $this->main->wpstream_player->wpstream_video_player_shortcode_low_latency($product_id);
890 460 $return_string= ob_get_contents();
891 - ob_end_clean();
461 + ob_end_clean();
892 462
893 463 return $return_string;
894 464 }
895 465
896 -
897 - /**
898 - * Resolve the first channel/event id belonging to a given author.
899 - *
900 - * @param string|int $received_user_id Author user id.
901 - * @return int|string Post id of the author's first channel, or 0 when none.
902 - */
903 - public function wpstream_player_retrieve_first_id($received_user_id=''){
904 - // Free vs paid channel type is a site-wide option.
466 +
467 +
468 + public function wpstream_player_retrive_first_id($received_user_id=''){
905 469 $channel_type = get_option ('wpstream_user_streaming_channel_type');
906 - // Look up the author's most relevant event id for that type.
907 470 $product_id = $this->wpstream_get_current_event_per_author($received_user_id,$channel_type);
908 471 return $product_id;
909 472 }
473 +
474 +
475 +
476 + /**
477 + * help function for chat elementor widget
478 + *
479 + * @since 3.0.1
480 + * @return string
481 + */
482 +
483 + public function wpstream_insert_chat_elementor($attributes, $content = null){
484 + $product_id = '';
485 + $return_string = '';
486 + $attributes = shortcode_atts(
487 + array(
488 + 'id' => 0,
489 + ), $attributes) ;
910 490
911 - /**
912 - * Deprecated misspelled alias of wpstream_player_retrieve_first_id().
913 - *
914 - * Kept because the method is public and may be called by external code.
915 - *
916 - * @deprecated 4.13.4 Use wpstream_player_retrieve_first_id() instead.
917 - */
918 - public function wpstream_player_retrive_first_id($received_user_id=''){
919 - return $this->wpstream_player_retrieve_first_id($received_user_id);
491 +
492 + if ( isset($attributes['id']) ){
493 + $product_id=$attributes['id'];
494 + }
495 +
496 + $return_string.= '<div class="wpstream_plugin_chat_wrapper">';
497 + ob_start();
498 + $this->main->wpstream_player->wpstream_chat_wrapper($product_id);
499 + $return_string.= ob_get_contents();
500 + ob_end_clean();
501 + $return_string.='</div>';
502 + $this->main->wpstream_player->wpstream_connect_to_chat($product_id);
503 +
504 + return $return_string;
920 505 }
921 506
922 507
923 -
924 508 /**
925 - * edited 4.0
926 - *
927 - * Check if the current user is allowed to stream.
509 + * Check if user is allowed to stream
928 510 *
929 - * The one broadcasting-permission rule: administrators always may; other
930 - * users need their primary role on the "streamer roles" list or the
931 - * "regular users may stream" option. The verdict passes through the
932 - * wpstream_user_can_stream filter, so membership plugins replace the
933 - * role rule in one place. Guests are refused before the filter.
934 - *
935 511 * @since 3.7
936 - * @return bool
937 512 */
938 513
939 514 public function wpstream_check_user_can_stream(){
940 - // Current user for the role/capability checks below.
941 515 $current_user = wp_get_current_user();
942 -
943 - // Guests can never stream.
516 +
944 517 if( !is_user_logged_in() ){
945 518 return false;
519 + exit('user not logged in 497');
946 520 }
947 -
948 - // Admins can always broadcast.
949 - $can = current_user_can( 'administrator' );
950 -
951 - if ( ! $can ) {
952 - // Site-configured list of roles that are allowed to stream.
953 - $extra_roles = get_option( 'wpstream_stream_role', true );
954 - // The user's primary role (first in the roles array).
955 - $user_role = '';
956 - if( is_array( $current_user->roles) && count( $current_user->roles ) > 0 ){
957 - $user_role = $current_user->roles[0];
958 - }
959 -
960 - // Allow when the user's role is in the configured allow-list.
961 - if ( is_array($extra_roles) && in_array( $user_role, $extra_roles ) ) {
962 - $can = true;
963 - }
964 -
965 - // Allow when the "regular users may stream" option is enabled.
966 - if(function_exists('wpstream_get_option') && intval(wpstream_get_option('allow_streaming_regular_users',''))==1 ){
967 - $can = true;
968 - }
521 +
522 + if(current_user_can('administrator')){
523 + // admins can always brodcast
524 + return true;
969 525 }
970 -
971 - /**
972 - * Filters whether the current (logged-in) user may broadcast.
973 - *
974 - * Gates every go-live surface: the start/stop endpoints, the
975 - * start-streaming dashboard and channel creation.
976 - *
977 - * @since 4.14.0
978 - *
979 - * @param bool $can The built-in verdict (administrator, streamer
980 - * role list, or the regular-users option).
981 - * @param int $user_id Current user ID.
982 - */
983 - return (bool) apply_filters( 'wpstream_user_can_stream', $can, intval( $current_user->ID ) );
526 +
527 + $extra_roles = get_option( 'wpstream_stream_role', true );
528 + $user_role = $current_user->roles[0];
529 +
530 + if (in_array($user_role, $extra_roles)){
531 + return true;
532 + }
533 +
534 + if(function_exists('wpstream_get_option') && intval(wpstream_get_option('allow_streaming_regular_users',''))==1 ){
535 + return true;
536 + }
537 +
538 + return false;
984 539 }
985 540
986 541
987 542 /**
@@ -986,172 +541,89 @@
986 541
987 542 /**
988 543 * Start Streaming wrapper
989 544 *
990 - * Ensures a channel exists (creating one for front-end streamers when
991 - * needed), prints the error-modal scaffolding, then renders the start-
992 - * streaming unit.
993 - *
994 545 * @since 3.7
995 - * @param int $item_id Channel/product id, or 0 to auto-resolve.
996 - * @param string $type Streaming unit type/context.
997 546 */
547 +
998 548 public function wpstream_live_stream_unit_wrapper($item_id,$type){
999 - // Coerce to an integer id.
1000 549 $item_id = intval($item_id);
1001 -
1002 - // The unit's controller script (+ its QR dependency chain) and the shared
1003 - // admin stylesheet are registered on every page but only enqueued here,
1004 - // where the go-live unit actually renders (scripts print in the footer).
1005 - wp_enqueue_script( 'wpstream-start-streaming' );
1006 - wp_enqueue_style( 'wpstream_front_style' );
1007 -
550 +
1008 551 if($item_id == 0){
1009 552 //retrive or create channel for front end streamers
1010 - $item_id=$this->wpstream_retrieve_front_end_channel();
553 + $item_id=$this->wpstream_retrive_front_end_channel();
1011 554 }
1012 - // Modal backdrop and reusable error-notification markup.
1013 - print'<div class="wpstream_modal_background"></div>';
1014 - print '<div class="wpstream_error_modal_notification"><div class="wpstream_error_content">er2</div>
1015 - <div class="wpstream_error_ok wpstream_button" type="button">'.esc_html__('Close','wpstream').'</div>
1016 - </div>';
1017 - // Render through the shared Live Channel presentation module.
1018 - $this->get_live_channel_presentation()->render_channel( $item_id, $type );
555 +
556 + $this->admin->wpstream_live_stream_unit( $item_id,$type );
1019 557 }
1020 558
1021 559
1022 - /**
1023 - * Start Streaming wrapper for wpstream theme
1024 - *
1025 - * Same as wpstream_live_stream_unit_wrapper() but renders the theme's
1026 - * variant of the start-streaming unit.
1027 - *
1028 - * @since 3.7
1029 - * @param int $item_id Channel/product id, or 0 to auto-resolve.
1030 - * @param string $type Streaming unit type/context.
1031 - */
1032 -
1033 - public function wpstream_live_stream_unit_wrapper_for_theme($item_id,$type){
1034 - // Coerce to an integer id.
1035 - $item_id = intval($item_id);
1036 -
1037 - // Same render-time asset loading as wpstream_live_stream_unit_wrapper().
1038 - wp_enqueue_script( 'wpstream-start-streaming' );
1039 - wp_enqueue_style( 'wpstream_front_style' );
1040 -
1041 - if($item_id == 0){
1042 - //retrive or create channel for front end streamers
1043 - $item_id=$this->wpstream_retrieve_front_end_channel();
1044 - }
1045 - // Modal backdrop and reusable error-notification markup.
1046 - print'<div class="wpstream_modal_background"></div>';
1047 - print '<div class="wpstream_error_modal_notification"><div class="wpstream_error_content">er2</div>
1048 - <div class="wpstream_error_ok wpstream_button" type="button">'.esc_html__('Close','wpstream').'</div>
1049 - </div>';
1050 - // Render the companion-theme variant through the same presentation module.
1051 - $this->get_live_channel_presentation()->render_channel( $item_id, 'theme' );
1052 - }
1053 560
1054 561
562 +
1055 563 /**
1056 564 * retrive channel for front end streaming
1057 565 *
1058 - * Returns the current user's front-end channel id, creating a new event
1059 - * when the user does not yet have one.
1060 - *
1061 566 * @since 3.7
1062 - * @return int Channel/product id for the current user.
1063 567 */
1064 - public function wpstream_retrieve_front_end_channel(){
1065 -
1066 - // Current user plus the site-wide channel type and default price.
568 + public function wpstream_retrive_front_end_channel(){
569 +
1067 570 $current_user = wp_get_current_user();
1068 571 $channel_type = get_option ('wpstream_user_streaming_channel_type');
1069 572 $channel_price = floatval( get_option ('wpstream_user_streaming_default_price') );
1070 -
1071 - // Look for an existing channel owned by this user.
573 +
1072 574 $front_end_streamin_channel = $this->wpstream_get_current_event_per_author($current_user->ID,$channel_type);
1073 -
1074 - // None found: create one on the fly.
575 +
1075 576 if(intval($front_end_streamin_channel) == 0){
1076 - $front_end_streamin_channel= $this->wpstream_create_front_end_event($current_user->ID,$current_user->user_login ,$channel_type,$channel_price);
577 + $front_end_streamin_channel= $this->wpstrea_create_front_end_event($current_user->ID,$current_user->user_login ,$channel_type,$channel_price);
1077 578 }
1078 579 return $front_end_streamin_channel;
1079 -
580 +
1080 581 }
1081 -
1082 - /**
1083 - * Deprecated misspelled alias of wpstream_retrieve_front_end_channel().
1084 - *
1085 - * Kept because the method is public and may be called by external code.
1086 - *
1087 - * @deprecated 4.13.4 Use wpstream_retrieve_front_end_channel() instead.
1088 - */
1089 - public function wpstream_retrive_front_end_channel(){
1090 - return $this->wpstream_retrieve_front_end_channel();
1091 - }
1092 -
1093 - /**
1094 - * create the event from front end
1095 - *
1096 - * Inserts a new channel post (free CPT or paid WooCommerce product),
1097 - * setting price/terms for paid channels, and flags it as a live event.
1098 - *
1099 - * @since 3.7
1100 - * @param int $userID Author user id.
1101 - * @param string $userLogin Author login, used in the channel title.
1102 - * @param string $channel_type 'paid' for a WooCommerce product, else free.
1103 - * @param float $channel_price Price to set for paid channels.
1104 - * @return int|void New post id, or void when the user may not stream.
1105 - */
1106 -
1107 - public function wpstream_create_front_end_event($userID,$userLogin,$channel_type,$channel_price){
1108 - $request = array(
1109 - 'actor_id' => intval( $userID ),
1110 - 'owner_id' => intval( $userID ),
1111 - 'kind' => 'live_channel',
1112 - 'access' => 'paid' === $channel_type ? 'paid' : 'free',
1113 - 'title' => sprintf( esc_html__( '%s Channel', 'wpstream' ), $userLogin ),
1114 - );
1115 - if ( 'paid' === $request['access'] ) {
1116 - $request['price'] = $channel_price;
1117 - }
1118 -
1119 - $result = $this->streaming_content_creation->create( $request );
1120 - return ! empty( $result['success'] ) ? intval( $result['content_id'] ) : null;
1121 - }
1122 -
1123 - /**
1124 - * Deprecated misspelled alias of wpstream_create_front_end_event().
1125 - *
1126 - * Kept because the method is public and may be called by external code.
1127 - *
1128 - * @deprecated 4.13.4 Use wpstream_create_front_end_event() instead.
1129 - */
582 +
583 +
1130 584 public function wpstrea_create_front_end_event($userID,$userLogin,$channel_type,$channel_price){
1131 - return $this->wpstream_create_front_end_event($userID,$userLogin,$channel_type,$channel_price);
585 +
586 + $post_type='wpstream_product';
587 + if($channel_type=='paid'){
588 + $post_type='product';
589 + }
590 +
591 + $post = array(
592 + 'post_title' => sprintf( esc_html__('%s Channel','wpstream'),$userLogin),
593 + 'post_content' => '',
594 + 'post_type' => $post_type ,
595 + 'post_author' => $userID,
596 + 'post_status' => 'publish',
597 + );
598 + $post_id = wp_insert_post($post );
599 + if($channel_type=='paid'){
600 + $product = wc_get_product($post_id);
601 + $price = wc_format_decimal($channel_price);
602 +
603 + $product = wc_get_product( $post_id );
604 + // Set the product active price (regular)
605 + $product->set_price( $price );
606 + $product->set_regular_price( $price ); // To be sure
607 + $product->save();
608 +
609 + wp_set_object_terms( $post_id, 'live_stream', 'product_type' );
610 + }
611 + update_post_meta($post_id,'wpstream_product_type',1);
612 +
613 + return $post_id;
1132 614 }
1133 -
1134 -
1135 -
1136 - /**
1137 - * Find the first channel/event id owned by a given author.
1138 - *
1139 - * @param int $userID Author user id.
1140 - * @param string $channel_type 'paid' for a WooCommerce product, else free.
1141 - * @return int Post id of the author's first matching channel, or 0.
1142 - */
615 +
616 +
1143 617 public function wpstream_get_current_event_per_author($userID,$channel_type){
1144 -
1145 - // Free channels are CPTs; paid channels are WooCommerce products.
618 +
1146 619 $post_type='wpstream_product';
1147 620 if($channel_type=='paid'){
1148 621 $post_type='product';
1149 622 }
1150 -
1151 - // Query for a single post id owned by this author.
623 +
1152 624 $args = array(
1153 -
625 +
1154 626 'post_type' => $post_type,
1155 627 'author' => $userID,
1156 628 'posts_per_page' => 1,
1157 629 'fields' => 'ids'
@@ -1157,27 +629,16 @@
1157 629 'fields' => 'ids'
1158 630 )
1159 631 ;
1160 632 $author_posts = new WP_Query( $args );
1161 - // Use the found id, or 0 when the author has no channel.
1162 633 if( $author_posts->have_posts() ) {
1163 634 $author_posts->the_post();
1164 - $the_id= get_the_ID();
635 + return get_the_ID();
1165 636 }else{
1166 - $the_id= 0;
637 + return 0;
1167 638 }
1168 -
1169 - // Restore global post/query state after the custom query.
639 +
1170 640 wp_reset_query();
1171 641 wp_reset_postdata();
1172 - return $the_id;
1173 642 }
1174 -
1175 - /**
1176 - * Cleanup old logs
1177 - */
1178 - public function cleanup_logs() {
1179 - // Delegate to the logger, which prunes entries past its retention window.
1180 - $logger = new WPStream_Logger();
1181 - $logger->clear_old_logs();
1182 - }
643 +
1183 644 }