__( 'Fashion, apparel & accessories', 'woocommerce-admin' ), 'health-beauty' => __( 'Health & beauty', 'woocommerce-admin' ), 'art-music-photography' => __( 'Art, music, & photography', 'woocommerce-admin' ), 'electronics-computers' => __( 'Electronics & computers', 'woocommerce-admin' ), 'food-drink' => __( 'Food & drink', 'woocommerce-admin' ), 'home-furniture-garden' => __( 'Home, furniture & garden', 'woocommerce-admin' ), 'other' => __( 'Other', 'woocommerce-admin' ), ) ); } /** * Get a list of allowed product types for the onboarding wizard. * * @return array */ public static function get_allowed_product_types() { $product_types = self::append_product_data( array( 'physical' => array( 'label' => __( 'Physical products', 'woocommerce-admin' ), 'description' => __( 'Products you ship to customers.', 'woocommerce-admin' ), ), 'downloads' => array( 'label' => __( 'Downloads', 'woocommerce-admin' ), 'description' => __( 'Virtual products that customers download.', 'woocommerce-admin' ), ), 'subscriptions' => array( 'label' => __( 'Subscriptions', 'woocommerce-admin' ), 'product' => 'woocommerce-subscriptions', ), 'memberships' => array( 'label' => __( 'Memberships', 'woocommerce-admin' ), 'product' => 'woocommerce-memberships', ), 'composite' => array( 'label' => __( 'Composite Products', 'woocommerce-admin' ), 'product' => 'woocommerce-composite-products', ), 'bookings' => array( 'label' => __( 'Bookings', 'woocommerce-admin' ), 'product' => 'WooCommerce Bookings', ), ) ); return apply_filters( 'woocommerce_admin_onboarding_product_types', $product_types ); } /** * Get a list of themes for the onboarding wizard. * * @return array */ public static function get_themes() { $themes = get_transient( self::THEMES_TRANSIENT ); if ( false === $themes ) { $theme_data = wp_remote_get( 'https://woocommerce.com/wp-json/wccom-extensions/1.0/search?category=themes' ); $themes = array(); if ( ! is_wp_error( $theme_data ) ) { $theme_data = json_decode( $theme_data['body'] ); foreach ( $theme_data->products as $theme ) { $slug = sanitize_title( $theme->slug ); $themes[ $slug ] = (array) $theme; $themes[ $slug ]['is_installed'] = false; $themes[ $slug ]['has_woocommerce_support'] = true; } } $installed_themes = wp_get_themes(); $active_theme = get_option( 'stylesheet' ); foreach ( $installed_themes as $slug => $theme ) { $theme_data = self::get_theme_data( $theme ); if ( ! $theme_data['has_woocommerce_support'] && $active_theme !== $slug ) { continue; } $installed_themes = wp_get_themes(); $themes[ $slug ] = $theme_data; } $themes = array( $active_theme => $themes[ $active_theme ] ) + $themes; set_transient( self::THEMES_TRANSIENT, $themes, DAY_IN_SECONDS ); } $themes = apply_filters( 'woocommerce_admin_onboarding_themes', $themes ); return array_values( $themes ); } /** * Get theme data used in onboarding theme browser. * * @param WP_Theme $theme Theme to gather data from. * @return array */ public static function get_theme_data( $theme ) { return array( 'slug' => sanitize_title( $theme->stylesheet ), 'title' => $theme->get( 'Name' ), 'price' => '0.00', 'is_installed' => true, 'image' => $theme->get_screenshot(), 'has_woocommerce_support' => self::has_woocommerce_support( $theme ), ); } /** * Add theme data to response from themes controller. * * @param WP_REST_Response $response Rest response. * @return WP_REST_Response */ public static function add_uploaded_theme_data( $response ) { if ( ! isset( $response->data['theme'] ) ) { return $response; } $theme = wp_get_theme( $response->data['theme'] ); $response->data['theme_data'] = self::get_theme_data( $theme ); return $response; } /** * Check if theme has declared support for WooCommerce * * @param WP_Theme $theme Theme to check. * @return bool */ public static function has_woocommerce_support( $theme ) { $themes = array( $theme ); if ( $theme->get( 'Template' ) ) { $parent_theme = wp_get_theme( $theme->get( 'Template' ) ); $themes[] = $parent_theme; } foreach ( $themes as $theme ) { $directory = new RecursiveDirectoryIterator( $theme->theme_root . '/' . $theme->stylesheet ); $iterator = new RecursiveIteratorIterator( $directory ); $files = new RegexIterator( $iterator, '/^.+\.php$/i', RecursiveRegexIterator::GET_MATCH ); foreach ( $files as $file ) { $content = file_get_contents( $file[0] ); if ( preg_match( '/add_theme_support\(([^(]*)(\'|\")woocommerce(\'|\")([^(]*)/si', $content, $matches ) ) { return true; } } } return false; } /** * Append dynamic product data from API. * * @param array $product_types Array of product types. * @return array */ public static function append_product_data( $product_types ) { $woocommerce_products = get_transient( self::PRODUCT_DATA_TRANSIENT ); if ( false === $woocommerce_products ) { $woocommerce_products = wp_remote_get( 'https://woocommerce.com/wp-json/wccom-extensions/1.0/search?category=product-type' ); if ( is_wp_error( $woocommerce_products ) ) { return $product_types; } set_transient( self::PRODUCT_DATA_TRANSIENT, $woocommerce_products, DAY_IN_SECONDS ); } $product_data = json_decode( $woocommerce_products['body'] ); $products = array(); // Map product data by slug. foreach ( $product_data->products as $product_datum ) { $products[ $product_datum->slug ] = $product_datum; } // Loop over product types and append data. foreach ( $product_types as $key => $product_type ) { if ( isset( $product_type['product'] ) ) { /* translators: Amount of product per year (e.g. Bookings - $240.00 per year) */ $product_types[ $key ]['label'] .= sprintf( __( ' — %s per year', 'woocommerce-admin' ), html_entity_decode( $products[ $product_type['product'] ]->price ) ); $product_types[ $key ]['description'] = $products[ $product_type['product'] ]->excerpt; $product_types[ $key ]['more_url'] = $products[ $product_type['product'] ]->link; } } return $product_types; } /** * Delete the stored themes transient. */ public static function delete_themes_transient() { delete_transient( self::THEMES_TRANSIENT ); } /** * Add profiler items to component settings. * * @param array $settings Component settings. */ public function component_settings( $settings ) { $profile = get_option( 'wc_onboarding_profile', array() ); $settings['onboarding'] = array( 'industries' => self::get_allowed_industries(), 'profile' => $profile, ); // Only fetch if the onboarding wizard is incomplete. if ( $this->should_show_profiler() ) { $settings['onboarding']['productTypes'] = self::get_allowed_product_types(); $settings['onboarding']['themes'] = self::get_themes(); $settings['onboarding']['activeTheme'] = get_option( 'stylesheet' ); } return $settings; } /** * Let the app know that we will be showing the onboarding route, so wp-admin elements should be hidden while loading. * * @param bool $is_loading Indicates if the `woocommerce-admin-is-loading` should be appended or not. * @return bool */ public function is_loading( $is_loading ) { $show_profiler = $this->should_show_profiler(); if ( ! $show_profiler ) { return $is_loading; } return true; } } WC_Admin_Onboarding::get_instance();