'; esc_html_e( 'Shoppable Video for WooCommerce requires WooCommerce to be installed and active.', 'addonn-shoppable-video' ); echo '

'; } ); return false; } return true; } /** * Load plugin files. */ function addoshvi_load_includes() { require_once ADDOSHVI_PLUGIN_DIR . 'includes/class-svp-post-type.php'; require_once ADDOSHVI_PLUGIN_DIR . 'includes/class-svp-admin.php'; require_once ADDOSHVI_PLUGIN_DIR . 'includes/class-svp-settings.php'; require_once ADDOSHVI_PLUGIN_DIR . 'includes/class-svp-shortcode.php'; require_once ADDOSHVI_PLUGIN_DIR . 'includes/class-svp-ajax.php'; require_once ADDOSHVI_PLUGIN_DIR . 'includes/class-svp-analytics.php'; require_once ADDOSHVI_PLUGIN_DIR . 'includes/class-svp-whatsapp.php'; require_once ADDOSHVI_PLUGIN_DIR . 'includes/class-svp-elementor.php'; require_once ADDOSHVI_PLUGIN_DIR . 'includes/class-svp-gutenberg.php'; require_once ADDOSHVI_PLUGIN_DIR . 'includes/class-svp-frontend-editor.php'; require_once ADDOSHVI_PLUGIN_DIR . 'includes/elementor/class-svp-elementor-sync.php'; } /** * Init plugin. */ function addoshvi_init_plugin() { if ( ! addoshvi_check_woocommerce_active() ) { return; } addoshvi_load_includes(); ADDOSHVI_Post_Type::instance(); ADDOSHVI_Admin::instance(); ADDOSHVI_Settings::instance(); ADDOSHVI_Shortcode::instance(); ADDOSHVI_Ajax::instance(); ADDOSHVI_Analytics::instance(); ADDOSHVI_Elementor::instance(); ADDOSHVI_Gutenberg::instance(); ADDOSHVI_Frontend_Editor::instance(); ADDOSHVI_Elementor_Sync::instance(); } add_action( 'plugins_loaded', 'addoshvi_init_plugin' ); /** * Activation: register CPT then flush rewrite rules. */ function addoshvi_activate_plugin() { require_once ADDOSHVI_PLUGIN_DIR . 'includes/class-svp-post-type.php'; ADDOSHVI_Post_Type::register_post_type(); flush_rewrite_rules(); } register_activation_hook( __FILE__, 'addoshvi_activate_plugin' ); function addoshvi_deactivate_plugin() { flush_rewrite_rules(); } register_deactivation_hook( __FILE__, 'addoshvi_deactivate_plugin' ); /** * Frontend + admin asset enqueue. */ function addoshvi_enqueue_frontend_assets() { /* Enqueued unconditionally on every frontend request (not just * registered + lazily enqueued inside the shortcode/widget render()). * Reason: ADDOSHVI_Shortcode::render() can fire from very different * rendering contexts — a normal shortcode/block in the_content, * an Elementor widget render, or Elementor's editor-canvas iframe * pipeline — and some of those render content after wp_head() has * already printed enqueued styles. A style enqueued that late never * makes it onto the page. Enqueuing here, on wp_enqueue_scripts * (which always fires before wp_head), guarantees the CSS/JS is * present regardless of which context renders the widget. */ wp_enqueue_style( 'addoshvi-frontend', ADDOSHVI_PLUGIN_URL . 'assets/css/frontend.css', array(), ADDOSHVI_VERSION ); wp_enqueue_script( 'addoshvi-frontend', ADDOSHVI_PLUGIN_URL . 'assets/js/frontend.js', array( 'jquery' ), ADDOSHVI_VERSION, true ); wp_localize_script( 'addoshvi-frontend', 'ADDOSHVI_Data', array( 'ajax_url' => admin_url( 'admin-ajax.php' ), 'nonce' => wp_create_nonce( 'addoshvi_frontend_nonce' ), 'whatsapp_number' => get_option( 'addoshvi_default_whatsapp_number', '' ), 'whatsapp_message_template' => class_exists( 'ADDOSHVI_Whatsapp' ) ? ADDOSHVI_Whatsapp::get_message_template() : '', 'currency_symbol' => get_woocommerce_currency_symbol(), 'i18n' => array( 'add_to_cart' => __( 'Add to Cart', 'addonn-shoppable-video' ), 'added' => __( 'Added!', 'addonn-shoppable-video' ), 'view_cart' => __( 'View Cart', 'addonn-shoppable-video' ), 'order_whatsapp'=> __( 'Order on WhatsApp', 'addonn-shoppable-video' ), 'out_of_stock' => __( 'Out of stock', 'addonn-shoppable-video' ), ), ) ); // Front-end "Add Video" editor is disabled — not needed. Videos are // managed from wp-admin (Shoppable Videos → Add New) instead. } add_action( 'wp_enqueue_scripts', 'addoshvi_enqueue_frontend_assets' ); function addoshvi_enqueue_admin_assets( $hook ) { global $post_type; if ( ADDOSHVI_POST_TYPE !== $post_type && 'settings_page_addoshvi-settings' !== $hook ) { return; } wp_enqueue_style( 'addoshvi-admin', ADDOSHVI_PLUGIN_URL . 'assets/css/admin.css', array(), ADDOSHVI_VERSION ); wp_enqueue_media(); wp_enqueue_script( 'addoshvi-admin', ADDOSHVI_PLUGIN_URL . 'assets/js/admin.js', array( 'jquery' ), ADDOSHVI_VERSION, true ); wp_localize_script( 'addoshvi-admin', 'ADDOSHVI_Admin_Data', array( 'product_search_nonce' => wp_create_nonce( 'addoshvi_product_search' ), 'ajax_url' => admin_url( 'admin-ajax.php' ), ) ); } add_action( 'admin_enqueue_scripts', 'addoshvi_enqueue_admin_assets' ); /** * One-time migration: versions up to 1.5.11 stored everything under the * `svp_` / `_svp_` / `svp_video` prefix, which WordPress.org review flagged * as too short (3 characters; 4+ required to avoid collisions) — first for * the internal-only PHP/JS identifiers (fixed in 1.5.12: functions, * classes, constants, meta/option keys, nonces, AJAX actions, script * handles), then for the post type slug, shortcode tag, Elementor widget * name, and Gutenberg block name themselves (fixed in 1.5.13, after the * reviewer confirmed those need it too). * * This runs once and: * 1. Re-types any post still saved under the old `svp_video` post type to * the new `addoshvi_video` one, so it shows up in the admin list again * (the CPT is no longer registered under the old slug at all). * 2. Copies each such post's old `_svp_*` meta (video attachment, tagged * products, WhatsApp settings, view/cart counts, Elementor sync keys) * to the new `_addoshvi_*` keys. * 3. Copies the old `svp_default_whatsapp_number` / `svp_default_layout` * options to their new names. * * Nothing old is deleted — this only ever fills in a new key/value that's * still empty, so it's safe to run more than once if the "already done" * flag is ever cleared. * * Note: this does NOT rewrite `[svp_feed]` shortcodes already saved inside * post_content, or the `widgetType`/block name already saved inside * Elementor's `_elementor_data` or Gutenberg block comments on existing * pages — those still reference the old names and would need each * affected page re-saved (or a separate content-rewriting migration) to * pick up the new `addoshvi_feed` shortcode / `addoshvi/feed` block / * `addoshvi_shoppable_video` widget after upgrading from a pre-1.5.13 * install with already-published pages. */ function addoshvi_maybe_migrate_legacy_data() { if ( get_option( 'addoshvi_legacy_data_migrated' ) ) { return; } $legacy_options = array( 'svp_default_whatsapp_number' => 'addoshvi_default_whatsapp_number', 'svp_default_layout' => 'addoshvi_default_layout', ); foreach ( $legacy_options as $old_key => $new_key ) { $old_value = get_option( $old_key, false ); if ( false !== $old_value && false === get_option( $new_key, false ) ) { update_option( $new_key, $old_value ); } } $legacy_meta_map = array( '_svp_video_attachment_id' => '_addoshvi_video_attachment_id', '_svp_products' => '_addoshvi_products', '_svp_whatsapp_enabled' => '_addoshvi_whatsapp_enabled', '_svp_whatsapp_number' => '_addoshvi_whatsapp_number', '_svp_view_count' => '_addoshvi_view_count', '_svp_cart_count' => '_addoshvi_cart_count', '_svp_source_page_id' => '_addoshvi_source_page_id', '_svp_source_widget_id' => '_addoshvi_source_widget_id', '_svp_source_item_key' => '_addoshvi_source_item_key', ); // Old post type slug is hardcoded here (not a constant) — it's no // longer registered anywhere in the plugin as of 1.5.13, so this is // the only place it needs to appear, purely to find posts an earlier // version left behind under it. $video_ids = get_posts( array( 'post_type' => array( ADDOSHVI_POST_TYPE, 'svp_video' ), 'post_status' => 'any', 'posts_per_page' => -1, 'fields' => 'ids', ) ); foreach ( $video_ids as $video_id ) { if ( ADDOSHVI_POST_TYPE !== get_post_type( $video_id ) ) { wp_update_post( array( 'ID' => $video_id, 'post_type' => ADDOSHVI_POST_TYPE, ) ); } foreach ( $legacy_meta_map as $old_key => $new_key ) { if ( '' !== get_post_meta( $video_id, $new_key, true ) ) { continue; // Already has a value under the new key — nothing to migrate. } $old_value = get_post_meta( $video_id, $old_key, true ); if ( '' !== $old_value ) { update_post_meta( $video_id, $new_key, $old_value ); } } } update_option( 'addoshvi_legacy_data_migrated', 1 ); } add_action( 'admin_init', 'addoshvi_maybe_migrate_legacy_data' );