is_from_partner( $product ) ) { return false; } if ( ! apply_filters( $product->get_slug() . '_load_dashboard_widget', true ) ) { return false; } return true; } /** * Registers the hooks. * * @param Product $product Product to load. * * @return Dashboard_Widget Module instance. */ public function load( $product ) { if ( apply_filters( 'themeisle_sdk_hide_dashboard_widget', false ) ) { return; } $this->product = $product; $this->dashboard_name = apply_filters( 'themeisle_sdk_dashboard_widget_name', 'WordPress Guides/Tutorials' ); $this->feeds = apply_filters( 'themeisle_sdk_dashboard_widget_feeds', [ 'https://themeisle.com/blog/feed', 'https://www.codeinwp.com/blog/feed', 'https://wpshout.com/feed', ] ); add_action( 'wp_dashboard_setup', array( &$this, 'add_widget' ) ); add_action( 'wp_network_dashboard_setup', array( &$this, 'add_widget' ) ); add_filter( 'themeisle_sdk_recommend_plugin_or_theme', array( &$this, 'recommend_plugin_or_theme' ) ); return $this; } /** * Add widget to the dashboard * * @return string|void */ public function add_widget() { global $wp_meta_boxes; if ( isset( $wp_meta_boxes['dashboard']['normal']['core']['themeisle'] ) ) { return; } wp_add_dashboard_widget( 'themeisle', $this->dashboard_name, [ $this, 'render_dashboard_widget', ] ); } /** * Render widget content */ public function render_dashboard_widget() { $this->setup_feeds(); if ( empty( $this->items ) || ! is_array( $this->items ) ) { return; } ?> product ); ?> $recommend['slug'], ], network_admin_url( 'theme-install.php' ) ); if ( 'plugin' === $type ) { $url = add_query_arg( array( 'tab' => 'plugin-information', 'plugin' => $recommend['slug'], ), network_admin_url( 'plugin-install.php' ) ); } ?> feeds; add_action( 'wp_feed_options', function ( $feed, $url ) use ( $sdk_feeds ) { if ( defined( 'TI_SDK_PHPUNIT' ) && true === TI_SDK_PHPUNIT ) { return; } if ( ! is_string( $url ) && in_array( $url, $sdk_feeds, true ) ) { $feed->force_feed( false ); return; } if ( is_array( $url ) ) { foreach ( $url as $feed_url ) { if ( in_array( $feed_url, $sdk_feeds, true ) ) { $feed->force_feed( false ); return; } } } }, PHP_INT_MAX, 2 ); // Load SimplePie Instance. $feed = fetch_feed( $sdk_feeds ); // TODO report error when is an error loading the feed. if ( is_wp_error( $feed ) ) { return; } $items = $feed->get_items( 0, 5 ); $items = is_array( $items ) ? $items : []; $items_normalized = []; foreach ( $items as $item ) { $items_normalized[] = array( 'title' => $item->get_title(), 'date' => $item->get_date( 'U' ), 'link' => $item->get_permalink(), ); } set_transient( 'themeisle_sdk_feed_items', $items_normalized, 48 * HOUR_IN_SECONDS ); } $this->items = $items_normalized; } /** * Either the current product is installed or not. * * @param array $val The current recommended product. * * @return bool Either we should exclude the plugin or not. */ public function remove_current_products( $val ) { if ( 'theme' === $val['type'] ) { $exist = wp_get_theme( $val['slug'] ); return ! $exist->exists(); } else { $all_plugins = array_keys( get_plugins() ); foreach ( $all_plugins as $slug ) { if ( strpos( $slug, $val['slug'] ) !== false ) { return false; } } return true; } } /** * Contact the API and fetch the recommended plugins/themes */ public function recommend_plugin_or_theme() { $products = $this->get_product_from_api(); if ( ! is_array( $products ) ) { $products = array(); } $products = array_filter( $products, array( $this, 'remove_current_products' ) ); $products = array_merge( $products ); if ( count( $products ) > 1 ) { shuffle( $products ); $products = array_slice( $products, 0, 1 ); } $to_recommend = isset( $products[0] ) ? $products[0] : $products; return $to_recommend; } /** * Fetch products from the recomended section. * * @return array|mixed The list of products to use in recomended section. */ public function get_product_from_api() { if ( false === ( $products = get_transient( 'themeisle_sdk_products' ) ) ) { //phpcs:ignore Squiz.PHP.DisallowMultipleAssignments.FoundInControlStructure $products = array(); $all_themes = $this->get_themes_from_wporg( 'themeisle' ); $all_plugins = $this->get_plugins_from_wporg( 'themeisle' ); static $allowed_products = [ 'hestia' => true, 'neve' => true, 'visualizer' => true, 'feedzy-rss-feeds' => true, 'wp-product-review' => true, 'otter-blocks' => true, 'themeisle-companion' => true, ]; foreach ( $all_themes as $theme ) { if ( $theme->active_installs < 4999 ) { continue; } if ( ! isset( $allowed_products[ $theme->slug ] ) ) { continue; } $products[] = array( 'name' => $theme->name, 'type' => 'theme', 'slug' => $theme->slug, 'installs' => $theme->active_installs, ); } foreach ( $all_plugins as $plugin ) { if ( $plugin->active_installs < 4999 ) { continue; } if ( ! isset( $allowed_products[ $plugin->slug ] ) ) { continue; } $products[] = array( 'name' => $plugin->name, 'type' => 'plugin', 'slug' => $plugin->slug, 'installs' => $plugin->active_installs, ); } set_transient( 'themeisle_sdk_products', $products, 6 * HOUR_IN_SECONDS ); } return $products; } /** * Fetch themes from wporg api. * * @param string $author The author name. * * @return array The list of themes. */ public function get_themes_from_wporg( $author ) { $products = $this->safe_get( 'https://api.wordpress.org/themes/info/1.1/?action=query_themes&request[author]=' . $author . '&request[per_page]=30&request[fields][active_installs]=true' ); $products = json_decode( wp_remote_retrieve_body( $products ) ); if ( is_object( $products ) ) { $products = isset( $products->themes ) ? $products->themes : array(); } else { $products = array(); } return (array) $products; } /** * Fetch plugin from wporg api. * * @param string $author The author slug. * * @return array The list of plugins for the selected author. */ public function get_plugins_from_wporg( $author ) { $products = $this->safe_get( 'https://api.wordpress.org/plugins/info/1.1/?action=query_plugins&request[author]=' . $author . '&request[per_page]=40&request[fields][active_installs]=true' ); $products = json_decode( wp_remote_retrieve_body( $products ) ); if ( is_object( $products ) ) { $products = isset( $products->plugins ) ? $products->plugins : array(); } else { $products = array(); } return (array) $products; } }