Posts_Import
Class Posts_Import
Source
File: includes/libs/posts-import.class.php
class Posts_Import{ /** * @var Post_Type */ protected $post_type; /** * Posts_Import constructor. * * @param Post_Type $post_type */ public function __construct( Post_Type $post_type ) { $this->post_type = $post_type; } /** * Imports videos from a given feed source. * Used by automatic updates. * * @param $raw_feed * @param Feed|array $import_options * * @return array|void */ public function run_import( $raw_feed, $import_options ){ /** * @var array $native_tax * @var array $native_tag * @var bool $import_description * @var string $import_status * @var bool $import_title * @var bool $import_date * @var int $import_user */ extract( $this->get_import_options( $import_options ), EXTR_SKIP ); // get import options $options = Plugin::instance()->get_options(); // overwrite plugin import settings with import settings $options['import_description'] = $import_description; $options['import_status'] = $import_status; $options['import_title'] = $import_title; // store results $result = [ 'private' => 0, 'imported' => 0, 'skipped' => 0, 'total' => count( $raw_feed ), 'ids' => [], 'error' => [] ]; $duplicates = $this->get_duplicate_posts( $raw_feed, $this->post_type->get_post_type() ); // parse feed foreach( $raw_feed as $video ){ // video already exists, don't do anything if( array_key_exists( $video['video_id'], $duplicates ) ){ /** * Generate an error and pass it for debugging * @var WP_Error */ $error = new WP_Error( 'cvm_import_skip_existing_video', sprintf( '%s %s', sprintf( __( 'Skipped video having ID %s because it already exists.', 'codeflavors-vimeo-video-post-lite' ), $video['video_id'] ), sprintf( __( 'Existing post has ID %s.', 'codeflavors-vimeo-video-post-lite' ), $duplicates[ $video['video_id'] ][0] ) ), [ 'video_data' => $video, 'existing_posts' => $duplicates[ $video['video_id'] ] ] ); $result['error'][] = $error; /** * Pass error to debug function */ Helper::debug_message( 'Import error: ' . $error->get_error_message(), "\n", $error ); foreach( $duplicates[ $video['video_id'] ] as $_post_id ){ // retrieve the post object for backwards compatibility $post = get_post( $_post_id ); /** * Action triggered when duplicate posts were detected. * Can be used to set extra taxonomies for already existing posts. * * @param \WP_Post $post The WordPress post object that was found as duplicate. * @param string $taxonomy The taxonomy that must be imported for the post. * @param string $taxonomy_value The plugin taxonomy that must be set up. * @param string $tag_taxonomy The tag taxonomy that must be set up. * @param string $tag_taxonomy_value The tag taxonomy value that must be set for the post. */ do_action( 'vimeotheque\import_duplicate_taxonomies', $post, $this->post_type->get_post_tax(), $native_tax, $this->post_type->get_tag_tax(), $native_tag ); } $result['skipped'] += 1; continue; } if( 'private' == $video['privacy'] ){ $result['private'] += 1; if( 'skip' == $options['import_privacy'] ){ $result['skipped'] += 1; /** * Generate an error and pass it for debugging * @var WP_Error */ $error = new WP_Error( 'cvm_import_skip_private_video', sprintf( __( 'Skipped private video having ID %s because of plugin settings.', 'cvm-video' ), $video['video_id'] ), [ 'video_data' => $video ] ); $result['error'][] = $error; /** * Send error to debug function */ Helper::debug_message( 'Import error: ' . $error->get_error_message(), "\n", $error ); continue; } } $post_id = $this->import_video( [ 'video' => $video, // video details retrieved from Vimeo 'category' => $native_tax, // category name (if any) - will be created if category_id is false 'tags' => $native_tag, 'user' => ( isset( $import_user ) ? absint( $import_user ) : false ), // save as a given user if any 'post_format' => 'video', // post format will default to video 'status' => $this->post_type->get_post_settings()->post_status( $import_status ), // post status 'options' => $options ] ); if( $post_id ){ $result['imported'] += 1; $result['ids'][] = $post_id; $video = Helper::get_video_post( $post_id ); $video->set_embed_options( $this->get_import_options( $import_options ), true ); } } Helper::debug_message( sprintf( 'Processed %d entries: created %d posts, skipped %d entries, %d entries were marked private.', $result['total'], $result['imported'], $result['skipped'], $result['private'] ) ); return $result; } /** * @param array $raw_feed * @param $post_type * * @return array */ public function get_duplicate_posts( $raw_feed, $post_type ){ if( !$raw_feed ){ return []; } $video_ids = []; foreach( $raw_feed as $video ){ $video_ids[] = $video['video_id']; } /** * @var \WP_Query */ global $wpdb; $query = $wpdb->prepare( " SELECT {$wpdb->postmeta}.post_id, {$wpdb->postmeta}.meta_value FROM {$wpdb->postmeta} LEFT JOIN {$wpdb->posts} ON {$wpdb->postmeta}.post_id = {$wpdb->posts}.ID WHERE {$wpdb->posts}.post_type LIKE '%s' AND meta_value IN(" . implode( ',', $video_ids ) . ") ", $post_type ); $existing = $wpdb->get_results( $query ); $_result = []; if( $existing ){ foreach( $existing as $r ){ $_result[ $r->meta_value ][] = $r->post_id; } } /** * Filter the duplicate posts found by the plugin. * When perfoming imports, the filter runs when duplicate imports are detected. * * @param array $_result The post IDs found as duplicates. */ $result = apply_filters( 'vimeotheque\duplicate_posts_found', $_result ); if( $_result !== $result ){ Helper::debug_message( sprintf( 'Detected duplicate posts override by filter "%s".', 'vimeotheque\duplicate_posts_found' ) ); } return $result; } /** * Import a single video based on the passed data * * @param array $args * * @return bool|int */ public function import_video( $args = [] ){ $defaults = [ 'video' => [], // video details retrieved from Vimeo 'post_id' => false, 'category' => false, // category name (if any) - will be created if category_id is false 'tags' => false, 'user' => false, // save as a given user if any 'post_format' => 'video', // post format will default to video 'status' => 'draft', // post status 'options' => false, ]; /** * @var array $video * @var int $post_id * @var string $category * @var array $tags * @var int $user * @var string $post_format * @var string $status * @var array $options */ extract( wp_parse_args( $args, $defaults ), EXTR_SKIP ); if( !$options ){ $options = Plugin::instance()->get_options(); } // if no video details, bail out if( !$video ){ return false; } /** * Filter that allows changing of post format when importing videos. * * @param string $post_format The post format. */ $post_format = apply_filters( 'vimeotheque\import_post_format', $post_format ); /** * Filter that allows video imports. * Can be used to prevent importing of videos. * * @param bool $allow Allow video improts to be made (true) or prevent them (false). * @param array $video Video details array. * @param string $post_type The post type that should be created from the video details. * @param false $false An unset parameter. */ $allow_import = apply_filters( 'vimeotheque\allow_import', true, $video, $this->post_type->get_post_type(), false ); if( !$allow_import ){ /** * Generate an error and pass it for debugging * @var WP_Error */ $error = new WP_Error( 'vimeotheque_video_import_prevented_by_filter', sprintf( __( 'Video having ID %s could not be imported because of a filter blocking all imports.', 'codeflavors-vimeo-video-post-lite' ), $video['video_id'] ), [ 'video_data' => $video ] ); /** * Send error to debug function */ Helper::debug_message( 'Import error: ' . $error->get_error_message(), "\n", $error ); return false; } // plugin settings; caller can pass their own import options if( !$options ){ $options = Plugin::instance()->get_options(); } if( 'private' == $video['privacy'] && 'pending' == $options['import_privacy'] ){ $status = 'pending'; } // post content $post_content = ''; if( 'content' == $options['import_description'] || 'content_excerpt' == $options['import_description'] ){ $post_content = $video['description']; } // post excerpt $post_excerpt = ''; if( 'excerpt' == $options['import_description'] || 'content_excerpt' == $options['import_description'] ){ $post_excerpt = $video['description']; } // post title $post_title = $options['import_title'] ? $video['title'] : ''; /** * Action that runs before the post is inserted into the database. * * @param array $video The video details array retrieved from Vimeo. * @param false $false Always false in Vimeotheque Lite. */ do_action( 'vimeotheque\import_before', $video, false ); // set post data $post_data = [ /** * Post title filter before the post is inserted into the database. * * @param string $title The post title. * @param array $video The video details. * @param bool $false Unused parameter. */ 'post_title' => apply_filters( 'vimeotheque\import_post_title', $post_title, $video, false ), /** * Post content filter before the post is inserted into the database. * * @param string $content The post content. * @param array $video The video details. * @param false $false Unused parameter. */ 'post_content' => apply_filters( 'vimeotheque\import_post_content', $post_content, $video, false ), /** * Post excerpt filter before the post is inserted into the database. * * @param string $excerpt The post excerpt. * @param array $video The video details. * @param false $false Unused parameter. */ 'post_excerpt' => apply_filters( 'vimeotheque\import_post_excerpt', $post_excerpt, $video, false ), 'post_type' => $this->post_type->get_post_type(), /** * Post status filter before the post is inserted into the database. * * @param string $status The post status. * @param array $video The video details. * @param false $false Unused parameter. */ 'post_status' => apply_filters( 'vimeotheque\import_post_status', $status, $video, false ) ]; $pd = $options['import_date'] ? date('Y-m-d H:i:s', strtotime( $video['published'] )) : current_time( 'mysql' ); /** * Post date filter before the post is inserted into the database. * * @param string $date The post date. * @param array $video The video details. * @param false $false Unused parameter. */ $post_date = apply_filters( 'vimeotheque\import_post_date', $pd, $video, false ); if( isset( $options['import_date'] ) && $options['import_date'] ){ $post_data['post_date_gmt'] = $post_date; $post_data['edit_date'] = $post_date; $post_data['post_date'] = $post_date; } // set user if( $user ){ $post_data['post_author'] = $user; } /** * @var int|\WP_Error $post_id */ // single video import will pass post ID if( isset( $post_id ) && $post_id ){ $post_data['ID'] = $post_id; $post_id = wp_update_post( $post_data, true ); }else { // allow empty insert into post content add_filter( 'wp_insert_post_empty_content', '__return_false' ); $post_id = wp_insert_post( $post_data, true ); } if( is_wp_error( $post_id ) ){ Helper::debug_message( sprintf( 'Video with ID %s generated the following database error on insert: "%s"; video post could not be created.', $video['video_id'], $post_id->get_error_message() ) ); } // check if post was created if( !is_wp_error( $post_id ) ){ // set post format if( $post_format ){ set_post_format( $post_id, $post_format ); } // set post category if( $category ){ $category = is_array( $category ) ? $category : [ $category ]; wp_set_post_terms( $post_id, $category, $this->post_type->get_post_tax() ); } if( $tags ){ wp_set_post_terms( $post_id, $tags, $this->post_type->get_tag_tax() ); } // insert tags if( ( isset( $options['import_tags'] ) && $options['import_tags'] ) && $this->post_type->get_tag_tax() ){ if( isset( $video['tags'] ) && is_array( $video['tags'] ) ){ $count = absint( $options['max_tags'] ); $tags = array_slice( $video['tags'], 0, $count ); if( $tags ){ wp_set_post_terms( $post_id, $tags, $this->post_type->get_tag_tax(), true ); } } } // set post meta $_post = Helper::get_video_post( $post_id ); $_post->set_video_data( $video ); $_post->set_video_id_meta(); $_post->set_video_url_meta(); /** * Action after a video post was successfully imported into the database. * * @param int $post_id ID of the post newly created from the Vimeo video. * @param array $video Array of video details retrieved from Vimeo. * @param false $unknown Unused parameter. * @param string $post_type The post type that was created. */ do_action( 'vimeotheque\import_success', $post_id, $video, false, $this->post_type->get_post_type() ); /** * Send a debug message */ Helper::debug_message( sprintf( 'Imported video ID %s into post #%d having post type "%s".', $video['video_id'], $post_id, $this->post_type->get_post_type() ) ); // import image if( $options['featured_image'] ){ $_post->set_featured_image(); } return $post_id; }// end checking if not wp error on post insert return false; } /** * Process the import options * * @param array $source * * @return array */ private function get_import_options( $source = [] ){ $taxonomy = $this->post_type->get_post_tax(); $tag_tax = $this->post_type->get_tag_tax(); $native_tax = isset( $source['tax_input'][ $taxonomy ] ) ? (array) $source['tax_input'][ $taxonomy ] : []; $native_tag = isset( $source['tax_input'][ $tag_tax ] ) ? (array) $source['tax_input'][ $tag_tax ] : []; $import_options = [ 'native_tax' => $native_tax, 'native_tag' => $native_tag, 'import_description' => $source['import_description'], 'import_status' => $source['import_status'], 'import_title' => isset( $source['import_title'] ) ]; return $import_options; } }
Methods
- __construct — Posts_Import constructor.
- get_duplicate_posts
- get_import_options — Process the import options
- import_video — Import a single video based on the passed data
- run_import — Imports videos from a given feed source.