PluginProbe
WpStream – Live Streaming, Video on Demand, Pay Per View / 4.8
WpStream – Live Streaming, Video on Demand, Pay Per View v4.8
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 | wpstream.php +49 -358 4.14.14.8 View file →
@@ -2,118 +2,34 @@
2 2 /**
3 3 * Plugin Name: WpStream - Live Streaming, Video on Demand, Pay Per View
4 4 * Plugin URI: http://wpstream.net
5 5 * Description: WpStream is a platform that allows you to live stream, create Video-on-Demand, and offer Pay-Per-View videos. We provide an affordable and user-friendly way for businesses, non-profits, and public institutions to broadcast their content and monetize their work.
6 - * Version: 4.14.1
6 + * Version: 4.8
7 7 * Author: wpstream
8 8 * Author URI: http://wpstream.net
9 9 * Text Domain: wpstream
10 10 * Domain Path: /languages/
11 - * License: GPLv2 or later
12 - * License URI: https://www.gnu.org/licenses/gpl-2.0.html
13 - * Requires at least: 5.8
14 - * Requires PHP: 7.1
15 11 */
16 12
17 -/**
18 - * Main plugin bootstrap file for WpStream.
19 - *
20 - * WordPress reads the header comment above to list the plugin. This file then
21 - * defines the plugin's global constants (version, remote API/player/click host
22 - * URLs, path helpers), wires activation/deactivation hooks, schedules a daily
23 - * log cleanup cron event, loads the core plugin class plus the Elementor
24 - * integration, conditionally loads the hello-wpstream theme
25 - * framework, registers the custom broadcaster-page rewrite endpoint, and finally
26 - * instantiates and runs the Wpstream class.
27 - *
28 - * @package Wpstream
29 - */
30 -
31 13 // If this file is called directly, abort.
32 -// WPINC is defined by WordPress core; its absence means direct access.
33 14 if ( ! defined( 'WPINC' ) ) {
34 15 die;
35 16 }
36 -// Current plugin version (kept in sync with the header "Version" field above).
37 -define('WPSTREAM_PLUGIN_VERSION', '4.14.1');
38 -// Base host for WpStream account/club links.
17 +define('WPSTREAM_PLUGIN_VERSION', '4.8');
39 18 define('WPSTREAM_CLUBLINK', 'wpstream.net');
40 -// Scheme used when building club links.
41 19 define('WPSTREAM_CLUBLINKSSL', 'https');
42 -// URL to the site's plugins directory.
43 20 define('WPSTREAM_PLUGIN_URL', plugins_url() );
44 -// URL to this plugin's own directory.
45 21 define('WPSTREAM_PLUGIN_DIR_URL', plugin_dir_url(__FILE__) );
46 -// Filesystem path to this plugin's directory.
47 22 define('WPSTREAM_PLUGIN_PATH', plugin_dir_path(__FILE__) );
48 -// Plugin basename (folder/file) used for hook identification.
49 23 define('WPSTREAM_PLUGIN_BASE', plugin_basename(__FILE__) );
50 -// Remote WpStream API endpoint; guarded so it can be overridden before load.
51 -if( !defined('WPSTREAM_API' ) ) {
52 - // Default API host.
53 - define('WPSTREAM_API', 'https://baker.wpstream.net');
54 -}
55 -// Legacy REST API host (server-id lookups); guarded so it can be overridden.
56 -if( !defined('WPSTREAM_REST_API' ) ) {
57 - // Default legacy REST host.
58 - define('WPSTREAM_REST_API', 'https://rest-baker.wpstream.net');
59 -}
60 -// Telemetry/click-tracking host; guarded so it can be overridden.
61 -if ( !defined( 'WPSTREAM_CLICK' ) ) {
62 - // Default click-tracking host.
63 - define( 'WPSTREAM_CLICK', 'https://click.wpstream.net' );
64 -}
65 -// Player host; guarded so it can be overridden.
66 -if ( !defined( 'WPSTREAM_PLAYER') ) {
67 - // Default player host.
68 - define ( 'WPSTREAM_PLAYER', 'https://player.wpstream.net' );
69 -}
70 -// Prefix for live player URLs; guarded so it can be overridden.
71 -if ( !defined( 'LIVE_PLAYER_URL_PREFIX' ) ) {
72 - // Default live player URL prefix.
73 - define('LIVE_PLAYER_URL_PREFIX', 'https://player.wpstream.net/player/live');
74 -}
24 +define('WPSTREAM_API', 'https://baker.wpstream.net');
75 25
76 -
77 -// Default network timeout (seconds) for remote API requests.
78 26 define('WPSTREAM_TIMEOUT_CONST', 20); // in seconds
79 27
80 -// Register the classmap autoloader before anything references a plugin class,
81 -// so activation hooks, cron callbacks, and the bootstrap below all resolve.
82 -require_once plugin_dir_path( __FILE__ ) . 'includes/class-wpstream-autoloader.php';
83 -Wpstream_Autoloader::register();
84 -
85 -/**
86 - * Declare WooCommerce High-Performance Order Storage (HPOS) compatibility.
87 - *
88 - * All order access in the plugin goes through wc_get_orders() /
89 - * wc_customer_bought_product(), which are HPOS-safe, so the plugin can be
90 - * declared compatible with custom order tables. WooCommerce requires this
91 - * declaration to run inside the before_woocommerce_init hook.
92 - *
93 - * @return void
94 - */
95 -function wpstream_declare_hpos_compatibility() {
96 - // Guard: FeaturesUtil only exists on WooCommerce 6.9+.
97 - if ( class_exists( \Automattic\WooCommerce\Utilities\FeaturesUtil::class ) ) {
98 - \Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( 'custom_order_tables', __FILE__, true );
99 - }
100 -}
101 -// WooCommerce fires this hook early on init; the declaration must happen there.
102 -add_action( 'before_woocommerce_init', 'wpstream_declare_hpos_compatibility' );
103 -
104 -/**
105 - * Cron callback that purges expired WpStream log entries.
106 - *
107 - * @return void
108 - */
109 28 function wpstream_cleanup_logs_handler() {
110 - // Instantiate the logger.
111 29 $logger = new WpStream_Logger();
112 - // Delete log entries older than the retention window.
113 30 $logger->clear_old_logs();
114 31 }
115 -// Run the cleanup handler whenever the scheduled 'wpstream_log_cleanup' event fires.
116 32 add_action('wpstream_log_cleanup', 'wpstream_cleanup_logs_handler');
117 33
118 34 /**
119 35 * The code that runs during plugin activation.
@@ -119,16 +35,12 @@
119 35 * The code that runs during plugin activation.
120 36 * This action is documented in includes/class-wpstream-activator.php
121 37 */
122 38 function activate_wpstream() {
123 - // Load the activator class on demand.
124 39 require_once plugin_dir_path( __FILE__ ) . 'includes/class-wpstream-activator.php';
125 - // Run the activation routine (creates DB tables, options, etc.).
126 40 Wpstream_Activator::activate();
127 41
128 - // Schedule the daily log-cleanup cron event if it isn't already scheduled.
129 42 if( !wp_next_scheduled( 'wpstream_log_cleanup' ) ) {
130 - // Register a daily recurring event starting now.
131 43 wp_schedule_event( time(), 'daily', 'wpstream_log_cleanup' );
132 44 }
133 45 }
134 46
@@ -136,114 +48,24 @@
136 48 * The code that runs during plugin deactivation.
137 49 * This action is documented in includes/class-wpstream-deactivator.php
138 50 */
139 51 function deactivate_wpstream() {
140 - // Load the deactivator class on demand.
141 52 require_once plugin_dir_path( __FILE__ ) . 'includes/class-wpstream-deactivator.php';
142 - // Run the deactivation routine.
143 53 Wpstream_Deactivator::deactivate();
144 54
145 - // Remove the scheduled daily log-cleanup cron event.
146 55 wp_clear_scheduled_hook( 'wpstream_log_cleanup' );
147 56 }
148 57
149 -// Register the activation/deactivation callbacks with WordPress.
150 58 register_activation_hook( __FILE__, 'activate_wpstream' );
151 59 register_deactivation_hook( __FILE__, 'deactivate_wpstream' );
152 60
153 61 /**
154 - * One-time cleanup of leftovers from the removed streamify HLS proxy.
155 - *
156 - * Older plugin versions shipped a /wpstreamify/ proxy that scheduled a
157 - * recurring cron event, registered a rewrite rule, and kept a cache directory
158 - * under uploads. Sites upgrading past its removal still carry all three, so
159 - * this clears them once and records a marker option so later loads skip it.
160 - *
161 - * @return void
162 - */
163 -function wpstream_cleanup_streamify_leftovers() {
164 - // Already cleaned on this site — nothing to do.
165 - if ( get_option( 'wpstream_streamify_removed' ) ) {
166 - return;
167 - }
168 -
169 - // Remove the recurring proxy-cache cleanup event the old code scheduled.
170 - wp_clear_scheduled_hook( 'wpstreamify_cleanup_event' );
171 -
172 - // Regenerate the saved rewrite rules so the stale /wpstreamify/ route
173 - // (whose query var no longer exists) drops out of them.
174 - flush_rewrite_rules();
175 -
176 - // Delete the orphaned proxy cache directory and its segment files.
177 - $wpstream_streamify_cache_dir = WP_CONTENT_DIR . '/uploads/wpstreamify_cache/';
178 - if ( is_dir( $wpstream_streamify_cache_dir ) ) {
179 - $wpstream_streamify_files = glob( $wpstream_streamify_cache_dir . '*' );
180 - foreach ( is_array( $wpstream_streamify_files ) ? $wpstream_streamify_files : array() as $wpstream_streamify_file ) {
181 - if ( is_file( $wpstream_streamify_file ) ) {
182 - unlink( $wpstream_streamify_file );
183 - }
184 - }
185 - rmdir( $wpstream_streamify_cache_dir );
186 - }
187 -
188 - // Mark the cleanup done; autoloaded because it is checked on every load.
189 - update_option( 'wpstream_streamify_removed', 1 );
190 -}
191 -// Run late on init so every remaining rewrite registration precedes the flush.
192 -add_action( 'init', 'wpstream_cleanup_streamify_leftovers', 99 );
193 -
194 -/**
195 - * One-time rename of the VOD list Elementor widget key in stored page data.
196 - *
197 - * Older plugin versions registered the widget under 'class Wpstream_Media_List_Vod'
198 - * (a stray "class " prefix left in get_name()). The name is now the clean
199 - * 'Wpstream_Media_List_Vod', so any Elementor page saved with the old key would
200 - * render the widget as "missing". This rewrites the stored widgetType in every
201 - * _elementor_data row (pages and revisions alike), clears Elementor's generated
202 - * CSS so the wrapper class regenerates, and records a marker option so later
203 - * loads skip it.
204 - *
205 - * @return void
206 - */
207 -function wpstream_fix_vod_widget_name() {
208 - // Already migrated on this site — nothing to do.
209 - if ( get_option( 'wpstream_vod_widget_name_fixed' ) ) {
210 - return;
211 - }
212 -
213 - global $wpdb;
214 -
215 - // Rewrite the exact quoted JSON pair so user-authored content can never match.
216 - $wpdb->query(
217 - "UPDATE {$wpdb->postmeta}
218 - SET meta_value = REPLACE( meta_value,
219 - '\"widgetType\":\"class Wpstream_Media_List_Vod\"',
220 - '\"widgetType\":\"Wpstream_Media_List_Vod\"' )
221 - WHERE meta_key = '_elementor_data'
222 - AND meta_value LIKE '%class Wpstream_Media_List_Vod%'"
223 - );
224 -
225 - // Elementor caches per-post CSS containing the old wrapper class; regenerate it.
226 - if ( class_exists( '\\Elementor\\Plugin' ) ) {
227 - \Elementor\Plugin::instance()->files_manager->clear_cache();
228 - }
229 -
230 - // Mark the migration done; autoloaded because it is checked on every load.
231 - update_option( 'wpstream_vod_widget_name_fixed', 1 );
232 -}
233 -// Run on init so Elementor (loaded on plugins_loaded) is available for the cache clear.
234 -add_action( 'init', 'wpstream_fix_vod_widget_name', 99 );
235 -
236 -/**
237 62 * Wrapper function for wpstream_dashboard_save_channel_data to be called from theme
238 63 * This provides backward compatibility for the theme
239 64 */
240 65 function wpstream_dashboard_save_channel_data_plugin() {
241 - // Reach the global plugin instance created at the bottom of this file.
242 66 global $wpstream_plugin;
243 - // Only delegate if the plugin and its AJAX handler are available.
244 67 if (isset($wpstream_plugin) && isset($wpstream_plugin->wpstream_ajax)) {
245 - // Forward the call to the real AJAX save-channel handler.
246 68 $wpstream_plugin->wpstream_ajax->wpstream_dashboard_save_channel_data();
247 69 }
248 70 }
249 71
@@ -250,31 +72,17 @@
250 72 /**
251 73 * The core plugin class that is used to define internationalization,
252 74 * admin-specific hooks, and public-facing site hooks.
253 75 */
254 -// Load the core plugin class (defines i18n, admin, and public hooks).
255 76 require plugin_dir_path( __FILE__ ) . 'includes/class-wpstream.php';
256 -// Migrate legacy option, transient and user-meta names once per site.
257 -require plugin_dir_path( __FILE__ ) . 'includes/class-wpstream-storage-migration.php';
258 -// Elementor requirement gate + widget registrar (autoloaded; checks run on plugins_loaded).
259 -new Wpstream_Elementor_Widgets();
260 -// Load third-party integrations bootstrap.
77 +require plugin_dir_path( __FILE__ ) . 'wpstream-elementor.php';
78 +require plugin_dir_path( __FILE__ ) . 'streamify/streamify.php';
79 +
261 80 require plugin_dir_path( __FILE__ ) . 'integrations/integrations.php';
262 81
263 -/**
264 - * Load the bundled hello-wpstream theme framework files.
265 - *
266 - * Hooked to after_setup_theme so the theme's helper functions, post types,
267 - * WooCommerce glue, widgets, and (when Elementor is active) Elementor pieces are
268 - * available. Missing files are logged rather than fatal.
269 - *
270 - * @return void
271 - */
272 82 function wpstream_load_theme_functionality() {
273 - // Absolute path to the bundled hello-wpstream framework directory.
274 83 define ('WPSTREAM_FRAMEWORK_BASE', plugin_dir_path(__FILE__) . 'hello-wpstream' );
275 84
276 - // Framework files to load, relative to WPSTREAM_FRAMEWORK_BASE.
277 85 $core_files = array(
278 86 '/framework/metaboxes.php',
279 87 '/framework/query-functions.php',
280 88 '/framework/wpstream-video-functions.php',
@@ -294,42 +102,30 @@
294 102 '/framework/classes/class-wpstream_theme-social-login.php',
295 103 );
296 104
297 105 // Load core files
298 - // Include each framework file, or log it if the file is missing.
299 106 foreach ( $core_files as $file ) {
300 - // Build the absolute path to this framework file.
301 107 $file_path = WPSTREAM_FRAMEWORK_BASE . $file;
302 - // Include it if present; otherwise record the missing file.
303 108 if ( file_exists( $file_path ) ) {
304 - // File exists: load it once.
305 109 require_once $file_path;
306 110 } else {
307 - // File missing: log an error but keep loading the rest.
308 111 error_log( 'Missing required file: ' . $file_path );
309 112 }
310 113 }
311 114
312 115 // Load Elementor integration if the plugin is active
313 - // ELEMENTOR_VERSION is only defined when Elementor is loaded.
314 116 if ( defined( 'ELEMENTOR_VERSION' ) ) {
315 117
316 - // Additional framework files needed only for the Elementor integration.
317 118 $elementor_files = array(
318 119 '/elementor/functions/blog_functions.php',
319 120 '/elementor/wpstream-elementor.php'
320 121 );
321 122
322 - // Include each Elementor file, or log it if missing.
323 123 foreach ( $elementor_files as $file ) {
324 - // Build the absolute path to this Elementor file.
325 124 $file_path = WPSTREAM_FRAMEWORK_BASE . $file;
326 - // Include it if present; otherwise record the missing file.
327 125 if ( file_exists( $file_path ) ) {
328 - // File exists: load it once.
329 126 require_once $file_path;
330 127 } else {
331 - // File missing: log an error but keep loading the rest.
332 128 error_log( 'Missing required file: ' . $file_path );
333 129 }
334 130 }
335 131 }
@@ -334,9 +130,8 @@
334 130 }
335 131 }
336 132 }
337 133
338 -// Load the theme framework after the active theme is set up.
339 134 add_action( 'after_setup_theme', 'wpstream_load_theme_functionality' );
340 135
341 136 /**
342 137 * Load js for players
@@ -342,92 +137,15 @@
342 137 * Load js for players
343 138 *
344 139 * @return void
345 140 */
346 -// Guard the definition so the theme can define its own version without collision.
347 -if ( ! function_exists( 'wpstream_enqueue_player_assets' ) ) {
348 - /**
349 - * Enqueue the full player stack (scripts + styles) at a player render site.
350 - *
351 - * Every handle is registered (not enqueued) on wp_enqueue_scripts, so nothing
352 - * loads on pages without a player; render sites call this the moment player
353 - * markup is emitted. Scripts print in the footer; the two stylesheets print
354 - * late as well, which is fine because the player element is built by JS.
355 - * videojs-logo / quality-selector / quality-levels arrive as dependencies
356 - * of wpstream-player.
357 - *
358 - * @return void
359 - */
360 - function wpstream_enqueue_player_assets() {
361 - // Video.js core.
362 - wp_enqueue_script( 'video.min' );
363 - // WpStream player wrapper script (drags logo/quality deps with it).
364 - wp_enqueue_script( 'wpstream-player' );
365 - // Base Video.js CSS + the WpStream player skin.
366 - wp_enqueue_style( 'video-js.min' );
367 - wp_enqueue_style( 'videojs-wpstream-player' );
368 - }
369 -}
370 -
371 -if ( ! function_exists( 'wpstream_get_product_type_name' ) ) {
372 - /**
373 - * Safely read a product's first product_type term name.
374 - *
375 - * wp_get_post_terms() returns a WP_Error when the taxonomy is unavailable
376 - * and an empty array when the product carries no term; naive
377 - * $term_list[0]->name reads crash on both under PHP 8. Callers that need the
378 - * display label use this accessor; branching logic uses the slug accessor below.
379 - *
380 - * @param int $product_id Product/post id.
381 - * @return string The first term name, or '' when none can be read.
382 - */
383 - function wpstream_get_product_type_name( $product_id ) {
384 - $term_list = wp_get_post_terms( intval( $product_id ), 'product_type' );
385 -
386 - // WP_Error (missing taxonomy) or no assigned term: report "no type".
387 - if ( is_wp_error( $term_list ) || empty( $term_list[0]->name ) ) {
388 - return '';
389 - }
390 -
391 - return $term_list[0]->name;
392 - }
393 -}
394 -
395 -if ( ! function_exists( 'wpstream_get_product_type_slug' ) ) {
396 - /**
397 - * Return the stable WooCommerce product-type identifier for a post.
398 - *
399 - * Product-type names are editable display labels, while the slug is the
400 - * identifier used by WooCommerce and WpStream branching logic.
401 - *
402 - * @param int $product_id Product/post id.
403 - * @return string The first term slug, or '' when none can be read.
404 - */
405 - function wpstream_get_product_type_slug( $product_id ) {
406 - $term_list = wp_get_post_terms( intval( $product_id ), 'product_type' );
407 -
408 - if ( is_wp_error( $term_list ) || empty( $term_list[0]->slug ) ) {
409 - return '';
410 - }
411 -
412 - return $term_list[0]->slug;
413 - }
414 -}
415 -
416 141 if ( ! function_exists( 'wpstream_load_player_js_on_demand' ) ) {
417 - /**
418 - * Enqueue player scripts only when unit cards are configured to use video.
419 - *
420 - * @return void
421 - */
422 142 function wpstream_load_player_js_on_demand()
423 143 {
424 - // Read the customizer setting that toggles video previews on unit cards.
425 144 $wpstream_unit_card_use_video = get_theme_mod('wpstream_unit_card_use_video');
426 - // Only enqueue the player assets when that setting is enabled.
427 145 if ($wpstream_unit_card_use_video) {
428 - // Full player stack (scripts + styles).
429 - wpstream_enqueue_player_assets();
146 + wp_enqueue_script('video.min');
147 + wp_enqueue_script('wpstream-player');
430 148 }
431 149
432 150 }
433 151 }
@@ -441,82 +159,72 @@
441 159 *
442 160 * @since 3.0.1
443 161 */
444 162
445 -// Expose the plugin instance globally so themes/helpers can reach it.
446 163 global $wpstream_plugin;
447 -// Build the core plugin object.
448 164 $wpstream_plugin = new Wpstream();
449 -// Register all of the plugin's hooks and start it running.
450 165 $wpstream_plugin->run();
451 166
452 -// After any core/plugin/theme update completes, run our upgrade cleanup.
453 -add_action( 'upgrader_process_complete', 'wpstream_my_upgrade_function',10, 2);
167 +add_action( 'upgrader_process_complete', 'wpstream_my_upgrate_function',10, 2);
454 168
455 -/**
456 - * Clear cached API token data after this plugin is updated.
457 - *
458 - * @param WP_Upgrader $upgrader_object The upgrader instance (unused).
459 - * @param array $options Details about what was upgraded.
460 - * @return void
461 - */
462 -function wpstream_my_upgrade_function( $upgrader_object, $options ) {
169 +function wpstream_my_upgrate_function( $upgrader_object, $options ) {
463 170
464 -
465 - // This plugin's basename, used to detect if it was among the updated plugins.
171 +
466 172 $current_plugin_path_name = plugin_basename( __FILE__ );
467 -
468 - // Only act on plugin update operations.
173 +
469 174 if ($options['action'] == 'update' && $options['type'] == 'plugin' ) {
470 - // Guard against a missing/non-array options payload.
471 175 if(is_array($options)):
472 - // Inspect every plugin that was updated in this batch.
473 176 foreach($options['plugins'] as $each_plugin) {
474 - // Match against this plugin.
475 177 if ($each_plugin==$current_plugin_path_name) {
476 - // Drop the cached API token transient.
477 178 delete_transient('wpstream_token_api');
478 - // Reset the stored token expiry timestamp.
479 - update_option('wpstream_token_expire',0);
480 - // Blank out the stored current token.
481 - update_option('wpstream_current_token',' ');
179 + update_option('wp_estate_token_expire',0);
180 + update_option('wp_estate_curent_token',' ');
482 181
483 182 }
484 183 }
485 184 endif;
486 185 }
186 +
187 +
188 +}
487 189
488 190
489 -}
490 191
192 +add_action('wp_head', 'wpstream_add_custom_meta_to_header');
491 193
194 +function wpstream_add_custom_meta_to_header(){
195 + global $post;
492 196
493 -// Front-end SEO metadata (Open Graph, Twitter cards, structured data). The file
494 -// registers its own wp_head hook when loaded — see Wpstream_Seo::init().
495 -require plugin_dir_path( __FILE__ ) . 'includes/class-wpstream-seo.php';
496 197
198 + if ( is_singular('product') || is_singular('wpstream_product') || is_singular('wpstream_product_vod') ){
199 + $image_id = get_post_thumbnail_id();
200 + $share_img = wp_get_attachment_image_src( $image_id, 'full');
201 + $the_post = get_post($post->ID); ?>
497 202
203 + <meta property='og:title' content="<?php print esc_html(get_the_title($post->ID)); ?>"/>
204 + <?php if(isset($share_img[0])){ ?>
205 + <meta property="og:image" content="<?php print esc_url($share_img[0]); ?>"/>
206 + <meta property="og:image:secure_url" content="<?php print esc_url($share_img[0]); ?>" />
207 + <?php }?>
208 +
209 + <meta property="og:description" content=" <?php print wp_strip_all_tags( $the_post->post_content);?>" />
210 + <?php }
211 +
212 +
213 +}
214 +
215 +
498 216 /*
499 217 *
500 218 * Check integrations
501 219 *
502 220 */
503 -// Only wire the One Click Demo Import (OCDI) hooks when the hello-wpstream theme is active.
504 -if ( get_template() === 'hello-wpstream' ) {
505 - // Load the theme-import helper functions referenced by the filters below.
506 - require_once plugin_dir_path( __FILE__ ) . 'integrations/hello-wpstream/theme-import.php';
507 - // Register the set of demo import files offered by OCDI.
508 - add_filter( 'pt-ocdi/import_files', 'wpstream_ocdi_import_files' );
509 - // Run post-import setup (menus, pages, options) after a demo import.
510 - add_action( 'pt-ocdi/after_import', 'wpstream_ocdi_after_import_setup' );
511 - // Customize the intro text shown on the OCDI import screen.
512 - add_filter( 'pt-ocdi/plugin_intro_text', 'wpstream_ocdi_plugin_intro_text' );
513 - // Send telemetry when a demo content import is attempted.
514 - add_action( 'ocdi/before_content_import', 'wpstream_track_ocdi_import_attempt', 10, 1 );
515 -}
221 +require_once plugin_dir_path(__FILE__) . 'integrations/hello-wpstream/theme-import.php';
222 +add_filter('pt-ocdi/import_files', 'ocdi_import_files');
223 +add_action('pt-ocdi/after_import', 'ocdi_after_import_setup');
224 +add_filter('pt-ocdi/plugin_intro_text', 'ocdi_plugin_intro_text');
516 225
517 226
518 -// Once all plugins are loaded, evaluate which integrations should run.
519 227 add_action( 'plugins_loaded', 'wpstream_check_integrations' );
520 228
521 229
522 230 /*
@@ -524,10 +232,14 @@
524 232 * Redirect on plugin activation
525 233 *
526 234 */
527 235
528 -// Queue activation intent, then consume it safely on the next admin request.
529 -require_once plugin_dir_path( __FILE__ ) . 'includes/class-wpstream-activation-redirect.php';
236 +function wpstream_activation_redirect( $plugin ) {
237 + if( $plugin == plugin_basename( __FILE__ ) ) {
238 + exit( wp_redirect( admin_url( 'admin.php?page=wpstream_onboard' ) ) );
239 + }
240 +}
241 +add_action( 'activated_plugin', 'wpstream_activation_redirect' );
530 242
531 243
532 244
533 245 /*
@@ -534,30 +246,24 @@
534 246 *
535 247 * remove the style selectWoo for the theme
536 248 *
537 249 */
538 -// The existence of wpstream_get_author_id signals the wpstream theme is active.
539 250 if ( function_exists( 'wpstream_get_author_id' ) ) {
540 251 // only if wpstream-theme is activated
541 -
252 +
542 253 remove_filter( 'pre_user_description', 'wp_filter_kses' ); // Removes the filter that applies KSES filtering for user descriptions
543 254 remove_filter( 'term_description', 'wp_kses_data' ); // Removes the filter that applies KSES data filtering for term descriptions
544 255
545 - // Define the Select2 dequeue callback only once (guard against redefinition).
546 256 if ( ! function_exists( 'wsis_dequeue_stylesandscripts_select2' ) ) {
547 - // Run the dequeue late (priority 100) so it overrides earlier enqueues.
548 257 add_action( 'wp_enqueue_scripts', 'wsis_dequeue_stylesandscripts_select2', 100 );
549 258 /**
550 259 * Remove CSS and/or JS for Select2 used by WooCommerce
551 260 */
552 261 function wsis_dequeue_stylesandscripts_select2() {
553 - // Only relevant when WooCommerce is present.
554 262 if ( class_exists( 'woocommerce' ) ) {
555 - // Remove WooCommerce's selectWoo stylesheet.
556 263 wp_dequeue_style( 'selectWoo' );
557 264 wp_deregister_style( 'selectWoo' );
558 265
559 - // Remove WooCommerce's selectWoo script.
560 266 wp_dequeue_script( 'selectWoo' );
561 267 wp_deregister_script( 'selectWoo' );
562 268 }
563 269 }
@@ -567,29 +273,20 @@
567 273 /**
568 274 * Register broadcaster page endpoint
569 275 */
570 276 function wpstream_register_broadcaster_endpoint() {
571 - // Register the query var that flags a broadcaster page request (0 or 1).
572 277 add_rewrite_tag('%broadcaster_page%', '([0-1]{1})');
573 - // Register the numeric channel-id query var.
574 278 add_rewrite_tag('%channel_id%', '([0-9]+)');
575 279
576 - // Current stored rewrite rules, used to detect if our rule already exists.
577 280 $rewrite_rules = get_option('rewrite_rules');
578 - // Pretty-URL pattern: /broadcaster-page/{id}/
579 281 $rule_pattern = 'broadcaster-page/([0-9]+)/?$';
580 - // Internal target that maps the captured id onto our query vars.
581 282 $rule_target = 'index.php?broadcaster_page=1&channel_id=$matches[1]';
582 283
583 - // Add the rewrite rule at the top so it takes precedence.
584 284 add_rewrite_rule($rule_pattern, $rule_target, 'top');
585 - // Flush rules only when they are missing our pattern (avoids flushing every request).
586 - if ( !is_array($rewrite_rules) || !key_exists( $rule_pattern, $rewrite_rules ) ) {
587 - // Rebuild the rewrite rules so the new endpoint works immediately.
285 + if ( !key_exists( $rule_pattern, $rewrite_rules ) ) {
588 286 flush_rewrite_rules();
589 287 }
590 288 }
591 -// Register the broadcaster endpoint on every init.
592 289 add_action('init', 'wpstream_register_broadcaster_endpoint');
593 290
594 291 /**
595 292 * Load broadcaster template when the custom endpoint is accessed
@@ -594,17 +291,14 @@
594 291 /**
595 292 * Load broadcaster template when the custom endpoint is accessed
596 293 */
597 294 function wpstream_load_broadcaster_template($template) {
598 - // When the broadcaster_page query var is set, serve our custom template.
599 295 if (get_query_var('broadcaster_page') == 1) {
600 296 // Return the path to our broadcaster template
601 297 return plugin_dir_path(__FILE__) . 'templates/broadcaster-template.php';
602 298 }
603 - // Otherwise fall back to the theme's normal template.
604 299 return $template;
605 300 }
606 -// Intercept template selection to swap in the broadcaster template when needed.
607 301 add_filter('template_include', 'wpstream_load_broadcaster_template');
608 302
609 303 /**
610 304 * Flush rewrite rules on plugin activation to ensure our endpoint works
@@ -609,11 +303,8 @@
609 303 /**
610 304 * Flush rewrite rules on plugin activation to ensure our endpoint works
611 305 */
612 306 function wpstream_flush_rewrite_rules() {
613 - // Register the endpoint's rewrite tags/rules first.
614 307 wpstream_register_broadcaster_endpoint();
615 - // Then flush so the new rules are active immediately after activation.
616 308 flush_rewrite_rules();
617 309 }
618 -// Ensure rewrite rules are flushed when the plugin is activated.
619 310 register_activation_hook(__FILE__, 'wpstream_flush_rewrite_rules');