PluginProbe
WpStream – Live Streaming, Video on Demand, Pay Per View / 4.4.10
WpStream – Live Streaming, Video on Demand, Pay Per View v4.4.10
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 | admin/class-wpstream-admin.php +2181 -2465 4.14.14.4.10 View file →
@@ -9,26 +9,13 @@
9 9 * @package Wpstream
10 10 * @subpackage Wpstream/admin
11 11 */
12 12
13 -
14 -// Exit if accessed directly.
15 -if ( ! defined( 'ABSPATH' ) ) {
16 - exit;
17 -}
18 -
19 13 /**
20 14 * The admin-specific functionality of the plugin.
21 15 *
22 - * This is the admin "god class": it wires up the whole wp-admin surface of the
23 - * plugin. Responsibilities include registering admin CSS/JS, building the
24 - * top-level WpStream menu and its sub-pages (Credentials, Channels, Recordings,
25 - * Settings, Quick Start), rendering channel/settings/onboarding screens and
26 - * their modal dialogs, defining the per-event global streaming options, hooking
27 - * into WooCommerce to register the custom stream/VOD product types and their
28 - * pricing/metabox behaviour, rendering post metaboxes, driving the multipart S3
29 - * upload AJAX endpoints, and emitting the various admin notices (plugin update,
30 - * cache flush, theme, etc.). Many methods echo HTML directly.
16 + * Defines the plugin name, version, and two examples hooks for how to
17 + * enqueue the admin-specific stylesheet and JavaScript.
31 18 *
32 19 * @package Wpstream
33 20 * @subpackage Wpstream/admin
34 21 * @author wpstream <[email protected]>
@@ -33,20 +20,11 @@
33 20 * @subpackage Wpstream/admin
34 21 * @author wpstream <[email protected]>
35 22 */
36 23 class Wpstream_Admin {
37 -
24 +
25 +
38 26 /**
39 - * Most parts a multipart VOD upload may be split into.
40 - *
41 - * The storage backend assembles at most this many parts, so a larger
42 - * split uploads every byte and still can never complete.
43 - *
44 - * @var int
45 - */
46 - const MULTIPART_MAX_PARTS = 1000;
47 -
48 - /**
49 27 * Store plugin main class to allow public access.
50 28 *
51 29 * @since 20180622
52 30 * @var object The main class.
@@ -53,370 +31,1026 @@
53 31 */
54 32 public $main;
55 33
56 34
57 - /**
58 - * The ID of this plugin.
59 - *
60 - * @since 3.0.1
61 - * @access private
62 - * @var string $plugin_name The ID of this plugin.
63 - */
64 - private $plugin_name;
35 + /**
36 + * The ID of this plugin.
37 + *
38 + * @since 3.0.1
39 + * @access private
40 + * @var string $plugin_name The ID of this plugin.
41 + */
42 + private $plugin_name;
65 43
66 - /**
67 - * The version of this plugin.
68 - *
69 - * @since 3.0.1
70 - * @access private
71 - * @var string $version The current version of this plugin.
72 - */
73 - private $version;
44 + /**
45 + * The version of this plugin.
46 + *
47 + * @since 3.0.1
48 + * @access private
49 + * @var string $version The current version of this plugin.
50 + */
51 + private $version;
74 52
75 - /**
76 - * @var array Definitions of the per-event "global" streaming options (record,
77 - * view count, autoplay, encryption, etc.). Each entry holds a
78 - * translated label, a help "details" string, and a default value.
79 - * Populated lazily on `init` by load_global_event_options().
80 - */
53 + /**
54 + * Initialize the class and set its properties.
55 + *
56 + * @since 3.0.1
57 + * @param string $plugin_name The name of this plugin.
58 + * @param string $version The version of this plugin.
59 + */
60 +
81 61 public $global_event_options ;
62 +
63 +
64 +
65 +
66 +
67 + public function __construct( $plugin_name, $version,$plugin_main ) {
82 68
69 + $this->plugin_name = $plugin_name;
70 + $this->version = $version;
71 + $this->main = $plugin_main;
72 +
73 + $this->global_event_options = array(
74 +
75 + 'record' =>array(
76 + 'name' => esc_html__('Record Live Stream','wpstream'),
77 + 'details' => esc_html__('If enabled, live streams will be recorded and saved to your library.','wpstream'),
78 + 'defaults' => 'no',
79 +
80 + ),
81 + 'view_count' =>array(
82 + 'name' => esc_html__('Display Viewer Count','wpstream'),
83 + 'details' => esc_html__('If enabled, the live viewer count will show up in the player.','wpstream'),
84 + 'defaults' => 'yes',
85 + ),
86 + 'domain_lock'=>array(
87 + 'name' => esc_html__('Lock To Website','wpstream'),
88 + 'details' => sprintf ( esc_html__('If enabled, live video will only display on %1$s, otherwise it can show up on any website.','wpstream'),get_bloginfo('wpurl') ),
89 + 'defaults' => 'no',
90 + ),
91 + 'autoplay' =>array(
92 + 'name' => esc_html__('Autoplay','wpstream'),
93 + 'details' => esc_html__('If enabled, live video will attempt to start playing automatically. This is only achievable in some browsers.','wpstream'),
94 + 'defaults' => 'yes',
95 + ),
96 + 'mute' =>array(
97 + 'name' => esc_html__('Start Muted','wpstream'),
98 + 'details' => esc_html__('If enabled, live video will start muted. This may increase the rate of autoplay in some browsers. ','wpstream'),
99 + 'defaults' => 'no',
83 100
101 + ),
102 +
103 + 'encrypt' =>array(
104 + 'name' => esc_html__('Encrypt Live Stream','wpstream'),
105 + 'details' => esc_html__('If enabled, video data will be encrypted. Enabling encryption may lead to reduced website performance under certain configurations. Encrypted video may not display in all browsers.','wpstream'),
106 + 'defaults' => 'no',
107 + ),
108 + 'ses_encrypt'=>array(
109 + 'name' => esc_html__('Use Sessions with Encryption','wpstream'),
110 + 'details' => esc_html__('If enabled, encryption key distribution will be checked against valid user sessions. Setting may malfunction or lead to reduced website performance under certain configurations. ','wpstream'),
111 + 'defaults' => 'no',
112 + ),
113 + 'autostart' =>array(
114 + 'name' => esc_html__('Auto TURN ON','wpstream'),
115 + 'details' => esc_html__('If enabled, channel will TURN ON automatically when broadcasting with an External Streaming App (RTMP Encoder/Broadcaster)','wpstream'),
116 + 'defaults' => 'no',
117 + ),
84 118
119 + 'vod_domain_lock' =>array(
120 + 'name' => esc_html__('Video On Demand - Lock To Website','wpstream'),
121 + 'details' => sprintf ( esc_html__('If enabled, VODS will only display on %1$s, otherwise they can show up on any website.','wpstream'),get_bloginfo('wpurl') ),
122 + 'defaults' => 'no',
123 + ),
124 + 'vod_encrypt' =>array(
125 + 'name' => esc_html__('Encrypt Video on Demand','wpstream'),
126 + 'details' => esc_html__('If enabled, video data will be encrypted. Enabling encryption may lead to reduced website performance under certain configurations. Encrypted video may not display in all browsers.','wpstream'),
127 + 'defaults' => 'no',
128 + ),
129 + );
85 130
131 + }
86 132
87 - /**
88 - * Initialize the class and set its properties.
89 - *
90 - * @since 3.0.1
91 - * @param string $plugin_name The name (ID) of this plugin.
92 - * @param string $version The version of this plugin.
93 - * @param object $plugin_main The main plugin class instance, kept for public access.
94 - * @return void
95 - */
96 - public function __construct( $plugin_name, $version,$plugin_main ) {
133 + /**
134 + * Register the stylesheets for the admin area.
135 + *
136 + * @since 3.0.1
137 + */
138 + public function enqueue_styles() {
97 139
98 - // Remember the plugin identity and the main class for later use.
99 - $this->plugin_name = $plugin_name;
100 - $this->version = $version;
101 - $this->main = $plugin_main;
140 + /**
141 + * This function is provided for demonstration purposes only.
142 + *
143 + * An instance of this class should be passed to the run() function
144 + * defined in Wpstream_Loader as all of the hooks are defined
145 + * in that particular class.
146 + *
147 + * The Wpstream_Loader will then create the relationship
148 + * between the defined hooks and the functions defined in this
149 + * class.
150 + */
151 + wp_enqueue_style( 'wpstream-roboto', "https://fonts.googleapis.com/css?family=Roboto:300,400,500,600,700,900&display=swap&subset=latin-ext" );
152 + wp_enqueue_style( $this->plugin_name, plugin_dir_url( __FILE__ ) . 'css/wpstream-admin.css', array(), WPSTREAM_PLUGIN_VERSION, 'all' );
153 +
154 + wp_enqueue_style( 'wpstream-on-boarding-css', plugin_dir_url( __FILE__ ) . 'css/wpstream-admin-onboarding.css', array(), rand(1,999999999999), 'all' );
155 +
156 +
157 + }
102 158
103 - // Build the translatable global event options once WP (and its i18n) is ready.
104 - add_action('init', array($this, 'load_global_event_options'));
105 - }
159 + /**
160 + * Register the JavaScript for the admin area.
161 + *
162 + * @since 3.0.1
163 + */
164 + public function enqueue_scripts() {
106 165
107 - /**
108 - * Populate $global_event_options with the translatable per-event settings.
109 - *
110 - * Deferred to the `init` hook so the esc_html__() translations resolve
111 - * against a loaded text domain.
112 - *
113 - * @return void
114 - */
115 - public function load_global_event_options() {
116 - // Each key maps to a label/details/default triple used when rendering the event option toggles.
117 - $this->global_event_options = array(
118 - 'record' => array(
119 - 'name' => esc_html__('Record Live Stream','wpstream'),
120 - 'details' => esc_html__('If enabled, live streams will be recorded and saved to your library.','wpstream'),
121 - 'defaults' => 'no',
122 - ),
123 - 'view_count' => array(
124 - 'name' => esc_html__('Display Viewer Count','wpstream'),
125 - 'details' => esc_html__('If enabled, the live viewer count will show up in the player.','wpstream'),
126 - 'defaults' => 'yes',
127 - ),
128 - 'domain_lock' => array(
129 - 'name' => esc_html__('Lock To Website','wpstream'),
130 - 'details' => sprintf ( esc_html__('If enabled, live video will only display on %1$s, otherwise it can show up on any website.','wpstream'),get_bloginfo('wpurl') ),
131 - 'defaults' => 'no',
132 - ),
133 - 'autoplay' => array(
134 - 'name' => esc_html__('Autoplay','wpstream'),
135 - 'details' => esc_html__('If enabled, live video will attempt to start playing automatically. This is only achievable in some browsers.','wpstream'),
136 - 'defaults' => 'yes',
137 - ),
138 - 'mute' => array(
139 - 'name' => esc_html__('Start Muted','wpstream'),
140 - 'details' => esc_html__('If enabled, live video will start muted. This may increase the rate of autoplay in some browsers. ','wpstream'),
141 - 'defaults' => 'no',
142 - ),
143 - 'low_latency' => array(
144 - 'name' => esc_html__('Low Latency (beta)','wpstream'),
145 - 'details' => esc_html__('Shortens the live delay between streamer and viewers. Useful for interactive applications like gaming, auctions, trading etc. Low latency may worsen the viewer experience on some devices.','wpstream'),
146 - 'defaults' => 'no',
147 - ),
148 - 'adaptive_bitrate' => array(
149 - 'name' => esc_html__('Adaptive Bitrate (beta)','wpstream'),
150 - 'details' => esc_html__('Ensures a smooth and uninterrupted viewing experience by adjusting video quality for viewers with reduced network speed or device capabilities.','wpstream'),
151 - 'defaults' => 'no',
152 - ),
153 - 'encrypt' =>array(
154 - 'name' => esc_html__('Encrypt Live Stream','wpstream'),
155 - 'details' => esc_html__('If enabled, video data will be encrypted. Enabling encryption may lead to reduced website performance under certain configurations. Encrypted video may not display in all browsers.','wpstream'),
156 - 'defaults' => 'no',
157 - ),
158 - 'ses_encrypt'=>array(
159 - 'name' => esc_html__('Use Sessions with Encryption','wpstream'),
160 - 'details' => esc_html__('If enabled, encryption key distribution will be checked against valid user sessions. Setting may malfunction or lead to reduced website performance under certain configurations. ','wpstream'),
161 - 'defaults' => 'no',
162 - ),
163 - );
166 + wp_enqueue_script("jquery-ui-slider");
167 + wp_enqueue_script("jquery-ui-datepicker");
168 + wp_enqueue_script('jquery.fileupload', plugin_dir_url( __FILE__ ) .'js/jquery.fileupload.js?v='.time(),array(), WPSTREAM_PLUGIN_VERSION, true);
169 + wp_enqueue_script('wpstream-admin-control', plugin_dir_url( __FILE__ ) .'js/admin_control.js?v='.time(),array(), WPSTREAM_PLUGIN_VERSION, true);
170 + wp_localize_script('wpstream-admin-control', 'wpstream_admin_control_vars',
171 + array(
172 + 'admin_url' => get_admin_url(),
173 + 'loading_url' => WPSTREAM_PLUGIN_DIR_URL.'/img/loading.gif',
174 + 'download_mess' => esc_html__('Click to download!','wpstream'),
175 + 'uploading' => esc_html('We are uploading your file.Do not close this window!','wpstream'),
176 + 'upload_complete2' => esc_html('Upload Complete! You can upload another file!','wpstream'),
177 + 'not_accepted' => esc_html('The file is not an accepted video format','wpstream'),
178 + 'upload_complete' => esc_html('Upload Complete!','wpstream'),
179 + 'no_band' => esc_html('Not enough streaming data.','wpsteam'),
180 + 'no_band_no_store' => esc_html('Not enough streaming data or storage.','wpsteam')
164 181
182 + ));
183 +
184 +
185 +
186 + wp_enqueue_script('wpstream-start-streaming_admin', plugin_dir_url( __DIR__ ) .'/public/js/start_streaming.js?v='.time(),array(), WPSTREAM_PLUGIN_VERSION, true);
187 + wp_localize_script('wpstream-start-streaming_admin', 'wpstream_start_streaming_vars',
188 + array(
189 + 'admin_url' => get_admin_url(),
190 + 'loading_url' => WPSTREAM_PLUGIN_DIR_URL.'/img/loading.gif',
191 + 'download_mess' => esc_html__('Click to download!','wpstream'),
192 + 'uploading' => esc_html('We are uploading your file.Do not close this window!','wpstream'),
193 + 'upload_complete2' => esc_html('Upload Complete! You can upload another file!','wpstream'),
194 + 'not_accepted' => esc_html('The file is not an accepted video format','wpstream'),
195 + 'upload_complete' => esc_html('Upload Complete!','wpstream'),
196 + 'no_band' => esc_html('Not enough streaming data.','wpsteam'),
197 + 'no_band_no_store' => esc_html('Not enough streaming data or storage.','wpsteam'),
198 +
199 + 'start_streaming_action'=> esc_html__('TURNING ON','wpstream'),
200 + 'stop_streaming_action' => esc_html__('TURNING OFF','wpstream'),
201 + 'start_streaming' => esc_html__('TURN ON','wpstream'),
202 + 'stop_streaming' => esc_html__('TURN OFF','wpstream'),
203 + 'turned_on_tooltip' => esc_html__('Channel is now OFF. Click to turn ON.','wpstream'),
204 + 'turned_off_tooltip' => esc_html__('Click to turn channel off. This will interrupt any ongoing broadcast.','wpstream'),
205 + 'turning_on_tooltip' => esc_html__('Turning a channel on may take 1-2 minutes or more. Please be patient.','wpstream'),
206 + 'turning_off_tooltip' => esc_html__('This may take a few minutes.','wpstream'),
207 + 'error1' => esc_html__('You don\'t have enough data to start a new event!','wpstream'),
208 + 'failed_event_creation' => esc_html__('Failed to start the channel. Please try again in a few minutes.','wpstream'),
209 + 'channel_turning_on' => esc_html__('Channel is turning on','wpstream'),
210 + 'channel_turning_off' => esc_html__('Channel is turning off','wpstream'),
211 + 'channel_on' => esc_html__('Channel is ON','wpstream'),
212 + 'channel_off' => esc_html__('Channel is OFF','wpstream'),
213 + 'turn_off_confirm' => esc_html__('ARE YOU SURE you\'d like to TURN OFF the channel now? '.PHP_EOL.PHP_EOL.'Channels TURN OFF automatically after 1 hour of inactivity (no active broadcast).'.PHP_EOL.PHP_EOL.'Manual TURN OFF is only useful if you require to change the channel settings immediately.'.PHP_EOL.PHP_EOL.'Statistics may be unavailable or incomplete for up to an hour.'.PHP_EOL.PHP_EOL.'If your channel is configured with Auto TURN ON, it will turn back on as soon as there is a broadcast.','wpstream')
214 + ));
215 +
216 +
217 + wp_enqueue_script('wpstream-on-boarding-js', plugin_dir_url( __DIR__ ) .'/admin/js/wpstream-onboarding2.js?v='.time(),array(), WPSTREAM_PLUGIN_VERSION, true);
218 + wp_localize_script('wpstream-on-boarding-js', 'wpstreamonboarding_js_vars',
219 + array(
220 + 'admin_url' => get_admin_url(),
221 + 'plugin_url' => get_dashboard_url().'/plugins.php',
222 + 'upload_url' => get_dashboard_url().'admin.php?page=wpstream_recordings'
223 +
224 + ));
225 +
226 + }
227 +
228 +
165 229 /**
166 - * Filter the catalog of per-channel options shown as toggles.
167 - *
168 - * Each entry is `key => array( name, details, defaults )`. An added key
169 - * renders a toggle on the settings and channel screens; it is stored
170 - * only if the Channel Settings Module knows the key.
171 - *
172 - * @since 4.14.0
173 - *
174 - * @param array $options Option catalog keyed by setting.
175 - */
176 - $this->global_event_options = (array) apply_filters( 'wpstream_default_event_options', $this->global_event_options );
177 - }
230 + * Add Plugin Administation menu
231 + *
232 + * @since 3.0.1
233 + */
234 +
235 + public function wpstream_manage_admin_menu() {
178 236
179 - /**
180 - * Register and enqueue the plugin's admin-area stylesheets.
181 - *
182 - * Hooked (via Wpstream_Loader) to admin_enqueue_scripts.
183 - *
184 - * @since 3.0.1
185 - * @return void
186 - */
187 - public function enqueue_styles() {
237 + add_menu_page( __('WpStream','wpestream'), __('WpStream ','wpstream'), 'administrator', 'wpstream_credentials', array($this,'wpstream_set_wpstream_credentials'), WPSTREAM_PLUGIN_DIR_URL.'img/wpstream-icon-menu_2.png',20 );
238 + add_submenu_page( 'wpstream_credentials', __('WpStream Credentials','wpestream'), __('Credentials','wpestream'), 'administrator', 'wpstream_credentials', array($this,'wpstream_set_wpstream_credentials') );
239 + add_submenu_page( 'wpstream_credentials', __('WpStream Live Channels','wpestream'), __('All Channels','wpestream'), 'administrator', 'wpstream_live_channels', array( $this,'wpstream_new_general_set'));
240 + add_submenu_page( 'wpstream_credentials', __('WpStream Recordings','wpestream'), __('Recordings','wpestream'), 'administrator', 'wpstream_recordings', array($this,'wpstream_media_management'));
241 + add_submenu_page( 'wpstream_credentials', __('WpStream Settings','wpestream'), __('Settings','wpestream'), 'administrator', 'wpstream_settings', array($this,'wpstream_settings'));
242 +
243 + add_submenu_page( 'wpstream_credentials', __('WpStream Quick Start','wpestream'), __('WpStream Quick Start','wpestream'), 'administrator', 'wpstream_onboard', array($this,'wpstream_pre_onboard_display'));
244 +
188 245
246 +
247 +
248 + }
249 +
250 +
251 +
252 +
189 253 /**
190 - * This function is provided for demonstration purposes only.
191 - *
192 - * An instance of this class should be passed to the run() function
193 - * defined in Wpstream_Loader as all of the hooks are defined
194 - * in that particular class.
195 - *
196 - * The Wpstream_Loader will then create the relationship
197 - * between the defined hooks and the functions defined in this
198 - * class.
199 - */
200 - // No external webfont: the admin UI falls back to the system font stack
201 - // declared in the stylesheets, so no request leaves the site for fonts.
202 - // Main admin stylesheet; filemtime() is used as the cache-busting version.
203 - wp_enqueue_style(
204 - $this->plugin_name,
205 - plugin_dir_url( __FILE__ ) . 'css/wpstream-admin.css',
206 - array(),
207 - filemtime(plugin_dir_path(__FILE__) . 'css/wpstream-admin.css' ),
208 - 'all'
254 + * Shows events wpstream
255 + *
256 + * @since 3.0.1
257 + */
258 +
259 + public function wpstream_new_general_set() {
260 +
261 + $no_channel=1;
262 +
263 + if(class_exists ('WC_Subscription')){
264 +
265 + }
266 +
267 + //event_passed
268 + $args = array(
269 + 'posts_per_page' => -1,
270 + 'post_type' => 'product',
271 + 'post_status' => 'publish',
272 + 'meta_query' => array(
273 + array(
274 + 'key' => 'event_passed',
275 + 'value' => 1,
276 + 'compare' => '!=',
277 + )
278 + ),
279 +
280 + 'tax_query' => array(
281 + 'relation' => 'AND',
282 + array(
283 + 'taxonomy' => 'product_type',
284 + 'field' => 'slug',
285 + 'terms' => array('live_stream','subscription')
286 + )
287 + ),
209 288 );
210 289
211 - // Ensure the WP media library scripts/styles are available (for logo/image pickers) if not already loaded.
212 - if (!did_action('wp_enqueue_media')) {
213 - wp_enqueue_media();
214 - }
215 - }
216 290
217 - /**
218 - * Register, enqueue and localize the plugin's admin-area JavaScript.
219 - *
220 - * Enqueues jQuery UI helpers, the fileupload lib, the admin control/upload
221 - * scripts, the start-streaming and settings scripts, and the onboarding
222 - * bundles. Each script is fed a localized vars array (translated strings,
223 - * URLs, nonces, feature flags). Some bundles are only loaded on specific
224 - * admin screens. Hooked (via Wpstream_Loader) to admin_enqueue_scripts.
225 - *
226 - * @since 3.0.1
227 - * @return void
228 - */
229 - public function enqueue_scripts() {
230 291
231 - // jQuery UI widgets used by the settings/date pickers and sliders.
232 - wp_enqueue_script("jquery-ui-slider");
233 - wp_enqueue_script("jquery-ui-datepicker");
234 - // Blueimp-style file upload library backing the recordings/VOD uploader.
235 - wp_enqueue_script('jquery.fileupload', plugin_dir_url( __FILE__ ) .'js/jquery.fileupload.js?v='.time(),array(), WPSTREAM_PLUGIN_VERSION, true);
292 + $event_list = new WP_Query($args);
293 + global $live_event_for_user;
294 + $live_event_for_user = $this->main->wpstream_live_connection->wpstream_get_live_event_for_user();
295 + $pack_details = $this->main->wpstream_live_connection->wpstream_request_pack_data_per_user();
236 296
237 - // Shared admin utility helpers, then the main admin control script that drives uploads and channel actions.
238 - wp_enqueue_script( 'wpstream-admin-utils', plugin_dir_url( __FILE__ ) .'js/utils/admin_utils.js?v='.time(),array(), WPSTREAM_PLUGIN_VERSION, true);
239 - wp_enqueue_script('wpstream-admin-control', plugin_dir_url( __FILE__ ) .'js/admin_control.js?v='.time(),array(), WPSTREAM_PLUGIN_VERSION, true);
240 - // Hand the control script all of its translated status strings, the admin URL, and the multipart upload nonce.
241 - wp_localize_script('wpstream-admin-control', 'wpstream_admin_control_vars',
242 - array(
243 - 'admin_url' => get_admin_url(),
244 - 'multipart_upload_nonce' => wp_create_nonce( 'wpstream_multipart_upload_nonce' ),
245 - 'recordings_nonce' => wp_create_nonce( 'wpstream_recordings_nonce' ),
246 - 'loading_url' => WPSTREAM_PLUGIN_DIR_URL.'/img/loading.gif',
247 - 'download_mess' => esc_html__('Click to download!','wpstream'),
248 - 'uploading' => esc_html__('We are uploading your file. Do not close this window!','wpstream'),
249 - 'upload_complete2' => esc_html__('Upload Complete! You can upload another file!','wpstream'),
250 - 'not_accepted' => esc_html__('The file is not an accepted video format','wpstream'),
251 - 'upload_complete' => esc_html__('Upload Complete!','wpstream'),
252 - 'no_band' => esc_html__('Not enough streaming data.','wpstream'),
253 - 'no_band_no_store' => esc_html__('Not enough streaming data or storage.','wpstream'),
254 - 'no_streaming_hours' => esc_html__('Not enough streaming hours.','wpstream'),
255 - 'exceeding_limit' => esc_html__('File size exceeds 5GB. Initiating multipart upload...','wpstream'),
256 - 'upload_failed' => esc_html__('Upload Failed!','wpstream'),
257 - 'upload_failed2' => esc_html__('Upload Failed! Please Try again!','wpstream'),
258 - 'choose_a_file' => esc_html__('Choose a file&hellip;','wpstream'),
259 - 'preparing_multipart' => esc_html__('Preparing multipart upload...','wpstream'),
260 - 'uploading_part' => esc_html__('Uploading part {part} of {total}...','wpstream'),
261 - 'upload_failed_part' => esc_html__('Failed to upload part {part}. Please try again.','wpstream'),
262 - 'completing_upload' => esc_html__('Completing upload. Please wait...','wpstream'),
263 - 'upload_failed_part_retry' => esc_html__('Failed to upload part {part}. Retrying...','wpstream'),
264 - 'choose_recording' => esc_html__( 'Choose Recording', 'wpstream' ),
265 - 'select_recording' => esc_html__( 'Please select a recording from the list', 'wpstream' ),
266 - 'invalid_response' => esc_html__('Invalid response from server. Missing required upload data.', 'wpstream'),
267 - 'video_processing' => esc_html__( 'The video is still processing', 'wpstream' ),
268 - 'file_name_text' => esc_html__('File Name:','wpstream'),
269 - 'channel_create_error' => esc_html__('Something did not work. Please try again.', 'wpstream'),
270 - 'select_caption_file' => esc_html__('Select .vtt Captions File', 'wpstream'),
271 - 'select_button' => esc_html__('Select', 'wpstream'),
272 - 'remove_button' => esc_html__('Remove', 'wpstream'),
273 - 'use_streaming_hours' => $this->main->quota_manager->get_streaming_ui_flags_from_cache()['use_streaming_hours'],
274 - ));
297 + $this->main->show_user_data($pack_details);
298 + if( $event_list->have_posts()){
299 +
275 300
276 - // Recordings list script + its localized labels and the "create VOD from recording" links (free vs paid depending on WooCommerce).
277 - wp_enqueue_script('wpstream-recordings-videos-list', plugin_dir_url( __FILE__ ) .'js/recordings_videos_list.js?v='.time(),array(), WPSTREAM_PLUGIN_VERSION, true);
278 - wp_localize_script( 'wpstream-recordings-videos-list', 'wpstream_recordings_videos_list_vars',
279 - array(
280 - 'delete_file' => esc_html__('Delete file', 'wpstream'),
281 - 'download' => esc_html__( 'Download', 'wpstream'),
282 - 'download_available' => esc_html__( 'Click to download! The url will work for the next 20 minutes!', 'wpstream'),
283 - 'add_free_video_url' => esc_url( admin_url( 'post-new.php?post_type=wpstream_product_vod') . '&new_video_name=' ),
284 - 'create_ftv_vod' => esc_html__( 'Create new Free-To-View VOD from this recording' , 'wpstream' ),
285 - 'woocommerce_exists' => class_exists( 'WooCommerce' ),
286 - 'add_paid_video_url' => esc_url( admin_url( 'post-new.php?post_type=product').'&new_video_name=' ),
287 - 'create_ptv_vod' => esc_html__( 'Create new Pay-Per-View VOD from this recording' , 'wpstream' ),
288 - )
289 - );
301 + print '<div class="pack_details_wrapper_transparent">
302 + <h3>'.__('Your Pay-Per-View Channel List','wpstream').'</h3>';
290 303
304 +
305 + $link_new = admin_url('post-new.php?post_type=product').'&new_stream='. rawurlencode('new');
306 +
307 + print '<a href="'.esc_url($link_new).'" class="wpstream_create_new_product_link">'.esc_html__('Create new Pay-Per-View channel.','wpstream').'</a>';
308 + print '</div>';
291 309
292 - // Settings-page script with its save/logo-picker strings and the broadcaster page URL.
293 - wp_enqueue_script('wpstream-settings', plugin_dir_url( __DIR__ ) .'/admin/js/wpstream_settings.js?v='.time(),array(), WPSTREAM_PLUGIN_VERSION, true);
294 - wp_localize_script('wpstream-settings', 'wpstream_settings_vars', array(
295 - 'error_message' => esc_html__( 'Failed to save settings. Please try again.', 'wpstream'),
296 - 'choose_image_text' => esc_html__( 'Choose Logo Image', 'wpstream'),
297 - 'select_image_text' => esc_html__( 'Select Image', 'wpstream'),
298 - 'update_successful' => esc_html__( 'Update Successful.', 'wpstream'),
299 - 'update_failed' => esc_html__( 'Something went wrong. Try again.', 'wpstream'),
300 - 'broadcaster_url' => esc_url( esc_url(home_url('/broadcaster-page/') ) ),
301 - ));
310 + print '<div style="clear: both;"></div><div class="event_list_wrapper">';
302 311
312 + while ($event_list->have_posts()): $event_list->the_post();
303 313
304 - // Identify the current admin screen so screen-specific bundles load only where needed.
305 - $current_screen=get_current_screen();
314 + $the_id = get_the_ID();
315 + $is_subscription_live_event = esc_html(get_post_meta($the_id,'_subscript_live_event',true));
316 + $term_list = wp_get_post_terms($the_id, 'product_type');
306 317
307 - // On the credentials/channels/recordings/onboard screens, load the quota widget updater.
308 - if ( in_array( $current_screen->base, ['toplevel_page_wpstream_credentials', 'wpstream_page_wpstream_live_channels', 'wpstream_page_wpstream_recordings', 'wpstream_page_wpstream_onboard'] ) ) {
309 - wp_enqueue_script( 'wpstream-user-quota-update', plugin_dir_url( __DIR__ ) . 'admin/js/wpstream-user-quota.js', array(), WPSTREAM_PLUGIN_VERSION, true );
310 - wp_localize_script( 'wpstream-user-quota-update', 'wpstream_user_quota_vars', array(
311 - 'admin_url' => get_admin_url()
312 - ));
313 - }
318 + if( $term_list[0]->name=='subscription' && $is_subscription_live_event=='no'){
319 + continue;
320 + }
314 321
315 - // Add localized variables for broadcaster
316 - // Provide the broadcaster script (registered elsewhere) with its AJAX URL and nonce.
317 - wp_localize_script('wpstream-broadcaster', 'wpstream_broadcaster_vars', array(
318 - 'ajax_url' => admin_url('admin-ajax.php'),
319 - 'nonce' => wp_create_nonce('wpstream_broadcaster_nonce'),
320 - 'plugin_url' => plugin_dir_url(__FILE__),
321 - // Gates the broadcaster's diagnostic console logging (see broadcaster.js).
322 - 'debug' => defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG,
323 - ));
322 + $this->wpstream_live_stream_unit($the_id);
324 323
324 + endwhile;
325 +
326 + print'</div>';
327 + $no_channel=1;
328 + }else{
329 + $no_channel=0;
330 + }
331 +
332 +
333 + $ajax_nonce = wp_create_nonce( "wpstream_start_event_nonce" );
334 + print '<input type="hidden" id="wpstream_start_event_nonce" value="'.$ajax_nonce.'">';
335 + $current_user = wp_get_current_user();
336 + $allowded_html = array();
337 + $userID = $current_user->ID;
338 + $user_live_streams = get_user_meta($userID,'live_shows');
339 +
340 +
341 + wp_reset_postdata();
342 +
343 +
344 +
345 +
346 + // free
347 +
348 + $args_free = array(
349 + 'posts_per_page' => -1,
350 + 'post_type' => 'wpstream_product',
351 + 'post_status' => 'publish',
352 +
353 +
354 + );
355 + $event_list_free = new WP_Query($args_free);
356 +
357 +
358 + if( $event_list_free->have_posts()){
359 + print '<div class="pack_details_wrapper_transparent">
360 + <h3>'.__('Free-To-View Channels','wpstream').'</h3>';
361 +
362 + $link_new = admin_url('post-new.php?post_type=wpstream_product');
363 + print '<a href="'.esc_url($link_new).'" class="wpstream_create_new_product_link">'.esc_html__('Create new Free-To-View channel.','wpstream').'</a>';
364 + print '</div>';
365 + print '<div style="clear: both;"></div><div class="event_list_wrapper">';
366 +
367 + while ($event_list_free->have_posts()): $event_list_free->the_post();
368 +
369 +
370 + $the_id = get_the_ID();
371 +
372 + if( get_post_meta ($the_id,'event_passed',true)!=1){
373 + $this->wpstream_live_stream_unit($the_id);
374 + }
375 +
376 + endwhile;
377 +
378 + print'</div><div class="wpstream_modal_background"></div>';
379 + print '<div class="wpstream_error_modal_notification"><div class="wpstream_error_content">er2</div>
380 + <div class="wpstream_error_ok wpstream_button" type="button">'.esc_html__('Close','wpstream').'</div>
381 + </div>';
382 + $no_channel=1;
383 + }else{
384 + $no_channel=0;
385 + }
386 +
387 +
388 +
389 +
390 + $link_new_paid = admin_url('post-new.php?post_type=product').'&new_stream='. rawurlencode('new');
391 + $link_new_free = admin_url('post-new.php?post_type=wpstream_product');
392 + print '<div class="no_events_warning"> ';
393 + if($event_list->found_posts==0){
394 + print '<div class="no_events_warning_mes">'.__('* You do not have any Pay-Per-View channels!','wpstream').'</div>';
395 + }
396 + if($event_list_free->found_posts==0){
397 + print '<div class="no_events_warning_mes">'. __('* You do not have any free channels!','wpstream').'</div>';
398 + }
399 +
400 + print '<a href="'.esc_url($link_new_free).'" class="wpstream_no_chanel_add_channel">'.esc_html__('Add new Free-To-View channel ','wpstream').'</a>';
401 + print '<a href="'.esc_url($link_new_paid).'" class="wpstream_no_chanel_add_channel">'.esc_html__('Add new Pay-Per-View channel ','wpstream').'</a>';
402 +
403 + print '</div>';
404 +
405 +
406 +
407 +
325 408 }
326 -
409 + // end wpstream_new_general_set
410 +
411 +
412 + /**
413 + * Social share
414 + *
415 + * @since 3.0.1
416 + */
327 417
418 + public function wpstream_social_share($the_id){
419 + $protocol = is_ssl() ? 'https' : 'http';
420 + $pinterest = wp_get_attachment_image_src(get_post_thumbnail_id($the_id), 'full');
421 + $link = esc_url ( get_permalink($the_id) );
422 + $title = get_the_title($the_id);
423 + $twiter_status = urlencode( $title.' '.$link);
424 + $email_link = 'subject='.urlencode ( $title ) .'&body='. urlencode( esc_url($link));
425 +
426 + $facebook_link = esc_html($protocol).'://www.facebook.com/sharer.php?u='. esc_url($link) .'&amp;t='. urlencode(get_the_title());
427 +
428 + ?>
429 + <div class="wpstream_social_share_wrapper">
430 +
431 + <a href="<?php print esc_url( $facebook_link); ?>" target="_blank" class="social_facebook wpstream_sharing_social">
432 + <span class="dashicons dashicons-facebook-alt"></span>
433 + </a>
434 +
435 + <a href="<?php print esc_html($protocol);?>://twitter.com/intent/tweet?text=<?php echo esc_html($twiter_status); ?>" class="social_tweet wpstream_sharing_social" target="_blank">
436 + <span class="dashicons dashicons-twitter"></span>
437 + </a>
438 +
439 + <a href="<?php print esc_html($protocol);?>://pinterest.com/pin/create/button/?url=<?php echo esc_url($link); ?>&amp;media=<?php if (isset( $pinterest[0])){ echo esc_url($pinterest[0]); }?>&amp;description=<?php echo urlencode(get_the_title()); ?>" target="_blank" class="social_pinterest wpstream_sharing_social">
440 + <span class="dashicons dashicons-pinterest"></span>
441 + </a>
442 +
443 + <a href="<?php print esc_html($protocol);?>://api.whatsapp.com/send?text=<?php echo urlencode( get_the_title().' '. esc_url( $link )); ?>" class="social_whatsup wpstream_sharing_social" target="_blank">
444 + <span class="dashicons dashicons-whatsapp"></span>
445 + </a>
446 +
447 + <a href="<?php print esc_html($protocol);?>://www.linkedin.com/sharing/share-offsite/?url=<?php echo urlencode(esc_url($link)); ?>" class="social_linkedin wpstream_sharing_social" target="_blank">
448 + <span class="dashicons dashicons-linkedin"></span>
449 + </a>
450 +
451 + <a href="<?php print esc_html($protocol);?>:///www.reddit.com/submit?url==<?php echo urlencode(esc_url($link)); ?>" class="social_linkedin wpstream_sharing_social" target="_blank">
452 + <span class="dashicons dashicons-reddit"></span>
453 + </a>
454 +
455 + <a href="mailto:[email protected]?<?php echo trim(esc_html($email_link));?>" data-action="share email" class="social_email wpstream_sharing_social">
456 + <span class="dashicons dashicons-email-alt"></span>
457 + </a>
458 +
459 + <div class="wpstream_modal_explanations"> <?php print esc_html__('Spread the word! To let people know about your channel, click on the corresponding icon and share on the social platforms of your choice. The more the merrier!','wpstream'); ?> </div>
460 + <?php
461 + print '</div>';
462 + }
463 +
464 +
465 +
466 +
328 467 /**
329 - * Add Plugin Administation menu
330 - *
331 - * Registers the top-level "WpStream" menu and its sub-pages (Credentials,
332 - * All Channels, Recordings, Settings, Quick Start), each mapped to a render
333 - * callback on this class and gated to the `administrator` capability.
334 - *
335 - * @since 3.0.1
336 - * @return void
337 - */
338 - public function wpstream_manage_admin_menu() {
468 + * Shows event unit card in admin
469 + *
470 + * @since 3.0.1
471 + */
339 472
340 - // Top-level menu; its page defaults to the Credentials screen and uses the WpStream icon at position 20.
341 - add_menu_page( __('WpStream','wpstream'), __('WpStream ','wpstream'), 'administrator', 'wpstream_credentials', array($this,'wpstream_set_wpstream_credentials'), WPSTREAM_PLUGIN_DIR_URL.'img/wpstream-icon-menu_2.png',20 );
342 - // Credentials sub-page (same slug as the parent so it is the default view).
343 - add_submenu_page( 'wpstream_credentials', __('WpStream Credentials','wpstream'), __('Credentials','wpstream'), 'administrator', 'wpstream_credentials', array($this,'wpstream_set_wpstream_credentials') );
344 - // All Channels listing.
345 - add_submenu_page( 'wpstream_credentials', __('WpStream Live Channels','wpstream'), __('All Channels','wpstream'), 'administrator', 'wpstream_live_channels', array( $this,'wpstream_new_general_set'));
346 - // Recordings / media management.
347 - add_submenu_page( 'wpstream_credentials', __('WpStream Recordings','wpstream'), __('Recordings','wpstream'), 'administrator', 'wpstream_recordings', array($this,'wpstream_media_management'));
348 - // Global plugin settings.
349 - add_submenu_page( 'wpstream_credentials', __('WpStream Settings','wpstream'), __('Settings','wpstream'), 'administrator', 'wpstream_settings', array($this,'wpstream_settings'));
473 + public function wpstream_live_stream_unit($the_id,$is_front=''){
474 + global $live_event_for_user;
475 + global $wpstream_plugin;
476 + $current_user = wp_get_current_user();
477 +
478 + if( !current_user_can('administrator')){
479 + if($is_front=='' ){
480 + print '<div class="event_list_unit">';
481 + esc_html_e('You are not allowed to broadcast.','wpstream');
482 + print '</div>';
483 + return;
484 + }
485 +
486 + }
487 +
488 + if( !$this->main->wpstream_check_user_can_stream() ){
489 + print '<div class="event_list_unit">';
490 + esc_html_e('You are not allowed to broadcast','wpstream');
491 + print '</div>';
492 + return;
493 + }
494 +
350 495
351 - // Quick Start / onboarding entry point.
352 - add_submenu_page( 'wpstream_credentials', __('WpStream Quick Start','wpstream'), __('WpStream Quick Start','wpstream'), 'administrator', 'wpstream_onboard', array($this,'wpstream_pre_onboard_display'));
496 + $live_class='';
497 + if(isset($live_event_for_user[$the_id])) {
498 + $live_class=" wpstream_show_started";
499 + }
353 500
354 501
502 + if(has_post_thumbnail($the_id)){
503 + $thumb = get_the_post_thumbnail_url($the_id,'thumbnail');
504 + }else{
505 + $thumb= plugin_dir_url( dirname( __FILE__ ) ). 'img/plugin-logo.png';
506 + }
355 507
508 + $pending_streaming_class = 'hide_stream_data';
509 + $external_software_streaming_class = '';
510 + $obs_uri = '';
511 + $obs_stream = '';
512 + $live_data_url = '';
356 513
514 + if( $live_event_for_user=='' && $is_front=='front' ){
515 + $live_event_for_user = $this->main->wpstream_live_connection->wpstream_get_live_event_for_user();
516 + }
517 + $channel_status = esc_html__('Channel is OFF','wpstream');
518 + if(is_array($live_event_for_user) && isset($live_event_for_user[$the_id])) {
519 + $pending_streaming_class = 'pending_trigger';
520 + $live_data_url = get_post_meta($the_id,'qos_url',true);
521 + // $channel_status = esc_html__('Channel is on','wpstream');
522 + }
523 +
524 + $server_id = get_post_meta($the_id,'server_id',true);
525 + $obs_uri = get_post_meta($the_id,'obs_uri',true);
526 + $obs_stream = get_post_meta($the_id,'obs_stream',true);
527 + $webcaster_url = get_post_meta($the_id,'webcaster_url',true);
528 + $rtmp_ip_uri = '';
529 +
530 + print '<div class="event_list_unit '.$live_class.' '.$pending_streaming_class.' event_unit_style_'.esc_attr($is_front).'" data-show-id="'.intval($the_id).'" data-server-id="'.$server_id.'" data-server-url="'.$rtmp_ip_uri.'"">';
531 +
532 + print '<div class="wpstream_channel_status">'.$channel_status.'</div>';
533 +
534 + print '<div class="server_notification"></div>';
535 +
536 + print '<div class="event_thumb_wrapper" style="background-image:url('.$thumb.')"></div>';
537 +
538 + print '<div class="event_title" data-prodid="'.$the_id.'">'.wp_trim_words(get_the_title($the_id),10);
539 +
540 +
541 + /* print '***</br>'.get_post_meta($the_id,'obs_uri',true) .'***</br>'.
542 + get_post_meta($the_id,'obs_stream',true).'***</br>'.
543 + get_post_meta($the_id,'broadcast_url',true);
544 + */
545 + print '<div class="wpstream_channel_item_id">'.esc_html('#ID','wpstream').' '.$the_id.'</div>';
546 + print '</div>';
547 +
548 +
549 + print '<div class="start_event wpstream_button wpstream_tooltip_wrapper" data-show-id="'.$the_id.'" > '.esc_html__('TURN ON','wpstream');
550 + print '<div class="wpstream_tooltip">'.esc_html__('Channel is now OFF. Click to turn ON.','wpestream').'</div>';
551 + print '</div>';
552 +
553 + print '<div class="wpstream_options_col1 wpstream_stream_browser_wrapper">';
554 +
555 + print '<div class="wpstream_inactive_icon start_webcaster wpstream_stream_browser wpstream-button-icon wpstream_tooltip_wrapper" data-webcaster-url="'.$webcaster_url.'" data-show-id="'.$the_id.'"">';
556 +
557 + print '<div class="wpstream_tooltip_disabled">'.esc_html__('Turn ON the channel to go live.','wpestream').'</div>';
558 + print '<div class="wpstream_tooltip">'.esc_html__('Go live with your webcam','wpestream').'</div>';
559 +
560 + print '<svg width="41" height="51" viewBox="0 0 41 51" fill="none" xmlns="http://www.w3.org/2000/svg">
561 + <path d="M40.7646 44.2989C39.8782 41.4216 38.3361 38.7814 36.181 36.4522C35.7274 35.9619 35.1629 35.3518 34.4858 34.8356C34.0448 34.4996 33.4262 34.5281 33.0182 34.9035C29.358 38.2714 25.2628 39.9088 20.4979 39.9088H20.4853C15.7103 39.9059 11.6117 38.264 7.95648 34.889C7.52404 34.4896 6.85874 34.484 6.41953 34.8764C3.30565 37.6569 1.20501 40.9206 0.175434 44.5778C-0.276291 46.1833 0.15652 47.8497 1.33328 49.0353C2.22709 49.9362 3.39869 50.4173 4.61958 50.4173C5.0357 50.4173 5.45813 50.3613 5.87645 50.247C10.147 49.081 14.0772 48.4108 17.8916 48.1983C21.1954 48.014 24.4465 48.1323 27.5541 48.5495C29.9559 48.8718 32.4237 49.3888 35.0996 50.1299C36.823 50.6076 38.459 50.1562 39.7059 48.86C40.9268 47.5901 41.2933 46.0132 40.7651 44.2994L40.7646 44.2989ZM38.0572 47.274C37.3825 47.9754 36.6367 48.1823 35.7092 47.9257C32.9321 47.1565 30.3638 46.6187 27.8578 46.2827C24.6079 45.8465 21.2117 45.723 17.7643 45.9151C13.7874 46.1365 9.70183 46.8319 5.27439 48.041C4.43435 48.2706 3.5673 48.0403 2.9568 47.425C2.35932 46.8227 2.14793 46.0108 2.37712 45.1975C3.21567 42.2171 4.7982 39.6162 7.2018 37.2734C11.0641 40.5378 15.5276 42.193 20.4845 42.196H20.4978C25.4557 42.196 29.9251 40.5386 33.7967 37.2667C34.024 37.4904 34.254 37.7359 34.5032 38.0059C36.4236 40.0816 37.7951 42.4256 38.5799 44.9728C38.8603 45.8811 38.6941 46.6125 38.0581 47.274L38.0572 47.274ZM20.4954 30.7538C13.8088 30.7523 8.54664 25.4128 8.54379 18.6256C8.5412 12.2624 13.9961 6.83353 20.3776 6.84872C27.1094 6.86467 32.4526 12.1652 32.4488 18.8231C32.4447 25.4243 27.1038 30.7547 20.4954 30.7538V30.7538ZM29.4401 18.8383C29.5559 13.9512 25.4358 9.8445 20.5347 9.83671C15.5301 9.82892 11.6488 13.9279 11.5328 18.5667C11.4086 23.5202 15.344 27.7103 20.3381 27.7926C25.5542 27.8783 29.554 23.5758 29.4401 18.8383V18.8383ZM20.4917 25.1342C17.2131 25.2436 14.1541 22.4349 14.1567 18.8924C14.1593 15.2627 16.9642 12.4191 20.5858 12.4662C24.0109 12.5111 26.8269 15.2466 26.8362 18.8471C26.8451 22.4293 23.782 25.2436 20.4917 25.1342V25.1342ZM18.5119 13.9982C17.3006 13.9908 15.6202 15.656 15.6295 16.8543C15.6328 17.3209 15.961 17.661 16.3983 17.6513C17.5973 17.6246 19.2281 16.0169 19.2696 14.8205C19.2881 14.2742 19.0371 14.0016 18.5119 13.9982L18.5119 13.9982ZM20.4964 0.568359C10.4428 0.568359 2.26333 8.74761 2.26333 18.8014C2.26333 28.8551 10.4426 37.0345 20.4964 37.0345C30.5502 37.0345 38.7295 28.8553 38.7295 18.8014C38.7291 8.7478 30.5502 0.568359 20.4964 0.568359V0.568359ZM20.4964 33.3886C12.4528 33.3886 5.90919 26.8449 5.90919 18.8014C5.90919 11.3105 11.585 5.12093 18.8624 4.30631C18.8561 4.36009 18.8528 4.41423 18.8528 4.46912C18.8468 5.37368 19.6112 6.16064 20.4927 6.15846C21.3636 6.15586 22.1283 5.39706 22.142 4.52143C22.1431 4.44874 22.1372 4.3768 22.1279 4.30596C29.4067 5.11929 35.0849 11.3092 35.0849 18.802C35.0842 26.8456 28.5404 33.3892 20.4968 33.3892L20.4964 33.3886Z" fill="black"/>
562 + </svg>';
563 + print '</div>';
564 +
565 +
566 + print '<div class="wpstream_inactive_icon wpstream_stream_pro wpstream-button-icon wpstream-trigger-modal wpstream_tooltip_wrapper" data-modal="wpestate_broadcast_modal" data-show-id="'.$the_id.'"">';
567 +
568 + print '<div class="wpstream_tooltip_disabled">'.esc_html__('Turn ON the channel to go live.','wpestream').'</div>';
569 + print '<div class="wpstream_tooltip">'.esc_html__('Go Live with external streaming app','wpestream').'</div>';
570 +
571 + print '<svg width="51" height="38" viewBox="0 0 51 38" fill="none" xmlns="http://www.w3.org/2000/svg">
572 + <path d="M48.1266 13.9634L41.891 17.5343V13.6438C41.891 10.8723 39.6525 8.63384 36.8811 8.63384H33.1504L30.1124 3.62393C28.7268 1.3324 26.2751 0 23.6103 0H10.2863C8.84722 0 7.67471 1.17251 7.67471 2.6116C7.67471 4.05068 8.84722 5.22319 10.2863 5.22319H23.6103C24.4631 5.22319 25.2093 5.64961 25.6888 6.3957L27.0744 8.63413L5.00991 8.63376C2.23843 8.63376 0 10.8722 0 13.6437V32.9901C0 35.7616 2.23843 38 5.00991 38H36.9342C39.7057 38 41.9441 35.7616 41.9441 32.9901V29.0461L48.1797 32.6169C49.2991 33.2564 50.6846 32.4571 50.6846 31.1778L50.6842 15.4022C50.6311 14.123 49.2455 13.3237 48.1261 13.9632L48.1266 13.9634ZM38.1603 32.9368C38.1603 33.6297 37.574 34.1625 36.9345 34.1625L5.01029 34.1629C4.31733 34.1629 3.78458 33.5766 3.78458 32.9372V13.5907C3.78458 12.8978 4.37086 12.365 5.01029 12.365H36.9345C37.6275 12.365 38.1603 12.9513 38.1603 13.5907V32.9368Z" fill="black"/>
573 + <path d="M22.4917 21.585H9.70066C8.84784 21.585 8.15527 22.2779 8.15527 23.1304V28.247C8.15527 29.0998 8.84823 29.7923 9.70066 29.7923H22.4917C23.3445 29.7923 24.0371 29.0994 24.0371 28.247V23.1304C24.0371 22.2775 23.3445 21.585 22.4917 21.585Z" fill="black"/>
574 + </svg>';
575 + print '</div>';
576 +
577 +
578 +
579 +
580 + print '<a href="'.esc_url($live_data_url).'" target="_blank" class="wpstream_inactive_icon wpstream_live_data wpstream_statistics_channel wpstream-button-icon wpstream_tooltip_wrapper" data-show-id="'.$the_id.'" >';
581 +
582 + print '<div class="wpstream_tooltip_disabled">'.esc_html__('Turn ON the channel to see live stats.','wpestream').'</div>';
583 + print '<div class="wpstream_tooltip">'.esc_html__('Live Statistics','wpestream').'</div>';
584 +
585 + print'<svg width="50" height="42" viewBox="0 0 50 42" fill="none" xmlns="http://www.w3.org/2000/svg">
586 + <path fill-rule="evenodd" clip-rule="evenodd" d="M48.9001 9.02344H40.3342C39.7288 9.02344 39.2344 9.51791 39.2344 10.1233V40.4275C39.2344 41.033 39.7288 41.5274 40.3342 41.5274H48.9001C49.5055 41.5274 50 41.0329 50 40.4275V10.1233C50 9.51791 49.5055 9.02344 48.9001 9.02344V9.02344Z" fill="black"/>
587 + <path fill-rule="evenodd" clip-rule="evenodd" d="M35.821 22.4067H27.2551C26.6497 22.4067 26.1553 22.9012 26.1553 23.5066V40.4277C26.1553 41.0332 26.6497 41.5276 27.2551 41.5276H35.821C36.4264 41.5276 36.9209 41.0332 36.9209 40.4277V23.5066C36.9209 22.9012 36.4264 22.4067 35.821 22.4067V22.4067Z" fill="black"/>
588 + <path fill-rule="evenodd" clip-rule="evenodd" d="M22.7439 0H14.178C13.5726 0 13.0781 0.494478 13.0781 1.09989V40.4275C13.0781 41.0329 13.5726 41.5274 14.178 41.5274H22.7439C23.3493 41.5274 23.8438 41.0329 23.8438 40.4275V1.09989C23.8438 0.49447 23.3493 0 22.7439 0V0Z" fill="black"/>
589 + <path fill-rule="evenodd" clip-rule="evenodd" d="M9.66573 15.2559H1.09987C0.49445 15.2559 -2.24584e-05 15.7512 -2.24584e-05 16.3558V40.4285C-2.24584e-05 41.0331 0.495325 41.5284 1.09987 41.5284H9.66573C10.2703 41.5284 10.7656 41.034 10.7656 40.4285V16.3558C10.7656 15.7503 10.2711 15.2559 9.66573 15.2559V15.2559Z" fill="black"/>
590 + </svg>';
591 + print '</a>';
592 + print '</div>';
593 +
594 + print '<div class="wpstream_options_col2 wpstream_show_settings_wrapper">';
595 + if($is_front==''){
596 + print '<div class="wpstream_show_settings wpstream-button-icon wpstream-trigger-modal wpstream_tooltip_wrapper" data-modal="wpestate_settings_modal" data-show-id="'.$the_id.'" value="'.esc_html__('Settings','wpstream').'">';
597 +
598 + print '<div class="wpstream_tooltip_disabled">'.esc_html__('Turn OFF the channel to change its settings.','wpestream').'</div>';
599 + print '<div class="wpstream_tooltip">'.esc_html__('Channel Settings','wpestream').'</div>';
600 +
601 + print '<svg width="50" height="50" viewBox="0 0 50 50" fill="none" xmlns="http://www.w3.org/2000/svg">
602 + <path d="M49.22 21.8648C48.82 21.6099 45.665 19.7247 44.415 19.15L42.8651 15.4C43.3251 14.1601 44.2099 10.6849 44.3652 10.0798H44.3649C44.4911 9.52035 44.3213 8.93514 43.9149 8.52987L41.47 6.09995C41.0658 5.69189 40.4795 5.52168 39.9201 5.65003C39.4601 5.75501 35.92 6.64994 34.5999 7.15012L30.8499 5.60021C30.3048 4.40012 28.4699 1.32529 28.1351 0.795199V0.79485C27.8337 0.301688 27.298 0.00069643 26.7201 0H23.2798C22.7057 0.000348769 22.1718 0.294715 21.8648 0.779859C21.6098 1.1799 19.7247 4.33487 19.15 5.58487L15.4 7.13478C14.1601 6.67476 10.6849 5.78996 10.0798 5.63469V5.63504C9.52035 5.50878 8.93513 5.67864 8.52987 6.08496L6.09995 8.52988C5.69189 8.9341 5.52168 9.52042 5.65003 10.0798C5.75501 10.5398 6.64994 14.0799 7.15012 15.4L5.60021 19.15C4.40012 19.6951 1.32529 21.53 0.795198 21.8648H0.79485C0.301688 22.1662 0.00069643 22.7019 0 23.2798V26.7149C0.000348751 27.2893 0.294715 27.8233 0.779858 28.1299C1.1799 28.3849 4.33486 30.27 5.58487 30.8448L7.13478 34.5948C6.67475 35.8347 5.78996 39.3099 5.63469 39.915H5.63504C5.50878 40.4747 5.67863 41.06 6.08496 41.4649L8.51487 43.8948V43.8951C8.9191 44.3032 9.50541 44.4731 10.0648 44.3451C10.5248 44.2401 14.0649 43.3451 15.385 42.845L19.135 44.3949C19.6801 45.595 21.515 48.6698 21.8498 49.1999C22.1525 49.6997 22.6956 50.0035 23.2798 50H26.7149C27.2893 49.9996 27.8233 49.7053 28.1299 49.2201C28.3849 48.8201 30.27 45.6651 30.8447 44.4151L34.5947 42.8652C35.8347 43.3252 39.3098 44.21 39.9149 44.3653V44.3649C40.4747 44.4912 41.0599 44.3213 41.4649 43.915L43.8948 41.4851H43.8951C44.3032 41.0809 44.473 40.4945 44.345 39.9352C44.2401 39.4751 43.3451 35.9351 42.8449 34.615L44.3949 30.865C45.5949 30.3198 48.6698 28.485 49.1999 28.1501C49.6997 27.8474 50.0034 27.3044 49.9999 26.7201V23.2799C50.0045 22.7047 49.7087 22.1683 49.2201 21.8649L49.22 21.8648ZM24.9995 35.8845C22.1099 35.882 19.3399 34.7314 17.2985 32.6866C15.2572 30.6414 14.1118 27.8694 14.1146 24.9798C14.1171 22.0903 15.2676 19.3199 17.3125 17.2785C19.3577 15.2372 22.1297 14.0921 25.0193 14.0946C27.9088 14.0974 30.6792 15.2477 32.7205 17.2928C34.7619 19.338 35.907 22.1101 35.9045 24.9996C35.8978 27.8879 34.7462 30.6557 32.7021 32.6964C30.6576 34.7367 27.8876 35.8834 24.9994 35.8845H24.9995Z" fill="black"/>
603 + </svg>
604 + </div>';
605 +
606 +
607 + print '<a href="'.get_edit_post_link($the_id).'" class="wpstream_edit_channel wpstream-button-icon wpstream_tooltip_wrapper" target="_blank" data-show-id="'.$the_id.'"">';
608 + print '<div class="wpstream_tooltip">'.esc_html__('Edit Channel','wpestream').'</div>';
609 + print '<svg width="50" height="50" viewBox="0 0 50 50" fill="none" xmlns="http://www.w3.org/2000/svg">
610 + <path d="M44.8203 1.79549C42.4263 -0.598498 38.5591 -0.598498 36.1651 1.79549L4.67494 33.2246C4.55203 33.3475 4.49079 33.4088 4.42954 33.5317C4.42954 33.5317 4.42954 33.5929 4.36829 33.5929C4.30705 33.7159 4.24539 33.7771 4.24539 33.9V33.9613L0.0711091 47.5886C-0.113044 48.264 0.0711092 48.9389 0.500659 49.4301C0.868966 49.7984 1.29852 49.9826 1.78973 49.9826C1.97388 49.9826 2.15804 49.9826 2.34219 49.9213L15.9085 45.747H15.9697C16.0926 45.6858 16.2151 45.6858 16.2768 45.6241C16.2768 45.6241 16.338 45.6241 16.338 45.5629C16.4609 45.5016 16.5834 45.44 16.6451 45.3175L48.0742 13.8884C50.4682 11.4944 50.4682 7.62715 48.0742 5.23316L44.8203 1.79549Z" fill="black"/>
611 + </svg>';
612 + print '</a>';
613 + }
614 +
615 + print '<a href="'.get_permalink($the_id).'" target="_blank" class="wpstream_view_channel wpstream-button-icon wpstream_tooltip_wrapper" data-show-id="'.$the_id.'"">';
616 + print '<div class="wpstream_tooltip">'.esc_html__('View Channel','wpestream').'</div>';
617 + print '<svg width="50" height="32" viewBox="0 0 50 32" fill="none" xmlns="http://www.w3.org/2000/svg">
618 + <path d="M18.6201 15.2828H21.8752C21.8752 14.069 22.8681 13.0207 24.1373 13.0207V9.76562C21.1032 9.76562 18.6201 12.2487 18.6201 15.2828Z" fill="black"/>
619 + <path d="M24.855 0C12.9378 0 3.28272 10.9792 0.579292 14.3447C-0.193097 15.2826 -0.193097 16.662 0.579292 17.6553C3.28282 21.0208 12.9378 32 24.855 32C36.7722 32 46.4273 21.0208 49.1307 17.6553C49.9031 16.7174 49.9031 15.338 49.1307 14.3447C46.4275 10.9792 36.7722 0 24.855 0V0ZM24.855 25.8205C19.4482 25.8205 15.0344 21.4067 15.0344 15.9999C15.0344 10.5931 19.4482 6.17927 24.855 6.17927C30.2618 6.17927 34.6756 10.5931 34.6756 15.9999C34.6756 21.4067 30.2618 25.8205 24.855 25.8205Z" fill="black"/>
620 + </svg>';
621 + print '</a>';
622 +
623 +
624 + print '<div class="wpstream_share_channel wpstream-button-icon wpstream-trigger-modal wpstream_tooltip_wrapper" data-modal="wpestate_share_modal" data-show-id="'.$the_id.'"">';
625 + print '<div class="wpstream_tooltip">'.esc_html__('Share Channel','wpestream').'</div>';
626 + print '<svg width="44" height="50" viewBox="0 0 44 50" fill="none" xmlns="http://www.w3.org/2000/svg">
627 + <path d="M20.0777 20.5087L24.3481 17.9427C26.6432 16.5645 29.4554 16.2443 31.96 17.198C33.443 17.7642 35.1166 17.9363 36.852 17.6105C40.3163 16.9521 43.1162 14.1831 43.8115 10.7248C45.0606 4.51597 39.7751 -0.910703 33.5907 0.12835C30.2924 0.682061 27.5604 3.16211 26.5942 6.36168C26.4405 6.86646 26.3418 7.35835 26.2804 7.84466C25.9482 10.5028 24.2498 12.8044 21.9547 14.1827L19.3458 15.7456C17.1061 17.0869 14.3986 17.1792 11.9494 16.2748C10.9956 15.9241 9.96159 15.7271 8.88507 15.7271C3.39004 15.7271 -0.960663 20.7607 0.184097 26.4527C0.879447 29.911 3.67936 32.68 7.14364 33.3384C8.87902 33.6706 10.5525 33.492 12.0356 32.9259C14.5402 31.9721 17.3461 32.2919 19.6475 33.6706L23.906 36.2241C25.346 37.0855 26.2195 38.6424 26.2195 40.3159V40.3403C26.2195 45.8229 31.2287 50.1611 36.9018 49.0472C40.3602 48.3703 43.1415 45.583 43.8244 42.1246C44.9383 36.451 40.6 31.4423 35.1175 31.4423C34.0406 31.4423 33.007 31.6394 32.0532 31.9901C29.604 32.8944 26.9029 32.8022 24.6627 31.4608L20.0721 28.7038C18.6445 27.8484 17.7706 26.304 17.7706 24.6364V24.5875C17.7642 22.9208 18.6441 21.37 20.0777 20.5085L20.0777 20.5087Z" fill="black"/>
628 + </svg>';
629 + print '</div>';
630 + print '</div>';
631 +
632 +
633 +
634 +
635 +
636 +
637 + $this->wpstream_display_modal_seetings($the_id);
638 + $this->wpstream_display_modal_share($the_id);
639 + $this->wpstream_display_modal_broadcast($the_id,$external_software_streaming_class,$obs_uri,$obs_stream);
640 +
641 + print '</div>';
642 +
357 643 }
358 644
359 -
360 -
361 -
362 - /**
363 - * Shows events wpstream
645 +
646 +
647 + /*
364 648 *
365 - * Renders the "All Channels" admin screen: the Pay-Per-View (WooCommerce
366 - * `product`) channel list, the Free-To-View (`wpstream_product`) list, the
367 - * quota/pack summary, and the "no channels" call-to-action. Each channel is
368 - * drawn via wpstream_live_stream_unit(). Echoes HTML directly.
649 + * Close modal button
369 650 *
370 - * @since 3.0.1
371 - * @return void
372 651 */
373 - public function wpstream_new_general_set() {
374 - return $this->main->get_live_channel_presentation()->render_channels_page();
652 +
653 + public function wpstream_close_modal_button(){
654 + print '<div class="wpstream_close_modal"></div>';
375 655 }
376 - public function wpstream_social_share($the_id){
377 - return $this->main->get_live_channel_presentation()->render_part( 'social_share', array( $the_id ) );
656 +
657 + /*
658 + *
659 + * Display modal settings
660 + *
661 + */
662 +
663 + public function wpstream_display_modal_seetings($the_id){
664 + print '<div class="wpstream_modal_form wpestate_settings_modal">';
665 + $this->wpstream_close_modal_button();
666 + print '<h3>';
667 + printf( esc_html__('Channel Settings (#ID %s)','wpstream'),$the_id);
668 + print '</h3>';
669 + $local_event_options = get_post_meta($the_id,'local_event_options',true);
670 + if(!is_array($local_event_options)){
671 + $local_event_options = get_option('wpstream_user_streaming_global_channel_options') ;
672 + }
673 +
674 + $local_array_exclude=array('ses_encrypt','vod_domain_lock','vod_encrypt');
675 +
676 + print '<div class="wpstream_event_streaming_local">';
677 + $this->user_streaming_global_channel_options('',$local_event_options, $local_array_exclude);
678 + print '</div>';
679 + print '</div>';
378 680 }
379 - public function wpstream_live_stream_unit($the_id,$is_front=''){
380 - $context = '' === $is_front ? 'admin' : $is_front;
381 - return $this->main->get_live_channel_presentation()->render_channel( $the_id, $context );
681 +
682 +
683 + /*
684 + *
685 + * Display share settings
686 + *
687 + */
688 + public function wpstream_display_modal_share($the_id){
689 + print '<div class="wpstream_modal_form wpestate_share_modal">';
690 + $this->wpstream_close_modal_button();
691 + print '<h3>'.esc_html__('Share your Channel','wpstream').'</h3>';
692 + $this->wpstream_social_share($the_id);
693 + print '</div>';
382 694 }
383 - public function wpstream_live_stream_unit_for_theme($the_id,$is_front=''){
384 - return $this->main->get_live_channel_presentation()->render_part( 'theme_channel', array( $the_id, $is_front ) );
695 +
696 +
697 + /*
698 + *
699 + * Display broadcast modal
700 + *
701 + */
702 +
703 + public function wpstream_display_modal_broadcast($the_id,$external_software_streaming_class,$obs_uri,$obs_stream){
704 + print '<div class="wpstream_modal_form wpestate_broadcast_modal">';
705 + $this->wpstream_close_modal_button();
706 + print '<h3>'.esc_html__('Go Live with External Streaming App','wpstream').'</h3>';
707 +
708 + print '<div class="wpstream_modal_explanations">'.esc_html__('Please choose your RTMP encoder/broadcaster','wpstream').'</div>';
709 +
710 + print '<select class="wpstream_external_broadcast_options">';
711 + print '<option value="wpstream_obs_settings">'.esc_html('OBS','wpstream').'</option>';
712 + print '<option value="wpstream_streamyard_settings">'.esc_html('StreamYard','wpstream').'</option>';
713 + print '<option value="wpstream_restream_settings">'.esc_html('Restream','wpstream').'</option>';
714 + print '<option value="wpstream_wimx_settings">'.esc_html('vMix','wpstream').'</option>';
715 + print '<option value="wpstream_wirecast_settings">'.esc_html('Wirecast','wpstream').'</option>';
716 + print '<option value="wpstream_xplit_settings">'.esc_html('XSplit','wpstream').'</option>';
717 + print '<option value="wpstream_larix_settings">'.esc_html('Larix Broadcaster','wpstream').'</option>';
718 +
719 + print '</select>';
720 +
721 + $this->wpstream_obs_settings($obs_uri,$obs_stream);
722 + $this->wpstream_streamyard_settings($obs_uri,$obs_stream);
723 + $this->wpstream_restream_settings($obs_uri,$obs_stream);
724 + $this->wpstream_wmix_settings($obs_uri,$obs_stream);
725 + $this->wpstream_wirecast_settings($obs_uri,$obs_stream);
726 + $this->wpstream_xplit_settings($obs_uri,$obs_stream);
727 + $this->wpstream_larix_settings($obs_uri,$obs_stream);
728 +
729 + print '</div>';
385 730 }
386 - public function wpstream_close_modal_button(){
387 - return $this->main->get_live_channel_presentation()->render_part( 'close_modal_button' );
731 +
732 +
733 +
734 +
735 + /*
736 + *
737 + * Display OBS settings
738 + *
739 + */
740 +
741 + public function wpstream_obs_settings($obs_uri,$obs_stream){
742 +
743 + print '<div class="external_software_streaming wpstream_obs_settings" style="display:block;">';
744 +
745 + print '<div class="external_software_streaming_details">';
746 + print '<div class="event_list_unit_notificationx"><strong>'.esc_html__('Server:').' </strong>';
747 + print '<div class="wpstream_live_uri_text">' . $obs_uri.'</div>
748 + <div class="copy_live_uri">'.__('copy','wpstream').'</div>';
749 +
750 + print '<div class="event_list_stream_key_wrap"><strong>'.__('Stream Key:').' </strong>
751 + <div class="wpstream_live_key_text">'. $obs_stream.'</div><div class="copy_live_key">'.__('copy','wpstream').'</div></div>';
752 + print '</div>';
753 +
754 + print'</div>';
755 +
756 + print ' <div class="wpstream_modal_explanations">';
757 + print '<ul>
758 + <li>1. Click Settings in the OBS Window and then Select Stream.</li>
759 + <li>2. Choose Custom Streaming Server in the Stream Type dropdown menu.</li>
760 + <li>3. In the URL box, type/paste your Server.</li>
761 + <li>4. In the Stream key, type/paste your Stream key.</li>
762 + <li>5. Save changes.Close the Settings window and click on the “Start Streaming” button in the main window of OBS.</li></ul>';
763 +
764 + print '</div>';
765 +
766 +
767 + print'</div>';
388 768 }
389 - public function wpstream_local_event_options_toggle( $is_basic_stream_mode = false ) {
390 - return $this->main->get_live_channel_presentation()->render_part( 'local_event_options_toggle', array( $is_basic_stream_mode ) );
769 +
770 + /*
771 + *
772 + * Display StreamYard settings
773 + *
774 + */
775 +
776 + public function wpstream_streamyard_settings($obs_uri,$obs_stream){
777 +
778 + print '<div class="external_software_streaming wpstream_streamyard_settings">';
779 +
780 + print '<div class="external_software_streaming_details">';
781 + print '<div class="event_list_unit_notificationx"><strong>'.esc_html__('RTMP server URL:').' </strong>';
782 + print '<div class="wpstream_live_uri_text">' . $obs_uri.'</div>
783 + <div class="copy_live_uri">'.__('copy','wpstream').'</div>';
784 +
785 + print '<div class="event_list_stream_key_wrap"><strong>'.__('Stream key:').' </strong>
786 + <div class="wpstream_live_key_text">'. $obs_stream.'</div><div class="copy_live_key">'.__('copy','wpstream').'</div></div>';
787 + print '</div>';
788 +
789 + print'</div>';
790 +
791 + print ' <div class="wpstream_modal_explanations">';
792 + print '<ul>
793 + <li>1. Set up your destination by going to your StreamYard account.</li>
794 + <li>2. Choose "Custom RTMP" and add the RTMP server URL and Stream key from WpStream.</li>
795 + <li>3. Go to "Broadcasts" then "create a broadcast".</li>
796 + <li>4. Enter Live Studio.</li>
797 + <li>5. Adjust all your preferred settings and Click on "Go Live".</li></ul>';
798 +
799 + print '</div>';
800 +
801 +
802 + print'</div>';
391 803 }
392 - public function wpstream_basic_stream_mode_message() {
393 - return $this->main->get_live_channel_presentation()->render_part( 'basic_stream_mode_message' );
394 - }
395 - public function wpstream_display_modal_seetings($the_id){
396 - return $this->main->get_live_channel_presentation()->render_part( 'settings_modal', array( $the_id ) );
804 +
805 +
806 +
807 + /*
808 + *
809 + * Display StreamYard settings
810 + *
811 + */
812 +
813 + public function wpstream_restream_settings($obs_uri,$obs_stream){
814 +
815 + print '<div class="external_software_streaming wpstream_restream_settings">';
816 +
817 + print '<div class="external_software_streaming_details">';
818 + print '<div class="event_list_unit_notificationx"><strong>'.esc_html__('RTMP URL:').' </strong>';
819 + print '<div class="wpstream_live_uri_text">' . $obs_uri.'</div>
820 + <div class="copy_live_uri">'.__('copy','wpstream').'</div>';
821 +
822 + print '<div class="event_list_stream_key_wrap"><strong>'.__('Stream key:').' </strong>
823 + <div class="wpstream_live_key_text">'. $obs_stream.'</div><div class="copy_live_key">'.__('copy','wpstream').'</div></div>';
824 + print '</div>';
825 +
826 + print'</div>';
827 +
828 + print ' <div class="wpstream_modal_explanations">';
829 + print '<ul>
830 + <li>1. Go to your Restream account and set up a destination or channel.</li>
831 + <li>2. Choose "Custom RTMP" and add the RTMP URL and Stream Key from WpStream.</li>
832 + <li>3. Click on "Add Channel".</li>
833 + <li>4. Enter Live Studio.</li>
834 + <li>5. Adjust your preferred settings and Go Live.</li></ul>';
835 +
836 + print '</div>';
837 +
838 +
839 + print'</div>';
397 840 }
398 - public function wpstream_display_modal_share($the_id){
399 - return $this->main->get_live_channel_presentation()->render_part( 'share_modal', array( $the_id ) );
841 +
842 +
843 +
844 + /*
845 + *
846 + * Display Xplit settings
847 + *
848 + */
849 +
850 +
851 + public function wpstream_xplit_settings($obs_uri,$obs_stream){
852 + print '<div class="external_software_streaming wpstream_xplit_settings" style="display:none;">';
853 + print '<div class="external_software_streaming_details">';
854 + print '<div class="event_list_unit_notificationx"><strong>'.esc_html__('RTMP Url:').' </strong>';
855 + print '<div class="wpstream_live_uri_text">' . $obs_uri.'</div>
856 + <div class="copy_live_uri">'.__('copy','wpstream').'</div>';
857 +
858 + print '<div class="event_list_stream_key_wrap"><strong>'.__('Stream Key:').' </strong>
859 + <div class="wpstream_live_key_text">'. $obs_stream.'</div><div class="copy_live_key">'.__('copy','wpstream').'</div></div>';
860 + print '</div>';
861 +
862 + print'</div>';
863 +
864 + print ' <div class="wpstream_modal_explanations">';
865 + print '<ul>
866 + <li>1. Click Broadcast in the XSplit Window and then click "Set up a new output".</li>
867 + <li>2. Choose Custom RTMP in the Set up a new output dropdown menu.</li>
868 + <li>3. In the URL box, type/paste your RTMP Url.</li>
869 + <li>4. In the Stream key, type/paste your Stream key.</li>
870 + <li>5. Save changes and click on the “Stream” button in the main window.</li></ul>';
871 + print '</div>';
872 +
873 + print '</div>';
400 874 }
401 - public function wpstream_display_modal_broadcast($the_id,$external_software_streaming_class,$obs_uri,$obs_stream){
402 - return $this->main->get_live_channel_presentation()->render_part(
403 - 'broadcast_modal',
404 - array( $the_id, $external_software_streaming_class, $obs_uri, $obs_stream )
405 - );
875 +
876 +
877 +
878 + /*
879 + *
880 + * Display WireCast settings
881 + *
882 + */
883 +
884 +
885 + public function wpstream_wirecast_settings($obs_uri,$obs_stream){
886 + print '<div class="external_software_streaming wpstream_wirecast_settings" style="display:none;">';
887 +
888 + print '<div class="external_software_streaming_details">';
889 + print '<div class="event_list_unit_notificationx"><strong>'.esc_html__('Address:').' </strong>';
890 + print '<div class="wpstream_live_uri_text">' . $obs_uri.'</div>
891 + <div class="copy_live_uri">'.__('copy','wpstream').'</div>';
892 +
893 + print '<div class="event_list_stream_key_wrap"><strong>'.__('Stream:').' </strong>
894 + <div class="wpstream_live_key_text">'. $obs_stream.'</div><div class="copy_live_key">'.__('copy','wpstream').'</div></div>';
895 + print '</div>';
896 +
897 + print'</div>';
898 +
899 + print ' <div class="wpstream_modal_explanations">';
900 + print '<ul>
901 + <li>1. Click Output on the top of the screen and then Select Output Settings.</li>
902 + <li>2. In the destination, choose RTMP Server and click OK.</li>
903 + <li>3. In the Address box, type/paste your Address.</li>
904 + <li>4. In the Stream box, type/paste your Stream key.</li>
905 + <li>5. Click on OK to save changes just click the Output on the top of the screen and then Start/Stop Broadcasting.</li></ul>';
906 + print '</div>';
907 +
908 + print '</div>';
406 909 }
407 - public function wpstream_encoder_table(){
408 - return $this->main->get_live_channel_presentation()->render_part( 'encoder_table' );
910 +
911 +
912 +
913 + /*
914 + *
915 + * Display Larix settings
916 + *
917 + */
918 +
919 +
920 + public function wpstream_larix_settings($obs_uri,$obs_stream){
921 + print '<div class="external_software_streaming wpstream_larix_settings" style="display:none;">';
922 + $larix_rtmp=$obs_uri.$obs_stream;
923 + print '<div class="external_software_streaming_details">';
924 + print '<div class="event_list_unit_notificationx"><strong>'.esc_html__('RTMP:').'</strong>';
925 + print '<div class="wpstream_live_uri_text wpstream_larix_rtmp"></div>
926 + <div class="copy_live_uri">'.__('copy','wpstream').'</div>';
927 +
928 + print '</div>';
929 +
930 + print'</div>';
931 +
932 + print ' <div class="wpstream_modal_explanations">';
933 + print '<ul>
934 + <li>A. Scan the QR code.</li>
935 + <li>or</li>
936 + <li>B. Manually configure Larix with the above RTMP</li>';
937 + if(wp_is_mobile() ){
938 + print '
939 + <li>or</li>
940 + <li>C. Click on the button below </li></ul>';
941 + }
942 +
943 +
944 + print '</div>';
945 +
946 +
947 + print '<img class="print_qrcode" src="" />';
948 + if(wp_is_mobile() ){
949 + print '<a href="" class="wpstream_start_with_larix_mobile" >Start Streaming with Larix</a>';
950 + }
951 +
952 +
953 +
954 + print '</div>';
409 955 }
410 - public function wpstream_encoder_panel( $encoder, $obs_uri, $obs_stream, $visible = false ){
411 - return $this->main->get_live_channel_presentation()->render_part(
412 - 'encoder_panel',
413 - array( $encoder, $obs_uri, $obs_stream, $visible )
414 - );
956 +
957 +
958 +
959 +
960 + /*
961 + *
962 + * Display Wmix settings
963 + *
964 + */
965 +
966 +
967 + public function wpstream_wmix_settings($obs_uri,$obs_stream){
968 + print '<div class="external_software_streaming wpstream_wimx_settings" style="display:none;">';
969 +
970 + print '<div class="external_software_streaming_details">';
971 + print '<div class="event_list_unit_notificationx"><strong>'.esc_html__('URL:').' </strong>';
972 + print '<div class="wpstream_live_uri_text">' . $obs_uri.'</div>
973 + <div class="copy_live_uri">'.__('copy','wpstream').'</div>';
974 +
975 + print '<div class="event_list_stream_key_wrap"><strong>'.__('Stream Key:').' </strong>
976 + <div class="wpstream_live_key_text">'. $obs_stream.'</div><div class="copy_live_key">'.__('copy','wpstream').'</div></div>';
977 + print '</div>';
978 +
979 + print'</div>';
980 +
981 + print ' <div class="wpstream_modal_explanations">';
982 + print '<ul>
983 + <li>1. Click on the gear icon near the stream button on the bottom.</li>
984 + <li>2. Choose a custom RTMP Server in destination.</li>
985 + <li>3. In the URL box, type/paste your URL.</li>
986 + <li>4. In the Stream key, type/paste your Stream key.</li>
987 + <li>5. Save changes. You can start streaming by clicking on the stream button at the bottom of the dashboard.</li></ul>';
988 + print '</div>';
989 +
990 + print '</div>';
415 991 }
416 - private function wpstream_settings_fields(){
417 - // Definition of every settings field, keyed and grouped by 'tab' (general, subscription, messages, default options, VOD defaults, support).
418 - return array(
992 +
993 +
994 +
995 + /*
996 + * Set Settings
997 + *
998 + *
999 + */
1000 +
1001 + public function wpstream_settings(){
1002 +
1003 + if($_SERVER['REQUEST_METHOD'] === 'POST'){
1004 + $allowed_html = array();
1005 + $exclude_array = array();
1006 + $allowed_html = array();
1007 +
1008 +
1009 +
1010 + if( isset($_POST['user_streaming_channel_type_hidden']) && intval($_POST['user_streaming_channel_type_hidden'])==1 && !isset($_POST['stream_role']) ){
1011 + update_option( sanitize_key('wpstream_stream_role'), '' );
1012 + }
1013 +
1014 + foreach($_POST as $variable=>$value){
1015 + if ($variable!='submit'){
1016 + if (!in_array($variable, $exclude_array) ){
1017 + update_option( sanitize_key('wpstream_'.$variable), sanitize_text_field ($value) );
1018 + }
1019 +
1020 + if($variable=='stream_role'){
1021 + update_option( sanitize_key('wpstream_stream_role'), $value );
1022 + }
1023 +
1024 + }
1025 + }
1026 +
1027 +
1028 + if( isset($_GET['tab']) && $_GET['tab']=='default_options' ){
1029 + $event_settings=array();
1030 + foreach($this->global_event_options as $key=>$option){
1031 + $event_settings[$key]='';
1032 + if(isset($_POST['wpstream_event_set_'.$key]) && $_POST['wpstream_event_set_'.$key]=='on'){
1033 + $event_settings[$key]=1;
1034 + }else{
1035 + $event_settings[$key]=0;
1036 + }
1037 + }
1038 + update_option('wpstream_user_streaming_global_channel_options',$event_settings);
1039 + }
1040 +
1041 +
1042 +
1043 +
1044 + // reset permalinkgs
1045 + global $wp_rewrite;
1046 +
1047 + update_option( "rewrite_rules", FALSE );
1048 + $wp_rewrite->flush_rules( true );
1049 +
1050 + }
1051 +
1052 + $wpstream_settings_array =array(
419 1053 1 => array(
420 1054 'tab' => 'general_options',
421 1055 'label' => esc_html__('Slug for free video/channel pages ','wpstream'),
422 1056 'name' => 'free_media_slug',
@@ -422,16 +1056,8 @@
422 1056 'name' => 'free_media_slug',
423 1057 'type' => 'text',
424 1058 'details' => esc_html__('This will replace the default "wpstream" of all your free video/channel urls. Special characters like "&" are not permitted. To have your new slug show up you need to re-save the "Permalinks Settings" under Settings -> Permalinks, even if not making any changes.','wpstream'),
425 1059 ),
426 -
427 - 'free_vod_slug' => array(
428 - 'tab' => 'general_options',
429 - 'label' => esc_html__('Slug for free VOD pages ','wpstream'),
430 - 'name' => 'free_media_slug_vod',
431 - 'type' => 'text',
432 - 'details' => esc_html__('This will replace the default "wpstream_vod" of all your free VOD urls. Special characters like "&" are not permitted. To have your new slug show up you need to re-save the "Permalinks Settings" under Settings -> Permalinks, even if not making any changes.','wpstream'),
433 - ),
434 1060
435 1061 2 => array(
436 1062 'tab' => 'general_options',
437 1063 'label' => esc_html__('Non-Admin User Roles Allowed to Broadcast','wpstream'),
@@ -523,60 +1149,10 @@
523 1149 'label' => esc_html__('You are not live message','wpstream'),
524 1150 'name' => 'you_are_not_live',
525 1151 'type' => 'text',
526 1152 'details' => esc_html__('This message will be displayed in player.','wpstream'),
527 - 'default' => esc_html__('We are not live at this moment','wpstream'),
1153 + 'default' => esc_html__('We are not live at this moment. Please check back later.','wpstream'),
528 1154 ),
529 -
530 - 14 => array(
531 - 'tab' => 'general_options',
532 - 'label' => esc_html__('Video player theme','wpstream'),
533 - 'name' => 'video_player_theme',
534 - 'type' => 'select',
535 - 'select_values'=>array(
536 - 'default' => esc_html__('Default','wpstream'),
537 - 'city' => esc_html__('City','wpstream'),
538 - 'forest' => esc_html__('Forest','wpstream'),
539 - 'fantasy' => esc_html__('Fantasy','wpstream'),
540 - 'sea' => esc_html__('Sea','wpstream'),
541 - ),
542 - 'details' => esc_html__('Choose the video player theme to have a different look for the player.','wpstream'),
543 - ),
544 - 'wpstream_player_logo' => array(
545 - 'tab' => 'general_options',
546 - 'name' => 'player_logo',
547 - 'label' => esc_html__('Logo for the video player','wpstream'),
548 - 'type' => 'image',
549 - 'details' => esc_html__('This logo will be displayed on the the video player.','wpstream'),
550 - 'default' => '',
551 - 'image_size' => 'thumbnail',
552 - ),
553 - // hide the video player logo opacity for now
554 -// 'wpstream_player_logo_opacity' => array(
555 -// 'tab' => 'general_options',
556 -// 'name' => 'player_logo_opacity',
557 -// 'label' => esc_html__('Opacity of the video player logo','wpstream'),
558 -// 'type' => 'range',
559 -// 'details' => esc_html__('Set the opacity of the logo','wpstream'),
560 -// 'default' => '',
561 -// 'image_size' => 'thumbnail',
562 -// ),
563 - 'wpsteram_player_logo_position' => array(
564 - 'tab' => 'general_options',
565 - 'name' => 'player_logo_position',
566 - 'label' => esc_html__('Position of the video player logo','wpstream'),
567 - 'type' => 'select',
568 - 'select_values'=>array(
569 - 'top-left' => esc_html__('Top Left','wpstream'),
570 - 'top-right' => esc_html__('Top Right','wpstream'),
571 - 'bottom-left' => esc_html__('Bottom Left','wpstream'),
572 - 'bottom-right' => esc_html__('Bottom Right','wpstream'),
573 - ),
574 - 'details' => esc_html__('Choose the position of the logo on the video player.','wpstream'),
575 - 'default' => '',
576 - ),
577 -
578 -
579 1155
580 1156 99 => array(
581 1157 'tab' => 'default_options',
582 1158 'label' => esc_html__('Events Options ','wpstream'),
@@ -583,263 +1159,37 @@
583 1159 'name' => 'user_streaming_global_channel_options',
584 1160 'type' => 'user_streaming_global_channel_options',
585 1161 'details' => esc_html__('Global Options for live events.','wpstream'),
586 1162 ),
587 -
588 - 100 => array(
589 - 'tab' => 'default_options_vod',
590 - 'label' => esc_html__('Autoplay','wpstream'),
591 - 'name' => 'vod_autoplay',
592 - 'type' => 'slidertoogle',
593 - 'details' => esc_html__('If enabled, video will attempt to start playing automatically. This is only achievable in some browsers.','wpstream'),
594 - ),
595 -
596 -
597 - 101 => array(
598 - 'tab' => 'default_options_vod',
599 - 'label' => esc_html__('Start Muted','wpstream'),
600 - 'name' => 'vod_start_muted',
601 - 'type' => 'slidertoogle',
602 - 'details' => esc_html__('If enabled, video will start muted. This may increase the rate of autoplay in some browsers.','wpstream'),
603 - ),
604 -
605 - 102 => array(
606 - 'tab' => 'default_options_vod',
607 - 'label' => esc_html__('Lock To Website','wpstream'),
608 - 'name' => 'vod_domain_lock',
609 - 'type' => 'slidertoogle',
610 - 'details' =>sprintf ( esc_html__('If enabled, video will only display on %1$s, otherwise it can show up on any website.','wpstream'),get_bloginfo('wpurl') ),
611 - ),
612 -
613 - 103 => array(
614 - 'tab' => 'default_options_vod',
615 - 'label' => esc_html__('Encrypt Video','wpstream'),
616 - 'name' => 'vod_encrypt',
617 - 'type' => 'slidertoogle',
618 - 'details' => esc_html__('If enabled, video data will be encrypted. Enabling encryption may lead to reduced website performance under certain configurations. Encrypted video may not display in all browsers.','wpstream'),
619 - ),
620 -
621 - /* 'vod_domain_lock' =>array(
622 - 'name' => esc_html__('Video On Demand - Lock To Website','wpstream'),
623 - 'details' => sprintf ( esc_html__('If enabled, VODS will only display on %1$s, otherwise they can show up on any website.','wpstream'),get_bloginfo('wpurl') ),
624 - 'defaults' => 'no',
625 - ),
626 - 'vod_encrypt' =>array(
627 - 'name' => esc_html__('Encrypt Video on Demand','wpstream'),
628 - 'details' => esc_html__('If enabled, video data will be encrypted. Enabling encryption may lead to reduced website performance under certain configurations. Encrypted video may not display in all browsers.','wpstream'),
629 - 'defaults' => 'no',
630 - ),*/
631 -
632 - 104 => array(
633 - 'tab' => 'support_tab',
634 - 'label' => esc_html__('Logs','wpstream'),
635 - 'name' => 'logs',
636 - 'type' => 'logs_table',
637 - 'details' => esc_html__('This is the error log of the plugin.','wpstream'),
638 - )
639 -
640 1163 );
641 - }
642 -
643 - /**
644 - * Stop the request unless the current user may manage plugin settings.
645 - *
646 - * Shared by the settings and credentials screens so both enforce the
647 - * same capability (`manage_options`).
648 - *
649 - * @return void
650 - */
651 - private function wpstream_require_settings_capability(){
652 - if ( ! current_user_can( 'manage_options' ) ) {
653 - wp_die( esc_html__( 'Not enough permissions to make this change', 'wpstream' ) );
654 - }
655 - }
656 -
657 - /**
658 - * Render the WpStream Settings admin screen and persist submitted values.
659 - *
660 - * On POST it verifies the nonce, then stores only the fields declared for
661 - * the active tab as `wpstream_*` options (the streamer role is checked
662 - * against the site's roles, the "default options" tab folds its checkboxes
663 - * into one map), and flushes rewrite rules. It then renders the tabbed
664 - * form from the same field definitions. Echoes HTML.
665 - *
666 - * @return void
667 - */
668 - public function wpstream_settings(){
669 -
670 - // Admin-only screen.
671 - $this->wpstream_require_settings_capability();
672 -
673 -
674 - $active_tab = isset( $_GET['tab'] ) ? sanitize_key( $_GET['tab'] ) : 'general_options';
675 -
676 - /**
677 - * Filter the settings field definitions.
678 - *
679 - * Field definitions drive both the save allow-list and the rendered
680 - * form, so an added field (`tab`, `label`, `name`, `type`, `details`)
681 - * is rendered on its tab and saved as the `wpstream_{name}` option
682 - * through sanitize_text_field().
683 - *
684 - * @since 4.14.0
685 - *
686 - * @param array $fields Field definitions.
687 - * @param string $active_tab Tab being rendered or saved.
688 - */
689 - $wpstream_settings_array = (array) apply_filters( 'wpstream_settings_fields', $this->wpstream_settings_fields(), $active_tab );
690 -
691 - /**
692 - * Filter the settings tabs.
693 - *
694 - * Added tabs render their fields from `wpstream_settings_fields`
695 - * and fire `wpstream_settings_tab_{slug}` for a custom body.
696 - *
697 - * @since 4.14.0
698 - *
699 - * @param array $tabs Tab slug => label.
700 - * @param string $active_tab Tab being rendered or saved.
701 - */
702 - $tabs = (array) apply_filters(
703 - 'wpstream_settings_tabs',
704 - array(
705 - 'general_options' => esc_html__( 'General Options', 'wpstream' ),
706 - 'default_options' => esc_html__( 'Default Channel Settings', 'wpstream' ),
707 - 'default_options_vod' => esc_html__( 'VOD Settings', 'wpstream' ),
708 - 'subscription_options' => esc_html__( 'Subscription Options', 'wpstream' ),
709 - 'messages_options' => esc_html__( 'Customize Messages', 'wpstream' ),
710 - 'support_tab' => esc_html__( 'Support', 'wpstream' ),
711 - ),
712 - $active_tab
713 - );
714 -
715 - // Handle a settings submission.
716 - if($_SERVER['REQUEST_METHOD'] === 'POST'){
717 - // CSRF protection.
718 - check_admin_referer( 'wpstream-settings-nonce', 'wpstream-settings-nonce' );
719 -
720 - // Only the fields declared for the active tab may be persisted.
721 - $allowed = array();
722 - foreach ( $wpstream_settings_array as $field ) {
723 - if ( isset( $field['tab'], $field['name'] ) && $field['tab'] === $active_tab ) {
724 - $allowed[] = $field['name'];
725 - }
726 - }
727 -
728 - // Option values as they were before this submission, and as written by it
729 - // (both keyed by option name) — announced together once the save is complete.
730 - $previous_options = array();
731 - $saved_options = array();
732 -
733 - // If the "channel type" section was shown but no streamer role was chosen, clear the stored role.
734 - if( isset($_POST['user_streaming_channel_type_hidden']) && intval($_POST['user_streaming_channel_type_hidden'])==1 && !isset($_POST['stream_role']) ){
735 - $previous_options['wpstream_stream_role'] = get_option( 'wpstream_stream_role' );
736 - $saved_options['wpstream_stream_role'] = '';
737 - update_option( sanitize_key('wpstream_stream_role'), '' );
738 - }
739 -
740 - // Persist each declared field as a sanitized wpstream_* option; anything else is ignored.
741 - foreach ( $allowed as $variable ) {
742 - if ( ! isset( $_POST[ $variable ] ) ) {
743 - continue;
744 - }
745 - $value = $_POST[ $variable ];
746 -
747 - // Streamer role is a list of role slugs; keep only the roles the form offers
748 - // (editable roles minus administrator, who can always broadcast).
749 - if ( 'stream_role' === $variable ) {
750 - $known = array_diff( array_keys( get_editable_roles() ), array( 'administrator' ) );
751 - $roles = array_values( array_intersect( (array) $value, $known ) );
752 - $previous_options['wpstream_stream_role'] = get_option( 'wpstream_stream_role' );
753 - $saved_options['wpstream_stream_role'] = $roles;
754 - update_option( 'wpstream_stream_role', $roles );
755 - continue;
756 - }
757 -
758 - $option_name = sanitize_key( 'wpstream_' . $variable );
759 - $previous_options[ $option_name ] = get_option( $option_name );
760 - $saved_options[ $option_name ] = sanitize_text_field( $value );
761 - update_option( $option_name, $saved_options[ $option_name ] );
762 - }
763 -
764 -
765 - // On the "default options" tab, fold the per-option checkboxes into a single 1/0 map.
766 - if ( 'default_options' === $active_tab ) {
767 - $event_settings=array();
768 - foreach($this->global_event_options as $key=>$option){
769 - $event_settings[$key]='';
770 - if(isset($_POST['wpstream_event_set_'.$key]) && $_POST['wpstream_event_set_'.$key]=='on'){
771 - $event_settings[$key]=1;
772 - }else{
773 - $event_settings[$key]=0;
774 - }
775 - }
776 - $this->main->channel_settings->apply(
777 - array(
778 - 'type' => 'save_defaults',
779 - 'options' => $event_settings,
780 - )
781 - );
782 - }
783 -
784 -
785 -
786 -
787 - // reset permalinkgs
788 - // Slug settings can change permalinks, so drop and rebuild the rewrite rules.
789 - global $wp_rewrite;
790 -
791 - update_option( "rewrite_rules", FALSE );
792 - $wp_rewrite->flush_rules( true );
793 -
794 - /**
795 - * Fires after a WpStream Settings tab was saved and the rewrite
796 - * rules rebuilt. Default Channel Settings saved from the
797 - * "default options" tab are announced separately by
798 - * wpstream_default_channel_settings_saved.
799 - *
800 - * @since 4.14.0
801 - *
802 - * @param string $active_tab Settings tab that was submitted.
803 - * @param array $saved Option values written, keyed by option name.
804 - * @param array $previous The values those options held before.
805 - */
806 - do_action( 'wpstream_settings_saved', $active_tab, $saved_options, $previous_options );
807 -
808 - }
809 -
810 -
811 -
812 -
813 - // Open the settings panel and the form.
1164 +
1165 + $active_tab = 'general_options';
1166 + if( isset( $_GET[ 'tab' ] ) ) {
1167 + $active_tab = $_GET[ 'tab' ];
1168 + }
1169 +
1170 +
814 1171 print '<div class="theme_options_tab_wpstream" style="display:block;" >
815 1172 <h1>'.__('WpStream Settings','wpstream').'</h1>
816 1173 <form method="post" action="" >';
817 1174
818 - // Tab navigation bar; the current tab gets the nav-tab-active class.
819 - print '<h2 class="nav-tab-wrapper">';
820 - foreach ( $tabs as $tab_slug => $tab_label ) {
821 - $tab_slug = sanitize_key( $tab_slug );
822 - print '<a href="' . esc_url( add_query_arg( array( 'page' => 'wpstream_settings', 'tab' => $tab_slug ), admin_url( 'admin.php' ) ) ) . '" class="nav-tab ' . ( $active_tab === $tab_slug ? 'nav-tab-active' : '' ) . '">' . esc_html( $tab_label ) . '</a>';
823 - }
824 - print '</h2>';
825 - $help_link='';
826 -
827 - // Basic-stream mode disables/annotates some default-channel controls.
828 - $is_basic_stream_mode = $this->wpstream_is_basic_streaming_mode();
1175 + print '<h2 class="nav-tab-wrapper">
1176 + <a href="?page=wpstream_settings&tab=general_options" class="nav-tab '; echo $active_tab == 'general_options' ? 'nav-tab-active' : ''; echo '">General Options</a>
1177 + <a href="?page=wpstream_settings&tab=default_options" class="nav-tab '; echo $active_tab == 'default_options' ? 'nav-tab-active' : ''; echo '">Default Channel Settings</a>
1178 + <a href="?page=wpstream_settings&tab=subscription_options" class="nav-tab '; echo $active_tab == 'subscription_options' ? 'nav-tab-active' : ''; echo '">Subscription Options</a>
1179 + <a href="?page=wpstream_settings&tab=messages_options" class="nav-tab '; echo $active_tab == 'messages_options' ? 'nav-tab-active' : ''; echo '">Customize Messages</a>
1180 +
1181 + </h2>';
1182 +
829 1183 print '<div class="wpstream_option_wrapper">';
830 1184
831 - // Pick the contextual "Video Help" docs link for the active tab.
832 1185 switch ($active_tab) {
833 1186 case 'general_options':
834 1187 $help_link='https://docs.wpstream.net/docs/general-settings/';
835 1188 break;
836 1189 case 'default_options':
837 - $help_link='https://docs.wpstream.net/docs/default-channel-settings/';
1190 + $help_link='https://docs.wpstream.net/docs/default-settings/';
838 1191 break;
839 - case 'default_options_vod':
840 - $help_link='https://docs.wpstream.net/docs/vod-settings/';
841 - break;
842 1192 case 'subscription_options':
843 1193 $help_link='https://docs.wpstream.net/docs/subscription-options/';
844 1194 break;
845 1195 case 'messages_options':
@@ -846,51 +1196,33 @@
846 1196 $help_link='https://docs.wpstream.net/docs/customize-messages/';
847 1197 break;
848 1198 }
849 1199
850 - print '<div class="options_wrapper">';
851 - // Render each field that belongs to the active tab.
1200 + print '<div class="wpstream_options_help"><a href="'.esc_url($help_link).'" target="_blank" >Video Help</a></div>';
1201 +
852 1202 foreach ($wpstream_settings_array as $key=>$option){
853 - // Skip fields from other tabs.
854 1203 if($option['tab']!=$active_tab){
855 1204 continue;
856 1205 }
857 -
858 - // Intro blurb (and basic-mode notice) shown above the global channel options control.
859 - if ( $option['type']=='user_streaming_global_channel_options' ) {
860 - print '<div class="default-channel-settings-info">';
861 - print esc_html__( 'These settings will apply to newly created channels; existing channels will not change settings if you change them here', 'wpstream');
862 - if ( $is_basic_stream_mode ) {
863 - $this->wpstream_basic_stream_mode_message();
864 - }
865 - print '</div>';
866 -
867 - }
1206 +
868 1207 print '<div class="wpstream_option">';
869 - // Load this option's stored value.
870 1208 $options_value = get_option('wpstream_'.$option['name']) ;
1209 +
1210 +
1211 + if($option['type']=='user_roles'){
1212 +
1213 + print '<label for="'.$option['name'].'">'.$option['label'].'</label>';
1214 + print $this->wpstream_select_user_roles($option['name'],$options_value);
1215 + print '<div class="settings_details">'.$option['details'].'</div>';
871 1216
1217 + }else if($option['type']=='user_streaming_global_channel_options'){
1218 +
1219 + $exclude_array=array();
1220 + $this->user_streaming_global_channel_options($option['name'],$options_value,$exclude_array);
1221 +
1222 +
1223 + }else if($option['type']=='text'){
872 1224
873 - // Render the appropriate control for this field's type.
874 - switch( $option['type'] ) {
875 - // Multi-select of WordPress user roles allowed to broadcast.
876 - case 'user_roles':
877 - print '<label for="'.esc_attr( $option['name'] ).'">'.wp_kses_post( $option['label'] ).'</label>';
878 - print $this->wpstream_select_user_roles(esc_attr( $option['name'] ),$options_value);
879 - print '<div class="settings_details">'.wp_kses_post( $option['details'] ).'</div>';
880 - break;
881 - // The grid of default per-event streaming options.
882 - case 'user_streaming_global_channel_options':
883 - $exclude_array=array();
884 - $this->user_streaming_global_channel_options(
885 - $option['name'],
886 - $options_value,
887 - $exclude_array,
888 - $is_basic_stream_mode
889 - );
890 - break;
891 - // Plain text input; falls back to the field's default when unset.
892 - case 'text':
893 1225 if($options_value==''){
894 1226 $options_value='';
895 1227 if(isset($option['default'])){
896 1228 $options_value=$option['default'];
@@ -895,20 +1227,19 @@
895 1227 if(isset($option['default'])){
896 1228 $options_value=$option['default'];
897 1229 }
898 1230 }
899 -
900 - print '<label for="'.esc_attr( $option['name'] ).'">'.wp_kses_post( $option['label'] ).'</label>';
901 - print '<input class="wpstream-text-input-setting" id="'.esc_attr( $option['name'] ).'" type="'.$option['type'].'" size="36" name="'.esc_attr( $option['name'] ).'" value="'.esc_attr($options_value).'" />';
902 - print '<div class="settings_details">'.wp_kses_post( $option['details'] ).'</div>';
903 - break;
904 - // Dropdown built from the field's select_values map; a hidden mirror marks the field as present.
905 - case 'select':
906 - print '<label for="'.esc_attr( $option['name'] ).'">'.wp_kses_post( $option['label'] ).'</label>';
907 - print '<select id="'.esc_attr( $option['name'] ).'" name="'.esc_attr( $option['name'] ).'" >';
1231 +
1232 + print '<label for="'.$option['name'].'">'.$option['label'].'</label>';
1233 + print '<input id="'.$option['name'].'" type="'.$option['type'].'" size="36" name="'.$option['name'].'" value="'.esc_attr($options_value).'" />';
1234 + print '<div class="settings_details">'.$option['details'].'</div>';
1235 +
1236 + } else if($option['type']=='select'){
1237 +
1238 + print '<label for="'.$option['name'].'">'.$option['label'].'</label>';
1239 + print '<select id="'.$option['name'].'" name="'.$option['name'].'" >';
908 1240 foreach($option['select_values'] as $key=>$value){
909 1241 print '<option value="'.$key.'" ';
910 - // Pre-select the currently stored value.
911 1242 if( $key == esc_html($options_value) ){
912 1243 print ' selected ';
913 1244 }
914 1245 print '>'.$value.'</option>';
@@ -913,496 +1244,81 @@
913 1244 }
914 1245 print '>'.$value.'</option>';
915 1246 }
916 1247 print '</select>';
917 - print '<input type="hidden" name="'.esc_attr( $option['name'] ).'_hidden" value="1" >';
918 - print '<div class="settings_details">'.wp_kses_post( $option['details'] ).'</div>';
919 - break;
920 - // On/off switch; a hidden 0-valued twin ensures "off" posts a value.
921 - case 'slidertoogle':
922 - print '<label for="'.esc_attr( $option['name'] ).'">'.wp_kses_post( $option['label'] ).'</label>';
923 - print '<div style="display: flex; gap: 25px; justify-content: space-between;">';
924 - print '<div class="settings_details">'.wp_kses_post( $option['details'] ).'</div>';
1248 + print '<input type="hidden" name="'.$option['name'].'_hidden" value="1" >';
1249 + print '<div class="settings_details">'.$option['details'].'</div>';
1250 +
1251 + } else if($option['type']=='slidertoogle'){
1252 + print '<label for="'.$option['name'].'">'.$option['label'].'</label>';
925 1253 print '<label class="wpstream_switch">
926 - <input type="hidden" class="wpstream_event_option_itemc" value="0" name="'.esc_attr( $option['name'] ).'" >
927 - <input type="checkbox" class="wpstream_event_option_itemc" value="1" name="'.esc_attr( $option['name'] ).'" ';
928 - if( intval($options_value) !==0 ){
929 - print ' checked ';
930 - }
931 - print '> <span class="wpstream_slider round"></span>';
932 - print '</label>';
933 - print '</div>';
934 - break;
935 - // Media-library image picker with preview + upload/remove buttons.
936 - case 'image':
937 - $image_url = $options_value ? esc_url($options_value) : '';
938 - $has_image = !empty($image_url);
1254 + <input type="hidden" class="wpstream_event_option_itemc" value="0" name="'.$option['name'].'" >
1255 + <input type="checkbox" class="wpstream_event_option_itemc" value="1" name="'.$option['name'].'" ';
1256 +
1257 + if( intval($options_value) !==0 ){
1258 + print ' checked ';
1259 + }
1260 +
939 1261
940 - print '<label for="' . esc_attr( $option['name'] ) . '">' . wp_kses_post( $option['label'] ) . '</label>';
941 - print '<div class="wpstream-image-upload-wrapper">';
942 - print '<input type="hidden" id="' . esc_attr( $option['name'] ) . '" name="' . esc_attr( $option['name'] ) . '" value="' . $image_url . '" />';
943 1262
944 - // Preview area
945 - print '<div class="wpstream-image-preview" style="' . (!$has_image ? 'display:none;' : '') . '">';
946 - print '<img src="' . $image_url . '" alt="Preview" />';
947 - print '</div>';
948 -
949 - // Upload/remove buttons
950 - print '<div class="wpstream-image-upload-buttons">';
951 - print '<button type="button" class="wpstream-upload-image button">' . esc_html__('Upload Image', 'wpstream') . '</button>';
952 - print '<button type="button" class="wpstream-remove-image button" style="' . (!$has_image ? 'display:none;' : '') . '">' . esc_html__('Remove Image', 'wpstream') . '</button>';
953 - print '</div>';
954 -
955 - print '</div>';
956 - print '<div class="settings_details">' . wp_kses_post( $option['details'] ) . '</div>';
957 - break;
958 - // 0-100 range slider.
959 - case 'range':
960 - print '<label for="'.esc_attr( $option['name'] ).'">'.wp_kses_post( $option['label'] ).'</label>';
961 - print '<input class="wpstream-range-input" type="range" id="'.esc_attr( $option['name'] ).'" name="'.esc_attr( $option['name'] ).'" min="0" max="100" step="10" value="'.esc_attr($options_value).'" />';
962 - print '<div class="settings_details">'.wp_kses_post( $option['details'] ).'</div>';
963 - break;
964 - // Delegates to the Support tab renderer (plugin error log table).
965 - case 'logs_table':
966 - $this->wpstream_support_tab();
967 - break;
968 - }
1263 + print '> <span class="wpstream_slider round"></span>';
1264 + print '</label>';
1265 + print '<div class="settings_details">'.$option['details'].'</div>';
1266 + }
969 1267 print '</div>';
970 1268 }
971 -
972 - /**
973 - * Fires inside the options wrapper of a settings tab, after its fields.
974 - *
975 - * The dynamic part is the tab slug. Callbacks echo their own markup
976 - * and own its escaping; fields they add to the form are saved only
977 - * when declared through `wpstream_settings_fields`.
978 - *
979 - * @since 4.14.0
980 - *
981 - * @param string $active_tab Tab being rendered.
982 - */
983 - do_action( 'wpstream_settings_tab_' . $active_tab, $active_tab );
984 - print '</div>'; // options wrapper
985 - // Contextual help link for tabs that have one.
986 - if($help_link!==''){
987 - print '<div class="wpstream_options_help"><a href="'.esc_url($help_link).'" target="_blank" >'.esc_html__('Video Help','wpstream').'</a></div>';
988 - }
989 1269 print '</div>';
990 1270
991 1271
992 - // Save button (hidden on the read-only Support tab).
993 - if ( $active_tab != 'support_tab') {
994 - print '<div class="wpstream-save-settings">';
995 1272 print '<input type="submit" name="submit" class="wpstream_button wpstream_button_action" value="'.__('Save Changes','wpstream').'" />';
996 - print '<div class="spinner"></div>';
997 - print '</div>';
998 - }
999 1273
1000 - // CSRF nonce for the submission handled at the top of this method.
1001 - print '<input id="wpstream-settings-nonce" name="wpstream-settings-nonce" type="hidden" value="'.wp_create_nonce('wpstream-settings-nonce').'" /> ';
1274 +
1002 1275 print '</form>';
1003 1276 print '</div>';
1004 -
1277 +
1005 1278 }
1006 -
1007 - /**
1008 - * Get system information for support tab
1009 - *
1010 - * @return array System information
1011 - */
1012 - private function get_system_info() {
1013 - global $wp_version;
1014 -
1015 - // Environment facts: PHP/WP version, debug flag, memory limit and the plugin version.
1016 - $php_version = phpversion();
1017 - $wp_version_info = $wp_version;
1018 - $site_debug_mode = (defined('WP_DEBUG') && WP_DEBUG);
1019 - $wp_memory_limit = WP_MEMORY_LIMIT;
1020 -
1021 - $wpstream_version = WPSTREAM_PLUGIN_VERSION;
1022 - $wpstream_plugin_outdated = false;
1023 -
1024 - // Check if plugin is outdated
1025 - // Mark the plugin outdated if WP's update transient lists an available update for it.
1026 - $update_plugins = get_site_transient('update_plugins');
1027 - if (isset($update_plugins->response['plugin/wpstream.php'])) {
1028 - $wpstream_plugin_outdated = true;
1029 - }
1030 -
1031 - // Check API status
1032 - // API is "connected" when a WpStream cloud token can be obtained.
1033 - $api_status = false;
1034 - if (method_exists($this->main->wpstream_live_connection, 'is_connected')) {
1035 - $api_status = $this->main->wpstream_live_connection->is_connected();
1036 - }
1037 -
1038 - // Return the collected diagnostics for the Support tab to render.
1039 - return array(
1040 - 'php_version' => $php_version,
1041 - 'wp_version' => $wp_version_info,
1042 - 'site_debug_mode' => $site_debug_mode,
1043 - 'wp_memory_limit' => $wp_memory_limit,
1044 - 'wpstream_version' => $wpstream_version,
1045 - 'wpstream_plugin_outdated' => $wpstream_plugin_outdated,
1046 - 'api_status' => $api_status
1047 - );
1048 - }
1049 -
1050 - /**
1051 - * Render system information HTML
1052 - *
1053 - * Prints the Support-tab diagnostics table (PHP/WP versions, debug mode,
1054 - * memory limit, plugin version + update button, API connection) with a
1055 - * warning/OK dashicon per row. Echoes HTML.
1056 - *
1057 - * @return void
1058 - */
1059 - private function render_system_info() {
1060 - // Pull the current environment diagnostics.
1061 - $system_info = $this->get_system_info();
1062 - // Below: diagnostics table; each row shows a value and a warning/OK indicator based on recommended thresholds.
1063 - ?>
1064 -
1065 - <div class="wpstream-system-info">
1066 - <h3><?php esc_html_e('System Information', 'wpstream'); ?></h3>
1067 - <table class="widefat">
1068 - <tbody>
1069 - <tr>
1070 - <td><strong><?php esc_html_e('PHP Version', 'wpstream'); ?></strong></td>
1071 - <td><?php echo esc_html($system_info['php_version']); ?></td>
1072 - <td>
1073 - <?php if (version_compare($system_info['php_version'], '7.4', '<')): ?>
1074 - <span class="dashicons dashicons-warning" style="color: #ffb900;"></span>
1075 - <?php esc_html_e('We recommend PHP 7.4 or higher', 'wpstream'); ?>
1076 - <?php else: ?>
1077 - <span class="dashicons dashicons-yes-alt" style="color: #46b450;"></span>
1078 - <?php endif; ?>
1079 - </td>
1080 - </tr>
1081 - <tr>
1082 - <td><strong><?php esc_html_e('WordPress Version', 'wpstream'); ?></strong></td>
1083 - <td><?php echo esc_html($system_info['wp_version']); ?></td>
1084 - <td>
1085 - <?php if (version_compare($system_info['wp_version'], '5.6', '<')): ?>
1086 - <span class="dashicons dashicons-warning" style="color: #ffb900;"></span>
1087 - <?php esc_html_e('We recommend WordPress 5.6 or higher', 'wpstream'); ?>
1088 - <?php else: ?>
1089 - <span class="dashicons dashicons-yes-alt" style="color: #46b450;"></span>
1090 - <?php endif; ?>
1091 - </td>
1092 - </tr>
1093 - <tr>
1094 - <td><strong><?php esc_html_e('WP Debug Mode', 'wpstream'); ?></strong></td>
1095 - <td><?php echo $system_info['site_debug_mode'] ? esc_html__('Enabled', 'wpstream') : esc_html__('Disabled', 'wpstream'); ?></td>
1096 - <td>
1097 - <?php if ($system_info['site_debug_mode']): ?>
1098 - <span class="dashicons dashicons-info" style="color: #00a0d2;"></span>
1099 - <?php esc_html_e('Debug mode should be disabled on production sites', 'wpstream'); ?>
1100 - <?php else: ?>
1101 - <span class="dashicons dashicons-yes-alt" style="color: #46b450;"></span>
1102 - <?php endif; ?>
1103 - </td>
1104 - </tr>
1105 - <tr>
1106 - <td><strong><?php esc_html_e('WP Memory Limit', 'wpstream'); ?></strong></td>
1107 - <td><?php echo esc_html($system_info['wp_memory_limit']); ?></td>
1108 - <td>
1109 - <?php
1110 - $memory_limit = wp_convert_hr_to_bytes($system_info['wp_memory_limit']);
1111 - if ($memory_limit < 64 * 1024 * 1024): // 64MB
1112 - ?>
1113 - <span class="dashicons dashicons-warning" style="color: #ffb900;"></span>
1114 - <?php esc_html_e('We recommend at least 64MB', 'wpstream'); ?>
1115 - <?php else: ?>
1116 - <span class="dashicons dashicons-yes-alt" style="color: #46b450;"></span>
1117 - <?php endif; ?>
1118 - </td>
1119 - </tr>
1120 - <tr>
1121 - <td><strong><?php esc_html_e('WpStream Version', 'wpstream'); ?></strong></td>
1122 - <td><?php echo esc_html($system_info['wpstream_version']); ?></td>
1123 - <td style="display: flex; align-items: center; gap: 5px;">
1124 - <?php if ($system_info['wpstream_plugin_outdated']): ?>
1125 - <span class="dashicons dashicons-warning" style="color: #ffb900;"></span>
1126 - <?php esc_html_e('Update available', 'wpstream'); ?>
1127 - <div class="update-button-wrapper">
1128 - <button class="wpstream-update-plugin-button button button-primary" data-plugin="wpstream/wpstream.php">
1129 - <?php esc_html_e('Update Now', 'wpstream'); ?>
1130 - </button>
1131 - </div>
1132 - <?php else: ?>
1133 - <span class="dashicons dashicons-yes-alt" style="color: #46b450;"></span>
1134 - <?php endif; ?>
1135 - </td>
1136 - </tr>
1137 - <tr>
1138 - <td><strong><?php esc_html_e('API Connection', 'wpstream'); ?></strong></td>
1139 - <td><?php echo $system_info['api_status'] ? esc_html__('Connected', 'wpstream') : esc_html__('Disconnected', 'wpstream'); ?></td>
1140 - <td>
1141 - <?php if (!$system_info['api_status']): ?>
1142 - <span class="dashicons dashicons-warning" style="color: #ffb900;"></span>
1143 - <?php esc_html_e('API connection issue', 'wpstream'); ?>
1144 - <?php else: ?>
1145 - <span class="dashicons dashicons-yes-alt" style="color: #46b450;"></span>
1146 - <?php endif; ?>
1147 - </td>
1148 - </tr>
1149 - </tbody>
1150 - </table>
1151 - </div>
1152 - <?php
1153 - }
1154 -
1155 - /**
1156 - * Render support tab content
1157 - *
1158 - * Prints the Support tab: the system-info table, a table of relevant active
1159 - * plugins with update tooltips, and a table of the plugin's recent logs.
1160 - * Echoes HTML.
1161 - *
1162 - * @return void
1163 - */
1164 - public function wpstream_support_tab() {
1165 - // Below: Support tab markup (system info, active plugins table, recent logs table).
1166 - ?>
1167 - <div class="wrap">
1168 - <div class="wpstream-support-tab-root">
1169 - <?php $this->render_system_info(); ?>
1170 -
1171 - <div class="wpstream-plugins-table-container">
1172 - <h3><?php esc_html_e('Active Plugins', 'wpstream'); ?></h3>
1173 - <table class="widefat wpstream-plugins-table">
1174 - <thead>
1175 - <tr>
1176 - <th><?php esc_html_e('Plugin', 'wpstream'); ?></th>
1177 - <th><?php esc_html_e('Version', 'wpstream'); ?></th>
1178 - </tr>
1179 - </thead>
1180 - <tbody>
1181 - <?php
1182 - // Build the relevant-plugins list; show a placeholder row when none are found.
1183 - $plugins_data = $this->wpstream_get_plugins_data();
1184 - if (empty($plugins_data)) {
1185 - echo '<tr><td colspan="3">' . esc_html__('No WPStream plugins found.', 'wpstream') . '</td></tr>';
1186 - } else {
1187 - // One row per plugin; append an "update available" tooltip when a newer version exists.
1188 - foreach ($plugins_data as $plugin) {
1189 - echo '<tr>';
1190 - echo '<td>' . esc_html($plugin['name']) . '</td>';
1191 - echo '<td>';
1192 - echo esc_html($plugin['version']);
1193 - if ( isset($plugin['new_version']) ) {
1194 - echo '<div class="wpstream-tooltip-container">';
1195 - echo '<span class="dashicons dashicons-info wpstream-tooltip" title="' . esc_attr($plugin['new_version']) . '">';
1196 - echo '</span>';
1197 - echo '<div class="wpstream-custom-tooltip">' . sprintf(
1198 - esc_html__('A new version is available: %s', 'wpstream'),
1199 - esc_html($plugin['new_version'])
1200 - ) . '</div>';
1201 - echo '</div>';
1202 - }
1203 - echo '</td>';
1204 - echo '</tr>';
1205 - }
1206 - }
1207 - ?>
1208 - </tbody>
1209 - </table>
1210 - </div>
1211 -
1212 - <div class="wpstream-logs-table-container">
1213 - <h3><?php esc_html_e('Recent Logs', 'wpstream'); ?></h3>
1214 - <table class="widefat wpstream-logs-table">
1215 - <thead>
1216 - <tr>
1217 - <th><?php esc_html_e('Time', 'wpstream'); ?></th>
1218 - <th><?php esc_html_e('Type', 'wpstream'); ?></th>
1219 - <th><?php esc_html_e('Description', 'wpstream'); ?></th>
1220 - </tr>
1221 - </thead>
1222 - <tbody>
1223 - <?php
1224 - // Load the stored plugin logs; show a placeholder row when empty.
1225 - $logs = get_option('wpstream_logs');
1226 - if ( !is_array($logs) || empty($logs) ) {
1227 - echo '<tr><td colspan="3">' . esc_html__('No logs found.', 'wpstream') . '</td></tr>';
1228 - } else {
1229 - // One row per log entry (time, type, description).
1230 - foreach ($logs as $log) {
1231 - echo '<tr>';
1232 - echo '<td>' . esc_html(date('Y-m-d H:i:s', $log['timestamp'] ) ) . '</td>';
1233 - echo '<td>' . esc_html($log['type']) . '</td>';
1234 - echo '<td>' . esc_html($log['description']) . '</td>';
1235 - echo '</tr>';
1236 - }
1237 - }
1238 - ?>
1239 - </tbody>
1240 - </table>
1241 - </div>
1242 - </div>
1243 - </div>
1244 - <?php
1245 - }
1246 -
1247 - /**
1248 - * Get plugins data.
1249 - *
1250 - * Collects name/version/active/update info for a fixed allow-list of plugins
1251 - * relevant to WpStream (WpStream, WooCommerce, Meta Box, One Click Demo
1252 - * Import, Better Messages), used by the Support tab.
1253 - *
1254 - * @return array List of plugin info arrays (name, version, path, active, needs_update, [new_version]).
1255 - */
1256 - public function wpstream_get_plugins_data() {
1257 - // Ensure get_plugins() is available in non-admin contexts.
1258 - if (!function_exists('get_plugins')) {
1259 - require_once ABSPATH . 'wp-admin/includes/plugin.php';
1260 - }
1261 -
1262 - // Get all installed plugins
1263 - $all_plugins = get_plugins();
1264 - $update_data = get_site_transient('update_plugins');
1265 - $all_plugins_info = [];
1266 -
1267 - // We want to get data only for the WpStream plugins
1268 - $wpstream_plugins = array(
1269 - 'WpStream' => array(
1270 - 'path' => 'wpstream/wpstream.php',
1271 - ),
1272 - 'WooCommerce' => array(
1273 - 'path' => 'woocommerce/woocommerce.php',
1274 - ),
1275 - 'Meta Box' => array(
1276 - 'path' => 'meta-box/meta-box.php',
1277 - ),
1278 - 'One Click Demo Import' => array(
1279 - 'path' => 'one-click-demo-import/one-click-demo-import.php',
1280 - ),
1281 - 'Better Messages' => array(
1282 - 'path' => 'bp-better-messages/bp-better-messages.php',
1283 - ),
1284 -
1285 - );
1286 -
1287 - // Build an info array for every installed plugin (filtered down afterwards).
1288 - foreach ($all_plugins as $plugin_path => $plugin_data) {
1289 - $is_active = is_plugin_active( $plugin_path );
1290 - $has_update = isset( $update_data->response[$plugin_path] );
1291 -
1292 - $plugin_info = [
1293 - 'name' => $plugin_data['Name'],
1294 - 'version' => $plugin_data['Version'],
1295 - 'path' => $plugin_path,
1296 - 'active' => $is_active ? 'Yes' : 'No',
1297 - 'needs_update' => $has_update ? 'Yes' : 'No'
1298 - ];
1299 -
1300 - // Record the offered version when an update is pending.
1301 - if ($has_update) {
1302 - $plugin_info['new_version'] = $update_data->response[$plugin_path]->new_version;
1303 - }
1304 -
1305 - $all_plugins_info[] = $plugin_info;
1306 - }
1307 -
1308 - // Filter out the elements from $all_plugins_info that are not in $wpstream_plugins
1309 - foreach ( $all_plugins_info as $key => $plugin_info ) {
1310 - // compare $plugin_info['path'] against the path property on each $wpstream_plugins element item
1311 - // if the path is not in $wpstream_plugins, unset the element
1312 - if ( !in_array( $plugin_info['path'], array_column( $wpstream_plugins, 'path' ) ) ) {
1313 - unset( $all_plugins_info[$key] );
1314 - }
1315 - }
1316 -
1317 - return $all_plugins_info;
1318 - }
1319 -
1320 - /**
1321 - * Print a dismissible admin notice when a WpStream plugin update is pending.
1322 - *
1323 - * @return void
1324 - */
1325 - public function wpstream_render_outdated_plugin_notice() {
1326 - // Only render when WP's update transient lists an update for the plugin.
1327 - $has_update = get_site_transient('update_plugins');
1328 - if (isset($has_update->response['plugin/wpstream.php'])) {
1329 - // Below: warning notice linking to the WP updates page.
1330 - ?>
1331 - <div class="notice notice-warning is-dismissible">
1332 - <p>
1333 - <?php
1334 - printf(
1335 - /* translators: 1: Link to update page */
1336 - esc_html__('A new version of WpStream is available. Please update to the latest version for the best experience. Go to the %1$s to update now.', 'wpstream'),
1337 - '<a href="' . esc_url(admin_url('update-core.php')) . '">' . esc_html__('updates page', 'wpstream') . '</a>'
1338 - );
1339 - ?>
1340 - </p>
1341 - </div>
1342 - <?php
1343 - }
1344 - }
1345 -
1346 -
1279 +
1280 +
1281 +
1347 1282 /**
1348 1283 * Set user roles
1349 1284 *
1350 - * Render the grid of per-event streaming option switches (from
1351 - * $global_event_options). Reused for both the site-wide default settings
1352 - * and the per-channel settings modal. Echoes HTML.
1353 - *
1354 - * @param string $name Field name prefix/context (unused in body; kept for callers).
1355 - * @param array|string $value Stored 1/0 map of option states (empty falls back to defaults).
1356 - * @param array|string $local_array Option keys to EXCLUDE from this render (per-channel context).
1357 - * @param bool $disabled True to render the switches disabled.
1358 - * @param bool $is_basic_stream_mode True to disable switches for basic-streaming accounts.
1359 - * @return void
1360 - */
1361 - public function user_streaming_global_channel_options(
1362 - $name,
1363 - $value,
1364 - $local_array='',
1365 - $disabled = false,
1366 - $is_basic_stream_mode = false
1367 - ) {
1285 + * @since 3.0.1
1286 + */
1368 1287
1369 - // Render one switch per defined global event option.
1288 + public function user_streaming_global_channel_options($name,$value,$local_array=''){
1289 +
1370 1290 foreach($this->global_event_options as $key=>$option){
1371 -
1372 - // Skip options listed in the exclude array (used by the per-channel modal).
1291 +
1373 1292 if( is_array($local_array) && !in_array($key,$local_array)){
1374 - print '<div class="wpstream_setting_event_unit_wrapper wpstream-setting-'.esc_attr($key).' ">';
1293 + print '<div class="wpstream_setting_event_unit_wrapper">';
1375 1294
1376 1295 print '<label for="'.$option['name'].'">'.$option['name'].'</label>';
1377 1296
1378 - print '<div style="display: flex; gap: 25px; justify-content: space-between;">';
1379 - print '<div class="settings_details">'.$option['details'].'</div>';
1380 1297 print '
1381 1298 <label class="wpstream_switch">
1382 1299 <input type="checkbox" class="wpstream_event_option_item" data-attr-ajaxname="'.esc_attr($key).'" name="wpstream_event_set_'.esc_attr($key).'" ';
1383 - // Check state: only a stored value of 1 renders the switch on.
1384 - // An absent key resolves to off everywhere the settings are
1385 - // consumed, so the screen must not promise otherwise.
1386 - if( isset($value[$key]) && intval($value[$key]) !== 0 ){
1387 - print ' checked ';
1300 + if( isset($value[$key]) ){
1301 + if( intval($value[$key]) !==0 ){
1302 + print ' checked ';
1303 + }
1304 + }else{
1305 + if($option['defaults']=='yes') {
1306 + print ' checked ';
1307 + }
1388 1308 }
1389 - // Disable the switch when requested or in basic-streaming mode.
1390 - if ( $disabled || $is_basic_stream_mode ) {
1391 - print ' disabled ';
1392 - }
1393 1309
1394 1310
1395 1311 print '> <span class="wpstream_slider round"></span>';
1396 1312 print '</label>';
1397 - print '</div>';
1313 + print '<div class="settings_details">'.$option['details'].'</div>';
1398 1314
1399 1315
1400 1316 print '</div>';
1401 1317 }
1402 1318 }
1403 -
1404 -
1319 +
1320 +
1405 1321 }
1406 1322
1407 1323
1408 1324
@@ -1415,29 +1331,19 @@
1415 1331 /*
1416 1332 * Set user roles
1417 1333 *
1418 1334 * @since 3.0.1
1419 - */
1420 - /**
1421 - * Build a multi-select of editable user roles (administrator excluded)
1422 - * for the "roles allowed to broadcast" setting.
1423 - *
1424 - * @param string $name Field name (rendered as name="{name}[]").
1425 - * @param array|string $value Currently selected role keys ('' becomes an empty array).
1426 - * @return string HTML <select> markup.
1427 - */
1335 + */
1336 +
1428 1337 public function wpstream_select_user_roles($name,$value){
1429 - // Normalize an empty stored value to an array for in_array() below.
1430 1338 if($value==''){
1431 1339 $value=array();
1432 1340 }
1433 -
1434 - // All editable roles minus administrator (admins always can broadcast).
1341 +
1435 1342 $roles = get_editable_roles();
1436 1343 $return = '<select id="wpstream_user_roles" name="'.esc_html($name).'[]" multiple>';
1437 1344 unset( $roles['administrator'] );
1438 -
1439 - // One option per role, pre-selecting those already chosen.
1345 +
1440 1346 foreach ($roles as $key=>$role){
1441 1347 $return .= '<option value="'.$key.'" ';
1442 1348 if( in_array($key, $value) ){
1443 1349 $return .= ' selected ';
@@ -1444,10 +1350,10 @@
1444 1350 }
1445 1351 $return .= '>'.$role['name'].'</option>';
1446 1352 }
1447 1353 $return .= '</select>';
1448 -
1449 -
1354 +
1355 +
1450 1356 return $return;
1451 1357 }
1452 1358
1453 1359
@@ -1454,119 +1360,39 @@
1454 1360 /*
1455 1361 * Set credential admin function
1456 1362 *
1457 1363 * @since 3.0.1
1458 - */
1459 - /**
1460 - * Render the Credentials admin screen and save submitted API credentials.
1461 - *
1462 - * On POST it stores the WpStream username/password options and clears the
1463 - * cached token/quota transients so the next request re-authenticates. It
1464 - * then shows the connection status and the credentials form. Echoes HTML.
1465 - *
1466 - * @return void
1467 - */
1364 + */
1468 1365 public function wpstream_set_wpstream_credentials(){
1469 - $credentials_from_constants = wpstream_api_credentials_from_constants();
1470 -
1471 - // Handle a credentials submission.
1472 - if($_SERVER['REQUEST_METHOD'] === 'POST'){
1473 - // CSRF/permission gate: only an admin submitting the credentials
1474 - // form (with its nonce) may overwrite the stored API credentials.
1475 - $this->wpstream_require_settings_capability();
1476 - check_admin_referer( 'wpstream_save_credentials', 'wpstream_credentials_nonce' );
1477 -
1478 - // wp-config owns the complete pair. A forged/manual POST must be the
1479 - // same no-op as the disabled form presented to the administrator.
1480 - if ( ! $credentials_from_constants ) {
1481 -
1366 +
1367 + if($_SERVER['REQUEST_METHOD'] === 'POST'){
1482 1368 $allowed_html = array();
1483 1369 $exclude_array = array();
1484 1370 $allowed_html = array();
1485 1371
1486 - // Username before this submission: tells a cleared form apart from a new account.
1487 - $previous_username = (string) get_option( 'wpstream_api_username', '' );
1488 -
1489 - // Persist only the recognised credential fields.
1490 - foreach($_POST as $variable=>$value){
1372 + foreach($_POST as $variable=>$value){
1491 1373 if ($variable!='submit'){
1492 1374 if (!in_array($variable, $exclude_array) ){
1493 - switch ( $variable ) {
1494 - case 'api_username':
1495 - // Unslashed first: WordPress slashes every $_POST value,
1496 - // so a username containing a quote would otherwise be
1497 - // stored with a stray backslash and never authenticate.
1498 - // Then sanitized as text.
1499 - update_option( sanitize_key('wpstream_api_username'), sanitize_text_field( wp_unslash( $value ) ) );
1500 - break;
1501 - case 'api_password':
1502 - // Only unslashed, never sanitized: the password is a secret
1503 - // sent verbatim to the API, and sanitizing would silently
1504 - // change it. Unslashing undoes the escaping WordPress adds
1505 - // to every $_POST value, without which a password holding a
1506 - // quote or a backslash is stored — and sent — wrong, so the
1507 - // customer is told their correct password is incorrect.
1508 - // Not autoloaded: it is only needed when authenticating.
1509 - // An empty submission keeps the current password, since the
1510 - // form never pre-fills the field with the stored secret.
1511 - $password = wp_unslash( $value );
1512 - if ( $password !== '' ) {
1513 - update_option( 'wpstream_api_password', $password, false );
1514 - } elseif (
1515 - array_key_exists( 'api_username', $_POST )
1516 - && '' === sanitize_text_field( wp_unslash( $_POST['api_username'] ) )
1517 - ) {
1518 - // Clearing the account is an explicit disconnect, not a
1519 - // password-only edit. Do not retain an orphaned secret.
1520 - delete_option( 'wpstream_api_password' );
1521 - }
1522 - break;
1523 - }
1524 - }
1525 - }
1375 + update_option( sanitize_key('wpstream_'.$variable), wp_kses ($value,$allowed_html) );
1376 + }
1377 + }
1526 1378 }
1379 +
1380 +
1527 1381
1528 1382
1529 -
1530 - // Invalidate any cached token/quota so the new credentials are used immediately.
1531 - update_option('wpstream_token_expire',0);
1532 - update_option('wpstream_current_token',' ');
1383 + update_option('wp_estate_token_expire',0);
1384 + update_option('wp_estate_curent_token',' ');
1533 1385 delete_transient( 'wpstream_token_api');
1534 1386 delete_transient('wpstream_token_request_30');
1535 - $this->main->quota_manager->invalidate();
1536 -
1537 - // Announce the account change. Only the username travels: the
1538 - // password and any token stay server-side.
1539 - $username = (string) get_option( 'wpstream_api_username', '' );
1540 - if ( '' !== $username ) {
1541 - /**
1542 - * Fires after WpStream account credentials were saved and the
1543 - * cached token/quota dropped; the connection itself is verified
1544 - * on the next API call.
1545 - *
1546 - * @since 4.14.0
1547 - *
1548 - * @param string $username WpStream.net username or e-mail.
1549 - */
1550 - do_action( 'wpstream_account_connected', $username );
1551 - } elseif ( '' !== $previous_username ) {
1552 - /**
1553 - * Fires after the WpStream account username was cleared.
1554 - *
1555 - * @since 4.14.0
1556 - *
1557 - * @param string $username The username that was removed.
1558 - */
1559 - do_action( 'wpstream_account_disconnected', $previous_username );
1560 - }
1561 - }
1387 + delete_transient('wpstream_request_pack_data_per_user_transient');
1562 1388 }
1563 1389
1564 1390
1565 1391 $allowed_html = array();
1392 +
1566 1393
1567 1394
1568 - // Field definitions for the credentials form (username + password).
1569 1395 $wpstream_options_array =array(
1570 1396 2 => array(
1571 1397 'label' => 'WpStream.net Username or Email',
1572 1398 'name' => 'api_username',
@@ -1580,67 +1406,38 @@
1580 1406
1581 1407 );
1582 1408
1583 1409
1584 - // Existing installs saved the password as an autoloaded option; flip it
1585 - // to non-autoloaded so the secret is not loaded on every request.
1586 - if ( function_exists( 'wp_set_option_autoload' ) ) {
1587 - wp_set_option_autoload( 'wpstream_api_password', false );
1588 - }
1589 -
1590 - // Connectivity and quota data drive the connection-status banner below.
1591 - $connected = $this->main->wpstream_live_connection->is_connected();
1592 - $pack_details = $this->main->quota_manager->get_live_quota_data( 'wpstream_set_wpstream_credentials' );
1593 -
1410 + $token = $this->main->wpstream_live_connection->wpstream_get_token();
1411 + $pack_details = $this->main->wpstream_live_connection->wpstream_request_pack_data_per_user();
1412 +
1594 1413 $this->main->show_user_data($pack_details);
1595 1414
1596 1415 print '<form method="post" action="" >';
1597 - // CSRF nonce for the credentials save handled at the top of this method.
1598 - wp_nonce_field( 'wpstream_save_credentials', 'wpstream_credentials_nonce' );
1599 1416 print '<div class="theme_options_tab_wpstream" style="display:block;" >
1600 1417 <h1>'.__('WpStream Credentials','wpstream').'</h1>';
1601 1418
1602 - // Credentials supplied via wp-config.php constants take
1603 - // precedence over anything saved here — tell the admin.
1604 - if( $credentials_from_constants ){
1605 - echo '<div class="api_conected">'.esc_html__('Your WpStream credentials are defined in wp-config.php; values saved on this screen are ignored.','wpstream').'</div>';
1606 - }
1607 -
1608 - // Connection status banner: no credentials, bad credentials, connected, or CURL failure.
1609 - if( wpstream_get_api_username()=='' || wpstream_get_api_password()== '' ){
1419 +
1420 + if( get_option('wpstream_api_username')=='' || get_option('wpstream_api_password')== '' ){
1610 1421 echo '<div class="api_not_conected wpstream_orange">';
1611 1422 $admin_url_onboard=get_admin_url().'admin.php?page=wpstream_onboard';
1612 1423 printf ( __('To connect your plugin, enter your WpStream credentials below or go <a href="%s" target="_blank">here</a> to create an account.','wpstream'),$admin_url_onboard);
1613 1424 echo '</div>';
1614 1425
1615 - }else if(!$connected){
1616 - // Translate the literals at definition — gettext cannot extract variable strings.
1617 - $text = get_option('wpstream_curl_failed') === "0" ?
1618 - __( ' Incorrect username or password. Please check your credentials or go <a href="https://wpstream.net/my-account/edit-account/" target="_blank">here</a> to reset your password.', 'wpstream' ) :
1619 - __( 'Not connected to WpStream. Please note the errors above and contact support.', 'wpstream' );
1620 - echo '<div class="api_not_conected">'.wp_kses_post($text).'</div>';
1426 + }else if($token==''){
1427 + echo '<div class="api_not_conected">'.__(' Incorrect username or password. Please check your credentials or go <a href="https://wpstream.net/my-account/edit-account/" target="_blank">here</a> to reset your password.','wpstream').'</div>';
1428 + }else if( $this->main->wpstream_live_connection->wpstream_client_check_api_status() ){
1429 + echo '<div class="api_conected">'.__('Connected to WpStream.net!','wpstream').'</div>';
1621 1430 }else{
1622 - // Credentials present and a token was obtained: connected.
1623 - echo '<div class="api_conected">'.__('Connected to WpStream.net!','wpstream').'</div>';
1431 + echo '<div class="api_not_conected wpstream_brown">'.__('Failed to connect to WpStream.net. Please address CURL connectivity with your hosting provider.','wpstream').'</div>';
1624 1432 }
1625 - // Render the credential inputs. The username is pre-filled;
1626 - // the password field is always left blank so the stored
1627 - // secret is never echoed into the page source (an empty
1628 - // submission keeps the saved password). Inputs are disabled
1629 - // when the wp-config constants are in charge.
1630 - $inputs_disabled = $credentials_from_constants ? ' disabled' : '';
1631 1433 print '<div class="wpstream_option_wrapper">';
1632 1434 foreach ($wpstream_options_array as $key=>$option){
1633 1435 print '<div class="wpstream_option">';
1634 1436
1437 + $options_value = esc_html( get_option('wpstream_'.$option['name'],'') );
1635 1438 print '<label for="'.$option['name'].'">'.$option['label'].'</label>';
1636 - if( $option['type']==='password' ){
1637 - $placeholder = get_option('wpstream_'.$option['name'],'') !== '' ? '*****' : '';
1638 - print '<input id="'.$option['name'].'" type="password" size="36" name="'.$option['name'].'" value="" autocomplete="new-password" placeholder="'.$placeholder.'"'.$inputs_disabled.' />';
1639 - }else{
1640 - $options_value = esc_html( get_option('wpstream_'.$option['name'],'') );
1641 - print '<input id="'.$option['name'].'" type="'.$option['type'].'" size="36" name="'.$option['name'].'" value="'.esc_html($options_value).'"'.$inputs_disabled.' />';
1642 - }
1439 + print '<input id="'.$option['name'].'" type="'.$option['type'].'" size="36" name="'.$option['name'].'" value="'.esc_html($options_value).'" />';
1643 1440
1644 1441 print '</div>';
1645 1442 }
1646 1443 print '</div>';
@@ -1645,9 +1442,9 @@
1645 1442 }
1646 1443 print '</div>';
1647 1444
1648 1445
1649 - print '<input type="submit"'.$inputs_disabled.' name="submit" class="wpstream_button wpstream_button_action" value="'.__('Save Changes','wpstream').'" />';
1446 + print '<input type="submit" name="submit" class="wpstream_button wpstream_button_action" value="'.__('Save Changes','wpstream').'" />';
1650 1447
1651 1448 print '<h3>Video Tutorials</h3>';
1652 1449
1653 1450 print '<a class="how_to_videos" target="_blank" href="https://youtu.be/9DQrxsKcpmQ">How to Live Stream to WordPress with OBS</a>';
@@ -1659,18 +1456,17 @@
1659 1456
1660 1457 print '</div>';
1661 1458 print '</form>';
1662 1459
1663 - // Quick-action links: create free / paid channel, or jump to the channels list.
1664 1460 print '<div class="theme_options_tab_wpstream" style="display:block;" >';
1665 1461 $link_new = admin_url('admin.php?page=wpstream_live_channels');
1666 1462 $link_new_paid = admin_url('post-new.php?post_type=product').'&new_stream='. rawurlencode('new');
1667 1463 $link_new_free = admin_url('post-new.php?post_type=wpstream_product');
1464 +
1668 1465
1669 -
1670 1466 print '<a href="'.esc_url($link_new_free).'" class="wpstream_no_chanel_add_channel">'.esc_html__('Create new Free-To-View channel','wpstream').'</a>';
1671 1467 print '<a href="'.esc_url($link_new_paid).'" class="wpstream_no_chanel_add_channel">'.esc_html__('Create Pay-Per-View channel','wpstream').'</a>';
1672 - print '<a href="'.esc_url($link_new).'" class="wpstream_no_chanel_add_channel">'.esc_html__('My Channels','wpstream').'</a>';
1468 + print '<a href="'.esc_url($link_new).'" class="wpstream_no_chanel_add_channel">'.esc_html('My Channels','wpstream').'</a>';
1673 1469 print '</div>';
1674 1470
1675 1471
1676 1472 }
@@ -1679,33 +1475,27 @@
1679 1475
1680 1476 /**
1681 1477 * Media Management
1682 1478 *
1683 - * Render the Recordings admin screen: the quota summary, the upload widget,
1684 - * and the list of existing recordings. Echoes HTML.
1685 - *
1686 - * @since 3.0.1
1687 - * @return void
1688 - */
1479 + * @since 3.0.1
1480 + */
1481 +
1689 1482 public function wpstream_media_management(){
1690 - // Storage/streaming quota data for the summary header.
1691 - $pack_details = $this->main->quota_manager->get_live_quota_data( 'wpstream_media_management' );
1483 + $pack_details = $this->main->wpstream_live_connection->wpstream_request_pack_data_per_user();
1692 1484
1693 1485 $this->main->show_user_data($pack_details);
1694 1486
1695 1487
1696 - // Upload widget section.
1697 1488 print '<div id="wpstream_media_upload"><h3>'.__('Upload New Recording','wpstream').'</h3>'.$this->wpstream_present_media_upload().'</div>';
1698 1489
1699 - // Existing recordings list section.
1700 1490 print '<div id="wpstream_file_management"><h3 id="video_management_title">'.__('Your Recordings','wpstream').'</h3>'.$this->wpstream_present_file_management().'</div>';
1701 1491
1702 -
1492 +
1703 1493 }
1704 1494
1705 1495
1706 -
1707 1496
1497 +
1708 1498 /**
1709 1499 *
1710 1500 *
1711 1501 * WpStream Pagination
@@ -1714,35 +1504,22 @@
1714 1504 *
1715 1505 *
1716 1506 */
1717 1507
1718 - /**
1719 - * Build a numeric pager (first/prev/window/next/last) for list screens.
1720 - *
1721 - * @param int $pages Total number of pages.
1722 - * @param int $range How many page links to show on each side of the current page.
1723 - * @return string Pager HTML, or '' when there is a single page / no pages.
1724 - */
1725 1508 public function wpstream_pagination($pages , $range = 2) {
1726 1509 $return='';
1727 - // Total visible window width around the current page.
1728 1510 $showitems = ($range * 2) + 1;
1729 - // Current page from the query string (defaults to 1).
1730 1511 $paged = ( isset( $_GET['paged'] ) ) ? intval($_GET['paged']) : 1;
1731 1512
1732 1513
1733 - // Only render a pager when there is more than one page.
1734 1514 if (1 != $pages && $pages != 0) {
1735 1515 $return.= '<ul class="pagination wpstream_pagination">';
1736 - // "Previous" arrow.
1737 1516 $return.= "<li class=\"roundleft\"><a href='" . get_pagenum_link($paged - 1) . "'><</a></li>";
1738 1517
1739 1518 $last_page = get_pagenum_link($pages);
1740 - // Emit page-number links, but only those within the visible window (or all if they fit).
1741 1519 for ($i = 1; $i <= $pages; $i++) {
1742 1520 if (1 != $pages && (!($i >= $paged + $range + 1 || $i <= $paged - $range - 1) || $pages <= $showitems )) {
1743 1521 if ($paged == $i) {
1744 - // Current page marker.
1745 1522 $return.= '<li class="active"><a href="' . esc_url(get_pagenum_link($i)) . '" >' . $i . '</a><li>';
1746 1523 } else {
1747 1524 $return.= '<li><a href="' . esc_url(get_pagenum_link($i)) . '" >' . $i . '</a><li>';
1748 1525 }
@@ -1748,9 +1525,8 @@
1748 1525 }
1749 1526 }
1750 1527 }
1751 1528
1752 - // "Next" target, clamped to the last page.
1753 1529 $prev_page = get_pagenum_link($paged + 1);
1754 1530 if (($paged + 1) > $pages) {
1755 1531 $prev_page = get_pagenum_link($paged);
1756 1532 } else {
@@ -1757,9 +1533,8 @@
1757 1533 $prev_page = get_pagenum_link($paged + 1);
1758 1534 }
1759 1535
1760 1536
1761 - // "Next" and "Last" arrows, then close the list.
1762 1537 $return.= "<li class=\"roundright\"><a href='" . $prev_page . "'>></a><li>";
1763 1538 $return.= "<li class=\"roundright\"><a href='" . $last_page . "'>>><li>";
1764 1539 $return.= "</ul>";
1765 1540 }
@@ -1773,38 +1548,22 @@
1773 1548
1774 1549 /**
1775 1550 * Media upload
1776 1551 *
1777 - * Build the S3 direct-upload widget for new recordings: checks storage
1778 - * quota and API connectivity, then renders a multipart form pre-populated
1779 - * with the signed S3 upload fields.
1780 - *
1781 - * @since 3.0.1
1782 - * @return string Upload widget HTML, or an alert/notice when unavailable.
1783 - */
1552 + * @since 3.0.1
1553 + */
1784 1554 public function wpstream_present_media_upload(){
1785 1555 $to_return='';
1556 + $formInputs=$this->main->wpstream_live_connection->wpstream_get_signed_form_upload_data();
1557 +
1786 1558
1787 - // Refuse when the account is out of storage/data quota.
1788 - if ( ! $this->main->quota_manager->has_storage_quota( null, 'recordings_screen' ) ) {
1789 - return '<div class="wpstream_upload_alert">'.esc_html__('You don\'t have enough cloud storage or data to upload a new item. Please delete some videos or upgrade your plan.','wpstream').'</div>';
1790 - }
1791 1559
1792 - // Request the signed S3 POST fields from the cloud API.
1793 - $formInputs=$this->main->wpstream_live_connection->wpstream_get_signed_form_upload_data();
1794 -
1795 - // On failure, show either a "not connected" or an "out of quota" message.
1560 +
1796 1561 if( !$formInputs['success'] ){
1797 - if ($formInputs['error'] == 'not_connected'){
1798 - $to_return.='<div class="wpstream_upload_container">'.esc_html__('Not connected. Please connect to WpStream to upload videos.','wpstream').'</div>';
1799 - }
1800 - else {
1801 - $to_return.='<div class="wpstream_upload_alert">'.esc_html__('You don\'t have enough cloud storage and data to upload a new item. Please delete some videos or upgrade your plan.','wpstream').'</div>';
1802 - }
1562 + $to_return.='<div class="wpstream_upload_alert">'.esc_html__('There isn\'t enough storage space under your account to upload a new item. Please delete some videos or upgrade your subscription.','wpstream').'</div>';
1803 1563 return $to_return;
1804 1564 }
1805 1565
1806 - // Signed data obtained: render the direct-to-S3 upload form.
1807 1566 if($formInputs['success'] ===true){
1808 1567
1809 1568
1810 1569
@@ -1818,26 +1577,24 @@
1818 1577 data-limitConcurrentUploads="1"
1819 1578 class="direct-upload">';
1820 1579
1821 1580 $to_return.='<input id="wpstream_upload" type="file" class="inputfile inputfile-1" value="Pick a video file" name="file" multiple>';
1822 - $to_return.='<label for="wpstream_upload"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="17" viewBox="0 0 20 17"><path d="M10 0l-5.2 4.9h3.3v5.1h3.8v-5.1h3.3l-5.2-4.9zm9.3 11.5l-3.2-2.1h-2l3.4 2.6h-3.5c-.1 0-.2.1-.2.1l-.8 2.3h-6l-.8-2.2c-.1-.1-.1-.2-.2-.2h-3.6l3.4-2.6h-2l-3.2 2.1c-.4.3-.7 1-.6 1.5l.6 3.1c.1.5.7.9 1.2.9h16.3c.6 0 1.1-.4 1.3-.9l.6-3.1c.1-.5-.2-1.2-.7-1.5z"/></svg> <span id="wpstream_label_action">' . esc_html__('Choose a file&hellip;','wpstream') . '</span></label>';
1581 + $to_return.='<label for="wpstream_upload"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="17" viewBox="0 0 20 17"><path d="M10 0l-5.2 4.9h3.3v5.1h3.8v-5.1h3.3l-5.2-4.9zm9.3 11.5l-3.2-2.1h-2l3.4 2.6h-3.5c-.1 0-.2.1-.2.1l-.8 2.3h-6l-.8-2.2c-.1-.1-.1-.2-.2-.2h-3.6l3.4-2.6h-2l-3.2 2.1c-.4.3-.7 1-.6 1.5l.6 3.1c.1.5.7.9 1.2.9h16.3c.6 0 1.1-.4 1.3-.9l.6-3.1c.1-.5-.2-1.2-.7-1.5z"/></svg> <span id="wpstream_label_action">Choose a file&hellip;</span></label>';
1823 1582
1824 1583
1825 1584 $to_return.='<div class="wpstream_file_drop_color">';
1826 1585 $to_return.='<div class="wpstream_form_ex">'.esc_html__('Drop a video file here!','wpstream').'</div>';
1827 - $to_return.='<div class="wpstream_form_ex_details">'.__('The Video File must be encoded with the following settings:<br>
1586 + $to_return.='<div class="wpstream_form_ex_details">'.__('The Video File must be encoded with the following settings:
1828 1587
1829 - Container: <strong>MP4</strong>,<br>
1830 - Video codec: <strong>H264</strong>,<br>
1831 - Audio codec: <strong>AAC</strong>.<br>
1832 - Media will fail to play if it does not follow the above settings.
1588 + Container: <strong>MP4</strong>,
1589 + Video codec: <strong>H264</strong>,
1590 + Audio codec: <strong>AAC</strong>. Media will fail to play if it does not follow the above settings.
1833 1591 You may use a tool like MediaInfo to verify your file. Also you may convert it with specialized software like HandBrake.','wpstream').'<strong> '.esc_html__('Accepted file extensions: .mp4, .mov','wpstream').'</strong></div>';
1834 - // Inject each signed S3 field as a hidden input so the browser POST is authorized.
1835 - if(is_array($formInputs)){
1836 - foreach ($formInputs['ref'] as $name => $value) {
1592 + if(is_array($formInputs)){
1593 + foreach ($formInputs['ref'] as $name => $value) {
1837 1594 $to_return.='<input type="hidden" name="'. $name.'" value="'.$value.'">';
1838 - }
1839 - }
1595 + }
1596 + }
1840 1597
1841 1598 $to_return.='
1842 1599 <div class="progress-bar-area"></div></div>
1843 1600 </form>';
@@ -1855,99 +1612,57 @@
1855 1612
1856 1613 /**
1857 1614 * Display movie list
1858 1615 *
1859 - * Fetch the account's recordings from the cloud API and render them:
1860 - * still-processing ("pending") items first, then completed items with
1861 - * delete/download links and "create VOD from this recording" actions.
1862 - *
1863 - * @since 3.0.1
1864 - * @return string Recordings list HTML, or a notice when not connected / empty.
1865 - */
1616 + * @since 3.0.1
1617 + */
1866 1618 public function wpstream_present_file_management(){
1867 - // Pull the raw recordings payload from the API.
1868 1619 $video_list_raw = $this->main->wpstream_live_connection->wpstream_get_videos_from_api();
1869 1620
1870 - // false means the API call failed / not connected.
1871 - if ( $video_list_raw === false ) {
1872 - return '<div class="wpstream_upload_container">'.esc_html__('Not connected. Please connect to WpStream to upload videos.','wpstream').'</div>';
1621 + $video_list_raw_array=array();
1622 + if(isset($video_list_raw['items'])){
1623 + $video_list_raw_array=$video_list_raw['items'];
1873 1624 }
1874 -
1875 - // Normalise the completed-items list.
1876 - $video_list_raw_array = [];
1877 - if( isset( $video_list_raw['items'] ) ){
1878 - $video_list_raw_array = $video_list_raw['items'];
1879 - }
1880 -
1881 - // Sort completed items newest-first by their 'time' field.
1882 - $keys = array_column( $video_list_raw_array, 'time' );
1625 +
1626 + $keys = array_column($video_list_raw_array, 'time');
1883 1627 array_multisort($keys, SORT_DESC , $video_list_raw_array);
1884 -
1628 +
1885 1629 $to_return='';
1886 -
1887 - // show pending items
1888 - // Render still-processing uploads with a "processing" badge.
1889 - if ( key_exists( 'pending', $video_list_raw ) && is_array( $video_list_raw['pending'] ) ) {
1890 - foreach ( $video_list_raw['pending'] as $key => $video ) {
1630 +
1631 + if(is_array($video_list_raw['items'])){
1632 + foreach ($video_list_raw_array as $key =>$video){
1633 +
1634 +
1891 1635 $video_size = intval($video['size']/1048576);
1892 1636 $video_name = esc_html($video['name']);
1893 1637 if($video_name!=''):
1894 1638 $to_return.='<div class="wpstream_video_wrapper">';
1639 +
1895 1640 $to_return.='<div class="wpstream_video_title">';
1896 1641 $to_return.='<div class="wpstream_video_notice"></div></div>';
1897 1642 $to_return.='<div class="wpstream_video_title"><strong class="storage_file_name">'.esc_html__('File Name :','wpstream').'</strong>'.'<span class="storage_file_name_real">'.$video_name.'</span><span class="storage_file_size">'.$video_size.' MB </span></div>';
1898 - $to_return.='<div class="wpstream_video_pending">' . esc_html__( 'The video is still processing', 'wpstream') . '</div>';
1899 - $to_return.='</div>';
1900 - endif;
1901 -
1902 - }
1903 - }
1904 -
1905 - // show uploaded items
1906 - // Render each completed recording with its size, delete/download controls and VOD-creation links.
1907 - if( is_array($video_list_raw['items'] ) ) {
1908 - foreach ($video_list_raw_array as $key =>$video){
1909 - // Keep the service-provided Source Recording identity
1910 - // separate from its context-specific HTML rendering.
1911 - $video_size = intval($video['size']/1048576);
1912 - $video_source_name = (string) $video['name'];
1913 - $video_name = esc_html($video_source_name);
1914 - if($video_name!=''):
1915 - $to_return.='<div class="wpstream_video_wrapper">';
1916 -
1917 - $to_return.='<div class="wpstream_video_title">';
1918 - $to_return.='<div class="wpstream_video_notice"></div></div>';
1919 - $to_return.='<div class="wpstream_video_title"><strong class="storage_file_name">'.esc_html__('File Name:','wpstream').'</strong>'.'<span class="storage_file_name_real">'.$video_name.'</span><span class="storage_file_size">'.$video_size.' MB </span></div>';
1920 - // Delete control. The shared JS utility owns the
1921 - // confirmation; the renderer supplies inert data
1922 - // only so any valid recording name remains safe.
1923 - $to_return.='<div class="wpstream_delete_media" data-filename="'.esc_attr($video_source_name).'">'.esc_html__('delete file','wpstream').'</div>';
1924 - // Download trigger (JS fetches a time-limited signed URL) and the resulting link.
1643 + $to_return.=' <div class="wpstream_delete_media" ';
1644 + $to_return.=' onclick="return confirm(\' Are you sure you wish to delete '.$video_name.'?\')" data-filename="'.$video_name.'">'.esc_html__('delete file','wpstream').'</div>';
1925 1645 $to_return.='<div class="wpstream_get_download_link" data-filename="'.$video_name.'">'.esc_html__('download','wpstream').'</div>';
1926 1646 $to_return.='<a href="" class="wpstream_download_link">'.esc_html__('Click to download! The url will work for the next 20 minutes!','wpstream').'</a>';
1927 1647
1928 - // Pre-fill new-VOD links (free and, if WooCommerce present, paid) with this recording's name.
1929 - $add_free_video_url=admin_url('post-new.php?post_type=wpstream_product_vod').'&new_video_name='. rawurlencode($video_source_name);
1930 - $add_paid_video_url=admin_url('post-new.php?post_type=product').'&new_video_name='. rawurlencode($video_source_name);
1648 + $add_free_video_url=admin_url('post-new.php?post_type=wpstream_product_vod').'&new_video_name='. rawurlencode($video_name);
1649 + $add_paid_video_url=admin_url('post-new.php?post_type=product').'&new_video_name='. rawurlencode($video_name);
1931 1650
1932 1651
1933 1652
1934 - $to_return .='<a class="create_new_free_video" href="'.esc_url($add_free_video_url).'">'.esc_html__('Create new Free-To-View VOD from this recording').'</a>';
1935 - if (class_exists('WooCommerce')) {
1936 - $to_return .='<a class="create_new_ppv_video" href="'.esc_url($add_paid_video_url).'">'.esc_html__('Create new Pay-Per-View VOD from this recording').'</a>';
1937 - }
1653 + $to_return .='<a class="create_new_free_video" href="'.esc_url($add_free_video_url).'">'.esc_html__('Create new Free-To-View VOD from this recording').'</a>';
1654 + $to_return .='<a class="create_new_ppv_video" href="'.esc_url($add_paid_video_url).'">'.esc_html__('Create new Pay-Per-View VOD from this recording').'</a>';
1938 1655
1939 1656 $to_return.='</div>';
1940 1657 endif;
1941 -
1658 +
1942 1659 }
1943 1660 $current_page= get_current_screen();
1944 - }
1945 -
1946 - // no items to show
1947 - // Empty-state message when there are neither completed nor pending items.
1948 - if ( !is_array( $video_list_raw['items'] ) || ( key_exists( 'pending', $video_list_raw ) && !is_array( $video_list_raw['pending'] ) ) ) {
1949 - $to_return.= '<div class="wpstream_video_wrapper">'.esc_html__('You don\'t have any videos.','wpstream').'</div>';
1661 +
1662 +
1663 + } else {
1664 + $to_return.= '<div class="wpstream_video_wrapper">'.esc_html__('You don\'t have any videos.','wpstream').'</div>';
1950 1665 }
1951 1666 return $to_return;
1952 1667 }
1953 1668
@@ -1952,259 +1667,88 @@
1952 1667 }
1953 1668
1954 1669
1955 1670 /**
1956 - * Preserve the legacy free-Channel publish marker.
1671 + * Set defualt channels values
1957 1672 *
1958 - * Channel Settings initialization is coordinated by the Streaming Content
1959 - * Creation Module; this compatibility hook only maintains historical meta.
1960 - *
1961 - * @since 3.0.1
1962 - * @param int $post_id Post ID being published.
1963 - * @param WP_Post $post Post object being published.
1964 - * @return void
1965 - */
1673 + * @since 3.0.1
1674 + */
1675 +
1676 +
1677 +
1678 +
1966 1679 public function wpstream_publish_wpstream_product($post_id,$post){
1967 - // Only applies to free channel posts.
1968 1680 if( $post->post_type == 'wpstream_product' ){
1969 - // Preserve the legacy marker used by existing installations.
1970 1681 update_post_meta ($post_id,'local_event_options_test','working_on_'.$post_id);
1971 - }
1972 - }
1682 + $to_save_option=array();
1973 1683
1974 - /**
1975 - * Initialize existing Streaming Content when it is published or saved.
1976 - *
1977 - * The shared Module performs safe legacy repair and retries cloud provisioning
1978 - * for Live Channels. VODs receive only their applicable local initialization.
1979 - *
1980 - * @param int $post_id Post ID being published.
1981 - * @param WP_Post $post Post object being published.
1982 - * @return void
1983 - */
1984 - public function wpstream_create_remote_channel_on_publish( $post_id, $post ) {
1985 - // Skip autosaves and revisions (they are not real publishes).
1986 - if ( defined( 'DOING_AUTOSAVE') && DOING_AUTOSAVE ) {
1987 - return;
1988 - }
1989 - if ( wp_is_post_revision( $post_id ) ) {
1990 - return;
1991 - }
1992 - $this->main->streaming_content_creation->initialize_existing( $post_id );
1993 - }
1684 + $global_options= get_option('wpstream_user_streaming_global_channel_options');
1685 +
1686 + $local_events = get_post_meta ($post_id ,'local_event_options',true) ;
1687 +
1688 + if( $local_events =='' ){
1689 + if( is_array($global_options) ){
1690 + foreach($global_options as $key=>$value){
1691 + $to_save_option[sanitize_key($key)]=sanitize_text_field($value);
1692 + }
1693 +
1694 + update_post_meta ($post_id,'local_event_options',$to_save_option);
1695 +
1696 + }
1697 + }
1994 1698
1995 - /**
1996 - * Initialize a manually saved paid streaming product after WooCommerce
1997 - * has persisted its product-type taxonomy. The earlier publish hook may
1998 - * run while a new product still looks like `simple`; this later adapter
1999 - * enters the same idempotent creation policy once `live_stream` or
2000 - * `video_on_demand` is observable.
2001 - *
2002 - * @param int $post_id WooCommerce product ID.
2003 - * @return void
2004 - */
2005 - public function wpstream_initialize_paid_streaming_product( $post_id ) {
2006 - if ( 'product' !== get_post_type( $post_id ) ) {
2007 - return;
2008 - }
2009 - if ( ! has_term( array( 'live_stream', 'video_on_demand' ), 'product_type', $post_id ) ) {
2010 - return;
2011 - }
2012 - $this->main->streaming_content_creation->initialize_existing( $post_id );
2013 - }
2014 1699
2015 - /**
2016 - * Delete the remote channel when its Live Channel post is deleted for good.
2017 - *
2018 - * Hooked to before_delete_post: fires only on permanent deletion, never on
2019 - * trash, so trashing stays reversible and a restored channel keeps its
2020 - * cloud identity. Only a Live Channel that was actually Provisioned
2021 - * (`channelId` meta present) has anything at the service to remove.
2022 - *
2023 - * The local deletion proceeds whatever the service answers — this hook
2024 - * cannot cancel it, and a channel the customer removed must leave the
2025 - * site either way.
2026 - *
2027 - * @param int $post_id Post ID being permanently deleted.
2028 - * @param WP_Post $post Post object being permanently deleted.
2029 - * @return void
2030 - */
2031 - public function wpstream_delete_remote_channel_on_delete( $post_id, $post ) {
2032 - // Only Live Channel posts: the free post type, or a WooCommerce
2033 - // product of the live_stream type (paid channels).
2034 - $is_live_channel = $post instanceof WP_Post
2035 - && ( 'wpstream_product' === $post->post_type
2036 - || ( 'product' === $post->post_type && has_term( 'live_stream', 'product_type', $post_id ) ) );
2037 - if ( ! $is_live_channel ) {
2038 - return;
2039 1700 }
2040 -
2041 - // A channel that never obtained a cloud identity has nothing to delete.
2042 - if ( '' === (string) get_post_meta( $post_id, 'channelId', true ) ) {
2043 - return;
2044 - }
2045 -
2046 - $this->main->wpstream_live_connection->wpstream_delete_channel( $post_id );
2047 1701 }
2048 1702
2049 1703 /**
2050 - * Restore a paid Live Channel as a draft instead of immediately putting
2051 - * it back on sale. WooCommerce restores ordinary products to their
2052 - * previous status; a channel requires the seller to republish it.
2053 - *
2054 - * @param string $new_status Status selected by earlier filters.
2055 - * @param int $post_id Restored post ID.
2056 - * @param string $previous_status Status before trashing.
2057 - * @return string
2058 - */
2059 - public function wpstream_paid_live_untrash_status( $new_status, $post_id, $previous_status ) {
2060 - if ( 'product' === get_post_type( $post_id ) && has_term( 'live_stream', 'product_type', $post_id ) ) {
2061 - return 'draft';
2062 - }
2063 - return $new_status;
2064 - }
2065 -
2066 - /** Invalidate VOD DRM lookup state whenever publication visibility changes. */
2067 - public function wpstream_invalidate_vod_drm_on_status_change( $new_status, $old_status, $post ) {
2068 - if ( $post instanceof WP_Post && 'wpstream_product_vod' === $post->post_type && $new_status !== $old_status ) {
2069 - $this->main->drm_key_delivery->invalidate_vod_lookup( $post->ID );
2070 - }
2071 - }
2072 -
2073 - /** Invalidate VOD DRM lookup state before its key-index metadata is deleted. */
2074 - public function wpstream_invalidate_vod_drm_on_delete( $post_id, $post ) {
2075 - if ( $post instanceof WP_Post && 'wpstream_product_vod' === $post->post_type ) {
2076 - $this->main->drm_key_delivery->invalidate_vod_lookup( $post_id );
2077 - }
2078 - }
2079 -
2080 - /**
2081 1704 * save meta options
2082 1705 *
2083 - * Persist the allow-listed free channel / VOD meta fields on save for the
2084 - * `wpstream_product` and `wpstream_product_vod` post types. Hooked to the
2085 - * post save action.
2086 - *
2087 - * @since 3.0.1
2088 - * @param int $post_id Post ID being saved.
2089 - * @param WP_Post $post Post object being saved.
2090 - * @return void
2091 - */
2092 - public function wpstream_free_product_update_post($post_id,$post){
2093 -
2094 - // Guard against non-post callers.
1706 + * @since 3.0.1
1707 + */
1708 + public function wpstream_free_product_update_post($post_id,$post){
1709 +
2095 1710 if(!is_object($post) || !isset($post->post_type)) {
2096 1711 return;
2097 1712 }
2098 1713
2099 1714
1715 +
2100 1716
2101 1717
2102 1718
2103 - // Only handle the free channel and VOD post types.
1719 +
2104 1720 if( $post->post_type == 'wpstream_product' ||
2105 1721 $post->post_type == 'wpstream_product_vod' ):
2106 - $previous_vod_type = 'wpstream_product_vod' === $post->post_type
2107 - ? intval( get_post_meta( $post_id, 'wpstream_product_type', true ) )
2108 - : 0;
2109 - $previous_recording = 'wpstream_product_vod' === $post->post_type
2110 - ? (string) get_post_meta( $post_id, 'wpstream_free_video', true )
2111 - : '';
2112 -
2113 - // Meta keys this handler is allowed to write.
1722 +
2114 1723 $allowed_keys=array(
2115 1724 'wpstream_product_type',
2116 1725 'wpstream_free_video',
2117 - 'wpstream_free_video_external',
2118 - 'wpstream_closed_captions_file'
1726 + 'wpstream_free_video_external'
2119 1727 );
2120 1728
2121 1729
2122 - // Save each allow-listed, scalar POST field as sanitized post meta.
2123 1730 foreach ($_POST as $key => $value) {
2124 1731 if( !is_array ($value) ){
2125 1732 if (in_array ($key, $allowed_keys)) {
2126 - $postmeta = sanitize_text_field ( $value );
1733 + $postmeta = sanitize_text_field ( $value );
2127 1734 update_post_meta($post_id, sanitize_key($key), $postmeta );
2128 1735 }
2129 - }
1736 + }
2130 1737 }
2131 1738
2132 - if ( 'wpstream_product_vod' === $post->post_type && isset( $_POST['wpstream_product_type'] ) ) {
2133 - $new_vod_type = intval( $_POST['wpstream_product_type'] );
2134 - if ( 3 === $new_vod_type ) {
2135 - $this->wpstream_retire_vod_recording_identity( $post_id );
2136 - delete_post_meta( $post_id, 'wpstream_free_video' );
2137 - } elseif ( 2 === $new_vod_type ) {
2138 - $new_recording = isset( $_POST['wpstream_free_video'] ) && is_scalar( $_POST['wpstream_free_video'] )
2139 - ? sanitize_text_field( wp_unslash( $_POST['wpstream_free_video'] ) )
2140 - : $previous_recording;
2141 - if ( 2 !== $previous_vod_type || $new_recording !== $previous_recording ) {
2142 - $this->wpstream_retire_vod_recording_identity( $post_id );
2143 - }
2144 - delete_post_meta( $post_id, 'wpstream_free_video_external' );
2145 - }
2146 - }
2147 -
2148 1739 endif;
2149 1740
2150 1741 }
2151 -
2152 - /** Retire key and hosted-player metadata owned by a VOD's old recording. */
2153 - private function wpstream_retire_vod_recording_identity( $post_id ) {
2154 - $this->main->drm_key_delivery->invalidate_vod_lookup( $post_id );
2155 - foreach ( array( 'hlsDecryptionKey', 'hlsDecryptionKeyIndex', 'wpstream_vod_video_data', 'wpstream_vod_embed_key', 'wpstream_vod_embed_url' ) as $meta_key ) {
2156 - delete_post_meta( $post_id, $meta_key );
2157 - }
2158 - }
2159 1742
2160 1743
2161 1744 /**
2162 1745 * save meta options
2163 1746 *
2164 - * Register the plugin's post metaboxes: VOD settings on `wpstream_product_vod`,
2165 - * the video collection box on `wpstream_bundles`, and (for WooCommerce bundle
2166 - * products) the video-collection options box on `product`. Hooked to add_meta_boxes.
2167 - *
2168 - * @since 3.0.1
2169 - * @return void
2170 - */
2171 - public function add_wpstream_product_metaboxes() {
2172 - global $post;
2173 - $post_id = $post->ID;
2174 -
2175 -
2176 - // VOD settings metabox and the bundle video-collection metabox.
2177 - add_meta_box( 'add_wpstream_product_metaboxes-sectionid', esc_html__( 'Video On Demand Settings', 'wpstream' ),array($this,'display_meta_options'),'wpstream_product_vod' ,'normal','default');
2178 - add_meta_box( 'custom_metabox_video_collection', esc_html__( 'Video Collection', 'wpstream' ), 'wpstream_bundle_custom_metabox_callback', 'wpstream_bundles', 'normal', 'high' );
2179 -
2180 - // For WooCommerce bundle products, add the video-collection options box on the product screen.
2181 - if(function_exists('wc_get_product')):
2182 - $product = wc_get_product( $post_id );
2183 - if ( $product ) {
2184 -
2185 - if ( $product->get_type() === 'wpstream_bundle' ) {
2186 - add_meta_box(
2187 - 'wpstream_woo_custom_metabox',
2188 - esc_html__( 'Video Collection Options', 'wpstream' ),
2189 - 'wpstream_bundle_custom_metabox_callback',
2190 - 'product',
2191 - 'normal',
2192 - 'default'
2193 - );
2194 - }
2195 - }
2196 - endif;
2197 -
2198 - /**
2199 - * Fires after the plugin registered its metaboxes for the edit screen.
2200 - *
2201 - * @since 4.14.0
2202 - *
2203 - * @param int $post_id Post being edited.
2204 - * @param WP_Post $post The post.
2205 - */
2206 - do_action( 'wpstream_registered_metaboxes', intval( $post_id ), $post );
1747 + * @since 3.0.1
1748 + */
1749 + public function add_wpstream_product_metaboxes() {
1750 + add_meta_box( 'add_wpstream_product_metaboxes-sectionid', __( 'Video On Demand Settings', 'wpstream' ),array($this,'display_meta_options'),'wpstream_product_vod' ,'normal','default');
2207 1751 }
2208 1752
2209 1753
2210 1754 /**
@@ -2209,27 +1753,18 @@
2209 1753
2210 1754 /**
2211 1755 * make woocomerce virtual products
2212 1756 *
2213 - * Force WpStream WooCommerce product types (live_stream, video_on_demand,
2214 - * wpstream_bundle) to be virtual so they need no shipping. Hooked to save.
2215 - *
2216 - * @since 3.0.1
2217 - * @param int $post_id Post ID being saved (unused; uses global $post).
2218 - * @param WP_Post $post Post object (overwritten by global $post).
2219 - * @return void
1757 + * @since 3.0.1
2220 1758 */
1759 +
1760 +
2221 1761 public function wpstream_make_product_virtual($post_id,$post){
2222 1762 global $post;
2223 1763 if(isset($post->ID)){
2224 - // Only WooCommerce products are relevant.
2225 1764 if ( $post->post_type !== 'product' ) return;
2226 - // Mark WpStream product types as virtual.
2227 1765 $term_list = wp_get_post_terms($post->ID, 'product_type');
2228 - if( !empty($term_list) &&
2229 - isset($term_list[0]->slug) &&
2230 - in_array($term_list[0]->slug, ['live_stream', 'video_on_demand', 'wpstream_bundle'])
2231 - ){
1766 + if( $term_list[0]->name=='video_on_demand' || $term_list[0]->name=='live_stream'){
2232 1767 update_post_meta( $post->ID, '_virtual', 'yes' );
2233 1768 }
2234 1769 }
2235 1770 }
@@ -2238,38 +1773,28 @@
2238 1773
2239 1774 /**
2240 1775 * render meta options
2241 1776 *
2242 - * Render the "Video On Demand Settings" metabox: media-type selector,
2243 - * recording chooser, optional captions (.vtt) picker, and the self-hosted/
2244 - * external video URL field. Echoes HTML.
2245 - *
2246 - * @since 3.0.1
2247 - * @param WP_Post $post Post being edited (overwritten by global $post).
2248 - * @return void
2249 - */
1777 + * @since 3.0.1
1778 + */
2250 1779 public function display_meta_options( $post ) {
2251 - // Nonce for the metabox save + use the global post object.
2252 1780 wp_nonce_field( plugin_basename( __FILE__ ), 'estate_agent_noncename' );
2253 1781 global $post;
2254 1782
2255 - // Determine the pre-selected media type / video.
2256 1783 $is_live = '';
2257 1784 $is_video = '';
2258 1785 $is_video_external = '';
2259 - // When arriving from "create VOD from recording", preselect the recording.
2260 1786 if( isset( $_GET['new_video_name']) && $_GET['new_video_name']!='' ){
2261 1787 $is_video = ' selected ';
2262 1788 $wpstream_free_video = esc_html( $_GET['new_video_name']);
2263 1789 }else{
2264 - // Otherwise read the saved type/video from post meta and select accordingly.
2265 1790 $wpstream_product_type = esc_html(get_post_meta($post->ID, 'wpstream_product_type', true));
2266 1791 $wpstream_free_video = esc_html(get_post_meta($post->ID, 'wpstream_free_video', true));
2267 -
1792 +
2268 1793 if($wpstream_product_type==1){
2269 1794 $is_live = ' selected ';
2270 1795 }
2271 -
1796 +
2272 1797 if($wpstream_product_type==2){
2273 1798 $is_video = ' selected ';
2274 1799 }
2275 1800
@@ -2277,9 +1802,8 @@
2277 1802 $is_video_external = ' selected ';
2278 1803 }
2279 1804 }
2280 1805
2281 - // Media-type dropdown (recording vs self-hosted/external).
2282 1806 print'
2283 1807 <p class="meta-options">
2284 1808 <label for="wpstream_product_type">'.__('Media Type:','wpstream').' </label><br />
2285 1809 <select id="wpstream_product_type" name="wpstream_product_type">
@@ -2289,54 +1813,37 @@
2289 1813 </p>
2290 1814 ';
2291 1815
2292 1816
2293 - // Fetch the account's recordings to populate the chooser.
2294 1817 $video_list = $this->main->wpstream_live_connection->wpstream_get_videos();
1818 +
2295 1819
2296 -
2297 - // Recording chooser dropdown, pre-selecting the saved recording.
2298 - print '<div class="meta-options video_free">';
2299 - print '<p class="meta-option wpstream_free_video">';
2300 - print '<label for="wpstream_free_video">'.__('Choose video:','wpstream').' </label><br />
1820 + print '
1821 + <p class="meta-options video_free">
1822 + <label for="wpstream_free_video">'.__('Choose video:','wpstream').' </label><br />
2301 1823 <select id="wpstream_free_video" name="wpstream_free_video">';
2302 -
2303 - if( is_array( $video_list ) ) {
2304 - foreach ($video_list as $key=>$value){
2305 - print '<option value="'.$key.'"';
2306 - if($wpstream_free_video === $key){
2307 - print ' selected ';
1824 +
1825 + if(is_array($video_list)){
1826 + foreach ($video_list as $key=>$value){
1827 + print '<option value="'.$key.'"';
1828 + if($wpstream_free_video === $key){
1829 + print ' selected ';
1830 + }
1831 + print '>'.$value.'</option>';
1832 + }
2308 1833 }
2309 - print '>'.$value.'</option>';
2310 - }
2311 - }
2312 - print'</select>';
2313 - print '</p> ';
2314 - print '</div>';
1834 +
1835 + print'
1836 + </select>
1837 + </p>
1838 + ';
2315 1839
2316 - // Optional captions (.vtt) picker; hide the select button when a file is already set.
2317 - $wpstream_closed_captions_file = get_post_meta($post->ID, 'wpstream_closed_captions_file', true);
2318 -
2319 - $button_style = $wpstream_closed_captions_file ? 'style="display:none;"' : '';
2320 -
2321 - print '<p class="meta-option wpstream_vod_captions_url">';
2322 - print '<label for="wpstream_vod_captions_url_button">'.__('Captions file (optional):','wpstream').' </label><br />
2323 - <input type="hidden" id="wpstream_closed_captions_file" name="wpstream_closed_captions_file" value="'.esc_attr($wpstream_closed_captions_file).'" />
2324 - <input id="wpstream_vod_captions_url_button" type="button" class="upload_button button" value="'.esc_html__('Select .vtt Captions File','wpstream').'" '.$button_style.' />
2325 - <span class="wpstream_caption_file_display">'.( $wpstream_closed_captions_file ? esc_html( basename( $wpstream_closed_captions_file ) ) : '' ).'</span>';
2326 - if ( $wpstream_closed_captions_file ) {
2327 - print '<input type="button" class="button wpstream_remove_caption" value="'.esc_html__('Remove','wpstream').'" style="margin-left: 5px;" />';
2328 - }
2329 - print '</p> ';
2330 -
2331 - // Self-hosted / external video URL field with a media-library select button.
2332 1840 $wpstream_free_video_external= esc_html(get_post_meta($post->ID, 'wpstream_free_video_external', true));
2333 - print '<div class="meta-options1 video_free_external">
1841 + print '<p class="meta-options1 video_free_external">
2334 1842 <label for="wpstream_free_video_external">'.__('Video:','wpstream').' </label><br />
2335 1843
2336 1844 <input id="wpstream_free_video_external" type="text" size="36" name="wpstream_free_video_external" value="'.$wpstream_free_video_external.'" />
2337 1845 <input id="wpstream_free_video_external_button" type="button" size="40" class="upload_button button" value="'.esc_html__('Select Video','wpstream').'" />';
2338 - // Show the recording hint vs the external hint depending on the saved media type.
2339 1846 if($wpstream_product_type==2){
2340 1847 $show_recording='';
2341 1848 $show_external='style="display:none"';
2342 1849 }else{
@@ -2343,24 +1850,11 @@
2343 1850 $show_recording='style="display:none"';
2344 1851 $show_external='';
2345 1852 }
2346 1853 print '<p '.$show_recording.' class="wpstream_option_vod_source wpstream_show_recording">'.esc_html__('Choose one of your existing recordings.','wpstream').'</p>';
2347 - print '<p '. $show_external.' class="wpstream_option_vod_source wpstream_show_external">'.esc_html__('Upload a video from your computer or paste the URL of a YouTube/external video.','wpstream').'</p>';
1854 + print '<p '. $show_external.' class="wpstream_option_vod_source wpstream_show_external">'.esc_html__('Upload a video from your computer or paste the URL of a YouTube/Vimeo/external video.','wpstream').'</p>';
2348 1855
2349 - print '</div> ';
2350 -
2351 - /**
2352 - * Fires at the end of the Video On Demand Settings metabox.
2353 - *
2354 - * Callbacks echo their own fields and own their escaping; saving
2355 - * them is the callback's job (hook `save_post`).
2356 - *
2357 - * @since 4.14.0
2358 - *
2359 - * @param int $post_id VOD post ID.
2360 - * @param WP_Post $post The post.
2361 - */
2362 - do_action( 'wpstream_vod_meta_options_after', intval( $post->ID ), $post );
1856 + print '</p> ';
2363 1857 }
2364 1858
2365 1859
2366 1860
@@ -2370,179 +1864,44 @@
2370 1864
2371 1865 /**
2372 1866 * Add new product types to Woocommerce select product type
2373 1867 *
2374 - * Register the "Live Channel" and "Video On Demand" WooCommerce product
2375 - * types in the product-type dropdown. Filter callback.
2376 - *
2377 - * @since 3.0.1
2378 - * @param array $types Existing product-type => label map.
2379 - * @return array The map with the WpStream types added.
2380 - */
1868 + * @since 3.0.1
1869 + */
2381 1870 public function wpstream_add_products( $types ){
2382 - $types[ 'live_stream' ] = __( 'Live Channel','wpstream' );
2383 - $types[ 'video_on_demand' ] = __( 'Video On Demand','wpstream' );
2384 -
1871 + $types[ 'live_stream' ] = __( 'Live Channel','wpestream' );
1872 + $types[ 'video_on_demand' ] = __( 'Video On Demand','wpestream' );
1873 +
2385 1874 return $types;
2386 1875 }
2387 -
2388 - /**
2389 - * Map the WpStream product-type slugs to their WC_Product subclasses.
2390 - * Filter callback for woocommerce_product_class.
2391 - *
2392 - * @param string $classname Default product class name.
2393 - * @param string $product_type The product type slug being instantiated.
2394 - * @return string The resolved product class name.
2395 - */
2396 - public function wpstream_add_products_class( $classname, $product_type ) {
2397 - /**
2398 - * Filter the product-type slug => WC_Product subclass map.
2399 - *
2400 - * A mapped class must exist; unknown classes leave WooCommerce's own
2401 - * resolution in place.
2402 - *
2403 - * @since 4.14.0
2404 - *
2405 - * @param array $map Slug => class name.
2406 - */
2407 - $map = (array) apply_filters(
2408 - 'wpstream_product_class_map',
2409 - array(
2410 - 'live_stream' => 'WC_Product_Live_Stream',
2411 - 'video_on_demand' => 'WC_Product_Video_On_Demand',
2412 - )
2413 - );
2414 - if ( isset( $map[ $product_type ] ) && class_exists( $map[ $product_type ] ) ) {
2415 - $classname = $map[ $product_type ];
2416 - }
2417 - return $classname;
2418 - }
2419 -
2420 - /**
2421 - * Load the custom WC_Product subclass files when WooCommerce is active.
2422 - *
2423 - * @return void
2424 - */
2425 - public function wpstream_add_custom_wc_products() {
2426 - // Require the live-stream and VOD product classes (WooCommerce only).
2427 - if( class_exists( 'WooCommerce' ) ){
2428 - require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-wc-product-live-stream.php';
2429 - require_once plugin_dir_path( dirname( __FILE__ ) ) . 'includes/class-wc-product-video-on-demand.php';
2430 - }
2431 - }
2432 -
1876 +
1877 +
1878 +
2433 1879 /**
2434 1880 * Js action to do when user pick live stream or video on demand
2435 1881 *
2436 1882 * @since 3.0.1
2437 - */
2438 -
2439 - /**
2440 - * Whether WpStream WooCommerce product UI should load for this product.
2441 - *
2442 - * Skips simple, course, and other non-WpStream types so LearnDash and
2443 - * other integrations can use the General product data tab without conflict.
2444 - *
2445 - * @param int $post_id Product post ID. Uses global $post when 0.
2446 - * @return bool
2447 - */
2448 - public function wpstream_is_wpstream_wc_product_context( $post_id = 0 ) {
2449 - // Creating a new stream/VOD from a query-string action always counts.
2450 - if ( isset( $_GET['new_stream'] ) || isset( $_GET['new_video_name'] ) ) {
2451 - return true;
2452 - }
2453 -
2454 - // On the first product save WooCommerce has not necessarily made
2455 - // the selected taxonomy term observable through wc_get_product()
2456 - // yet. Trust only its allow-listed product-type form field here;
2457 - // the save handler remains scoped to WooCommerce product metadata.
2458 - if ( isset( $_POST['product-type'] ) && is_scalar( $_POST['product-type'] ) ) {
2459 - $submitted_type = sanitize_key( wp_unslash( $_POST['product-type'] ) );
2460 - if ( in_array( $submitted_type, array( 'live_stream', 'video_on_demand', 'wpstream_bundle', 'subscription' ), true ) ) {
2461 - return true;
2462 - }
2463 - }
2464 -
2465 - // Fall back to the current global post when no ID was passed.
2466 - if ( ! $post_id ) {
2467 - global $post;
2468 - $post_id = ( $post && isset( $post->ID ) ) ? (int) $post->ID : 0;
2469 - }
2470 -
2471 - // Need a product ID and WooCommerce to resolve the type.
2472 - if ( ! $post_id || ! function_exists( 'wc_get_product' ) ) {
2473 - return false;
2474 - }
2475 -
2476 - $product = wc_get_product( $post_id );
2477 - if ( ! $product ) {
2478 - return false;
2479 - }
2480 -
2481 - // True only for WpStream (and subscription) product types.
2482 - return in_array(
2483 - $product->get_type(),
2484 - array( 'live_stream', 'video_on_demand', 'wpstream_bundle', 'subscription' ),
2485 - true
2486 - );
2487 - }
2488 -
2489 - /**
2490 - * WooCommerce product types that use the core Regular price field.
2491 - *
2492 - * @return string[]
2493 - */
2494 - public function wpstream_get_wc_product_types_with_pricing() {
2495 - return array( 'live_stream', 'video_on_demand', 'wpstream_bundle' );
2496 - }
2497 -
2498 - /**
2499 - * Add show_if_* classes to the pricing panel for WpStream product types.
2500 - *
2501 - * WooCommerce renders .options_group.pricing with show_if_simple only. Custom
2502 - * types rely on show_if_{type} classes so meta-boxes-product.js can toggle them
2503 - * when the product type dropdown changes, including on unsaved new products.
2504 - *
2505 - * @param string $hook Admin screen hook suffix.
2506 - */
2507 - public function wpstream_enqueue_wc_product_pricing_visibility( $hook ) {
2508 - // Only on the add/edit-post admin screens.
2509 - if ( ! in_array( $hook, array( 'post.php', 'post-new.php' ), true ) ) {
1883 + */
1884 +
1885 + public function wpstream_products_custom_js() {
1886 + if ( 'product' != get_post_type() ) :
2510 1887 return;
2511 - }
1888 + endif;
2512 1889
2513 - // Only on the WooCommerce product post type.
2514 - $screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null;
2515 - if ( ! $screen || 'product' !== $screen->post_type ) {
2516 - return;
2517 - }
1890 + ?>
1891 + <script type='text/javascript'>
1892 + jQuery( document ).ready( function() {
1893 + jQuery('.options_group.pricing' ).addClass ( 'show_if_live_stream' ).show();
1894 + jQuery('.options_group.pricing' ).addClass ( 'show_if_video_on_demand' ).show();
1895 + jQuery('._sold_individually_field').parent().addClass('show_if_live_stream').show();
1896 + jQuery('._sold_individually_field').parent().addClass('show_if_video_on_demand').show();
1897 + jQuery('._sold_individually_field').show();
1898 +
1899 + var selected = jQuery('#product-type').val();
1900 + });
1901 + </script>
1902 + <?php
2518 1903
2519 - // Need WooCommerce's product meta-boxes script to attach to.
2520 - if ( ! wp_script_is( 'wc-admin-product-meta-boxes', 'registered' ) ) {
2521 - return;
2522 - }
2523 -
2524 - // Pass the WpStream pricing types to JS and add show_if_{type} classes so the pricing panel toggles correctly.
2525 - $types_json = wp_json_encode( array_values( $this->wpstream_get_wc_product_types_with_pricing() ) );
2526 -
2527 - wp_add_inline_script(
2528 - 'wc-admin-product-meta-boxes',
2529 - "jQuery( function( $ ) {
2530 - var wpstreamPricingProductTypes = {$types_json};
2531 - var \$pricing = $( '.options_group.pricing' );
2532 - var \$soldIndividually = $( '._sold_individually_field' ).parent();
2533 -
2534 - wpstreamPricingProductTypes.forEach( function( type ) {
2535 - \$pricing.addClass( 'show_if_' + type );
2536 - \$soldIndividually.addClass( 'show_if_' + type );
2537 - } );
2538 -
2539 - if ( wpstreamPricingProductTypes.indexOf( $( '#product-type' ).val() ) !== -1 ) {
2540 - \$pricing.show();
2541 - \$soldIndividually.show();
2542 - }
2543 - } );"
2544 - );
2545 1904 }
2546 1905
2547 1906
2548 1907 /**
@@ -2547,21 +1906,17 @@
2547 1906
2548 1907 /**
2549 1908 * Add custom classes to the product types
2550 1909 *
2551 - * Adjust the WooCommerce product-data tab visibility classes so WpStream
2552 - * types hide the Shipping tab and show the Inventory tab. Filter callback.
2553 - *
2554 - * @since 3.0.1
2555 - * @param array $tabs WooCommerce product data tabs config.
2556 - * @return array The modified tabs config.
2557 - */
1910 + * @since 3.0.1
1911 + */
1912 +
2558 1913 public function wpstream_hide_attributes_data_panel( $tabs) {
1914 +
1915 + $tabs['shipping']['class'][] = 'hide_if_live_stream hide_if_video_on_demand';
1916 + $tabs['inventory']['class'][] = 'show_if_live_stream show_if_video_on_demand';
1917 + // $tabs['general']['class'][] = 'show_if_live_stream show_if_video_on_demand';
2559 1918
2560 - // Hide Shipping and show Inventory for WpStream product types.
2561 - $tabs['shipping']['class'][] = 'hide_if_live_stream hide_if_video_on_demand hide_if_wpstream_bundle';
2562 - $tabs['inventory']['class'][] = 'show_if_live_stream show_if_video_on_demand show_if_wpstream_bundle';
2563 -
2564 1919 return $tabs;
2565 1920 }
2566 1921
2567 1922
@@ -2568,33 +1923,25 @@
2568 1923
2569 1924 /**
2570 1925 * Hide buy now on products if Netflix mode
2571 1926 *
2572 - * When global subscription ("Netflix") mode is on, mark WpStream media
2573 - * products as not individually purchasable (access comes via the
2574 - * subscription instead). Filter callback for is_purchasable.
2575 - *
2576 - * @since 3.12
2577 - * @param bool $purchaseable_product_wpblog Current purchasable flag.
2578 - * @param WC_Product $product The product being checked.
2579 - * @return bool False for WpStream media in global-sub mode, else the original flag.
2580 - */
1927 + * @since 3.12
1928 + */
1929 +
1930 +
2581 1931 public function wpstream_hide_buy_now_subscription_mode( $purchaseable_product_wpblog,$product){
2582 1932 $product_id=$product->get_id();
2583 -
2584 - // Stable type slug is '' when the product has no term (never a crash).
2585 - $product_type_slug = wpstream_get_product_type_slug($product_id);
2586 -
2587 - // Global subscription ("Netflix") mode flag.
2588 - $subscription_model = intval( get_option('wpstream_global_sub','')) ;
2589 -
2590 - if($subscription_model==1){ // if we have Neflix mode
2591 - // WpStream media types are not directly purchasable in this mode.
2592 - if( $product_type_slug=='live_stream' || $product_type_slug=='video_on_demand' || $product_type_slug=='wpstream_bundle' ){
1933 +
1934 + $term_list = wp_get_post_terms($product_id, 'product_type');
1935 +
1936 + $subscription_model = esc_html( get_option('wpstream_global_sub','')) ;
1937 +
1938 + if($subscription_model==1){ // if we have Neflix mode
1939 + if( $term_list[0]->name=='live_stream' || $term_list[0]->name=='video_on_demand' ){
2593 1940 return false;
2594 1941 }
2595 1942 }
2596 -
1943 +
2597 1944 return $purchaseable_product_wpblog;
2598 1945 }
2599 1946
2600 1947
@@ -2604,46 +1951,28 @@
2604 1951
2605 1952 /**
2606 1953 * Add custom fields to custom product types
2607 1954 *
2608 - * Render the extra WooCommerce "General" product fields for WpStream types:
2609 - * the subscription-live flag, the recording/video chooser, and the
2610 - * "attach to subscription" multi-select. Echoes HTML.
2611 - *
2612 - * @since 3.0.1
2613 - * @return void
2614 - */
1955 + * @since 3.0.1
1956 + */
1957 +
2615 1958 public function wpstream_add_custom_general_fields() {
1959 +
2616 1960 global $woocommerce, $post;
2617 -
2618 - // A new WooCommerce product is still an auto-draft `simple` product
2619 - // when this hook renders. Emit the type-scoped controls there so
2620 - // WooCommerce can reveal them after the administrator selects a
2621 - // WpStream type; the show_if_* classes keep them hidden otherwise.
2622 - $post_id = isset( $post->ID ) ? (int) $post->ID : 0;
2623 - $is_new_product = $post_id && 'auto-draft' === get_post_status( $post_id );
2624 - if ( ! $is_new_product && ! $this->wpstream_is_wpstream_wc_product_context( $post_id ) ) {
2625 - return;
2626 - }
2627 - // Subscription-based live channel toggle (only when WC Subscriptions is active).
2628 1961 if(function_exists('wcs_user_has_subscription')){
2629 - echo '<div class="options_group show_if_subscription">';
1962 + echo '<div class="options_group show_if_subscription">';
2630 1963 woocommerce_wp_select(
2631 1964 array(
2632 1965 'id' => '_subscript_live_event',
2633 1966 'label' => __( 'Is a subscription based live channel ?', 'woocommerce' ),
2634 - 'options' => array("yes"=>"yes","no"=>"no", "none" => "none")
1967 + 'options' => array("yes"=>"yes","no"=>"no")
2635 1968 )
2636 1969 );
2637 1970 echo '</div>';
2638 1971 }
2639 1972
2640 - echo '<div class="options_group show_if_live_stream" style="border:none;"></div>';
2641 - // VOD video chooser section.
2642 - echo '<div class="options_group show_if_video_on_demand">';
2643 -
2644 -
2645 - // Pre-selected video: from the new-video query arg, else the saved _movie_url meta.
1973 + echo '<div class="options_group show_if_live_stream" style="border:none;"></div>';
1974 + echo '<div class="options_group show_if_video_on_demand">';
2646 1975 $selected='';
2647 1976 if( isset( $_GET['new_video_name']) && $_GET['new_video_name']!='' ){
2648 1977 $selected=esc_html($_GET['new_video_name']);
2649 1978 }
@@ -2649,31 +1978,26 @@
2649 1978 }
2650 1979 if($selected==''){
2651 1980 $selected= get_post_meta($post->ID,'_movie_url',true);
2652 1981 }
2653 - // Only administrators may assign videos.
2654 - if( !current_user_can('administrator') ){
2655 - print '<div style="margin:10px;">'.esc_html__('You need to be an administrator in order to assign videos','wpstream').'</div>';
2656 - }else{
2657 - woocommerce_wp_select(
2658 - array(
2659 - 'id' => '_movie_url',
2660 - 'label' => __( 'Choose video', 'woocommerce' ),
2661 - 'options' => $this->main->wpstream_live_connection->wpstream_get_videos(),
2662 - 'selected'=> true,
2663 - 'value' => $selected
2664 - )
2665 - );
2666 - }
1982 +
1983 + woocommerce_wp_select(
1984 + array(
1985 + 'id' => '_movie_url',
1986 + 'label' => __( 'Choose video', 'woocommerce' ),
1987 + 'options' => $this->main->wpstream_live_connection->wpstream_get_videos(),
1988 + 'selected'=> true,
1989 + 'value' => $selected
1990 + )
1991 + );
2667 1992
2668 1993
2669 1994
2670 1995 echo '</div>';
2671 1996
2672 - // "Attach to subscription" multi-select (only when WC Subscriptions is active).
2673 1997 if(function_exists('wcs_user_has_subscription')){
2674 1998 $selected_sub='';
2675 - echo '<div class="options_group show_if_video_on_demand show_if_live_stream">';
1999 + echo '<div class="options_group show_if_video_on_demand show_if_live_stream">';
2676 2000 if( isset( $_GET['wpstream_parent_sub']) && $_GET['wpstream_parent_sub']!='' ){
2677 2001 $selected_sub=esc_html($_GET['wpstream_parent_sub']);
2678 2002 }
2679 2003 if($selected_sub==''){
@@ -2696,19 +2020,11 @@
2696 2020 }
2697 2021 }
2698 2022
2699 2023
2700 - /**
2701 - * Build an id => title map of all WooCommerce subscription products,
2702 - * for the "attach to subscription" selector. Includes a "none" option.
2703 - *
2704 - * @return array Map of subscription product ID => title (0 => 'none').
2705 - */
2706 2024 public function wpstream_return_subscriptions_created(){
2707 - // Seed with the "none" choice.
2708 2025 $return=array('0'=>'none');
2709 -
2710 - // Query all subscription-type products, title-ordered.
2026 +
2711 2027 $args = array(
2712 2028 'post_type' => 'product',
2713 2029 'posts_per_page' => -1,
2714 2030 'orderby' => 'title',
@@ -2721,10 +2037,9 @@
2721 2037 'terms' => array( 'subscription'),
2722 2038 )
2723 2039 )
2724 2040 );
2725 -
2726 - // Collect each subscription's id => title.
2041 +
2727 2042 $subscriptions = new WP_Query($args);
2728 2043 if($subscriptions->have_posts()):
2729 2044 while ($subscriptions->have_posts()): $subscriptions->the_post();
2730 2045 $return[ get_the_ID() ] = get_the_title();
@@ -2729,13 +2044,12 @@
2729 2044 while ($subscriptions->have_posts()): $subscriptions->the_post();
2730 2045 $return[ get_the_ID() ] = get_the_title();
2731 2046 endwhile;
2732 2047 endif;
2733 -
2734 - // Restore the main query and return the map.
2048 +
2735 2049 wp_reset_postdata();
2736 2050 return $return;
2737 -
2051 +
2738 2052 }
2739 2053
2740 2054
2741 2055
@@ -2744,48 +2058,22 @@
2744 2058
2745 2059 /**
2746 2060 * Save custom fields
2747 2061 *
2748 - * Persist the WpStream WooCommerce product fields (_movie_url,
2749 - * _subscript_live_event, _wpstream_parent_sub) on save and reset the
2750 - * event_passed flag. Hooked to the product save action.
2751 - *
2752 - * @since 3.0.1
2753 - * @param int $post_id Product ID being saved.
2754 - * @return void
2755 - */
2062 + * @since 3.0.1
2063 + */
2064 +
2756 2065 public function wpstream_add_custom_general_fields_save( $post_id ){
2757 - // Only handle WpStream product contexts.
2758 - if ( ! $this->wpstream_is_wpstream_wc_product_context( (int) $post_id ) ) {
2759 - return;
2760 - }
2761 2066
2762 - // A Source Recording owns the cached DRM and hosted-player identity.
2763 - // Retire that identity before replacing the source so its old key index
2764 - // is still available to invalidate the lookup caches.
2765 - if (
2766 - has_term( 'video_on_demand', 'product_type', $post_id )
2767 - && ! empty( $_POST['_movie_url'] )
2768 - && is_scalar( $_POST['_movie_url'] )
2769 - ) {
2770 - $previous_recording = (string) get_post_meta( $post_id, '_movie_url', true );
2771 - $new_recording = sanitize_text_field( wp_unslash( $_POST['_movie_url'] ) );
2772 - if ( $new_recording !== $previous_recording ) {
2773 - $this->wpstream_retire_vod_recording_identity( $post_id );
2774 - }
2775 - }
2776 -
2777 - // Meta keys this handler may write.
2778 2067 $permited_values = array(
2779 2068 '_movie_url',
2780 2069 '_subscript_live_event',
2781 2070 '_wpstream_parent_sub',
2782 -
2071 +
2783 2072 );
2784 -
2785 -
2786 -
2787 - // Reset event_passed and save each allow-listed field.
2073 +
2074 +
2075 +
2788 2076 foreach($_POST as $key=>$value){
2789 2077 update_post_meta( $post_id, 'event_passed', 0 );
2790 2078 if( in_array($key, $permited_values) ){
2791 2079 if( !empty( $_POST[$key] ) ){
@@ -2790,14 +2078,13 @@
2790 2078 if( in_array($key, $permited_values) ){
2791 2079 if( !empty( $_POST[$key] ) ){
2792 2080 $key = sanitize_key($key);
2793 2081 $value = sanitize_text_field($_POST[$key]);
2794 -
2795 - // The parent-subscription field is an array; sanitize each element.
2082 +
2796 2083 if($key=='_wpstream_parent_sub'){
2797 2084 $value= $_POST[$key];
2798 2085 $value = array_map("sanitize_text_field", $value);
2799 -
2086 +
2800 2087 }
2801 2088 update_post_meta( $post_id, $key, $value );
2802 2089 }
2803 2090 }
@@ -2808,34 +2095,25 @@
2808 2095
2809 2096 /**
2810 2097 * Add to cart redirect
2811 2098 *
2812 - * Render the simple add-to-cart template for WpStream product types.
2813 - *
2814 - * @since 3.0.1
2815 - * @return void
2816 - */
2099 + * @since 3.0.1
2100 + */
2101 +
2817 2102 public function wpstream_add_to_cart() {
2818 2103 wc_get_template( 'single-product/add-to-cart/simple.php' );
2819 2104 }
2820 2105
2821 -
2106 +
2822 2107 /**
2823 2108 * Replace add to cart button
2824 2109 *
2825 - * For live_stream / video_on_demand products, swap the loop add-to-cart
2826 - * button for a direct shop add-to-cart link. Filter callback.
2827 - *
2828 - * @since 3.0.1
2829 - * @param string $button Original button HTML.
2830 - * @param WC_Product $product The product (overwritten by global $product).
2831 - * @return string The (possibly replaced) button HTML.
2832 - */
2110 + * @since 3.0.1
2111 + */
2833 2112 public function replacing_add_to_cart_button( $button, $product ) {
2834 2113 global $product;
2835 2114 $product_type = $product->get_type();
2836 2115
2837 - // Only WpStream media types get the custom link; others keep the default button.
2838 2116 if($product_type==='live_stream' || $product_type=='video_on_demand'){
2839 2117 return $button = '<a class="button" href="'.get_site_url().'/shop/?add-to-cart=' .$product->get_id(). '&quantity=1">' . __( 'Add to Cart', 'woocommerce' ) . '</a>';
2840 2118 }else{
2841 2119 return $button;
@@ -2845,27 +2123,21 @@
2845 2123
2846 2124 /**
2847 2125 * Admin notices
2848 2126 *
2849 - * Print global admin notices: (commented-out) WooCommerce-missing notice
2850 - * and an error if the PHP cURL extension is unavailable, plus the dismiss
2851 - * nonce. Echoes HTML.
2852 - *
2853 - * @since 3.0.1
2854 - * @return void
2855 - */
2127 + * @since 3.0.1
2128 + */
2856 2129 public function wpstream_admin_notice() {
2857 2130 global $pagenow;
2858 2131 global $typenow;
2859 2132
2860 - // Stored dismissed-notice flags.
2861 2133 $wpstream_notices = get_option('wpstream_notices');
2862 -
2134 +
2863 2135 /*
2864 2136 if ( !in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) {
2865 2137 if( !is_array($wpstream_notices) ||
2866 2138 !isset($wpstream_notices['wpstream_woo_notice']) ||
2867 - ( isset($wpstream_notices['wpstream_woo_notice']) && $wpstream_notices['wpstream_woo_notice']!='yes') ){
2139 + ( isset($wpestate_notices['wpstream_woo_notice']) && $wpestate_notices['wpstream_woo_notice']!='yes') ){
2868 2140
2869 2141
2870 2142 print '<div class="notice wpstream_notices notice-error is-dismissible" data-notice-type="wpstream_woo_notice" >
2871 2143 <p>'.__( 'WpStream Pay-Per-View Live Streaming and VOD only works with WooCommerce - Please enable and activate the WooCommerce plugin if you want to monetize your Live Events or Recorded Videos', 'wpstream' ).'</p>
@@ -2873,9 +2145,8 @@
2873 2145 }
2874 2146 }
2875 2147 */
2876 2148
2877 - // Hard requirement: warn when the PHP cURL extension is missing.
2878 2149 if( !in_array ('curl', get_loaded_extensions())) {
2879 2150 print '<div class="notice notice-error is-dismissible">
2880 2151 <p>'.__( 'The php CURL library is not enabled on your server. WpStream plugin needs this library in order to work. Please address this issue with your hosting provider.', 'wpstream' ).'</p>
2881 2152 </div>';
@@ -2881,141 +2152,29 @@
2881 2152 </div>';
2882 2153 }
2883 2154
2884 2155
2885 - // Nonce used by the JS that records notice dismissals.
2886 2156 $ajax_nonce = wp_create_nonce( "wpstream_notice_nonce" );
2887 2157 print '<input type="hidden" id="wpstream_notice_nonce" value="'.esc_html($ajax_nonce).'"/>';
2888 2158
2889 2159 }
2890 -
2891 - /**
2892 - * Get plugin latest update release date from WordPress.org
2893 - * @param $plugin_slug
2894 - * @param $version
2895 - *
2896 - * @return bool
2897 - */
2898 - public function get_plugin_release_date( $plugin_slug, $version = null ) {
2899 - // This runs on every admin page while an update is pending, so the
2900 - // answer is cached for 12h — including a negative one, otherwise a
2901 - // failed lookup would retry per page load. Keyed by version so a
2902 - // newer release triggers a fresh lookup.
2903 - $cache_key = 'wpstream_release_date_' . md5( $plugin_slug . '|' . (string) $version );
2904 - $cached = get_transient( $cache_key );
2905 - if ( false !== $cached ) {
2906 - // 'none' is the stored form of a negative result.
2907 - return 'none' === $cached ? false : $cached;
2908 - }
2909 -
2910 - // Query the WordPress.org plugins info API (short timeout: this is
2911 - // cosmetic notice logic and must never stall the admin).
2912 - $api_url = 'https://api.wordpress.org/plugins/info/1.0/' . $plugin_slug . '.json';
2913 - $response = wp_remote_get( $api_url, array( 'timeout' => 3 ) );
2914 -
2915 - // Resolve the answer (false = no usable date), then cache it once.
2916 - $release_date = false;
2917 -
2918 - if ( ! is_wp_error( $response ) ) {
2919 - // Decode the JSON body; a date needs a versions list to validate against.
2920 - $data = json_decode( wp_remote_retrieve_body( $response ), true );
2921 -
2922 - if ( $data && isset( $data['versions'] ) ) {
2923 - // no version provided, get the latest version
2924 - if ( ! $version ) {
2925 - $version = $data['version'];
2926 - }
2927 -
2928 - // The version must exist in the versions array.
2929 - // (note: last_updated is the plugin's overall date, not per-version)
2930 - if ( isset( $data['versions'][ $version ] ) && isset( $data['last_updated'] ) ) {
2931 - $release_date = date( 'Y-m-d', strtotime( $data['last_updated'] ) );
2932 - }
2933 - }
2934 - }
2935 -
2936 - set_transient( $cache_key, false === $release_date ? 'none' : $release_date, 12 * HOUR_IN_SECONDS );
2937 - return $release_date;
2938 - }
2939 -
2940 - /**
2941 - * Adds notice for the WpStream update availability
2942 - * when the update is not older than 30 days
2943 - */
2944 - public function wpstream_plugin_update_available_notice() {
2945 - // Only show to users who can update plugins.
2946 - if (!current_user_can('update_plugins')) {
2947 - return;
2948 - }
2949 -
2950 - // Look up a pending update for this plugin in WP's transient.
2951 - $plugin_slug = 'wpstream/wpstream.php';
2952 - $update_data = get_site_transient('update_plugins');
2953 -
2954 - if ( is_object( $update_data ) &&
2955 - property_exists( $update_data, 'response' ) &&
2956 - is_array($update_data->response) &&
2957 - key_exists($plugin_slug, $update_data->response)
2958 - ) {
2959 - $new_version = $update_data->response[$plugin_slug]->new_version;
2960 -
2961 - // Suppress the notice for very fresh releases (grace period).
2962 - $release_date = $this->get_plugin_release_date( 'wpstream', $new_version );
2963 -
2964 - if ( $release_date ) {
2965 - $days_since_release = ( time() - strtotime( $release_date ) ) / DAY_IN_SECONDS;
2966 -
2967 - // if there's an update newer than 7 days, do not show the notice
2968 - if ( $days_since_release < 7 ) {
2969 - return;
2970 - }
2971 - }
2972 - // Build the one-click update URL (nonce-protected) and print the notice.
2973 - $update_url = wp_nonce_url(
2974 - self_admin_url('update.php?action=upgrade-plugin&plugin=' . urlencode($plugin_slug)),
2975 - 'upgrade-plugin_' . $plugin_slug
2976 - );
2977 -
2978 - echo '<div class="notice notice-warning is-dismissible">';
2979 - echo '<p><strong>' . __('WpStream Plugin Update Available', 'wpstream') . '</strong></p>';
2980 - echo '<p>' . sprintf(
2981 - __('Version %s is available. Please update to the latest version for new features and security improvements.', 'wpstream'),
2982 - '<strong>' . esc_html($new_version) . '</strong>'
2983 - ) . '</p>';
2984 - echo '<p><a href="' . esc_url($update_url) . '" class="button button-primary">' .
2985 - __('Update Now', 'wpstream') . '</a></p>';
2986 - echo '</div>';
2987 - }
2988 - }
2989 -
2160 +
2990 2161 /**
2991 2162 * Admin notices
2992 2163 *
2993 - * AJAX handler that records a dismissed notice: marks the posted notice
2994 - * type as 'yes' in the wpstream_notices option so it stops showing.
2995 - *
2996 - * @since 3.0.1
2997 - * @return void Ends the request with die().
2998 - */
2164 + * @since 3.0.1
2165 + */
2999 2166 public function wpstream_update_cache_notice(){
3000 2167
3001 - // CSRF gate: the dismiss JS sends the nonce printed next to the notice.
3002 - check_ajax_referer( 'wpstream_notice_nonce', 'security' );
3003 - // Dismissals are stored in a site-wide option, so require admin rights.
3004 - if ( ! current_user_can( 'manage_options' ) ) {
3005 - die();
3006 - }
2168 + //check_ajax_referer( 'wpstream_notice_nonce', 'security' );
3007 2169
3008 - // Which notice was dismissed.
3009 2170 $notice_type = esc_html($_POST['notice_type']);
3010 2171 $notices = get_option('wp_stream_notices');
3011 2172
3012 - // Normalise to an array.
3013 2173 if(! is_array($notices) ){
3014 2174 $notices=array();
3015 2175 }
3016 2176
3017 - // Flag this notice as dismissed and persist.
3018 2177 $notices[$notice_type]='yes';
3019 2178
3020 2179 update_option('wpstream_notices',$notices);
3021 2180 die();
@@ -3026,65 +2185,94 @@
3026 2185
3027 2186 /**
3028 2187 * Activate metaboxes for Streaming controls on sidebar
3029 2188 *
3030 - * Register the "Live Streaming" sidebar metabox on free channel posts, and
3031 - * also on WooCommerce products that are live_stream (or a subscription
3032 - * flagged as a live event). Hooked to add_meta_boxes.
3033 - *
3034 - * @since 3.0.1
3035 - * @return void
3036 - */
2189 + * @since 3.0.1
2190 + */
3037 2191 public function wpstream_startstreaming_sidebar_meta() {
3038 - return $this->main->get_live_channel_presentation()->register_metaboxes();
2192 + global $post;
2193 + $term_list = wp_get_post_terms($post->ID, 'product_type');
2194 +
2195 + add_meta_box('wpstream-sidebar-meta', esc_html__('Live Streaming', 'wpstream'), array($this,'wpstream_start_stream_meta'), 'wpstream_product', 'side', 'high');
2196 +
2197 + $is_subscription_live_event = esc_html(get_post_meta($post->ID,'_subscript_live_event',true));
2198 + if(!is_wp_error( $term_list )){
2199 + if( isset($term_list[0]->name) ){
2200 + if( $term_list[0]->name=='live_stream' || ($term_list[0]->name=='subscription' && $is_subscription_live_event=='yes' ) ){
2201 + add_meta_box('wpstream-sidebar-meta', esc_html__('Live Streaming', 'wpstream'), array($this,'wpstream_start_stream_meta'), 'product', 'side', 'high');
2202 + }
2203 + }
2204 + }
2205 +
3039 2206 }
2207 +
2208 + /**
2209 + * edited 4.0
2210 + *
2211 + * Show Streaming controls on sidebar
2212 + *
2213 + * @since 3.0.1
2214 + */
3040 2215 public function wpstream_start_stream_meta(){
3041 - return $this->main->get_live_channel_presentation()->render_sidebar();
2216 + global $live_event_for_user;
2217 + $live_event_for_user = $this->main->wpstream_live_connection->wpstream_get_live_event_for_user();
2218 +
2219 + global $post;
2220 + $local_event_options = get_post_meta ($post->ID,'local_event_options','');
2221 +
2222 +
2223 +
2224 + if( get_post_status($post->ID)!='auto-draft' ){
2225 + $ajax_nonce = wp_create_nonce( "wpstream_start_event_nonce" );
2226 + print '<input type="hidden" id="wpstream_start_event_nonce" value="'.$ajax_nonce.'">';
2227 +
2228 + $this->wpstream_live_stream_unit($post->ID);
2229 + print '<div class="wpstream_modal_background"></div>';
2230 + print '<div class="wpstream_error_modal_notification"><div class="wpstream_error_content">er1</div>
2231 + <div class="wpstream_error_ok wpstream_button" type="button">'.esc_html__('Close','wpstream').'</div>
2232 + </div>';
2233 + }else{
2234 + esc_html_e('To Go Live, please publish your channel first !','wpstream');
2235 + }
3042 2236 }
3043 - public function wpstream_is_basic_streaming_mode(){
3044 - return $this->main->quota_manager->is_basic_streaming_mode( null, 'wpstream_is_basic_streaming_mode' );
3045 - }
3046 2237
3047 - /**
3048 - * Whether the account's plan meters streaming by hours (vs. data).
3049 - *
3050 - * @return bool
3051 - */
3052 - public function wpstream_is_use_streaming_hours() {
3053 - $pack_details = $this->main->quota_manager->get_live_quota_data( 'wpstream_start_channel' );
3054 - return $this->main->quota_manager->uses_streaming_hours( $pack_details );
3055 - }
3056 2238
3057 - /**
3058 - * Cached-only flags for start_streaming.js localization (no API on cold cache).
3059 - *
3060 - * @return array{is_basic_streaming: bool, use_streaming_hours: bool}
3061 - */
3062 - public function wpstream_get_start_streaming_localization_flags() {
3063 - return $this->main->get_live_channel_presentation()->get_localization_flags();
3064 - }
3065 2239
3066 2240
3067 2241
2242 +
3068 2243 /**
3069 - * Register a hidden dashboard page used as the onboarding wizard endpoint.
2244 + *
3070 2245 *
3071 - * @return void
2246 + *
3072 2247 */
3073 2248 public function add_dashboard_page() {
3074 - $this->main->get_onboarding()->render_part( 'dashboard_page' );
2249 + add_dashboard_page( '', '', 'administrator', 'wpstream-onboarding', '' );
3075 2250 }
2251 +
3076 2252
3077 2253
3078 2254
3079 2255
3080 - /**
3081 - * Bootstrap the full-screen onboarding wizard screen (non-AJAX requests).
3082 - *
3083 - * @return void
3084 - */
3085 2256 public function wpstream_load_onboarding_wizard() {
3086 - $this->main->get_onboarding()->render_part( 'standalone' );
2257 +
2258 + // Check for wizard-specific parameter
2259 + // Allow plugins to disable the onboarding wizard
2260 + // Check if current user is allowed to save settings.
2261 +
2262 +
2263 + // Don't load the interface if doing an ajax call.
2264 + if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
2265 + return;
2266 + }
2267 +
2268 + set_current_screen();
2269 +
2270 + // Remove an action in the Gutenberg plugin ( not core Gutenberg ) which throws an error.
2271 + remove_action( 'admin_print_styles', 'gutenberg_block_editor_admin_print_styles' );
2272 +
2273 + $this->actual_load_onboarding_wizard();
2274 +
3087 2275 }
3088 2276
3089 2277
3090 2278 /*
@@ -3089,30 +2277,62 @@
3089 2277
3090 2278 /*
3091 2279 * Add on boarding to footer
3092 2280 */
3093 - /**
3094 - * On the onboarding admin page, print the onboarding modal into the footer.
3095 - *
3096 - * @return void
3097 - */
2281 +
2282 +
2283 +
3098 2284 public function wpstream_admin_footer_onboarding(){
3099 - $this->main->get_onboarding()->render_part( 'page_footer' );
2285 + if( isset($_GET['page']) && $_GET['page']==='wpstream_onboard') {
2286 + $this->wpstream_onboard_display();
2287 + }
3100 2288 }
3101 2289
3102 2290
3103 2291 /*
3104 2292 * On Board Display
3105 - *
2293 + *
3106 2294 */
3107 - /**
3108 - * Render the Quick Start landing screen (logo, intro, "Start the Guide"
3109 - * button and the script that opens the onboarding wizard). Echoes HTML.
3110 - *
3111 - * @return void
3112 - */
2295 +
3113 2296 public function wpstream_pre_onboard_display(){
3114 - echo $this->main->get_onboarding()->render();
2297 + $pack_details = $this->main->wpstream_live_connection->wpstream_request_pack_data_per_user();
2298 +
2299 + $this->main->show_user_data($pack_details);
2300 +
2301 +
2302 + $thumb= plugin_dir_url( dirname( __FILE__ ) ). 'img/logo_onboarding.svg';
2303 + ?>
2304 +
2305 + <div class="wpstream_quick_start_wrapper">
2306 + <img class="wpstream_onboarding_logo" src="<?php echo esc_url($thumb); ?>" />
2307 +
2308 + <h1><?php print esc_html__('WpStream','wpstream').' <span class="header_special">'.esc_html__('Quick Start','wpstream').'</span>';?></h1>
2309 +
2310 +
2311 + <p>
2312 + <?php esc_html_e('The quick start guide will help you set up Live Streaming, Video On Demand, and Monetization in a fun and interactive way. Give it a shot! ','wpstream');?>
2313 + </p>
2314 +
2315 + <div id="wpstream_trigger_quick_start" class="wpstream_button wpstream_button_action"><?php esc_html_e('Start the Guide','wpstream');?></div>
2316 +
2317 +
2318 +
2319 + </div>
2320 +
2321 +
2322 +
2323 + <script type="text/javascript">
2324 + //<![CDATA[
2325 + jQuery(document).ready(function(){
2326 + jQuery(".wpstream_on_boarding_wrapper").show();
2327 + jQuery(".wpstream_modal_background_onboard").show();
2328 + });
2329 +
2330 + //]]>
2331 + </script>
2332 +
2333 + <?php
2334 +
3115 2335 }
3116 2336
3117 2337
3118 2338
@@ -3125,16 +2345,21 @@
3125 2345 *
3126 2346 * On Boarding Content
3127 2347 *
3128 2348 */
3129 - /**
3130 - * Emit the full onboarding wizard markup by rendering each step in order
3131 - * (header, account, path choice, live/VOD branches, footer). Echoes HTML.
3132 - *
3133 - * @return void
3134 - */
2349 +
2350 +
3135 2351 public function wpstream_onboard_display() {
3136 - $this->main->get_onboarding()->render_part( 'wizard' );
2352 + $this->onboarding_wizard_header();
2353 + $this->wpstream_onboarding_step1();
2354 + $this->wpstream_onboarding_step2();
2355 + $this->wpstream_onboarding_step3_live_streaming();
2356 + $this->wpstream_onboarding_step_3_A_live_streaming_free_view();
2357 + $this->wpstream_onboarding_step_3_B_live_streaming_pay_per_view();
2358 + $this->wpstream_onboarding_step4_vod();
2359 + $this->wpstream_onboarding_step_4_free_vod();
2360 + $this->wpstream_onboarding_step_4_ppv_vod();
2361 + $this->onboarding_wizard_footer();
3137 2362 }
3138 2363
3139 2364
3140 2365 /*
@@ -3141,61 +2366,489 @@
3141 2366 *
3142 2367 * On Boarding Step 1 - the login/register
3143 2368 *
3144 2369 */
3145 - /**
3146 - * Onboarding step 1: WpStream account login/registration UI, including the
3147 - * ALTCHA captcha widget (on HTTPS) and a hidden generated registration
3148 - * password. Emits a marker div when a token already exists. Echoes HTML.
3149 - *
3150 - * @return void
3151 - */
2370 +
2371 +
3152 2372 public function wpstream_onboarding_step1(){
3153 - $this->main->get_onboarding()->render_part( 'account' );
2373 +
2374 + $wpstream_options_array =array(
2375 + 2 => array(
2376 + 'label' => 'WpStream.net Username or Email',
2377 + 'name' => 'api_username',
2378 + 'type' => 'text',
2379 + ),
2380 + 3 => array(
2381 + 'label' => 'WpStream.net Password',
2382 + 'name' => 'api_password',
2383 + 'type' => 'password',
2384 + ),
2385 +
2386 + );
2387 + $token = $this->main->wpstream_live_connection->wpstream_get_token();
2388 +
2389 + ?>
2390 + <div class="wpstream_step_wrapper wpstream_step_1" id="wpstream_step_1">
2391 + <div class="wpstream_has_credential">
2392 + <h1><?php esc_html_e('WpStream Account','wpstream');?></h1>
2393 +
2394 + <div class="wpstream_on_board_login_wrapper_explanations">
2395 + <?php esc_html_e('A WpStream account is required to make use of the plugin.','wpstream');?>
2396 + </div>
2397 +
2398 +
2399 + <div class="wpstream_check_account_status">
2400 + Checking if you are already logged.....
2401 + </div>
2402 +
2403 + <div class="wpstream_onboarding_notification"></div>
2404 +
2405 + <div class="wpstream_option_wrapper wpstream_on_board_login_wrapper">
2406 + <h2><?php esc_html_e('Login with your WpStream Account','wpstream');?></h2>
2407 + <?php
2408 +
2409 + foreach ($wpstream_options_array as $key=>$option){
2410 + print '<div class="wpstream_option">';
2411 +
2412 + $options_value = esc_html( get_option('wpstream_'.$option['name'],'') );
2413 + print '<label for="'.$option['name'].'">'.$option['label'].'</label>';
2414 + print '<input id="'.$option['name'].'" type="'.$option['type'].'" size="36" name="'.$option['name'].'" value="'.esc_html($options_value).'" />';
2415 +
2416 + print '</div>';
2417 + }
2418 + ?>
2419 + <input type="submit" name="submit" class="wpstream_button wpstream_button_action wpstream_onboard_login" value="<?php esc_html_e('Login','wpstream');?>" />
2420 + </div>
2421 +
2422 +
2423 +
2424 +
2425 + <div class="wpstream_on_board_register_wrapper">
2426 + <h2><?php esc_html_e('Register for a WpStream Account','wpstream');?></h2>
2427 + <div class="wpstream_option">
2428 + <label for="wpstream_register_email"><?php esc_html_e('Your Email','wpstream');?></label>
2429 + <input id="wpstream_register_email" type="text" size="36" name="wpstream_register_email" value="<?php echo get_option('admin_email'); ?>" />
2430 +
2431 + </div>
2432 +
2433 + <div class="wpstream_option">
2434 + <label for="wpstream_register_password"><?php esc_html_e('Your Password','wpstream');?></label>
2435 + <input id="wpstream_register_password" type="text" size="36" name="wpstream_register_password" value="<?php echo $this->randomPassword();?>" />
2436 + </div>
2437 +
2438 +
2439 + <?php
2440 +
2441 + $curl_response_decoded['capthca']='';
2442 + $curl_response_decoded['capthca_id']='';
2443 +
2444 +
2445 + if( isset($_GET['page']) && $_GET['page']==='wpstream_onboard') {
2446 + $url = 'user/getcapthca';
2447 + $curl_post_fields = array();
2448 + $curl_response = $this->main->wpstream_live_connection->wpstream_baker_do_curl_base($url,$curl_post_fields);
2449 + $curl_response_decoded = json_decode($curl_response,JSON_OBJECT_AS_ARRAY);
2450 +
2451 + }
2452 +
2453 + ?>
2454 + <div class="wpstream_option">
2455 + <?php print '<div id="wpstream_capthca">'.$curl_response_decoded['capthca'].'</div>';?>
2456 + <label for="wpstream_register_captcha"><?php esc_html_e('Type the characters above','wpstream');?></label>
2457 +
2458 + <input id="wpstream_register_captcha" type="text" size="36" name="wpstream_register_captcha" />
2459 + <input id="wpstream_register_captcha_id" type="hidden" size="36" name="wpstream_register_captcha_id" value="<?php echo esc_html($curl_response_decoded['capthca_id']); ?>" />
2460 + </div>
2461 +
2462 +
2463 +
2464 + <input type="submit" name="submit" class="wpstream_button wpstream_button_action wpstream_onboard_register" value="<?php esc_html_e('register','wpstream');?>" />
2465 + </div>
2466 +
2467 +
2468 + <div id="wpstream_onboarding_action_login"><?php esc_html_e('I already have a WpStream Account','wpstream');?></div>
2469 +
2470 + <div id="wpstream_onboarding_action_register"><?php esc_html_e('Back to Registration','wpstream');?></div>
2471 +
2472 + </div>
2473 +
2474 +
2475 + <?php
2476 + $ajax_nonce = wp_create_nonce( "wpstream_onboarding_nonce");
2477 + print'<input type="hidden" id="wpstream_onboarding_nonce" value="'.esc_html($ajax_nonce).'" /> ';
2478 +
2479 + ?>
2480 +
2481 +
2482 + <div id="wpstream_on_board" class="wpstream_action_next_step" data-nextthing="wpstream_step_2" style="display:none;" >Move to step 2</div>
2483 + </div>
2484 + <?php
2485 +
2486 + if(trim($token)!==''){
2487 + print '<div id="wpstream_have_token"></div>';
2488 + }
3154 2489 }
2490 +
3155 2491
2492 +
2493 +
2494 +
2495 +
2496 +
2497 +
2498 +
2499 +
2500 + /*
2501 + *
2502 + * Generate random pass
2503 + *
2504 + */
2505 +
3156 2506 public function randomPassword() {
3157 - return $this->main->get_onboarding()->render_part( 'password' );
2507 + $alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890';
2508 + $pass = array(); //remember to declare $pass as an array
2509 + $alphaLength = strlen($alphabet) - 1; //put the length -1 in cache
2510 + for ($i = 0; $i < 8; $i++) {
2511 + $n = rand(0, $alphaLength);
2512 + $pass[] = $alphabet[$n];
2513 + }
2514 + return implode($pass); //turn the array into a string
3158 2515 }
3159 2516
2517 +
2518 + /*
2519 + *
2520 + *
2521 + *
2522 + */
2523 +
3160 2524 public function wpstream_onboarding_step2(){
3161 - $this->main->get_onboarding()->render_part( 'path' );
2525 + ?>
2526 +
2527 + <div class="wpstream_step_wrapper wpstream_step_2" id="wpstream_step_2">
2528 + <h1>Welcome to <span class="header_special">WpStream</span>! How would you like to start?</h1>
2529 +
2530 + <div class="wpstream_accordion_header wpstream_action_next_step" data-nextthing="wpstream_step_3" ><?php esc_html_e('Go LIVE!','wpstream');?></div>
2531 + <div class="wpstram_or">or</div>
2532 + <div class="wpstream_accordion_header wpstream_action_next_step" data-nextthing="wpstream_step_4" ><?php esc_html_e('Create a Video-On-Demand (VOD)','wpstream');?></div>
2533 +
2534 + </div>
2535 +
2536 +
2537 + <?php
3162 2538 }
3163 2539
2540 + /*
2541 + *
2542 + *
2543 + *
2544 + */
2545 +
3164 2546 public function wpstream_onboarding_step3_live_streaming(){
3165 - $this->main->get_onboarding()->render_part( 'live' );
2547 + ?>
2548 +
2549 + <div class="wpstream_step_wrapper wpstream_step_3 wpstream_onboarding_live" id="wpstream_step_3">
2550 + <h1><?php esc_html_e('Do you want to charge a fee for watching?','wpstream'); ?></h1>
2551 +
2552 + <div class="wpstream_accordion_header wpstream_action_next_step" data-nextthing="wpstream_step_3a"><?php esc_html_e('No - Free-To-View (FTV)','wpstream');?></div>
2553 + <div class="wpstram_or">or</div>
2554 + <div class="wpstream_accordion_header wpstream_action_next_step" data-nextthing="wpstream_step_3b" ><?php esc_html_e('Yes - Pay-Per-View (PPV)','wpstream');?></div>
2555 +
2556 + <div class="wpstream_initial_onboarding_controls_wrapper">
2557 + <span class="wpstream_onboard_initial_bubble_prev" data-step="wpstream_step_2"><?php esc_html_e('Prev','wpstream');?></span>
2558 + </div>
2559 +
2560 + </div>
2561 +
2562 +
2563 + <?php
3166 2564 }
2565 +
2566 +
2567 + /*
2568 + *
2569 + *
2570 + *
2571 + */
2572 + public function wpstream_onboarding_step_3_A_live_streaming_free_view(){
2573 + ?>
2574 +
2575 + <div class="wpstream_step_wrapper wpstream_step_3a wpstream_onboarding_live" id="wpstream_step_3a">
2576 + <h1><?php esc_html_e('Let’s create your first FTV live channel','wpstream');?></h1>
3167 2577
3168 - public function wpstream_onboarding_step_3_A_live_streaming_free_view(){
3169 - $this->main->get_onboarding()->render_part( 'live_free' );
2578 + <div id="wpstream_onboard_live_notice" class="wpstream_onboarding_notification"></div>
2579 + <div id="wpstream_onboard_live" class="wpstream_accordion_container">
2580 + <label>Name your first Free-To-View channel</label>
2581 + <input type="text" name="channel_name" id="wpstream_onboarding_channel_name" class="wpstream_onboarding_channel_name" value="<?php esc_html_e('My first FTV channel','wpstream');?>" >
2582 + <input type="submit" name="submit" id="wpstream_on_board_create_channel" class="wpstream_button wpstream_button_action wpstream_onboard_live_action" value="<?php esc_html_e('Create Channel','wpstream');?>" />
2583 +
2584 + </div>
2585 +
2586 + <div class="wpstream_initial_onboarding_controls_wrapper">
2587 + <span class="wpstream_onboard_initial_bubble_prev" data-step="wpstream_step_3"><?php esc_html_e('Prev','wpstream');?></span>
2588 + </div>
2589 +
2590 + </div>
2591 +
2592 +
2593 + <?php
3170 2594 }
3171 2595
2596 +
2597 + /*
2598 + *
2599 + *
2600 + *
2601 + */
2602 +
3172 2603 public function wpstream_onboarding_step_3_B_live_streaming_pay_per_view(){
3173 - $this->main->get_onboarding()->render_part( 'live_ppv' );
2604 + ?>
2605 +
2606 + <div class="wpstream_step_wrapper wpstream_step_3a wpstream_onboarding_live" id="wpstream_step_3b">
2607 + <h1><?php esc_html_e('Make your live stream Pay Per View','wpstream');?></h1>
2608 + <?php
2609 + if ( class_exists( 'WooCommerce' ) ) {
2610 + ?>
2611 + <div id="wpstream_onboard_live_ppv_notice" class="wpstream_onboarding_notification"></div>
2612 + <div id="wpstream_onboard_live_ppv" class="wpstream_accordion_container">
2613 + <label><?php esc_html_e('Choose a name for your channel','wpstream');?></label>
2614 + <input type="text" name="channel_name" id="wpstream_onboarding_channel_name_ppv" class="wpstream_onboarding_channel_name" value="<?php esc_html_e('My First PPV Channel','wpstream');?>">
2615 + <label><?php esc_html_e('Pay-Per-View Price ($)','wpstream');?></label>
2616 + <input type="text" name="channel_name" id="wpstream_onboarding_event_price_ppv" class="wpstream_onboarding_event_price" value="10">
2617 + <input type="submit" name="submit" id="wpstream_onboard_live_ppv_action" class="wpstream_button wpstream_button_action wpstream_onboard_live_ppv_action" value="<?php esc_html_e('Create Channel','wpstream');?>" />
2618 +
2619 + </div>
2620 + <?php
2621 + } else {
2622 + $this->wpstream_onboarding_woo_warning();
2623 + } ?>
2624 +
2625 +
2626 + <div class="wpstream_initial_onboarding_controls_wrapper">
2627 + <span class="wpstream_onboard_initial_bubble_prev" data-step="wpstream_step_3"><?php esc_html_e('Prev','wpstream');?></span>
2628 + </div>
2629 + </div>
2630 + <?php
3174 2631 }
3175 2632
2633 +
2634 +
2635 +
2636 +
2637 +
2638 + /*
2639 + * WooCommerce not installed Warning
2640 + *
2641 + *
2642 + */
2643 +
3176 2644 public function wpstream_onboarding_woo_warning(){
3177 - $this->main->get_onboarding()->render_part( 'woo_warning' );
2645 + print'<div class="wpstream_warning_onboarding">
2646 + '.esc_html__('Pay-Per-View streaming requires WooCommerce. Please install the WooCommerce plugin and try again.','wpstream').'
2647 + </br>
2648 + <div class="wpstream_install_plugin">'. esc_html__('Install WooCommerce','wpstream').'</div>
2649 +
2650 + <div class="wpstream_onboarding_tryagain">'.esc_html__('Try Again','wpstream').'</div>
2651 + </div>';
3178 2652 }
3179 2653
2654 +
2655 + /*
2656 + *
2657 + *
2658 + *
2659 + */
2660 +
3180 2661 public function wpstream_onboarding_step4_vod(){
3181 - $this->main->get_onboarding()->render_part( 'vod' );
2662 + ?>
2663 + <div class="wpstream_step_wrapper wpstream_step_4 wpstream_onboarding_vod" id="wpstream_step_4">
2664 + <h1><?php esc_html_e('Do you want to charge a fee for watching?','wpstream');?></h1>
2665 +
2666 + <div class="wpstream_accordion_header wpstream_action_next_step" data-control="wpstream_onboard_vod_free" data-nextthing="wpstream_step_4a" ><?php esc_html_e('No - Free-To-View (FTV)','wpstream'); ?></div>
2667 + <div class="wpstram_or">or</div>
2668 + <div class="wpstream_accordion_header wpstream_action_next_step" data-control="wpstream_onboard_vod_ppv" data-nextthing="wpstream_step_4b" ><?php esc_html_e('Yes - Pay-Per-View (PPV)','wpstream'); ?></div>
2669 +
2670 +
2671 + <div class="wpstream_initial_onboarding_controls_wrapper">
2672 + <span class="wpstream_onboard_initial_bubble_prev" data-step="wpstream_step_2"><?php esc_html_e('Prev','wpstream');?></span>
2673 + </div>
2674 +
2675 + </div>
2676 + <?php
3182 2677 }
3183 2678
2679 +
2680 + /*
2681 + *
2682 + *
2683 + *
2684 + */
3184 2685 public function wpstream_onboarding_step_4_free_vod(){
3185 - $this->main->get_onboarding()->render_part( 'vod_free' );
2686 +
2687 + $current_screen=get_current_screen();
2688 + if($current_screen->base !=='wpstream_page_wpstream_onboard'){
2689 + return;
2690 + }
2691 +
2692 + $token = $this->main->wpstream_live_connection->wpstream_get_token();
2693 + $video_list = array();
2694 + if($token!=''){
2695 + $video_list = $this->main->wpstream_live_connection->wpstream_get_videos();
2696 + }
2697 +
2698 + ?>
2699 +
2700 + <div class="wpstream_step_wrapper wpstream_step_3a wpstream_onboarding_live" id="wpstream_step_4a">
2701 + <h1><?php esc_html_e('Let’s create your first Free-To-View VOD','wpstream');?></h1>
2702 +
2703 +
2704 +
2705 + <?php
2706 + if( count($video_list) !== 0 ) {
2707 + ?>
2708 + <div id="wpstream_onboard_vod_free_notice" class="wpstream_onboarding_notification"></div>
2709 + <div id="wpstream_onboard_vod_free" class="wpstream_accordion_container">
2710 + <label><?php esc_html_e('Name your FTV Video-On-Demand','wpstream')?></label>
2711 + <input type="text" name="channel_name" class="wpstream_onboarding_vod_name" id="wpstream_onboarding_vod_name" value="<?php esc_html_e('My First FTV VOD','wpstream');?>" >
2712 + <?php $this->wpstream_show_vod_dropdown_onboarding($video_list); ?>
2713 + <input type="submit" name="submit" class="wpstream_button wpstream_button_action wpstream_onboard_vod_free_action" id="wpstream_onboard_vod_free_action" value="<?php esc_html_e('Create FTV VOD','wpstream');?>" />
2714 + </div>
2715 +
2716 + <?php }else{
2717 + $this->wpstream_obboarding_file_warning();
2718 + } ?>
2719 +
2720 +
2721 +
2722 + <div class="wpstream_initial_onboarding_controls_wrapper">
2723 + <span class="wpstream_onboard_initial_bubble_prev" data-step="wpstream_step_4"><?php esc_html_e('Prev','wpstream');?></span>
2724 + </div>
2725 +
2726 + </div>
2727 +
2728 +
2729 + <?php
3186 2730 }
3187 2731
2732 + /*
2733 + *
2734 + *
2735 + *
2736 + */
2737 +
2738 + public function wpstream_show_vod_dropdown_onboarding($video_list,$appendix=''){
2739 +
2740 + print '<label>'.esc_html__('Choose Recording','wpstream').'</label>
2741 + <select name="wpstream_free_vod_file_name" id="wpstream_free_vod_file_name'.$appendix.'">
2742 + <option value="">'.esc_html__('Please select a recording from the list','wpstream').'</option>';
2743 +
2744 + if(is_array($video_list)){
2745 + foreach ($video_list as $key=>$value){
2746 + print '<option value="'.$key.'"';
2747 + print '>'.$value.'</option>';
2748 + }
2749 + }
2750 + print'</select>';
2751 +
2752 + }
2753 +
2754 +
2755 +
2756 + /*
2757 + *
2758 + *
2759 + *
2760 + */
3188 2761 public function wpstream_obboarding_file_warning(){
3189 - $this->main->get_onboarding()->render_part( 'file_warning' );
2762 + print '<div class="wpstream_warning_onboarding">
2763 + '.esc_html__('A recording is needed to create a VOD from. There are no recordings under your account. You can create new recordings by recording a live channel or uploading video files directly.','wpstream').'
2764 + </br>
2765 + <div class="wpstream_upload_video">'.esc_html__('Upload Video','wpstream').'</div>
2766 +
2767 + <div class="wpstream_onboarding_tryagain">'.esc_html__('Try Again','wpstream').'</div>
2768 + </div>';
3190 2769 }
3191 2770
2771 +
2772 +
2773 +
2774 + /*
2775 + *
2776 + *
2777 + *
2778 + */
3192 2779 public function wpstream_onboarding_step_4_ppv_vod(){
3193 - $this->main->get_onboarding()->render_part( 'vod_ppv' );
2780 + $current_screen=get_current_screen();
2781 +
2782 + if($current_screen->base !=='wpstream_page_wpstream_onboard'){
2783 + return;
2784 + }
2785 +
2786 + $token = $this->main->wpstream_live_connection->wpstream_get_token();
2787 + $video_list = array();
2788 + if($token!=''){
2789 + $video_list = $this->main->wpstream_live_connection->wpstream_get_videos();
2790 + }
2791 + ?>
2792 +
2793 + <div class="wpstream_step_wrapper wpstream_step_3a wpstream_onboarding_live" id="wpstream_step_4b">
2794 + <h1><?php esc_html_e('Let\'s create your first Pay-Per-View VOD','wpstream');?></h1>
2795 +
2796 + <div id="wpstream_onboard_vod_ppv_notice" class="wpstream_onboarding_notification"></div>
2797 + <?php
2798 + if( count($video_list) !== 0 ) {
2799 + if ( class_exists( 'WooCommerce' ) ) {
2800 + ?>
2801 + <div id="wpstream_onboard_vod_ppv" class="wpstream_accordion_container">
2802 + <label><?php esc_html_e('Name your PPV Video-On-Demand','wpstream'); ?></label>
2803 + <input type="text" name="channel_name" class="wpstream_onboarding_ppv_vod_name" id="wpstream_onboarding_ppv_vod_name" value="<?php esc_html_e('My First PPV VOD','wpstream');?>">
2804 +
2805 + <?php $this->wpstream_show_vod_dropdown_onboarding($video_list,'_for_ppv'); ?>
2806 +
2807 + <label><?php esc_html_e('Pay-Per-View Price','wpstream');?></label>
2808 + <input type="text" name="channel_name" class="wpstream_onboarding_vod_price" id="wpstream_onboarding_vod_price" value="10">
2809 + <input type="submit" name="submit" class="wpstream_button wpstream_button_action wpstream_onboard_vod_ppv_action" id="wpstream_onboard_vod_ppv_action" value="<?php esc_html_e('Create PPV VOD','wpstream');?>" />
2810 +
2811 + </div>
2812 + <?php }else{
2813 + $this->wpstream_onboarding_woo_warning();
2814 + }
2815 +
2816 +
2817 + }else{
2818 + $this->wpstream_obboarding_file_warning();
2819 + }
2820 + ?>
2821 +
2822 +
2823 + <div class="wpstream_initial_onboarding_controls_wrapper">
2824 + <span class="wpstream_onboard_initial_bubble_prev" data-step="wpstream_step_4"><?php esc_html_e('Prev','wpstream');?></span>
2825 + </div>
2826 +
2827 + </div>
2828 +
2829 +
2830 + <?php
3194 2831 }
3195 2832
2833 +
2834 +
2835 +
2836 + /*
2837 + *
2838 + * On boarding Header
2839 + *
2840 + */
3196 2841 public function onboarding_wizard_header() {
3197 - $this->main->get_onboarding()->render_part( 'wizard_header' );
2842 + $thumb= plugin_dir_url( dirname( __FILE__ ) ). 'img/logo_onboarding.svg';
2843 + ?>
2844 +
2845 + <div class="wpstream_on_boarding_wrapper">
2846 + <div class="wpstream_close_onboarding wpstream_close_initial_onboarding"></div>
2847 + <img class="wpstream_onboarding_logo" src="<?php echo esc_url($thumb); ?>" />
2848 + <div class="wpstream_close_onboarding_warning"></div>
2849 +
2850 + <?php
3198 2851 }
3199 2852
3200 2853
3201 2854
@@ -3205,15 +2858,14 @@
3205 2858 *
3206 2859 * On Boarding Footer
3207 2860 *
3208 2861 */
3209 - /**
3210 - * Close the onboarding wizard wrapper and print its modal background. Echoes HTML.
3211 - *
3212 - * @return void
3213 - */
3214 2862 public function onboarding_wizard_footer() {
3215 - $this->main->get_onboarding()->render_part( 'wizard_footer' );
2863 + ?>
2864 + <div class="wpstream_modal_back"></div>
2865 + </div>
2866 + <div class="wpstream_modal_background_onboard"></div>
2867 + <?php
3216 2868 }
3217 2869
3218 2870
3219 2871
@@ -3223,19 +2875,57 @@
3223 2875 *
3224 2876 */
3225 2877
3226 2878
3227 - /**
3228 - * AJAX: create a Pay-Per-View live channel during onboarding.
3229 - *
3230 - * Inserts a WooCommerce `product`, sets its price, marks it live_stream,
3231 - * and returns the edit link (with onboarding query args) as JSON.
3232 - * Nonce- and administrator-gated.
3233 - *
3234 - * @return void Ends with die().
3235 - */
3236 2879 public function wpstream_on_board_create_channel_ppv(){
3237 - return $this->main->get_onboarding()->handle_ajax( 'wpstream_on_board_create_channel_ppv' );
2880 + check_ajax_referer( 'wpstream_onboarding_nonce', 'security' );
2881 + $current_user = wp_get_current_user();
2882 +
2883 + if(current_user_can('administrator')){
2884 + $channel_name = sanitize_text_field($_POST['channel_name']);
2885 + $channel_price = floatval($_POST['channel_price']);
2886 + $my_post = array(
2887 + 'post_title' => $channel_name,
2888 + 'post_content' => '',
2889 + 'post_status' => 'publish',
2890 + 'post_type' => 'product',
2891 + 'post_author' => $current_user->ID
2892 + );
2893 +
2894 + // Insert the post into the database
2895 + $post_id = wp_insert_post( $my_post );
2896 +
2897 + if(is_wp_error($post_id)){
2898 + echo json_encode( array('succes'=>false) );
2899 + }else{
2900 +
2901 + $product = wc_get_product($post_id);
2902 + $price = wc_format_decimal($channel_price);
2903 +
2904 + $product = wc_get_product( $post_id );
2905 + $product->set_price( $price );
2906 + $product->set_regular_price( $price ); // To be sure
2907 + $product->save();
2908 + update_post_meta ($post_id,'event_passed',0);
2909 + wp_set_object_terms( $post_id, 'live_stream', 'product_type' );
2910 +
2911 +
2912 +
2913 +
2914 + $permalink = get_edit_post_link($post_id);
2915 +
2916 + $permalink= add_query_arg( 'onboard', 'yes', $permalink );
2917 + $permalink= add_query_arg( 'branch', '2', $permalink );
2918 +
2919 +
2920 + echo json_encode( array(
2921 + 'success'=> true,
2922 + 'link' => ($permalink)
2923 + ));
2924 + }
2925 +
2926 + }
2927 + die();
3238 2928 }
3239 2929
3240 2930 /*
3241 2931 *
@@ -3243,35 +2933,91 @@
3243 2933 *
3244 2934 */
3245 2935
3246 2936
3247 - /**
3248 - * AJAX: create a Free-To-View live channel during onboarding.
3249 - *
3250 - * Inserts a `wpstream_product` post and returns its edit link (with
3251 - * onboarding query args) as JSON. Nonce- and administrator-gated.
3252 - *
3253 - * @return void Ends with die().
3254 - */
3255 2937 public function wpstream_on_board_create_channel(){
3256 - return $this->main->get_onboarding()->handle_ajax( 'wpstream_on_board_create_channel' );
2938 + check_ajax_referer( 'wpstream_onboarding_nonce', 'security' );
2939 + $current_user = wp_get_current_user();
2940 +
2941 + if(current_user_can('administrator')){
2942 + $channel_name=sanitize_text_field($_POST['channel_name']);
2943 + $my_post = array(
2944 + 'post_title' => $channel_name,
2945 + 'post_content' => '',
2946 + 'post_status' => 'publish',
2947 + 'post_type' => 'wpstream_product',
2948 + 'post_author' => $current_user->ID
2949 + );
2950 +
2951 + // Insert the post into the database
2952 + $post_id = wp_insert_post( $my_post );
2953 +
2954 + if(is_wp_error($post_id)){
2955 + echo json_encode( array('succes'=>false) );
2956 + }else{
2957 + $permalink = get_edit_post_link($post_id);
2958 +
2959 + $permalink= add_query_arg( 'onboard', 'yes', $permalink );
2960 + $permalink= add_query_arg( 'branch', '1', $permalink );
2961 +
2962 +
2963 + echo json_encode( array(
2964 + 'success'=> true,
2965 + 'link' => ($permalink)
2966 + ));
2967 + }
2968 +
2969 + }
2970 + die();
3257 2971 }
3258 2972
2973 +
2974 +
3259 2975 /*
3260 2976 *
3261 2977 * On Boarding create free vod
3262 2978 *
3263 2979 */
3264 - /**
3265 - * AJAX: create a Free-To-View VOD during onboarding.
3266 - *
3267 - * Inserts a `wpstream_product_vod` post, links the chosen recording, and
3268 - * returns the edit link (with onboarding query args). Nonce/admin gated.
3269 - *
3270 - * @return void Ends with die().
3271 - */
2980 +
2981 +
3272 2982 public function wpstream_on_board_create_free_vod(){
3273 - return $this->main->get_onboarding()->handle_ajax( 'wpstream_on_board_create_free_vod' );
2983 + $current_user = wp_get_current_user();
2984 + check_ajax_referer( 'wpstream_onboarding_nonce', 'security' );
2985 + if(current_user_can('administrator')){
2986 + $channel_name =sanitize_text_field($_POST['channel_name']);
2987 + $file_name =sanitize_text_field($_POST['file_name']);
2988 + $my_post = array(
2989 + 'post_title' => $channel_name,
2990 + 'post_content' => '',
2991 + 'post_status' => 'publish',
2992 + 'post_type' => 'wpstream_product_vod',
2993 + 'post_author' => $current_user->ID
2994 + );
2995 +
2996 + // Insert the post into the database
2997 + $post_id = wp_insert_post( $my_post );
2998 +
2999 + if(is_wp_error($post_id)){
3000 + echo json_encode( array('succes'=>false) );
3001 + }else{
3002 + update_post_meta($post_id, 'wpstream_product_type', 2);
3003 + update_post_meta($post_id, 'wpstream_free_video', $file_name);
3004 +
3005 +
3006 + $permalink = get_edit_post_link($post_id);
3007 +
3008 + $permalink= add_query_arg( 'onboard', 'yes', $permalink );
3009 + $permalink= add_query_arg( 'branch', '3', $permalink );
3010 +
3011 +
3012 + echo json_encode( array(
3013 + 'success'=> true,
3014 + 'link' => ($permalink)
3015 + ));
3016 + }
3017 +
3018 + }
3019 + die();
3274 3020 }
3275 3021
3276 3022
3277 3023 /*
@@ -3280,19 +3026,61 @@
3280 3026 *
3281 3027 */
3282 3028
3283 3029
3284 - /**
3285 - * AJAX: create a Pay-Per-View VOD during onboarding.
3286 - *
3287 - * Inserts a WooCommerce `product`, sets its price, links the recording,
3288 - * marks it video_on_demand, and returns the edit link (with onboarding
3289 - * query args). Nonce- and administrator-gated.
3290 - *
3291 - * @return void Ends with die().
3292 - */
3293 3030 public function wpstream_on_board_create_ppv_vod(){
3294 - return $this->main->get_onboarding()->handle_ajax( 'wpstream_on_board_create_ppv_vod' );
3031 + $current_user = wp_get_current_user();
3032 + check_ajax_referer( 'wpstream_onboarding_nonce', 'security' );
3033 +
3034 + if(current_user_can('administrator')){
3035 + $channel_name = sanitize_text_field($_POST['channel_name']);
3036 + $vod_price = floatval($_POST['vod_price']);
3037 + $file_name = sanitize_text_field($_POST['file_name']);
3038 +
3039 + $my_post = array(
3040 + 'post_title' => $channel_name,
3041 + 'post_content' => '',
3042 + 'post_status' => 'publish',
3043 + 'post_type' => 'product',
3044 + 'post_author' => $current_user->ID
3045 + );
3046 +
3047 + // Insert the post into the database
3048 + $post_id = wp_insert_post( $my_post );
3049 +
3050 + if(is_wp_error($post_id)){
3051 + echo json_encode( array('succes'=>false) );
3052 + }else{
3053 +
3054 + $product = wc_get_product($post_id);
3055 + $price = wc_format_decimal($vod_price);
3056 +
3057 + $product = wc_get_product( $post_id );
3058 + $product->set_price( $price );
3059 + $product->set_regular_price( $price ); // To be sure
3060 + $product->save();
3061 + update_post_meta ($post_id,'event_passed',0);
3062 + update_post_meta ($post_id,'_movie_url', $file_name);
3063 + wp_set_object_terms( $post_id, 'video_on_demand', 'product_type' );
3064 +
3065 +
3066 +
3067 +
3068 + $permalink = get_edit_post_link($post_id);
3069 +
3070 + $permalink= add_query_arg( 'onboard', 'yes', $permalink );
3071 + $permalink= add_query_arg( 'branch', '4', $permalink );
3072 +
3073 +
3074 + echo json_encode( array(
3075 + 'success'=> true,
3076 + 'link' => ($permalink) ,
3077 + ' $file_name'=> $file_name,
3078 + ));
3079 + }
3080 +
3081 + }
3082 + die();
3295 3083 }
3296 3084
3297 3085
3298 3086 /*
@@ -3299,257 +3087,185 @@
3299 3087 *
3300 3088 * On Boarding login
3301 3089 *
3302 3090 */
3303 - /**
3304 - * AJAX: log in to WpStream during onboarding.
3305 - *
3306 - * Stores the submitted credentials, clears the token cache, then attempts
3307 - * to fetch a token; returns success/failure JSON without ever exposing the
3308 - * token to the client. Nonce- and administrator-gated.
3309 - *
3310 - * @return void Ends with die().
3311 - */
3312 3091 public function wpstream_on_board_login(){
3313 - return $this->main->get_onboarding()->handle_ajax( 'wpstream_on_board_login' );
3092 + check_ajax_referer( 'wpstream_onboarding_nonce', 'security' );
3093 +
3094 + if(current_user_can('administrator')){
3095 + $username = sanitize_text_field($_POST['api_username']);
3096 + $password = sanitize_text_field($_POST['api_password']);
3097 + update_option('wpstream_api_username',$username);
3098 + update_option('wpstream_api_password',$password);
3099 +
3100 + $token = $this->main->wpstream_live_connection->wpstream_get_token();
3101 +
3102 + echo json_encode( array(
3103 + 'success'=> true,
3104 + 'token' => ($token)
3105 + ));
3106 +
3107 + }else{
3108 + echo json_encode( array(
3109 + 'success'=> false,
3110 + 'token' => esc_html('You are not an administrator','wpstream')
3111 + ));
3112 + }
3113 + die();
3314 3114 }
3315 3115
3316 - /**
3317 - * AJAX proxy: fetch a captcha challenge from the baker API and return it.
3318 - * Used on HTTP sites where the Altcha widget cannot run (requires Web Crypto / HTTPS).
3319 - * The JS side solves the PoW locally and sends back the full base64 Altcha payload.
3320 - * Logged-in administrators only: every call proxies an outbound request, so the
3321 - * endpoint is gated like the rest of the onboarding wizard.
3322 - */
3323 - public function wpstream_get_captcha_challenge() {
3324 - return $this->main->get_onboarding()->handle_ajax( 'wpstream_get_captcha_challenge' );
3325 - }
3326 -
3116 +
3117 + public function wpstream_register_refresh_capthca(){
3118 +
3119 + if(current_user_can('administrator')){
3120 +
3121 + }
3122 + }
3123 +
3327 3124 /*
3328 3125 *
3329 3126 * On Boarding login
3330 3127 *
3331 3128 */
3332 - /**
3333 - * AJAX: register a new WpStream account during onboarding.
3334 - *
3335 - * Validates the email/password, requires an ALTCHA solution, calls the
3336 - * account-create API, and on success stores the credentials and fetches a
3337 - * token. Returns JSON. Nonce- and administrator-gated.
3338 - *
3339 - * @return void Ends with die().
3340 - */
3341 3129 public function wpstream_on_board_register(){
3342 - return $this->main->get_onboarding()->handle_ajax( 'wpstream_on_board_register' );
3343 - }
3344 3130
3131 + check_ajax_referer( 'wpstream_onboarding_nonce', 'security' );
3132 +
3133 + if(current_user_can('administrator')){
3134 + $wpstream_register_email = sanitize_text_field($_POST['wpstream_register_email']);
3135 + $wpstream_register_password = sanitize_text_field($_POST['wpstream_register_password']);
3136 + $wpstream_register_captcha = sanitize_text_field($_POST['wpstream_register_captcha']);
3137 + $wpstream_register_captcha_id = sanitize_text_field($_POST['wpstream_register_captcha_id']);
3138 +
3139 + $validate = $this->wpstream_validate_onboard_register($wpstream_register_email,$wpstream_register_password);
3140 + if(!$validate['success']){
3141 + echo json_encode($validate);
3142 + die();
3143 + }
3345 3144
3346 - /*
3347 - *
3348 - * Validate for register
3349 - *
3350 - */
3351 - /**
3352 - * Validate the onboarding registration email + password.
3353 - *
3354 - * Checks for a non-empty, well-formed email whose domain has DNS records,
3355 - * and a password of at least 5 characters.
3356 - *
3357 - * @param string $wpstream_register_email Submitted email.
3358 - * @param string $wpstream_register_password Submitted password.
3359 - * @return array{success: bool, message?: string} Validation result.
3360 - */
3361 - public function wpstream_validate_onboard_register($wpstream_register_email,$wpstream_register_password){
3362 - return $this->main->get_onboarding()->validate_registration( $wpstream_register_email, $wpstream_register_password );
3363 - }
3145 + $url='user/create';
3146 + $curl_post_fields=array(
3147 + 'email' => $wpstream_register_email,
3148 + 'password' => $wpstream_register_password,
3149 + 'captcha' => $wpstream_register_captcha,
3150 + 'captcha_id' => $wpstream_register_captcha_id,
3151 + );
3152 +
3153 +
3154 +
3155 + $curl_response = $this->main->wpstream_live_connection->wpstream_baker_do_curl_base($url,$curl_post_fields);
3156 + $curl_response_decoded = json_decode($curl_response,JSON_OBJECT_AS_ARRAY);
3364 3157
3365 - /**
3366 - * Handle the AJAX request to initiate a multipart upload
3367 - *
3368 - * Validates the request, builds a clean filename, and asks the cloud API to
3369 - * open a multipart S3 upload; returns the upload id and per-part pre-signed
3370 - * URLs as JSON. Nonce- and administrator-gated.
3371 - *
3372 - * @since 3.0.1
3373 - * @return void Responds via wp_send_json_*.
3374 - */
3375 - public function handle_initiate_multipart_upload() {
3376 - check_ajax_referer( 'wpstream_multipart_upload_nonce', 'security' );
3158 +
3159 +
3160 + if($curl_response_decoded['success']){
3377 3161
3378 - // Security check - only admins can do this
3379 - if (!current_user_can('administrator')) {
3380 - wp_send_json_error('Unauthorized access');
3381 - return;
3382 - }
3162 + if($curl_response_decoded['request']['registred']){
3163 + // we are registerd
3383 3164
3384 - // Get file details from request
3385 - $file_name = sanitize_text_field($_POST['file_name']);
3386 - $file_size = intval($_POST['file_size']);
3387 - $content_type = sanitize_text_field($_POST['content_type']);
3388 - $num_parts = intval($_POST['parts']);
3165 + update_option('wpstream_api_username',$wpstream_register_email);
3166 + update_option('wpstream_api_password',$wpstream_register_password);
3167 +
3168 + $token = $this->main->wpstream_live_connection->wpstream_get_token();
3389 3169
3390 - // Reject incomplete/invalid file metadata.
3391 - if (empty($file_name) || $file_size <= 0 || $num_parts <= 0) {
3392 - wp_send_json_error('Invalid file information');
3393 - return;
3394 - }
3170 + echo json_encode( array(
3171 + 'success' => true,
3172 + 'token' => $token ,
3173 + 'message' => esc_html__('Your Account was created. Please stand by...','wpstream'),
3174 +
3175 + ));
3176 + die();
3177 + }else{
3395 3178
3396 - // The part count is caller-supplied: refuse a split the backend can
3397 - // never assemble before spending a cloud call on it.
3398 - if ($num_parts > self::MULTIPART_MAX_PARTS) {
3399 - wp_send_json_error(
3400 - sprintf(
3401 - /* translators: 1: requested part count, 2: maximum part count */
3402 - __('The file would be split into %1$d parts but at most %2$d are allowed. Reload the page to get the current uploader and try again.', 'wpstream'),
3403 - $num_parts,
3404 - self::MULTIPART_MAX_PARTS
3405 - )
3406 - );
3407 - return;
3408 - }
3179 + echo json_encode( array(
3180 + 'success'=> false,
3181 + 'message'=> $curl_response_decoded['request']['message'],
3182 + 'curl'=>$curl_response_decoded,
3183 +
3184 + ));
3185 + die();
3186 + }
3409 3187
3410 - // Prepare a clean filename (similar to the standard upload process)
3411 - // Keep the extension, slugify the base name (spaces -> _, strip non-word chars).
3412 - $file_name_array = explode(".", $file_name);
3413 - $file_extension = $file_name_array[count($file_name_array) - 1];
3414 - $temp_file_name = $file_name_array[0];
3415 - $temp_file_name = str_replace(' ', '_', $temp_file_name);
3416 - $temp_file_name = preg_replace('/\W/', '', $temp_file_name);
3417 - $clean_file_name = $temp_file_name . '.' . $file_extension;
3418 3188
3419 - // Make API call to initiate multipart upload; the auth token is
3420 - // injected by the transport (not-connected surfaces as a WP_Error
3421 - // whose message is the legacy "Not connected to WPStream service").
3422 - $api_params = array(
3423 - 'size' => $file_size,
3424 - 'name' => $clean_file_name,
3425 - 'content_type' => $content_type,
3426 - 'parts' => $num_parts
3427 - );
3428 3189
3429 - $response_data = $this->main->wpstream_live_connection->authorized_request('video/upload', $api_params);
3430 3190
3431 - // Bubble up any API error.
3432 - if (is_wp_error($response_data)) {
3433 - wp_send_json_error($response_data->get_error_message());
3434 - return;
3435 - }
3436 - if (!isset($response_data['success']) || $response_data['success'] !== true) {
3437 - $error_message = isset($response_data['error']) ? $response_data['error'] : 'Failed to initiate multipart upload';
3438 - wp_send_json_error($error_message);
3439 - return;
3440 - }
3191 + }else{
3441 3192
3442 - // Return the upload ID and pre-signed URLs for each part
3443 - wp_send_json_success($response_data);
3444 - }
3193 + echo json_encode( array(
3194 + 'success'=> false,
3195 + 'message'=> esc_html__('Register action could not be completed. Please register on wpstream.net','wpstream'),
3196 +
3197 + ));
3198 + die();
3199 + }
3445 3200
3446 - /**
3447 - * Handle the AJAX request to complete a multipart upload
3448 - *
3449 - * Validates the request and tells the cloud API to finalize the multipart S3
3450 - * upload for the given parts/handle. Nonce- and administrator-gated.
3451 - *
3452 - * @since 3.0.1
3453 - * @return void Responds via wp_send_json_*.
3454 - */
3455 - public function handle_complete_multipart_upload() {
3456 - check_ajax_referer( 'wpstream_multipart_upload_nonce', 'security' );
3457 3201
3458 - // Security check - only admins can do this
3459 - if (!current_user_can('administrator')) {
3460 - wp_send_json_error('Unauthorized access');
3461 - return;
3462 - }
3463 3202
3464 - // Get completion details. The client sends 'parts' as the plain part
3465 - // COUNT (not a part list), so parse it as a positive integer.
3466 - $parts = isset($_POST['parts']) ? absint(wp_unslash($_POST['parts'])) : 0;
3467 - $file_name = sanitize_text_field($_POST['file_name']);
3468 - $handle = sanitize_text_field($_POST['handle']);
3469 3203
3470 - // Reject incomplete completion metadata: no parts uploaded or no file name.
3471 - if ($parts < 1 || empty($file_name)) {
3472 - wp_send_json_error('Invalid completion information');
3473 - return;
3474 - }
3475 3204
3476 - // Send the finalize ("complete") request with the uploaded part list;
3477 - // the auth token is injected by the transport (not-connected surfaces
3478 - // as a WP_Error whose message is the legacy "Not connected to WPStream
3479 - // service").
3480 - $api_params = array(
3481 - 'parts' => $parts,
3482 - 'name' => $file_name,
3483 - 'handle' => $handle,
3484 - 'action' => 'complete'
3485 - );
3486 3205
3487 - $response_data = $this->main->wpstream_live_connection->authorized_request('video/upload', $api_params);
3488 3206
3489 - // Bubble up any API error.
3490 - if (is_wp_error($response_data)) {
3491 - wp_send_json_error($response_data->get_error_message());
3492 - return;
3207 +
3208 + }else{
3209 + echo json_encode( array(
3210 + 'success'=> false,
3211 + 'message' => esc_html('You are not an administrator','wpstream')
3212 + ));
3213 + die();
3214 + }
3215 +
3216 + die();
3493 3217 }
3494 - if (!isset($response_data['success']) || $response_data['success'] !== true) {
3495 - $error_message = isset($response_data['error']) ? $response_data['error'] : 'Failed to complete multipart upload';
3496 - wp_send_json_error($error_message);
3497 - return;
3498 - }
3499 3218
3500 - /**
3501 - * Fires after the cloud accepted a completed multipart VOD upload.
3502 - *
3503 - * @since 4.14.0
3504 - *
3505 - * @param string $file_name Uploaded file name.
3506 - * @param string $handle Upload handle issued at initiation.
3507 - * @param int $parts Number of parts uploaded.
3508 - */
3509 - do_action( 'wpstream_multipart_upload_completed', $file_name, $handle, $parts );
3510 3219
3511 - // Return success
3512 - wp_send_json_success();
3513 - }
3220 + /*
3221 + *
3222 + * Validate for register
3223 + *
3224 + */
3514 3225
3515 - /**
3516 - * AJAX: update the WpStream plugin in place from the Settings/Support tab.
3517 - *
3518 - * Loads the upgrader APIs, initializes WP_Filesystem, runs the plugin
3519 - * upgrade, re-activates the plugin, and returns success/error JSON.
3520 - * Requires the update_plugins capability.
3521 - *
3522 - * @return void Responds via wp_send_json_*.
3523 - */
3524 - public function wpstream_settings_tab_update_plugin() {
3525 - // CSRF gate: the update button JS sends the settings-page nonce as 'security'.
3526 - check_ajax_referer( 'wpstream-settings-nonce', 'security' );
3527 - // Capability gate.
3528 - if ( !current_user_can( 'update_plugins' ) ) {
3529 - wp_send_json_error( __( 'Not enough permissions to make this change', 'wpstream' ) );
3530 - }
3531 3226
3532 - // Load the core upgrade/filesystem APIs.
3533 - include_once ABSPATH . 'wp-admin/includes/plugin-install.php';
3534 - include_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
3535 - include_once ABSPATH . 'wp-admin/includes/file.php';
3227 + public function wpstream_validate_onboard_register($wpstream_register_email,$wpstream_register_password){
3228 +
3229 + $return= array(
3230 + 'success'=>true
3231 + );
3232 +
3233 + if ($wpstream_register_email=='' ){
3234 + $return= array(
3235 + 'success'=> false,
3236 + 'message' => esc_html('The email Field is Empty','wpstream')
3237 + );
3238 + return $return;die();
3239 + }
3536 3240
3537 - // Initialize the filesystem abstraction (needed to write plugin files).
3538 - $credentials = request_filesystem_credentials('');
3539 - if ( !WP_Filesystem( $credentials ) ) {
3540 - wp_send_json_error( __( 'Failed to connect to the filesystem', 'wpstream' ) );
3541 - }
3241 + if(filter_var($wpstream_register_email,FILTER_VALIDATE_EMAIL) === false) {
3242 + $return= array(
3243 + 'success'=> false,
3244 + 'message' => esc_html('The email doesn\'t look right !','wpstream')
3245 + );
3246 + return $return;die();
3247 + }
3248 +
3542 3249
3543 - // Run the in-place upgrade for this plugin, then re-activate it.
3544 - $upgrader = new Plugin_Upgrader(new Automatic_Upgrader_Skin());
3545 - $plugin_path = plugin_basename( WPSTREAM_PLUGIN_PATH . 'wpstream.php' );
3546 - $result = $upgrader->upgrade( $plugin_path );
3547 - activate_plugin( $plugin_path );
3250 + $domain = mb_substr(strrchr($wpstream_register_email, "@"), 1);
3251 + if( $domain!='' && !checkdnsrr ($domain) ){
3252 + $return= array(
3253 + 'success'=> false,
3254 + 'message' => esc_html('The email doesn\'t look right !','wpstream')
3255 + );
3256 + return $return;die();
3257 + }
3548 3258
3549 - if ( is_wp_error( $result ) ) {
3550 - wp_send_json_error( __( 'Update failed due to', 'wpstream' ) . $result->get_error_message() );
3551 - }
3552 3259
3553 - wp_send_json_success();
3554 - }
3555 -}
3260 +
3261 + if(strlen($wpstream_register_password)<5){
3262 + $return= array(
3263 + 'success'=> false,
3264 + 'message' => esc_html('The password is too short. Please use at least 5 characters.','wpstream')
3265 + );
3266 + return $return;die();
3267 + }
3268 +
3269 + return $return;die();
3270 + }
3271 +}