Posts_Import

Class Posts_Import


Source

File: includes/libs/posts-import.class.php

016class Posts_Import{
017    /**
018     * @var Post_Type
019     */
020    protected $post_type;
021 
022    /**
023     * Posts_Import constructor.
024     *
025     * @param Post_Type $post_type
026     */
027    public function __construct( Post_Type $post_type ) {
028        $this->post_type = $post_type;
029    }
030 
031    /**
032     * Imports videos from a given feed source.
033     * Used by automatic updates.
034     *
035     * @param $raw_feed
036     * @param Feed|array $import_options
037     *
038     * @return array|void
039     */
040    public function run_import( $raw_feed, $import_options ){
041        /**
042         * @var array $native_tax
043         * @var array $native_tag
044         * @var bool $import_description
045         * @var string $import_status
046         * @var bool $import_title
047         * @var bool $import_date
048         * @var int $import_user
049         */
050        extract( $this->get_import_options( $import_options ), EXTR_SKIP );
051 
052        // get import options
053        $options = Plugin::instance()->get_options();
054 
055        // overwrite plugin import settings with import settings
056        $options['import_description'] = $import_description;
057        $options['import_status'] = $import_status;
058        $options['import_title'] = $import_title;
059 
060        // store results
061        $result = [
062            'private'   => 0,
063            'imported'  => 0,
064            'skipped'   => 0,
065            'total'     => count( $raw_feed ),
066            'ids'       => [],
067            'error'     => []
068        ];
069 
070        $duplicates = $this->get_duplicate_posts( $raw_feed, $this->post_type->get_post_type() );
071 
072        // parse feed
073        foreach( $raw_feed as $video ){
074 
075            // video already exists, don't do anything
076            if( array_key_exists( $video['video_id'], $duplicates ) ){
077 
078                /**
079                 * Generate an error and pass it for debugging
080                 * @var WP_Error
081                 */
082                $error = new WP_Error(
083                    'cvm_import_skip_existing_video',
084                    sprintf(
085                        '%s %s',
086                        sprintf(
087                            __( 'Skipped video having ID %s because it already exists.', 'codeflavors-vimeo-video-post-lite' ),
088                            $video['video_id']
089                        ),
090                        sprintf(
091                            __( 'Existing post has ID %s.', 'codeflavors-vimeo-video-post-lite' ),
092                            $duplicates[ $video['video_id'] ][0]
093                        )
094                    ),
095                    [
096                        'video_data' => $video,
097                        'existing_posts' => $duplicates[ $video['video_id'] ]
098                    ]
099                );
100                $result['error'][] = $error;
101 
102                /**
103                 * Pass error to debug function
104                 */
105                Helper::debug_message(
106                    'Import error: ' . $error->get_error_message(),
107                    "\n",
108                    $error
109                );
110 
111                foreach( $duplicates[ $video['video_id'] ] as $_post_id ){
112                    // retrieve the post object for backwards compatibility
113                    $post = get_post( $_post_id );
114 
115                    /**
116                     * Action triggered when duplicate posts were detected.
117                     * Can be used to set extra taxonomies for already existing posts.
118                     *
119                     * @param \WP_Post $post             The WordPress post object that was found as duplicate.
120                     * @param string $taxonomy           The taxonomy that must be imported for the post.
121                     * @param string $taxonomy_value     The plugin taxonomy that must be set up.
122                     * @param string $tag_taxonomy       The tag taxonomy that must be set up.
123                     * @param string $tag_taxonomy_value The tag taxonomy value that must be set for the post.
124                     */
125                    do_action( 'vimeotheque\import_duplicate_taxonomies',
126                        $post,
127                        $this->post_type->get_post_tax(),
128                        $native_tax,
129                        $this->post_type->get_tag_tax(),
130                        $native_tag
131                    );
132                }
133 
134                $result['skipped'] += 1;
135                continue;
136            }
137 
138            if( 'private' == $video['privacy'] ){
139                $result['private'] += 1;
140                if( 'skip' == $options['import_privacy'] ){
141                    $result['skipped'] += 1;
142 
143                    /**
144                     * Generate an error and pass it for debugging
145                     * @var WP_Error
146                     */
147                    $error = new WP_Error(
148                        'cvm_import_skip_private_video',
149                        sprintf(
150                            __( 'Skipped private video having ID %s because of plugin settings.', 'cvm-video' ),
151                            $video['video_id']
152                        ),
153                        [
154                            'video_data' => $video
155                        ]
156                    );
157                    $result['error'][] = $error;
158 
159                    /**
160                     * Send error to debug function
161                     */
162                    Helper::debug_message(
163                        'Import error: ' . $error->get_error_message(),
164                        "\n",
165                        $error
166                    );
167 
168                    continue;
169                }
170            }
171 
172            $post_id = $this->import_video( [
173                'video'         => $video, // video details retrieved from Vimeo
174                'category'      => $native_tax, // category name (if any) - will be created if category_id is false
175                'tags'          => $native_tag,
176                'user'          => ( isset( $import_user ) ? absint( $import_user ) : false ), // save as a given user if any
177                'post_format'   => 'video', // post format will default to video
178                'status'        => $this->post_type->get_post_settings()->post_status( $import_status ), // post status
179                'options'       => $options
180            ] );
181 
182            if( $post_id ){
183                $result['imported'] += 1;
184                $result['ids'][] = $post_id;
185 
186                $video = Helper::get_video_post( $post_id );
187                $video->set_embed_options(
188                    $this->get_import_options( $import_options ),
189                    true
190                );
191            }
192        }
193 
194        Helper::debug_message(
195            sprintf(
196                'Processed %d entries: created %d posts, skipped %d entries, %d entries were marked private.',
197                $result['total'],
198                $result['imported'],
199                $result['skipped'],
200                $result['private']
201            )
202        );
203 
204        return $result;
205    }
206 
207    /**
208     * @param array $raw_feed
209     * @param $post_type
210     *
211     * @return array
212     */
213    public function get_duplicate_posts( $raw_feed, $post_type ){
214 
215        if( !$raw_feed ){
216            return [];
217        }
218 
219        $video_ids = [];
220        foreach( $raw_feed as $video ){
221            $video_ids[] = $video['video_id'];
222        }
223        /**
224         * @var \WP_Query
225         */
226        global $wpdb;
227        $query = $wpdb->prepare(
228            "
229            SELECT {$wpdb->postmeta}.post_id, {$wpdb->postmeta}.meta_value
230            FROM {$wpdb->postmeta}
231            LEFT JOIN {$wpdb->posts}
232            ON {$wpdb->postmeta}.post_id = {$wpdb->posts}.ID
233            WHERE
234            {$wpdb->posts}.post_type LIKE '%s'
235            AND meta_value IN(" . implode( ',', $video_ids ) . ")
236            ",
237            $post_type
238        );
239 
240        $existing = $wpdb->get_results( $query );
241        $_result = [];
242 
243        if( $existing ){
244            foreach( $existing as $r ){
245                $_result[ $r->meta_value ][] = $r->post_id;
246            }
247        }
248 
249        /**
250         * Filter the duplicate posts found by the plugin.
251         * When perfoming imports, the filter runs when duplicate imports are detected.
252         *
253         * @param array $_result    The post IDs found as duplicates.
254         */
255        $result = apply_filters( 'vimeotheque\duplicate_posts_found', $_result );
256 
257        if( $_result !== $result ){
258            Helper::debug_message(
259                sprintf(
260                    'Detected duplicate posts override by filter "%s".',
261                    'vimeotheque\duplicate_posts_found'
262                )
263            );
264        }
265 
266        return $result;
267    }
268 
269    /**
270     * Import a single video based on the passed data
271     *
272     * @param array $args
273     *
274     * @return bool|int
275     */
276    public function import_video( $args = [] ){
277 
278        $defaults = [
279            'video'             => [], // video details retrieved from Vimeo
280            'post_id'           => false,
281            'category'          => false, // category name (if any) - will be created if category_id is false
282            'tags'              => false,
283            'user'              => false, // save as a given user if any
284            'post_format'       => 'video', // post format will default to video
285            'status'            => 'draft', // post status
286            'options'           => false,
287        ];
288        /**
289         * @var array $video
290         * @var int $post_id
291         * @var string $category
292         * @var array $tags
293         * @var int $user
294         * @var string $post_format
295         * @var string $status
296         * @var array $options
297         */
298        extract( wp_parse_args( $args, $defaults ), EXTR_SKIP );
299 
300        if( !$options ){
301            $options = Plugin::instance()->get_options();
302        }
303 
304        // if no video details, bail out
305        if( !$video ){
306            return false;
307        }
308 
309        /**
310         * Filter that allows changing of post format when importing videos.
311         *
312         * @param string $post_format   The post format.
313         */
314        $post_format = apply_filters(
315            'vimeotheque\import_post_format',
316            $post_format
317        );
318 
319        /**
320         * Filter that allows video imports.
321         * Can be used to prevent importing of videos.
322         *
323         * @param bool $allow       Allow video improts to be made (true) or prevent them (false).
324         * @param array $video      Video details array.
325         * @param string $post_type The post type that should be created from the video details.
326         * @param false $false      An unset parameter.
327         */
328        $allow_import = apply_filters(
329            'vimeotheque\allow_import',
330            true,
331            $video,
332            $this->post_type->get_post_type(),
333            false
334        );
335 
336        if( !$allow_import ){
337            /**
338             * Generate an error and pass it for debugging
339             * @var WP_Error
340             */
341            $error = new WP_Error(
342                'vimeotheque_video_import_prevented_by_filter',
343                sprintf(
344                    __( 'Video having ID %s could not be imported because of a filter blocking all imports.', 'codeflavors-vimeo-video-post-lite' ),
345                    $video['video_id']
346                ),
347                [ 'video_data' => $video ]
348            );
349 
350            /**
351             * Send error to debug function
352             */
353            Helper::debug_message(
354                'Import error: ' . $error->get_error_message(),
355                "\n",
356                $error
357            );
358 
359            return false;
360        }
361 
362        // plugin settings; caller can pass their own import options
363        if( !$options ){
364            $options = Plugin::instance()->get_options();
365        }
366 
367        if( 'private' == $video['privacy'] && 'pending' == $options['import_privacy'] ){
368            $status = 'pending';
369        }
370 
371        // post content
372        $post_content = '';
373        if( 'content' == $options['import_description'] || 'content_excerpt' == $options['import_description'] ){
374            $post_content = $video['description'];
375        }
376        // post excerpt
377        $post_excerpt = '';
378        if( 'excerpt' == $options['import_description'] || 'content_excerpt' == $options['import_description'] ){
379            $post_excerpt = $video['description'];
380        }
381 
382        // post title
383        $post_title     = $options['import_title'] ? $video['title'] : '';
384 
385        /**
386         * Action that runs before the post is inserted into the database.
387         *
388         * @param array $video  The video details array retrieved from Vimeo.
389         * @param false $false  Always false in Vimeotheque Lite.
390         */
391        do_action(
392            'vimeotheque\import_before',
393            $video,
394            false
395        );
396 
397        // set post data
398        $post_data = [
399 
400            /**
401             * Post title filter before the post is inserted into the database.
402             *
403             * @param string $title     The post title.
404             * @param array $video      The video details.
405             * @param bool $false       Unused parameter.
406             */
407            'post_title'    => apply_filters(
408                'vimeotheque\import_post_title',
409                $post_title,
410                $video,
411                false
412            ),
413 
414            /**
415             * Post content filter before the post is inserted into the database.
416             *
417             * @param string $content   The post content.
418             * @param array $video      The video details.
419             * @param false $false      Unused parameter.
420             */
421            'post_content'  => apply_filters(
422                'vimeotheque\import_post_content',
423                $post_content,
424                $video,
425                false
426            ),
427 
428            /**
429             * Post excerpt filter before the post is inserted into the database.
430             *
431             * @param string $excerpt   The post excerpt.
432             * @param array $video      The video details.
433             * @param false $false      Unused parameter.
434             */
435            'post_excerpt'  => apply_filters(
436                'vimeotheque\import_post_excerpt',
437                $post_excerpt,
438                $video,
439                false
440            ),
441            'post_type'     => $this->post_type->get_post_type(),
442 
443            /**
444             * Post status filter before the post is inserted into the database.
445             *
446             * @param string $status    The post status.
447             * @param array $video      The video details.
448             * @param false $false      Unused parameter.
449             */
450            'post_status'   => apply_filters(
451                'vimeotheque\import_post_status',
452                $status,
453                $video,
454                false
455            )
456        ];
457 
458        $pd = $options['import_date'] ? date('Y-m-d H:i:s', strtotime( $video['published'] )) : current_time( 'mysql' );
459 
460        /**
461         * Post date filter before the post is inserted into the database.
462         *
463         * @param string $date      The post date.
464         * @param array $video      The video details.
465         * @param false $false      Unused parameter.
466         */
467        $post_date = apply_filters(
468            'vimeotheque\import_post_date',
469            $pd,
470            $video,
471            false
472        );
473 
474        if( isset( $options['import_date'] ) && $options['import_date'] ){
475            $post_data['post_date_gmt'] = $post_date;
476            $post_data['edit_date']     = $post_date;
477            $post_data['post_date']     = $post_date;
478        }
479 
480        // set user
481        if( $user ){
482            $post_data['post_author'] = $user;
483        }
484        /**
485         * @var int|\WP_Error $post_id
486         */
487        // single video import will pass post ID
488        if( isset( $post_id ) && $post_id ){
489            $post_data['ID'] = $post_id;
490            $post_id = wp_update_post( $post_data, true );
491        }else {
492            // allow empty insert into post content
493            add_filter(
494                'wp_insert_post_empty_content',
495                '__return_false'
496            );
497 
498            $post_id = wp_insert_post( $post_data, true );
499        }
500 
501        if( is_wp_error( $post_id ) ){
502            Helper::debug_message(
503                sprintf(
504                    'Video with ID %s generated the following database error on insert: "%s"; video post could not be created.',
505                    $video['video_id'],
506                    $post_id->get_error_message()
507                )
508            );
509        }
510 
511        // check if post was created
512        if( !is_wp_error( $post_id ) ){
513 
514            // set post format
515            if( $post_format  ){
516                set_post_format( $post_id, $post_format );
517            }
518 
519            // set post category
520            if( $category ){
521                $category = is_array( $category ) ? $category : [ $category ];
522                wp_set_post_terms( $post_id, $category, $this->post_type->get_post_tax() );
523            }
524 
525            if( $tags ){
526                wp_set_post_terms( $post_id, $tags, $this->post_type->get_tag_tax() );
527            }
528 
529            // insert tags
530            if( ( isset( $options['import_tags'] ) && $options['import_tags'] ) && $this->post_type->get_tag_tax() ){
531                if( isset( $video['tags'] ) && is_array( $video['tags'] ) ){
532                    $count = absint( $options['max_tags'] );
533                    $tags = array_slice( $video['tags'], 0, $count );
534                    if( $tags ){
535                        wp_set_post_terms( $post_id, $tags, $this->post_type->get_tag_tax(), true );
536                    }
537                }
538            }
539 
540            // set post meta
541            $_post = Helper::get_video_post( $post_id );
542            $_post->set_video_data( $video );
543            $_post->set_video_id_meta();
544            $_post->set_video_url_meta();
545 
546            /**
547             * Action after a video post was successfully imported into the database.
548             *
549             * @param int $post_id          ID of the post newly created from the Vimeo video.
550             * @param array $video          Array of video details retrieved from Vimeo.
551             * @param false $unknown        Unused parameter.
552             * @param string $post_type     The post type that was created.
553             */
554            do_action(
555                'vimeotheque\import_success',
556                $post_id,
557                $video,
558                false,
559                $this->post_type->get_post_type()
560            );
561 
562            /**
563             * Send a debug message
564             */
565            Helper::debug_message(
566                sprintf(
567                    'Imported video ID %s into post #%d having post type "%s".',
568                    $video['video_id'],
569                    $post_id,
570                    $this->post_type->get_post_type()
571                )
572            );
573 
574            // import image
575            if( $options['featured_image'] ){
576                $_post->set_featured_image();
577            }
578 
579            return $post_id;
580 
581        }// end checking if not wp error on post insert
582 
583        return false;
584    }
585 
586    /**
587     * Process the import options
588     *
589     * @param array $source
590     *
591     * @return array
592     */
593    private function get_import_options( $source = [] ){
594        $taxonomy = $this->post_type->get_post_tax();
595        $tag_tax = $this->post_type->get_tag_tax();
596        $native_tax = isset( $source['tax_input'][ $taxonomy ] ) ? (array) $source['tax_input'][ $taxonomy ] : [];
597        $native_tag = isset( $source['tax_input'][ $tag_tax ] ) ? (array) $source['tax_input'][ $tag_tax ] : [];
598 
599        $import_options = [
600            'native_tax'        => $native_tax,
601            'native_tag'        => $native_tag,
602            'import_description' => $source['import_description'],
603            'import_status' => $source['import_status'],
604            'import_title' => isset( $source['import_title'] )
605        ];
606 
607        return $import_options;
608    }
609}

Methods

Start your video site now!

Manage and coordinate your Vimeo channels, albums or videos with your WordPress website. Perfect fit for membership, portfolio, online courses or any type of video collection.

Get Vimeotheque PRO!