get_error_message() ); } $code = wp_remote_retrieve_response_code( $response ); if ( $code != 200) { throw new Squat_Radar_Connector_Exception( wp_remote_retrieve_body( $response ), $code ); } return json_decode( wp_remote_retrieve_body( $response ), true); } /** * Turn a Radar frontend Search URL into facets key value and language values. * * @param string $url * The https://radar.squat.net/events filtered URL. * * @return array * [ 'language' => language code, 'facets' => [key => value] ]. */ function decode_search_url( $url ) { $matches = []; $result = []; // Urldecode not required here because of the regex match. // Radar paramaters here are transcoded so will match. if (preg_match('|//radar.squat.net/([a-z]{2})/events/([a-zA-Z0-9/]*)|', $url, $matches)) { $result['language'] = $matches[1]; foreach (array_chunk(explode('/', $matches[2]), 2) as $key_value_pair) { $result['facets'][$key_value_pair[0]] = $key_value_pair[1]; } } return $result; } /** * Encode a query key value from facets, fields, language, limit. * * @param array $facets * Optional. Facet key => filter value array. * @param array $fields * Optional. Index array of API field names to retrieve. * @param string $language * Optional. Language code. * @param int $limit * Optional. Maximum number to items to return. * * @return array * Array for use in self::get_events(). */ function encode_api_query( $facets = [], $fields = [], $language = '', $limit = 10 ) { $query = []; // Urlencode should do nothing here @see comment in decode_search_url. // If someone has snuck something in it will however help. foreach ( $facets as $key => $value ) { $query[] = ['facets[' . urlencode($key) . '][]' => urlencode($value)]; } if ( ! empty($fields) ) { // {raw}urlencode is encoding : and , both of which are valid pchar. $query['fields'] = preg_replace('/[^a-z_:,]/', '', implode(',', $fields)); } if ( ! empty($language) ) { $query['language'] = urlencode($language); } if ( ! empty($limit) ) { $query['limit'] = urlencode($limit); } return $query; } /** * Return events meeting argument criteria. Either from cache, or retrieved from API. * * @param array $facets * Facet name key => filter value. * @param array $fields * Optional. Array of key names. * @param string $language * Optional. Language code. * @param int $limit * Maximum number of items to return. * @param int $expiration * Seconds to cache results. 0 never expires. * @param bool $reset * Force a cache reset. * * @return array * Array of event arrays, values keyed by field name. */ function events( $facets, $fields = [], $language = NULL, $limit = 10, $expiration = 10800, $reset = FALSE ) { // Fields we often want to get data out of but not necessarily are chosen to be shown. $fields = array_merge($fields, ['uuid', 'title', 'body:value', 'url', 'event_status']); $transient_key = 'squat_radar_events_' . sha1(implode($facets) . implode($fields) . $language . $limit); if (! $reset && $data = get_transient( $transient_key )) { return $data; } $query = $this->encode_api_query( $facets, $fields, $language, $limit ); $events = $this->get_events($query); set_transient( $transient_key, $events, $expiration ); return $events; } } class Squat_Radar_Connector_Exception extends Exception { }