(string) $author, 'plugins' => array_values( $plugins ), 'themes' => array_values( $themes ), ) ); if ( empty( $query ) ) { return array( 'data' => array(), 'wordpress' => '', ); } $key = 'trackpluse_stats_' . md5( (string) wp_json_encode( $query ) ); $cached = get_transient( $key ); if ( is_array( $cached ) ) { return $cached; } $last = get_transient( $key . '_last' ); // A recent failure: don't make every page wait on it again. if ( get_transient( $key . '_failed' ) ) { return is_array( $last ) ? $last : new WP_Error( 'trackpluse_unavailable', __( 'TrackWP couldn’t be reached. The figures will try again shortly.', 'trackpluse' ) ); } $response = wp_remote_get( self::base() . '/api/public/v1/stats?' . http_build_query( $query, '', '&' ), array( 'timeout' => $timeout, // WordPress's default user agent carries the site's address; this one doesn't. 'user-agent' => 'TrackPluse/' . TRACKPLUSE_VERSION, 'headers' => array( 'Accept' => 'application/json' ), ) ); $body = is_wp_error( $response ) ? null : json_decode( wp_remote_retrieve_body( $response ), true ); if ( ! is_array( $body ) || 200 !== wp_remote_retrieve_response_code( $response ) || ! isset( $body['data'] ) || ! is_array( $body['data'] ) ) { set_transient( $key . '_failed', 1, self::RETRY_MINUTES * MINUTE_IN_SECONDS ); self::remember( $key . '_failed' ); return is_array( $last ) ? $last : new WP_Error( 'trackpluse_unavailable', __( 'TrackWP couldn’t be reached. The figures will try again shortly.', 'trackpluse' ) ); } $result = array( 'data' => array_values( array_filter( $body['data'], 'is_array' ) ), 'wordpress' => isset( $body['wordpress'] ) ? (string) $body['wordpress'] : '', ); set_transient( $key, $result, self::CACHE_HOURS * HOUR_IN_SECONDS ); set_transient( $key . '_last', $result, WEEK_IN_SECONDS ); self::remember( $key ); self::remember( $key . '_last' ); return $result; } /** * Forget every kept figure, so the next view fetches fresh ones. */ public static function flush() { foreach ( (array) get_option( self::KEYS_OPTION, array() ) as $key ) { delete_transient( (string) $key ); } delete_option( self::KEYS_OPTION ); } /** * Note a transient's name for flush(). * * @param string $key Transient name. */ private static function remember( $key ) { $keys = (array) get_option( self::KEYS_OPTION, array() ); if ( ! in_array( $key, $keys, true ) ) { // The newest 200 are plenty: older ones expire on their own. $keys = array_slice( array_merge( $keys, array( $key ) ), -200 ); update_option( self::KEYS_OPTION, $keys, false ); } } }