Edit file File name : Init.php Content :<?php namespace Automattic\WooCommerce\Admin\Features\MarketingRecommendations; use Automattic\WooCommerce\Admin\RemoteSpecs\RemoteSpecsEngine; defined( 'ABSPATH' ) || exit; /** * Marketing Recommendations engine. * This goes through the specs and gets marketing recommendations. */ class Init extends RemoteSpecsEngine { /** * Slug of the category specifying marketing extensions on the WooCommerce.com store. * * @var string */ const MARKETING_EXTENSION_CATEGORY_SLUG = 'marketing'; /** * Slug of the subcategory specifying marketing channels on the WooCommerce.com store. * * @var string */ const MARKETING_CHANNEL_SUBCATEGORY_SLUG = 'sales-channels'; /** * Constructor. */ public function __construct() { add_action( 'woocommerce_updated', array( __CLASS__, 'delete_specs_transient' ) ); } /** * Delete the specs transient. */ public static function delete_specs_transient() { MarketingRecommendationsDataSourcePoller::get_instance()->delete_specs_transient(); } /** * Get specs or fetch remotely if they don't exist. */ public static function get_specs() { if ( 'no' === get_option( 'woocommerce_show_marketplace_suggestions', 'yes' ) ) { return DefaultMarketingRecommendations::get_all(); } $specs = MarketingRecommendationsDataSourcePoller::get_instance()->get_specs_from_data_sources(); // Fetch specs if they don't yet exist. if ( ! is_array( $specs ) || 0 === count( $specs ) ) { return DefaultMarketingRecommendations::get_all(); } return $specs; } /** * Process specs. * * @param array|null $specs Marketing recommendations spec array. * @return array */ protected static function evaluate_specs( array $specs = null ) { $suggestions = array(); $errors = array(); foreach ( $specs as $spec ) { try { $suggestions[] = self::object_to_array( $spec ); } catch ( \Throwable $e ) { $errors[] = $e; } } return array( 'suggestions' => $suggestions, 'errors' => $errors, ); } /** * Load recommended plugins from WooCommerce.com * * @return array */ public static function get_recommended_plugins(): array { $specs = self::get_specs(); $results = self::evaluate_specs( $specs ); $specs_to_return = $results['suggestions']; $specs_to_save = null; if ( empty( $specs_to_return ) ) { // When suggestions is empty, replace it with defaults and save for 3 hours. $specs_to_save = DefaultMarketingRecommendations::get_all(); $specs_to_return = self::evaluate_specs( $specs_to_save )['suggestions']; } elseif ( count( $results['errors'] ) > 0 ) { // When suggestions is not empty but has errors, save it for 3 hours. $specs_to_save = $specs; } if ( $specs_to_save ) { MarketingRecommendationsDataSourcePoller::get_instance()->set_specs_transient( $specs_to_save, 3 * HOUR_IN_SECONDS ); } $errors = $results['errors']; if ( ! empty( $errors ) ) { self::log_errors( $errors ); } return $specs_to_return; } /** * Return only the recommended marketing channels from WooCommerce.com. * * @return array */ public static function get_recommended_marketing_channels(): array { return array_filter( self::get_recommended_plugins(), function ( array $plugin_data ) { return self::is_marketing_channel_plugin( $plugin_data ); } ); } /** * Return all recommended marketing extensions EXCEPT the marketing channels from WooCommerce.com. * * @return array */ public static function get_recommended_marketing_extensions_excluding_channels(): array { return array_filter( self::get_recommended_plugins(), function ( array $plugin_data ) { return self::is_marketing_plugin( $plugin_data ) && ! self::is_marketing_channel_plugin( $plugin_data ); } ); } /** * Returns whether a plugin is a marketing extension. * * @param array $plugin_data The plugin properties returned by the API. * * @return bool */ protected static function is_marketing_plugin( array $plugin_data ): bool { $categories = $plugin_data['categories'] ?? array(); return in_array( self::MARKETING_EXTENSION_CATEGORY_SLUG, $categories, true ); } /** * Returns whether a plugin is a marketing channel. * * @param array $plugin_data The plugin properties returned by the API. * * @return bool */ protected static function is_marketing_channel_plugin( array $plugin_data ): bool { if ( ! self::is_marketing_plugin( $plugin_data ) ) { return false; } $subcategories = $plugin_data['subcategories'] ?? array(); foreach ( $subcategories as $subcategory ) { if ( isset( $subcategory['slug'] ) && self::MARKETING_CHANNEL_SUBCATEGORY_SLUG === $subcategory['slug'] ) { return true; } } return false; } /** * Convert an object to an array. * This is used to convert the specs to an array so that they can be returned by the API. * * @param mixed $obj Object to convert. * @param array &$visited Reference to an array keeping track of all seen objects to detect circular references. * @return array */ public static function object_to_array( $obj, &$visited = array() ) { if ( is_object( $obj ) ) { if ( in_array( $obj, $visited, true ) ) { // Circular reference detected. return null; } $visited[] = $obj; $obj = (array) $obj; } if ( is_array( $obj ) ) { $new = array(); foreach ( $obj as $key => $val ) { $new[ $key ] = self::object_to_array( $val, $visited ); } } else { $new = $obj; } return $new; } } Save