/** * Fetch Facebook Extended Token from the Service * * @return array */ public function get_facebook_token() { $args = array('referral' => urlencode(home_url())); $response = $this->get('facebook/token', $args); // If we have an WP_Error we return only CSV if (is_wp_error($response)) { return tribe_error('core:aggregator:invalid-facebook-token', array(), array('response' => $response)); } return $response; }
/** * Fetches an image from the service and saves it to the filesystem if needed * * @param string $image_id EA Image ID * * @return WP_Error|stdClass { * @type int $post_id Attachment ID on WP * @type string $filename Name of the image file * @type string $path Absolute path of the image * @type string $extension Extension of the image * } */ public function get($image_id) { $tribe_aggregator_meta_key = 'tribe_aggregator_image_id'; // Prevent Possible duplicated includes if (!function_exists('wp_upload_dir') || !function_exists('wp_generate_attachment_metadata')) { require_once ABSPATH . 'wp-admin/includes/image.php'; } $query = new WP_Query(array('post_type' => 'attachment', 'post_status' => 'any', 'posts_per_page' => 1, 'fields' => 'ids', 'meta_query' => array(array('key' => $tribe_aggregator_meta_key, 'value' => $image_id)))); $upload_dir = wp_upload_dir(); $file = new stdClass(); // if the file has already been added to the filesystem, don't create a duplicate...re-use it if ($query->have_posts()) { $attachment = reset($query->posts); $attachment_meta = wp_get_attachment_metadata($attachment); $file->post_id = (int) $attachment; $file->filename = basename($attachment_meta['file']); $file->path = $upload_dir['basedir'] . DIRECTORY_SEPARATOR . $attachment_meta['file']; // Fetch the Extension for this filename $filetype = wp_check_filetype($file->filename, null); $file->extension = $filetype['ext']; $file->status = 'skipped'; return $file; } // fetch an image $response = $this->service->get_image($image_id); if (is_wp_error($response)) { return $response; } // if the response isn't an image then we need to bail if (!preg_match('/image/', $response['headers']['content-type'])) { /** * @todo See a way for Tribe__Errors to handle overwriting */ return new WP_Error('invalid-image', $response['body']); } // Fetch the Extension (it's safe because it comes from our service) $extension = str_replace('image/', '', $response['headers']['content-type']); // Removed Query String if (false !== strpos($extension, '?')) { $parts = explode('?', $extension); $extension = reset($parts); } if (preg_match('/filename="([^"]+)"/', $response['headers']['content-disposition'], $matches) && !empty($matches[1])) { $filename = $matches[1]; // Removed Query String if (false !== strpos($filename, '?')) { $parts = explode('?', $filename); $filename = reset($parts); } } else { $filename = md5($response['body']) . '.' . $extension; } // Clean the Filename $filename = sanitize_file_name($filename); // get the file type $filetype = wp_check_filetype(basename($filename), null); // save the file to the filesystem in the upload directory somewhere $upload_results = wp_upload_bits($filename, null, $response['body']); // if the file path isn't set, all hope is lost if (empty($upload_results['file'])) { return tribe_error('core:aggregator:invalid-image-path'); } // create attachment args $attachment = array('guid' => $upload_dir['url'] . '/' . $filename, 'post_title' => preg_replace('/\\.[^.]+$/', '', $filename), 'post_content' => '', 'post_status' => 'inherit', 'post_mime_type' => $filetype['type']); // insert the attachment if (!($attachment_id = wp_insert_attachment($attachment, $upload_results['file']))) { return tribe_error('core:aggregator:attachment-error'); } if (is_wp_error($attachment_id)) { return $attachment_id; } // Generate attachment metadata $attachment_meta = wp_generate_attachment_metadata($attachment_id, $upload_results['file']); wp_update_attachment_metadata($attachment_id, $attachment_meta); // add our own custom meta field so the image is findable update_post_meta($attachment_id, $tribe_aggregator_meta_key, $image_id); $file->post_id = (int) $attachment_id; $file->filename = $filename; $file->path = $upload_results['file']; $file->extension = $extension; $file->status = 'created'; return $file; }
/** * Handles import data before queuing * * Ensures the import record source name is accurate, checks for errors, and limits import items * based on selection * * @param array $data Import data * * @return array|WP_Error */ public function prep_import_data($data = array()) { if (empty($this->meta['finalized'])) { return tribe_error('core:aggregator:record-not-finalized'); } // if $data is an object already, don't attempt to manipulate it into an importer object if (is_object($data)) { return $data; } // if $data is empty, grab the data from meta if (empty($data)) { $data = $this->meta; } $record = Tribe__Events__Aggregator__Records::instance()->get_by_import_id($data['import_id']); if (empty($data['column_map'])) { return tribe_error('core:aggregator:missing-csv-column-map'); } $content_type = $this->get_csv_content_type(); update_option('tribe_events_import_column_mapping_' . $content_type, $data['column_map']); try { $importer = $this->get_importer(); } catch (RuntimeException $e) { return tribe_error('core:aggregator:missing-csv-file'); } if (!empty($data['category'])) { $importer = $this->maybe_set_default_category($importer); } if (!empty($data['post_status'])) { $importer = $this->maybe_set_default_post_status($importer); } $required_fields = $importer->get_required_fields(); $missing = array_diff($required_fields, $data['column_map']); if (!empty($missing)) { $mapper = new Tribe__Events__Importer__Column_Mapper($content_type); /** * @todo allow to overwrite the default message */ $message = '<p>' . esc_html__('The following fields are required for a successful import:', 'the-events-calendar') . '</p>'; $message .= '<ul style="list-style-type: disc; margin-left: 1.5em;">'; foreach ($missing as $key) { $message .= '<li>' . $mapper->get_column_label($key) . '</li>'; } $message .= '</ul>'; return new WP_Error('csv-invalid-column-mapping', $message); } update_option('tribe_events_import_column_mapping_' . $content_type, $data['column_map']); return $importer; }
private function action_delete_record($records = array()) { $record_obj = Tribe__Events__Aggregator__Records::instance()->get_post_type(); $records = array_filter((array) $records, 'is_numeric'); $success = array(); $errors = array(); foreach ($records as $record_id) { $record = Tribe__Events__Aggregator__Records::instance()->get_by_post_id($record_id); if (is_wp_error($record)) { $errors[$record_id] = $record; continue; } if (!current_user_can($record_obj->cap->delete_post, $record->id)) { $errors[$record->id] = tribe_error('core:aggregator:delete-record-permissions', array('record' => $record)); continue; } $status = $record->delete(true); if (is_wp_error($status)) { $errors[$record->id] = $status; continue; } $success[$record->id] = true; } return array($success, $errors); }
/** * Returns an appropriate Record object for the given event id * * @param int $event_id Post ID for the Event * * @return Tribe__Events__Aggregator__Record__Abstract|null */ public function get_by_event_id($event_id) { $event = get_post($event_id); if (!$event instanceof WP_Post) { return tribe_error('core:aggregator:invalid-event-id', array(), array($event_id)); } $record_id = get_post_meta($event->ID, Tribe__Events__Aggregator__Event::$record_key, true); if (empty($record_id)) { return tribe_error('core:aggregator:invalid-import-id', array(), array($record_id)); } return $this->get_by_post_id($record_id); }
/** * Translates event JSON to the-events-calendar Event array format * * @param object $json Event data in Event Aggregator format * * @return array */ public function translate_json_to_event($json) { if (empty($json->title) || empty($json->start_date) || empty($json->start_hour) || empty($json->start_minute) || empty($json->end_date) || empty($json->end_hour) || empty($json->end_minute)) { return tribe_error('core:aggregator:invalid-event-json'); } $event = array(); $event['post_type'] = Tribe__Events__Main::POSTTYPE; $event['post_status'] = Tribe__Events__Aggregator__Settings::instance()->default_post_status($json->origin); // translate json key/value pairs to event array key/value pairs foreach (get_object_vars($json) as $key => $value) { // venues and organizers are a bit more complex. We'll handle those later if ('venue' === $key || 'organizer' === $key) { continue; } if (isset($this->event_field_map[$key])) { $key = $this->event_field_map[$key]; } $event[$key] = $value; } if (!empty($json->venue)) { $event['Venue'] = array(); if (!is_array($json->venue)) { $json->venue = array($json->venue); } foreach ($json->venue as $venue) { $venue_data = array(); if (empty($venue->venue)) { continue; } foreach (get_object_vars($venue) as $key => $value) { if (isset($this->venue_field_map[$key])) { $key = $this->venue_field_map[$key]; } $venue_data[$key] = $value; } $event['Venue'][] = $venue_data; } } if (!empty($json->organizer)) { $event['Organizer'] = array(); if (!is_array($json->organizer)) { $json->organizer = array($json->organizer); } foreach ($json->organizer as $organizer) { $organizer_data = array(); if (empty($organizer->organizer)) { continue; } foreach (get_object_vars($organizer) as $key => $value) { if (isset($this->organizer_field_map[$key])) { $key = $this->organizer_field_map[$key]; } $organizer_data[$key] = $value; } $event['Organizer'][] = $organizer_data; } } $show_map_setting = Tribe__Events__Aggregator__Settings::instance()->default_map($json->origin); $event['EventShowMap'] = $show_map_setting; $event['EventShowMapLink'] = $show_map_setting; return $event; }
/** * Handles import data before queuing * * Ensures the import record source name is accurate, checks for errors, and limits import items * based on selection * * @param array $data Import data * * @return array|WP_Error */ public function prep_import_data($data = array()) { if (empty($data)) { $data = $this->get_import_data(); } if (is_wp_error($data)) { return $data; } $this->update_source_name(empty($data->data->source_name) ? null : $data->data->source_name); if (empty($this->meta['finalized'])) { return tribe_error('core:aggregator:record-not-finalized'); } if (!isset($data->data->events)) { return 'fetch'; } $items = $this->filter_data_by_selected($data->data->events); return $items; }
/** * Allows us to Prevent too many of our Requests to be fired at on single Cron Job * * @param boolean $run Shouldn't trigger the call * @param array $request The Request that was made * @param string $url To which URL * * @return boolean|array|object */ public function filter_check_http_limit($run = false, $request = null, $url = null) { // We bail if it's not a CRON job if (!defined('DOING_CRON') || !DOING_CRON) { return $run; } // If someone changed this already we bail, it's not going to be fired if (false !== $run) { return $run; } // Bail if it wasn't done inside of the Actual Cron task if (true !== $this->is_running) { return $run; } $service = Tribe__Events__Aggregator__Service::instance(); // If the Domain is not we just keep the same answer if (0 !== strpos($url, $service->api()->domain)) { return $run; } // If we already reached 0 we throw an error if ($this->limit <= 0) { // Schedule a Cron Event to happen ASAP, and flag it for searching and we need to make it unique // By default WordPress won't allow more than one Action to happen twice in 10 minutes wp_schedule_single_event(time(), self::$single_action); return tribe_error('core:aggregator:http_request-limit', array('request' => $request, 'url' => $url)); } // Lower the Limit $this->limit--; // Return false to make the Actual Request Run return $run; }