manueljose

record.php

Nov 28th, 2014
907
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
PHP 119.70 KB | None | 0 0
  1. <?php
  2.  
  3. class PMXI_Import_Record extends PMXI_Model_Record {
  4.  
  5.     public static $cdata = array();
  6.  
  7.     protected $errors; 
  8.    
  9.     /**
  10.      * Some pre-processing logic, such as removing control characters from xml to prevent parsing errors
  11.      * @param string $xml
  12.      */
  13.     public static function preprocessXml( & $xml) {    
  14.        
  15.         if ( empty(PMXI_Plugin::$session->is_csv) and empty(PMXI_Plugin::$is_csv)){
  16.        
  17.             self::$cdata = array();        
  18.  
  19.             $xml = preg_replace_callback('/<!\[CDATA\[[^\]\]>]*\]\]>/s', 'pmxi_cdata_filter', $xml );
  20.  
  21.             $xml = str_replace("&", "&amp;", str_replace("&amp;","&", $xml));
  22.  
  23.             if ( ! empty(self::$cdata) ){
  24.                 foreach (self::$cdata as $key => $val) {
  25.                     $xml = str_replace('{{CPLACE_' . ($key + 1) . '}}', $val, $xml);
  26.                 }
  27.             }
  28.         }      
  29.     }
  30.  
  31.     /**
  32.      * Validate XML to be valid for import
  33.      * @param string $xml
  34.      * @param WP_Error[optional] $errors
  35.      * @return bool Validation status
  36.      */
  37.     public static function validateXml( & $xml, $errors = NULL) {
  38.         if (FALSE === $xml or '' == $xml) {
  39.             $errors and $errors->add('form-validation', __('WP All Import can\'t read your file.<br/><br/>Probably, you are trying to import an invalid XML feed. Try opening the XML feed in a web browser (Google Chrome is recommended for opening XML files) to see if there is an error message.<br/>Alternatively, run the feed through a validator: http://validator.w3.org/<br/>99% of the time, the reason for this error is because your XML feed isn\'t valid.<br/>If you are 100% sure you are importing a valid XML feed, please contact WP All Import support.', 'pmxi_plugin'));
  40.         } else {
  41.                        
  42.             PMXI_Import_Record::preprocessXml($xml);                                                                                       
  43.  
  44.             if ( function_exists('simplexml_load_string')){
  45.                 libxml_use_internal_errors(true);
  46.                 libxml_clear_errors();
  47.                 $_x = @simplexml_load_string($xml);
  48.                 $xml_errors = libxml_get_errors();         
  49.                 libxml_clear_errors();
  50.                 if ($xml_errors) {                             
  51.                     $error_msg = '<strong>' . __('Invalid XML', 'pmxi_plugin') . '</strong><ul>';
  52.                     foreach($xml_errors as $error) {
  53.                         $error_msg .= '<li>';
  54.                         $error_msg .= __('Line', 'pmxi_plugin') . ' ' . $error->line . ', ';
  55.                         $error_msg .= __('Column', 'pmxi_plugin') . ' ' . $error->column . ', ';
  56.                         $error_msg .= __('Code', 'pmxi_plugin') . ' ' . $error->code . ': ';
  57.                         $error_msg .= '<em>' . trim(esc_html($error->message)) . '</em>';
  58.                         $error_msg .= '</li>';
  59.                     }
  60.                     $error_msg .= '</ul>';
  61.                     $errors and $errors->add('form-validation', $error_msg);               
  62.                 } else {
  63.                     return true;
  64.                 }
  65.             }
  66.             else{
  67.                 $errors and $errors->add('form-validation', __('Required PHP components are missing.', 'pmxi_plugin'));            
  68.                 $errors and $errors->add('form-validation', __('WP All Import requires the SimpleXML PHP module to be installed. This is a standard feature of PHP, and is necessary for WP All Import to read the files you are trying to import.<br/>Please contact your web hosting provider and ask them to install and activate the SimpleXML PHP module.', 'pmxi_plugin'));              
  69.             }
  70.         }
  71.         return false;
  72.     }
  73.  
  74.     /**
  75.      * Initialize model instance
  76.      * @param array[optional] $data Array of record data to initialize object with
  77.      */
  78.     public function __construct($data = array()) {
  79.         parent::__construct($data);
  80.         $this->setTable(PMXI_Plugin::getInstance()->getTablePrefix() . 'imports');
  81.         $this->errors = new WP_Error();
  82.     }
  83.  
  84.     /**
  85.      * Import all files matched by path
  86.      * @param callback[optional] $logger Method where progress messages are submmitted
  87.      * @return PMXI_Import_Record
  88.      * @chainable
  89.      */
  90.     public function execute($logger = NULL, $cron = true, $history_log_id = false) {
  91.                
  92.         $uploads = wp_upload_dir();
  93.  
  94.         if ($this->path) {
  95.            
  96.             $files = array($this->path);                   
  97.            
  98.             foreach ($files as $ind => $path) {            
  99.  
  100.                 $filePath = '';
  101.  
  102.                 if ( $this->queue_chunk_number == 0 and $this->processing == 0 ) {
  103.  
  104.                     $this->set(array('processing' => 1))->update(); // lock cron requests  
  105.  
  106.                     if ($this->type == 'url'){
  107.  
  108.                         $uploader = new PMXI_Upload(trim($this->path), $this->errors);         
  109.                         $upload_result = $uploader->url($this->feed_type);                     
  110.                         if ($upload_result instanceof WP_Error){
  111.                             $this->errors = $upload_result;    
  112.                         }          
  113.                         else {
  114.                             $filePath  = $upload_result['filePath'];
  115.                         }
  116.                     }
  117.                     elseif ( $this->type == 'file'){
  118.                        
  119.                         $uploader = new PMXI_Upload(trim(basename($this->path)), $this->errors);           
  120.                         $upload_result = $uploader->file();                
  121.                         if ($upload_result instanceof WP_Error){
  122.                             $this->errors = $upload_result;    
  123.                         }          
  124.                         else{
  125.                             $filePath  = $upload_result['filePath'];
  126.                         }
  127.                     }
  128.                     elseif ( ! in_array($this->type, array('ftp'))){ // retrieve already uploaded file
  129.  
  130.                         $uploader = new PMXI_Upload(trim($this->path), $this->errors, rtrim(str_replace(basename($this->path), '', $this->path), '/'));        
  131.                         $upload_result = $uploader->upload();                  
  132.                         if ($upload_result instanceof WP_Error){
  133.                             $this->errors = $upload_result;    
  134.                         }          
  135.                         else{
  136.                             $filePath  = $upload_result['filePath'];                       
  137.                         }
  138.                     }
  139.  
  140.                     if ( ! $this->errors->get_error_codes() and "" != $filePath ) {
  141.  
  142.                         $this->set(array('queue_chunk_number' => 1))->update();                
  143.                        
  144.                     }
  145.                     elseif ( $this->errors->get_error_codes() ){
  146.  
  147.                         $msgs = $this->errors->get_error_messages();
  148.  
  149.                         if ( ! is_array($msgs)) {
  150.                             $msgs = array($msgs);
  151.                         }
  152.  
  153.                         foreach ($msgs as $msg){
  154.                             $logger and call_user_func($logger, sprintf(__('ERROR: %s', 'pmxi_plugin'), $msg));
  155.                         }                      
  156.                                                
  157.                         $this->set(array('processing' => 0))->update();
  158.  
  159.                         die;
  160.                     }
  161.                    
  162.                     $this->set(array('processing' => 0))->update(); // unlock cron requests
  163.  
  164.                 }
  165.                        
  166.                 // if empty file path, than it's mean feed in cron process. Take feed path from history.
  167.                 if (empty($filePath)){
  168.                     $history = new PMXI_File_List();
  169.                     $history->setColumns('id', 'name', 'registered_on', 'path')->getBy(array('import_id' => $this->id), 'id DESC');            
  170.                     if ($history->count()){
  171.                         $history_file = new PMXI_File_Record();
  172.                         $history_file->getBy('id', $history[0]['id']);
  173.                         $filePath = $history_file->path;                       
  174.                     }
  175.                 }          
  176.                
  177.                 // if feed path founded
  178.                 if ( ! empty($filePath) and @file_exists($filePath) ) {                
  179.                    
  180.                     if ( $this->queue_chunk_number === 1 and $this->processing == 0 ){ // import first cron request
  181.  
  182.                         $this->set(array('processing' => 1))->update(); // lock cron requests                                                                      
  183.                        
  184.                         if (empty($this->options['encoding'])){
  185.                             $currentOptions = $this->options;
  186.                             $currentOptions['encoding'] = 'UTF-8';
  187.                             $this->set(array(
  188.                                 'options' => $currentOptions
  189.                             ))->update();
  190.                         }
  191.                        
  192.                         set_time_limit(0);                                                 
  193.  
  194.                         $file = new PMXI_Chunk($filePath, array('element' => $this->root_element, 'encoding' => $this->options['encoding']));
  195.                        
  196.                         // chunks counting         
  197.                         $chunks = 0; $history_xml = '';
  198.                         while ($xml = $file->read()) {
  199.                             if (!empty($xml)) {                                            
  200.                                 PMXI_Import_Record::preprocessXml($xml);
  201.                                 $xml = "<?xml version=\"1.0\" encoding=\"". $this->options['encoding'] ."\"?>" . "\n" . $xml;                              
  202.                                
  203.                                 $dom = new DOMDocument('1.0', ( ! empty($this->options['encoding']) ) ? $this->options['encoding'] : 'UTF-8');
  204.                                 $old = libxml_use_internal_errors(true);
  205.                                 $dom->loadXML($xml);
  206.                                 libxml_use_internal_errors($old);
  207.                                 $xpath = new DOMXPath($dom);
  208.                                 if (($elements = @$xpath->query($this->xpath)) and $elements->length){
  209.                                     $chunks += $elements->length;
  210.                                     if ("" == $history_xml) $history_xml = $xml;
  211.                                 }
  212.                                 unset($dom, $xpath, $elements);
  213.                             }
  214.                         }
  215.                         unset($file);          
  216.                        
  217.                         if ( ! $chunks ){
  218.                             $logger and call_user_func($logger, sprintf(__('#%s No matching elements found for Root element and XPath expression specified', 'pmxi_plugin'), $this->id));
  219.                             $this->set(array(
  220.                                 'queue_chunk_number' => 0,
  221.                                 'processing' => 0,
  222.                                 'imported' => 0,
  223.                                 'created' => 0,
  224.                                 'updated' => 0,
  225.                                 'skipped' => 0,
  226.                                 'deleted' => 0 
  227.                             ))->update();
  228.                             die;
  229.                         }
  230.  
  231.                         // unlick previous files
  232.                         $history = new PMXI_File_List();
  233.                         $history->setColumns('id', 'name', 'registered_on', 'path')->getBy(array('import_id' => $this->id), 'id DESC');            
  234.                         if ($history->count()){
  235.                             foreach ($history as $file){                       
  236.                                 if (@file_exists($file['path']) and $file['path'] != $filePath){
  237.                                     if (in_array($this->type, array('upload')))
  238.                                         pmxi_remove_source($file['path'], false);                                  
  239.                                     else
  240.                                         pmxi_remove_source($file['path']);
  241.                                 }
  242.                                 $history_file = new PMXI_File_Record();
  243.                                 $history_file->getBy('id', $file['id']);
  244.                                 if ( ! $history_file->isEmpty()) $history_file->delete();
  245.                             }
  246.                         }
  247.  
  248.                         // update history
  249.                         $history_file = new PMXI_File_Record();
  250.                         $history_file->set(array(
  251.                             'name' => $this->name,
  252.                             'import_id' => $this->id,
  253.                             'path' => $filePath,
  254.                             //'contents' => (isset($history_xml)) ? $history_xml : '',
  255.                             'registered_on' => date('Y-m-d H:i:s')
  256.                         ))->insert();
  257.  
  258.                         do_action( 'pmxi_before_xml_import', $this->id );  
  259.  
  260.                         $this->set(array('count' => $chunks, 'processing' => 0))->update(); // set pointer to the first chunk, updates feed elements count and unlock cron process
  261.                        
  262.                     }                  
  263.                    
  264.                     // compose data to look like result of wizard steps                                
  265.                     if( $this->queue_chunk_number and $this->processing == 0 ) {   
  266.  
  267.                         $this->set(array('processing' => 1))->update(); // lock cron requests                      
  268.  
  269.                         @set_time_limit(0);                        
  270.  
  271.                         $file = new PMXI_Chunk($filePath, array('element' => $this->root_element, 'encoding' => $this->options['encoding'], 'pointer' => $this->queue_chunk_number));                  
  272.                        
  273.                         $feed = "<?xml version=\"1.0\" encoding=\"". $this->options['encoding'] ."\"?>" . "\n" . "<pmxi_records>";
  274.  
  275.                         $loop = 0;
  276.                         $xml = '';
  277.  
  278.                         $processing_time_limit = (PMXI_Plugin::getInstance()->getOption('cron_processing_time_limit')) ? PMXI_Plugin::getInstance()->getOption('cron_processing_time_limit') : 120;
  279.                         $start_rocessing_time = time();
  280.  
  281.                         $chunk_number = $this->queue_chunk_number;
  282.  
  283.                         while ($xml = $file->read() and $this->processing == 1 and (time() - $start_rocessing_time) <= $processing_time_limit ) {
  284.  
  285.                             if ( ! empty($xml) ) {
  286.  
  287.                                 $chunk_number++;
  288.  
  289.                                 PMXI_Import_Record::preprocessXml($xml);   
  290.                                 $xml_chunk = "<?xml version=\"1.0\" encoding=\"". $this->options['encoding'] ."\"?>" . "\n" . $xml;                                            
  291.  
  292.                                 $dom = new DOMDocument('1.0', ( ! empty($this->options['encoding']) ) ? $this->options['encoding'] : 'UTF-8');                                                         
  293.                                 $old = libxml_use_internal_errors(true);
  294.                                 $dom->loadXML($xml_chunk);                             
  295.                                 libxml_use_internal_errors($old);
  296.                                 $xpath = new DOMXPath($dom);
  297.  
  298.                                 if (($elements = @$xpath->query($this->xpath)) and $elements->length){                                 
  299.                                     $feed .= $xml;                                                                     
  300.                                     $loop += $elements->length;
  301.                                 }
  302.  
  303.                                 unset($dom, $xpath, $elements);                        
  304.  
  305.                             }                                                      
  306.                             if ($loop == $this->options['records_per_request'] or $this->count == $this->imported + $this->skipped or $this->count == $loop + $this->imported + $this->skipped ){ // skipping scheduled imports if any for the next hit
  307.                                 $feed .= "</pmxi_records>";    
  308.  
  309.                                 $this->process($feed, $logger, $chunk_number, $cron, '/pmxi_records');
  310.                                
  311.                                 // set last update
  312.                                 $this->set(array(
  313.                                     'registered_on' => date('Y-m-d H:i:s'),
  314.                                     'queue_chunk_number' => $chunk_number
  315.                                 ))->update();  
  316.  
  317.                                 $loop = 0;
  318.                                 $feed = "<?xml version=\"1.0\" encoding=\"". $this->options['encoding'] ."\"?>" . "\n" . "<pmxi_records>";
  319.                             }                          
  320.                         }
  321.                        
  322.                         unset($file);                              
  323.                        
  324.                         // delect, if cron process if finished
  325.                         if ( (int) $this->count <= (int) $this->imported + (int) $this->skipped ){
  326.                            
  327.                             // Delete posts that are no longer present in your file
  328.                             if (! empty($this->options['is_delete_missing']) and $this->options['duplicate_matching'] == 'auto'){
  329.  
  330.                                 $postList = new PMXI_Post_List();                                              
  331.                                 $missing_ids = array();
  332.                                 $missingPosts = $postList->getBy(array('import_id' => $this->id, 'iteration !=' => $this->iteration));
  333.  
  334.                                 if ( ! $missingPosts->isEmpty() ):
  335.                                
  336.                                     foreach ($missingPosts as $missingPost) {
  337.                                        
  338.                                         $missing_ids[] = $missingPost['post_id'];
  339.  
  340.                                         // Instead of deletion, set Custom Field
  341.                                         if ($this->options['is_update_missing_cf']){
  342.                                             update_post_meta( $missingPost['post_id'], $this->options['update_missing_cf_name'], $this->options['update_missing_cf_value'] );
  343.                                         }
  344.  
  345.                                         // Instead of deletion, change post status to Draft
  346.                                         if ($this->options['set_missing_to_draft']) $this->wpdb->update( $this->wpdb->posts, array('post_status' => 'draft'), array('ID' => $missingPost['post_id']) );                                    
  347.  
  348.                                         // Delete posts that are no longer present in your file
  349.                                         if ( ! $this->options['is_update_missing_cf'] and ! $this->options['set_missing_to_draft']){
  350.  
  351.                                             // Remove attachments
  352.                                             empty($this->options['is_keep_attachments']) and wp_delete_attachments($missingPost['post_id'], true, 'files');
  353.                                             // Remove images
  354.                                             empty($this->options['is_keep_imgs']) and wp_delete_attachments($missingPost['post_id'], ($this->options['download_images'] == 'yes'));
  355.  
  356.                                             if ( ! empty($missingPost['id'])){
  357.                                                 // Delete record form pmxi_posts                       
  358.                                                 $missingRecord = new PMXI_Post_Record();
  359.                                                 $missingRecord->getById($missingPost['id'])->delete();                     
  360.                                             }
  361.                                             else {
  362.                                                 $sql = "DELETE FROM " . PMXI_Plugin::getInstance()->getTablePrefix() . "posts WHERE post_id = " . $missingPost['post_id'] . " AND import_id = " . $missingPost['import_id'];
  363.                                                 $this->wpdb->query(
  364.                                                     $this->wpdb->prepare($sql, '')
  365.                                                 ); 
  366.                                             }
  367.                                                                                    
  368.                                             // Clear post's relationships
  369.                                             if ( $this->options['custom_type'] != "import_users" ) wp_delete_object_term_relationships($missingPost['post_id'], get_object_taxonomies('' != $this->options['custom_type'] ? $this->options['custom_type'] : 'post'));
  370.                                         }
  371.                                                                        
  372.                                     }  
  373.  
  374.                                 endif;                         
  375.  
  376.                                 // Delete posts from database
  377.                                 if (!empty($missing_ids) && is_array($missing_ids) and ! $this->options['is_update_missing_cf'] and ! $this->options['set_missing_to_draft']){                                 
  378.                                    
  379.                                     do_action('pmxi_delete_post', $missing_ids);
  380.                                    
  381.                                     if ( $this->options['custom_type'] == "import_users" ){
  382.                                         $sql = "delete a,b
  383.                                         FROM ".$this->wpdb->users." a
  384.                                         LEFT JOIN ".$this->wpdb->usermeta." b ON ( a.ID = b.user_id )                                      
  385.                                         WHERE a.ID IN (".implode(',', $missing_ids).");";
  386.                                     }
  387.                                     else {
  388.                                         $sql = "delete a,b,c
  389.                                         FROM ".$this->wpdb->posts." a
  390.                                         LEFT JOIN ".$this->wpdb->term_relationships." b ON ( a.ID = b.object_id )
  391.                                         LEFT JOIN ".$this->wpdb->postmeta." c ON ( a.ID = c.post_id )              
  392.                                         WHERE a.ID IN (".implode(',', $missing_ids).");";
  393.                                     }
  394.  
  395.                                     $this->wpdb->query(
  396.                                         $this->wpdb->prepare($sql, '')
  397.                                     );         
  398.  
  399.                                     $this->set(array('deleted' => count($missing_ids)))->update();
  400.                                 }
  401.                             }
  402.  
  403.                             // Set out of stock status for missing records [Woocommerce add-on option]
  404.                             if (empty($this->options['is_delete_missing']) and $this->options['custom_type'] == "product" and class_exists('PMWI_Plugin') and !empty($this->options['missing_records_stock_status'])) {
  405.                                
  406.                                 $postList = new PMXI_Post_List();                                                                          
  407.                                 $missingPosts = $postList->getBy(array('import_id' => $this->id, 'iteration !=' => $this->iteration));
  408.                                 if ( ! $missingPosts->isEmpty() ){
  409.                                     foreach ($missingPosts as $missingPost) {
  410.                                         update_post_meta( $missingPost['post_id'], '_stock_status', 'outofstock' );
  411.                                         update_post_meta( $missingPost['post_id'], '_stock', 0 );
  412.                                     }
  413.                                 }
  414.                             }                          
  415.  
  416.                             $this->set(array(
  417.                                 'processing' => 0,
  418.                                 'triggered' => 0,
  419.                                 'queue_chunk_number' => 0,
  420.                                 'registered_on' => date('Y-m-d H:i:s'), // update registered_on to indicated that job has been exectured even if no files are going to be imported by the rest of the method
  421.                                 'iteration' => ++$this->iteration
  422.                             ))->update();                          
  423.  
  424.                             wp_cache_flush();
  425.                             foreach ( get_taxonomies() as $tax ) {             
  426.                                 delete_option( "{$tax}_children" );
  427.                                 _get_term_hierarchy( $tax );
  428.                             }                              
  429.  
  430.                             if ( $history_log_id ){                                                        
  431.                                 $history_log = new PMXI_History_Record();                      
  432.                                 $history_log->getById( $history_log_id );
  433.                                 if ( ! $history_log->isEmpty() ){
  434.                                     $custom_type = get_post_type_object( $this->options['custom_type'] );      
  435.                                     $history_log->set(array(
  436.                                         'time_run' => time() - strtotime($history_log->date),
  437.                                         'summary' => sprintf(__("import finished & cron un-triggered<br>%s %s created %s updated %s deleted %s skipped", "pmxi_plugin"), $this->created, $custom_type->labels->name, $this->updated, $this->deleted, $this->skipped)
  438.                                     ))->save();                                                                
  439.                                 }
  440.                             }
  441.  
  442.                             do_action( 'pmxi_after_xml_import', $this->id );
  443.  
  444.                             $logger and call_user_func($logger, sprintf(__('Import #%s complete', 'pmxi_plugin'), $this->id));                         
  445.  
  446.                         }
  447.                         else{  
  448.  
  449.                             $this->set(array(
  450.                                 'processing' => 0                              
  451.                             ))->update();          
  452.  
  453.                             if ( $history_log_id ){
  454.                                 $history_log = new PMXI_History_Record();                      
  455.                                 $history_log->getById( $history_log_id );
  456.                                 if ( ! $history_log->isEmpty() ){
  457.                                     $custom_type = get_post_type_object( $this->options['custom_type'] );      
  458.                                     $history_log->set(array(
  459.                                         'time_run' => time() - strtotime($history_log->date),
  460.                                         'summary' => sprintf(__("%d %s created %d updated %d deleted %d skipped", "pmxi_plugin"), $this->created, $custom_type->labels->name, $this->updated, $this->deleted, $this->skipped)
  461.                                     ))->save();                                                                
  462.                                 }
  463.                             }
  464.                            
  465.                             $logger and call_user_func($logger, sprintf(__('Records Count %s', 'pmxi_plugin'), (int) $this->count));
  466.                             $logger and call_user_func($logger, sprintf(__('Records Processed %s', 'pmxi_plugin'), (int) $this->imported + (int) $this->skipped));
  467.                            
  468.                         }
  469.                     }                  
  470.                 }
  471.                 else {
  472.                     $this->set(array(
  473.                         'processing' => 0,
  474.                         'triggered' => 0,
  475.                         'queue_chunk_number' => 0,
  476.                         'imported' => 0,
  477.                         'created' => 0,
  478.                         'updated' => 0,
  479.                         'skipped' => 0,
  480.                         'deleted' => 0                                     
  481.                     ))->update();
  482.                     $logger and call_user_func($logger, sprintf(__('#%s source file not found', 'pmxi_plugin'), $this->id));
  483.                     die;
  484.                 }                                                                              
  485.             }          
  486.         }
  487.         return $this;
  488.     }
  489.    
  490.     public $post_meta_to_insert = array();
  491.  
  492.     /**
  493.      * Perform import operation
  494.      * @param string $xml XML string to import
  495.      * @param callback[optional] $logger Method where progress messages are submmitted
  496.      * @return PMXI_Import_Record
  497.      * @chainable
  498.      */
  499.     public function process($xml, $logger = NULL, $chunk = false, $is_cron = false, $xpath_prefix = '', $loop = 0) {
  500.         add_filter('user_has_cap', array($this, '_filter_has_cap_unfiltered_html')); kses_init(); // do not perform special filtering for imported content
  501.        
  502.         kses_remove_filters();
  503.  
  504.         $cxpath = $xpath_prefix . $this->xpath;    
  505.  
  506.         $this->options += PMXI_Plugin::get_default_import_options(); // make sure all options are defined
  507.        
  508.         $avoid_pingbacks = PMXI_Plugin::getInstance()->getOption('pingbacks');
  509.  
  510.         $cron_sleep = (int) PMXI_Plugin::getInstance()->getOption('cron_sleep');
  511.        
  512.         if ( $avoid_pingbacks and ! defined( 'WP_IMPORTING' ) ) define( 'WP_IMPORTING', true );
  513.  
  514.         $postRecord = new PMXI_Post_Record();      
  515.        
  516.         $tmp_files = array();
  517.         // compose records to import
  518.         $records = array();
  519.  
  520.         $is_import_complete = false;
  521.        
  522.         try {                      
  523.            
  524.             $chunk == 1 and $logger and call_user_func($logger, __('Composing titles...', 'pmxi_plugin'));
  525.             if ( ! empty($this->options['title'])){
  526.                 $titles = XmlImportParser::factory($xml, $cxpath, $this->options['title'], $file)->parse($records); $tmp_files[] = $file;                          
  527.             }
  528.             else{
  529.                 $loop and $titles = array_fill(0, $loop, '');
  530.             }
  531.  
  532.             $chunk == 1 and $logger and call_user_func($logger, __('Composing excerpts...', 'pmxi_plugin'));           
  533.             $post_excerpt = array();
  534.             if ( ! empty($this->options['post_excerpt']) ){
  535.                 $post_excerpt = XmlImportParser::factory($xml, $cxpath, $this->options['post_excerpt'], $file)->parse($records); $tmp_files[] = $file;
  536.             }
  537.             else{
  538.                 count($titles) and $post_excerpt = array_fill(0, count($titles), '');
  539.             }          
  540.  
  541.             if ( "xpath" == $this->options['status'] ){
  542.                 $chunk == 1 and $logger and call_user_func($logger, __('Composing statuses...', 'pmxi_plugin'));           
  543.                 $post_status = array();
  544.                 if (!empty($this->options['status_xpath'])){
  545.                     $post_status = XmlImportParser::factory($xml, $cxpath, $this->options['status_xpath'], $file)->parse($records); $tmp_files[] = $file;
  546.                 }
  547.                 else{
  548.                     count($titles) and $post_status = array_fill(0, count($titles), '');
  549.                 }
  550.             }
  551.  
  552.             $chunk == 1 and $logger and call_user_func($logger, __('Composing authors...', 'pmxi_plugin'));        
  553.             $post_author = array();
  554.             $current_user = wp_get_current_user();
  555.  
  556.             if (!empty($this->options['author'])){
  557.                 $post_author = XmlImportParser::factory($xml, $cxpath, $this->options['author'], $file)->parse($records); $tmp_files[] = $file;
  558.                 foreach ($post_author as $key => $author) {
  559.                     $user = get_user_by('login', $author) or $user = get_user_by('slug', $author) or $user = get_user_by('email', $author) or ctype_digit($author) and $user = get_user_by('id', $author);                 
  560.                     $post_author[$key] = (!empty($user)) ? $user->ID : $current_user->ID;
  561.                 }
  562.             }
  563.             else{                              
  564.                 count($titles) and $post_author = array_fill(0, count($titles), $current_user->ID);
  565.             }          
  566.  
  567.             $chunk == 1 and $logger and call_user_func($logger, __('Composing slugs...', 'pmxi_plugin'));          
  568.             $post_slug = array();
  569.             if (!empty($this->options['post_slug'])){
  570.                 $post_slug = XmlImportParser::factory($xml, $cxpath, $this->options['post_slug'], $file)->parse($records); $tmp_files[] = $file;
  571.             }
  572.             else{
  573.                 count($titles) and $post_slug = array_fill(0, count($titles), '');
  574.             }
  575.  
  576.             $chunk == 1 and $logger and call_user_func($logger, __('Composing menu order...', 'pmxi_plugin'));         
  577.             $menu_order = array();
  578.             if (!empty($this->options['order'])){
  579.                 $menu_order = XmlImportParser::factory($xml, $cxpath, $this->options['order'], $file)->parse($records); $tmp_files[] = $file;
  580.             }
  581.             else{
  582.                 count($titles) and $menu_order = array_fill(0, count($titles), '');
  583.             }
  584.  
  585.             $chunk == 1 and $logger and call_user_func($logger, __('Composing contents...', 'pmxi_plugin'));                                   
  586.             if (!empty($this->options['content'])){
  587.                 $contents = XmlImportParser::factory(
  588.                     ((!empty($this->options['is_keep_linebreaks']) and intval($this->options['is_keep_linebreaks'])) ? $xml : preg_replace('%\r\n?|\n%', ' ', $xml)),
  589.                     $cxpath,
  590.                     $this->options['content'],
  591.                     $file)->parse($records
  592.                 ); $tmp_files[] = $file;                       
  593.             }
  594.             else{
  595.                 count($titles) and $contents = array_fill(0, count($titles), '');
  596.             }
  597.                                        
  598.             $chunk == 1 and $logger and call_user_func($logger, __('Composing dates...', 'pmxi_plugin'));
  599.             if ('specific' == $this->options['date_type']) {
  600.                 $dates = XmlImportParser::factory($xml, $cxpath, $this->options['date'], $file)->parse($records); $tmp_files[] = $file;
  601.                 $warned = array(); // used to prevent the same notice displaying several times
  602.                 foreach ($dates as $i => $d) {
  603.                     if ($d == 'now') $d = current_time('mysql'); // Replace 'now' with the WordPress local time to account for timezone offsets (WordPress references its local time during publishing rather than the server’s time so it should use that)
  604.                     $time = strtotime($d);
  605.                     if (FALSE === $time) {
  606.                         in_array($d, $warned) or $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: unrecognized date format `%s`, assigning current date', 'pmxi_plugin'), $warned[] = $d));
  607.                         $logger and !$is_cron and PMXI_Plugin::$session->warnings++;
  608.                         $time = time();
  609.                     }
  610.                     $dates[$i] = date('Y-m-d H:i:s', $time);
  611.                 }
  612.             } else {
  613.                 $dates_start = XmlImportParser::factory($xml, $cxpath, $this->options['date_start'], $file)->parse($records); $tmp_files[] = $file;
  614.                 $dates_end = XmlImportParser::factory($xml, $cxpath, $this->options['date_end'], $file)->parse($records); $tmp_files[] = $file;
  615.                 $warned = array(); // used to prevent the same notice displaying several times
  616.                 foreach ($dates_start as $i => $d) {
  617.                     $time_start = strtotime($dates_start[$i]);
  618.                     if (FALSE === $time_start) {
  619.                         in_array($dates_start[$i], $warned) or $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: unrecognized date format `%s`, assigning current date', 'pmxi_plugin'), $warned[] = $dates_start[$i]));
  620.                         $logger and !$is_cron and PMXI_Plugin::$session->warnings++;
  621.                         $time_start = time();
  622.                     }
  623.                     $time_end = strtotime($dates_end[$i]);
  624.                     if (FALSE === $time_end) {
  625.                         in_array($dates_end[$i], $warned) or $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: unrecognized date format `%s`, assigning current date', 'pmxi_plugin'), $warned[] = $dates_end[$i]));
  626.                         $logger and !$is_cron and PMXI_Plugin::$session->warnings++;
  627.                         $time_end = time();
  628.                     }                  
  629.                     $dates[$i] = date('Y-m-d H:i:s', mt_rand($time_start, $time_end));
  630.                 }
  631.             }
  632.                        
  633.             // [custom taxonomies]
  634.             require_once(ABSPATH . 'wp-admin/includes/taxonomy.php');
  635.  
  636.             $taxonomies = array();                     
  637.             $exclude_taxonomies = (class_exists('PMWI_Plugin')) ? array('post_format', 'product_type', 'product_shipping_class') : array('post_format');   
  638.             $post_taxonomies = array_diff_key(get_taxonomies_by_object_type(array($this->options['custom_type']), 'object'), array_flip($exclude_taxonomies));
  639.             if ( ! empty($post_taxonomies) ):
  640.                 foreach ($post_taxonomies as $ctx): if ("" == $ctx->labels->name or (class_exists('PMWI_Plugin') and strpos($ctx->name, "pa_") === 0 and $this->options['custom_type'] == "product")) continue;
  641.                     $chunk == 1 and $logger and call_user_func($logger, sprintf(__('Composing terms for `%s` taxonomy...', 'pmxi_plugin'), $ctx->labels->name));
  642.                     $tx_name = $ctx->name;
  643.                     $mapping_rules = ( ! empty($this->options['tax_mapping'][$tx_name])) ? json_decode($this->options['tax_mapping'][$tx_name], true) : false;
  644.                     $taxonomies[$tx_name] = array();
  645.                     if ( ! empty($this->options['tax_logic'][$tx_name]) ){
  646.                         switch ($this->options['tax_logic'][$tx_name]){
  647.                             case 'single':
  648.                                 if ( ! empty($this->options['tax_single_xpath'][$tx_name]) ){
  649.                                     $txes = XmlImportParser::factory($xml, $cxpath, str_replace('\'','"',$this->options['tax_single_xpath'][$tx_name]), $file)->parse($records); $tmp_files[] = $file;     
  650.                                     foreach ($txes as $i => $tx) {
  651.                                         $taxonomies[$tx_name][$i][] = pmxi_ctx_mapping(array(
  652.                                             'name' => $tx,
  653.                                             'parent' => false,
  654.                                             'assign' => $this->options['tax_assing'][$tx_name],
  655.                                             'is_mapping' => (!empty($this->options['tax_enable_mapping'][$tx_name]))
  656.                                         ), $mapping_rules, $tx_name);
  657.                                     }                                  
  658.                                 }
  659.                                 break;
  660.                             case 'multiple':
  661.                                 if ( ! empty($this->options['tax_multiple_xpath'][$tx_name]) ){
  662.                                     $txes = XmlImportParser::factory($xml, $cxpath, str_replace('\'','"',$this->options['tax_multiple_xpath'][$tx_name]), $file)->parse($records); $tmp_files[] = $file;       
  663.                                     foreach ($txes as $i => $tx) {
  664.                                         $delimeted_taxonomies = explode( ! empty($this->options['tax_multiple_delim'][$tx_name]) ? $this->options['tax_multiple_delim'][$tx_name] : ',', $tx);
  665.                                         if ( ! empty($delimeted_taxonomies) ){
  666.                                             foreach ($delimeted_taxonomies as $cc) {                                               
  667.                                                 $taxonomies[$tx_name][$i][] = pmxi_ctx_mapping(array(
  668.                                                     'name' => $cc,
  669.                                                     'parent' => false,
  670.                                                     'assign' => $this->options['tax_assing'][$tx_name],
  671.                                                     'is_mapping' => (!empty($this->options['tax_enable_mapping'][$tx_name]))
  672.                                                 ), $mapping_rules, $tx_name);
  673.                                             }
  674.                                         }
  675.                                     }
  676.                                 }
  677.                                 break;
  678.                             case 'hierarchical':
  679.                                 if ( ! empty($this->options['tax_hierarchical_logic'][$tx_name])){
  680.                                     switch ($this->options['tax_hierarchical_logic'][$tx_name]) {
  681.                                         case 'entire':
  682.                                             if (! empty($this->options['tax_hierarchical_xpath'][$tx_name]) and is_array($this->options['tax_hierarchical_xpath'][$tx_name])){
  683.                                                 count($titles) and $iterator = array_fill(0, count($titles), 0);
  684.                                                 foreach ($this->options['tax_hierarchical_xpath'][$tx_name] as $tx_xpath) { if (empty($tx_xpath)) continue;
  685.                                                     $txes = XmlImportParser::factory($xml, $cxpath, str_replace('\'','"',$tx_xpath), $file)->parse($records); $tmp_files[] = $file;    
  686.                                                     foreach ($txes as $i => $tx) {
  687.                                                         $delimeted_taxonomies = explode( ! empty($this->options['tax_hierarchical_delim'][$tx_name]) ? $this->options['tax_hierarchical_delim'][$tx_name] : ',', $tx);
  688.                                                         if ( ! empty($delimeted_taxonomies) ){                                                         
  689.                                                             foreach ($delimeted_taxonomies as $j => $cc) {                                                                                                             
  690.                                                                 $taxonomies[$tx_name][$i][] = pmxi_ctx_mapping(array(
  691.                                                                     'name' => $cc,
  692.                                                                     'parent' => (!empty($taxonomies[$tx_name][$i][$iterator[$i] - 1]) and $j) ? $taxonomies[$tx_name][$i][$iterator[$i] - 1] : false,
  693.                                                                     'assign' => $this->options['tax_assing'][$tx_name],
  694.                                                                     'is_mapping' => (!empty($this->options['tax_enable_mapping'][$tx_name]))
  695.                                                                 ), $mapping_rules, $tx_name);                                                          
  696.                                                                 $iterator[$i]++;   
  697.                                                             }
  698.                                                         }
  699.                                                     }
  700.                                                 }                                                  
  701.                                             }
  702.                                             break;                                     
  703.                                         case 'manual':
  704.                                             if ( ! empty($this->options['post_taxonomies'][$tx_name]) ){
  705.                                                 $taxonomies_hierarchy = json_decode($this->options['post_taxonomies'][$tx_name], true);
  706.                                                
  707.                                                 foreach ($taxonomies_hierarchy as $k => $taxonomy){ if ("" == $taxonomy['xpath']) continue;                            
  708.                                                     $txes_raw =  XmlImportParser::factory($xml, $cxpath, str_replace('\'','"',$taxonomy['xpath']), $file)->parse($records); $tmp_files[] = $file;                      
  709.                                                     $warned = array();
  710.                                                    
  711.                                                     foreach ($txes_raw as $i => $cc) {
  712.                                                         if (empty($taxonomies_hierarchy[$k]['txn_names'][$i])) $taxonomies_hierarchy[$k]['txn_names'][$i] = array();
  713.                                                         if (empty($taxonomies[$tx_name][$i])) $taxonomies[$tx_name][$i] = array();
  714.                                                         $count_cats = count($taxonomies[$tx_name][$i]);                                                                                                        
  715.                                                        
  716.                                                         if (!empty($taxonomy['parent_id'])) {                                                                          
  717.                                                             foreach ($taxonomies_hierarchy as $key => $value){
  718.                                                                 if ($value['item_id'] == $taxonomy['parent_id'] and !empty($value['txn_names'][$i])){                                                  
  719.                                                                     foreach ($value['txn_names'][$i] as $parent) {                                                                         
  720.                                                                         $taxonomies[$tx_name][$i][] = pmxi_ctx_mapping(array(
  721.                                                                             'name' => trim($cc),
  722.                                                                             'parent' => $parent,
  723.                                                                             'assign' => $this->options['tax_assing'][$tx_name],
  724.                                                                             'is_mapping' => (!empty($this->options['tax_enable_mapping'][$tx_name]))
  725.                                                                         ), $mapping_rules, $tx_name);                                                                      
  726.                                                                     }                                                                                                              
  727.                                                                 }
  728.                                                             }                                                          
  729.                                                         }
  730.                                                         else {                                                             
  731.                                                             $taxonomies[$tx_name][$i][] = pmxi_ctx_mapping(array(
  732.                                                                 'name' => trim($cc),
  733.                                                                 'parent' => false,
  734.                                                                 'assign' => $this->options['tax_assing'][$tx_name],
  735.                                                                 'is_mapping' => (!empty($this->options['tax_enable_mapping'][$tx_name]))
  736.                                                             ), $mapping_rules, $tx_name);
  737.                                                         }                              
  738.                                                        
  739.                                                         if ($count_cats < count($taxonomies[$tx_name][$i])) $taxonomies_hierarchy[$k]['txn_names'][$i][] = $taxonomies[$tx_name][$i][count($taxonomies[$tx_name][$i]) - 1];
  740.                                                     }
  741.                                                 }
  742.                                             }
  743.                                             break;
  744.  
  745.                                         default:
  746.                                            
  747.                                             break;
  748.                                     }
  749.                                 }                              
  750.                                 break;
  751.  
  752.                             default:
  753.                                            
  754.                                 break;
  755.                         }
  756.                     }
  757.                 endforeach;
  758.             endif;         
  759.             // [/custom taxonomies]            
  760.  
  761.             // [custom fields]
  762.             $chunk == 1 and $logger and call_user_func($logger, __('Composing custom parameters...', 'pmxi_plugin'));
  763.             $meta_keys = array(); $meta_values = array();          
  764.            
  765.             foreach ($this->options['custom_name'] as $j => $custom_name) {
  766.                 $meta_keys[$j]   = XmlImportParser::factory($xml, $cxpath, $custom_name, $file)->parse($records); $tmp_files[] = $file;
  767.                 if (is_serialized($this->options['custom_value'][$j])){
  768.                     $meta_values[$j] = array_fill(0, count($titles), $this->options['custom_value'][$j]);
  769.                 }
  770.                 else{
  771.                     if ('' != $this->options['custom_value'][$j] and ! is_serialized($this->options['custom_value'][$j])){
  772.                         $meta_values[$j] = XmlImportParser::factory($xml, $cxpath, $this->options['custom_value'][$j], $file)->parse($records); $tmp_files[] = $file;
  773.                         // mapping custom fields
  774.                        
  775.                         if ( ! empty($this->options['custom_mapping_rules'][$j])){
  776.                             $mapping_rules = (!empty($this->options['custom_mapping_rules'][$j])) ? json_decode($this->options['custom_mapping_rules'][$j], true) : false; 
  777.                             if ( ! empty($mapping_rules) and is_array($mapping_rules)){
  778.                                 foreach ($meta_values[$j] as $key => $val) {
  779.                                     foreach ($mapping_rules as $rule_number => $rule) {
  780.                                         if ( ! empty($rule[trim($val)])){
  781.                                             $meta_values[$j][$key] = trim($rule[trim($val)]);                                      
  782.                                             break;
  783.                                         }
  784.                                     }                                  
  785.                                 }
  786.                             }
  787.                         }                      
  788.                     }                  
  789.                     else{
  790.                         $meta_values[$j] = array_fill(0, count($titles), '');
  791.                     }
  792.                 }
  793.             }      
  794.  
  795.             // serialized custom post fields
  796.             $serialized_meta = array();
  797.  
  798.             if ( ! empty($meta_keys) ){
  799.  
  800.                 foreach ($meta_keys as $j => $custom_name) {                                                   
  801.                    
  802.                     if ( ! in_array($custom_name[0], array_keys($serialized_meta)) ){
  803.  
  804.                         // custom field in serialized format
  805.                         if (!empty($this->options['custom_format']) and $this->options['custom_format'][$j])
  806.                         {
  807.                             $meta_values[$j] = array_fill(0, count($titles), array());
  808.  
  809.                             $serialized_values = (!empty($this->options['serialized_values'][$j])) ? json_decode($this->options['serialized_values'][$j], true) : false;                                                       
  810.                            
  811.                             if (!empty($serialized_values) and is_array($serialized_values)) {
  812.                                
  813.                                 $serialized_meta_keys = array(); $serialized_meta_values = array();
  814.  
  815.                                 foreach ( array_filter($serialized_values) as $key => $value) {
  816.                                     $k = $key;
  817.                                     if (is_array($value)){
  818.                                         $keys = array_keys($value);
  819.                                         $k = $keys[0];
  820.                                     }
  821.                                     if (empty($k) or is_numeric($k)){
  822.                                         array_push($serialized_meta_keys, array_fill(0, count($titles), $k));
  823.                                     }
  824.                                     else{
  825.                                         array_push($serialized_meta_keys, XmlImportParser::factory($xml, $cxpath, $k, $file)->parse($records)); $tmp_files[] = $file;
  826.                                     }
  827.                                     $v = (is_array($value)) ? $value[$k] : $value;
  828.                                     if ( "" == $v){
  829.                                         array_push($serialized_meta_values, array_fill(0, count($titles), ""));
  830.                                     }
  831.                                     elseif ( is_serialized($v) ){
  832.                                         array_push($serialized_meta_values, array_fill(0, count($titles), $v));
  833.                                     }
  834.                                     else{
  835.                                         array_push($serialized_meta_values, XmlImportParser::factory($xml, $cxpath, $v, $file)->parse($records)); $tmp_files[] = $file;
  836.                                     }
  837.                                 }                              
  838.  
  839.                                 if (!empty($serialized_meta_keys)){
  840.                                     foreach ($serialized_meta_keys as $skey => $sval) {
  841.                                         foreach ($sval as $ipost => $ival) {
  842.                                             $v = (is_serialized($serialized_meta_values[$skey][$ipost])) ? unserialize($serialized_meta_values[$skey][$ipost]) : $serialized_meta_values[$skey][$ipost];
  843.                                             ( "" == $ival or is_numeric($ival) ) ? array_push($meta_values[$j][$ipost], $v) : $meta_values[$j][$ipost][$ival] = $v;                                        
  844.                                         }                                                                              
  845.                                     }
  846.                                 }
  847.  
  848.                             }
  849.  
  850.                         }
  851.                        
  852.                         $serialized_meta[stripcslashes($custom_name[0])] = $meta_values[$j];
  853.                        
  854.                     }                  
  855.                 }
  856.             }  
  857.             // [/custom fields]                        
  858.  
  859.             // Composing featured images
  860.             if ( ! (($uploads = wp_upload_dir()) && false === $uploads['error'])) {
  861.                 $logger and call_user_func($logger, __('<b>WARNING</b>', 'pmxi_plugin') . ': ' . $uploads['error']);
  862.                 $logger and call_user_func($logger, __('<b>WARNING</b>: No featured images will be created. Uploads folder is not found.', 'pmxi_plugin'));            
  863.                 $logger and !$is_cron and PMXI_Plugin::$session->warnings++;               
  864.             } else {
  865.                 $chunk == 1 and $logger and call_user_func($logger, __('Composing URLs for featured images...', 'pmxi_plugin'));
  866.                 $featured_images = array();            
  867.                 if ( "no" == $this->options['download_images']){
  868.                     if ($this->options['featured_image']) {                
  869.                         $featured_images = XmlImportParser::factory($xml, $cxpath, $this->options['featured_image'], $file)->parse($records); $tmp_files[] = $file;                                                                            
  870.                     } else {
  871.                         count($titles) and $featured_images = array_fill(0, count($titles), '');
  872.                     }                  
  873.                 }
  874.                 else{
  875.                     if ($this->options['download_featured_image']) {                   
  876.                         $featured_images = XmlImportParser::factory($xml, $cxpath, $this->options['download_featured_image'], $file)->parse($records); $tmp_files[] = $file;                                                                               
  877.                     } else {
  878.                         count($titles) and $featured_images = array_fill(0, count($titles), '');
  879.                     }
  880.                 }              
  881.             }  
  882.            
  883.             // Composing images meta titles
  884.             if ( $this->options['set_image_meta_title'] ){                                                                 
  885.                 $chunk == 1 and $logger and call_user_func($logger, __('Composing image meta data (titles)...', 'pmxi_plugin'));
  886.                 $image_meta_titles = array();              
  887.  
  888.                 if ($this->options['image_meta_title']) {                  
  889.                     $image_meta_titles = XmlImportParser::factory($xml, $cxpath, $this->options['image_meta_title'], $file)->parse($records); $tmp_files[] = $file;                    
  890.                 } else {
  891.                     count($titles) and $image_meta_titles = array_fill(0, count($titles), '');
  892.                 }
  893.             }
  894.  
  895.             // Composing images meta captions
  896.             if ( $this->options['set_image_meta_caption'] ){   
  897.                 $chunk == 1 and $logger and call_user_func($logger, __('Composing image meta data (captions)...', 'pmxi_plugin'));
  898.                 $image_meta_captions = array();            
  899.                 if ($this->options['image_meta_caption']) {                
  900.                     $image_meta_captions = XmlImportParser::factory($xml, $cxpath, $this->options['image_meta_caption'], $file)->parse($records); $tmp_files[] = $file;                            
  901.                 } else {
  902.                     count($titles) and $image_meta_captions = array_fill(0, count($titles), '');
  903.                 }
  904.             }
  905.  
  906.             // Composing images meta alt text
  907.             if ( $this->options['set_image_meta_alt'] ){   
  908.                 $chunk == 1 and $logger and call_user_func($logger, __('Composing image meta data (alt text)...', 'pmxi_plugin'));
  909.                 $image_meta_alts = array();            
  910.                 if ($this->options['image_meta_alt']) {                
  911.                     $image_meta_alts = XmlImportParser::factory($xml, $cxpath, $this->options['image_meta_alt'], $file)->parse($records); $tmp_files[] = $file;                    
  912.                 } else {
  913.                     count($titles) and $image_meta_alts = array_fill(0, count($titles), '');
  914.                 }
  915.             }
  916.  
  917.             // Composing images meta description
  918.             if ( $this->options['set_image_meta_description'] ){   
  919.                 $chunk == 1 and $logger and call_user_func($logger, __('Composing image meta data (description)...', 'pmxi_plugin'));
  920.                 $image_meta_descriptions = array();            
  921.                 if ($this->options['image_meta_description']) {                
  922.                     $image_meta_descriptions = XmlImportParser::factory($xml, $cxpath, $this->options['image_meta_description'], $file)->parse($records); $tmp_files[] = $file;                    
  923.                 } else {
  924.                     count($titles) and $image_meta_descriptions = array_fill(0, count($titles), '');
  925.                 }                              
  926.             }
  927.  
  928.             if ( "yes" == $this->options['download_images'] ){
  929.                 // Composing images suffix
  930.                 $chunk == 1 and $this->options['auto_rename_images'] and $logger and call_user_func($logger, __('Composing images suffix...', 'pmxi_plugin'));         
  931.                 $auto_rename_images = array();
  932.                 if ( $this->options['auto_rename_images'] and ! empty($this->options['auto_rename_images_suffix'])){
  933.                     $auto_rename_images = XmlImportParser::factory($xml, $cxpath, $this->options['auto_rename_images_suffix'], $file)->parse($records); $tmp_files[] = $file;
  934.                 }
  935.                 else{
  936.                     count($titles) and $auto_rename_images = array_fill(0, count($titles), '');
  937.                 }
  938.  
  939.                 // Composing images extensions
  940.                 $chunk == 1 and $this->options['auto_set_extension'] and $logger and call_user_func($logger, __('Composing images extensions...', 'pmxi_plugin'));         
  941.                 $auto_extensions = array();
  942.                 if ( $this->options['auto_set_extension'] and ! empty($this->options['new_extension'])){
  943.                     $auto_extensions = XmlImportParser::factory($xml, $cxpath, $this->options['new_extension'], $file)->parse($records); $tmp_files[] = $file;
  944.                 }
  945.                 else{
  946.                     count($titles) and $auto_extensions = array_fill(0, count($titles), '');
  947.                 }
  948.             }
  949.  
  950.             // Composing attachments
  951.             if ( ! (($uploads = wp_upload_dir()) && false === $uploads['error'])) {
  952.                 $logger and call_user_func($logger, __('<b>WARNING</b>', 'pmxi_plugin') . ': ' . $uploads['error']);               
  953.                 $logger and call_user_func($logger, __('<b>WARNING</b>: No attachments will be created', 'pmxi_plugin'));              
  954.                 $logger and !$is_cron and PMXI_Plugin::$session->warnings++;
  955.             } else {
  956.                 $chunk == 1 and $logger and call_user_func($logger, __('Composing URLs for attachments files...', 'pmxi_plugin'));
  957.                 $attachments = array();
  958.  
  959.                 if ($this->options['attachments']) {
  960.                     // Detect if attachments is separated by comma
  961.                     $atchs = explode(',', $this->options['attachments']);                  
  962.                     if (!empty($atchs)){
  963.                         $parse_multiple = true;
  964.                         foreach($atchs as $atch) if (!preg_match("/{.*}/", trim($atch))) $parse_multiple = false;          
  965.  
  966.                         if ($parse_multiple)
  967.                         {                          
  968.                             foreach($atchs as $atch)
  969.                             {                              
  970.                                 $posts_attachments = XmlImportParser::factory($xml, $cxpath, trim($atch), $file)->parse($records); $tmp_files[] = $file;                                                               
  971.                                 foreach($posts_attachments as $i => $val) $attachments[$i][] = $val;                               
  972.                             }
  973.                         }
  974.                         else
  975.                         {
  976.                             $attachments = XmlImportParser::factory($xml, $cxpath, $this->options['attachments'], $file)->parse($records); $tmp_files[] = $file;                               
  977.                         }
  978.                     }
  979.                    
  980.                 } else {
  981.                     count($titles) and $attachments = array_fill(0, count($titles), '');
  982.                 }
  983.             }              
  984.  
  985.             $chunk == 1 and $logger and call_user_func($logger, __('Composing unique keys...', 'pmxi_plugin'));
  986.             if (!empty($this->options['unique_key'])){
  987.                 $unique_keys = XmlImportParser::factory($xml, $cxpath, $this->options['unique_key'], $file)->parse($records); $tmp_files[] = $file;
  988.             }
  989.             else{
  990.                 count($titles) and $unique_keys = array_fill(0, count($titles), '');
  991.             }
  992.            
  993.             $chunk == 1 and $logger and call_user_func($logger, __('Processing posts...', 'pmxi_plugin'));
  994.            
  995.             if ('post' == $this->options['type'] and '' != $this->options['custom_type']) {
  996.                 $post_type = $this->options['custom_type'];
  997.             } else {
  998.                 $post_type = $this->options['type'];
  999.             }                  
  1000.            
  1001.             $custom_type_details = get_post_type_object( $post_type );
  1002.  
  1003.             $addons = array();
  1004.             $addons_data = array();
  1005.  
  1006.             // data parsing for WP All Import add-ons
  1007.             $chunk == 1 and $logger and call_user_func($logger, __('Data parsing via add-ons...', 'pmxi_plugin'));
  1008.             $parsingData = array(
  1009.                 'import' => $this,
  1010.                 'count'  => count($titles),
  1011.                 'xml'    => $xml,
  1012.                 'logger' => $logger,
  1013.                 'chunk'  => $chunk,
  1014.                 'xpath_prefix' => $xpath_prefix
  1015.             );         
  1016.             foreach (PMXI_Admin_Addons::get_active_addons() as $class) {                           
  1017.                 $model_class = str_replace("_Plugin", "_Import_Record", $class);   
  1018.                 if (class_exists($model_class)){                       
  1019.                     $addons[$class] = new $model_class();
  1020.                     $addons_data[$class] = ( method_exists($addons[$class], 'parse') ) ? $addons[$class]->parse($parsingData) : false;             
  1021.                 }
  1022.                 else{
  1023.                     $parse_func = $class . '_parse';                   
  1024.                     if (function_exists($parse_func)) $addons_data[$class] = call_user_func($parse_func, $parsingData);                
  1025.                 }
  1026.             }
  1027.  
  1028.             // save current import state to variables before import        
  1029.             $created = $this->created;
  1030.             $updated = $this->updated;
  1031.             $skipped = $this->skipped;         
  1032.            
  1033.             $specified_records = array();
  1034.  
  1035.             if ($this->options['is_import_specified']) {
  1036.                 $chunk == 1 and $logger and call_user_func($logger, __('Calculate specified records to import...', 'pmxi_plugin'));
  1037.                 foreach (preg_split('% *, *%', $this->options['import_specified'], -1, PREG_SPLIT_NO_EMPTY) as $chank) {
  1038.                     if (preg_match('%^(\d+)-(\d+)$%', $chank, $mtch)) {
  1039.                         $specified_records = array_merge($specified_records, range(intval($mtch[1]), intval($mtch[2])));
  1040.                     } else {
  1041.                         $specified_records = array_merge($specified_records, array(intval($chank)));
  1042.                     }
  1043.                 }
  1044.  
  1045.             }                  
  1046.  
  1047.             foreach ($titles as $i => $void) {         
  1048.  
  1049.                 if ($is_cron and $cron_sleep) sleep($cron_sleep);      
  1050.  
  1051.                 $logger and call_user_func($logger, __('---', 'pmxi_plugin'));
  1052.                 $logger and call_user_func($logger, sprintf(__('Record #%s', 'pmxi_plugin'), $this->imported + $i + 1));
  1053.  
  1054.                 wp_cache_flush();
  1055.  
  1056.                 $logger and call_user_func($logger, __('<b>ACTION</b>: pmxi_before_post_import ...', 'pmxi_plugin'));
  1057.                 do_action('pmxi_before_post_import', $this->id);                                                           
  1058.  
  1059.                 if ( empty($titles[$i]) ) {
  1060.                     if ( ! empty($addons_data['PMWI_Plugin']) and !empty($addons_data['PMWI_Plugin']['single_product_parent_ID'][$i]) ){
  1061.                         $titles[$i] = $addons_data['PMWI_Plugin']['single_product_parent_ID'][$i] . ' Product Variation';
  1062.                     }                  
  1063.                     else{
  1064.                         $logger and call_user_func($logger, __('<b>WARNING</b>: title is empty.', 'pmxi_plugin'));
  1065.                         $logger and !$is_cron and PMXI_Plugin::$session->warnings++;
  1066.                     }
  1067.                 }              
  1068.                
  1069.                 if ( $this->options['custom_type'] == 'import_users' ){                
  1070.                     $articleData = array(          
  1071.                         'user_pass' => $addons_data['PMUI_Plugin']['pmui_pass'][$i],
  1072.                         'user_login' => $addons_data['PMUI_Plugin']['pmui_logins'][$i],
  1073.                         'user_nicename' => $addons_data['PMUI_Plugin']['pmui_nicename'][$i],
  1074.                         'user_url' =>  $addons_data['PMUI_Plugin']['pmui_url'][$i],
  1075.                         'user_email' =>  $addons_data['PMUI_Plugin']['pmui_email'][$i],
  1076.                         'display_name' =>  $addons_data['PMUI_Plugin']['pmui_display_name'][$i],
  1077.                         'user_registered' =>  $addons_data['PMUI_Plugin']['pmui_registered'][$i],
  1078.                         'first_name' =>  $addons_data['PMUI_Plugin']['pmui_first_name'][$i],
  1079.                         'last_name' =>  $addons_data['PMUI_Plugin']['pmui_last_name'][$i],
  1080.                         'description' =>  $addons_data['PMUI_Plugin']['pmui_description'][$i],
  1081.                         'nickname' => $addons_data['PMUI_Plugin']['pmui_nickname'][$i],
  1082.                         'role' => ('' == $addons_data['PMUI_Plugin']['pmui_role'][$i]) ? 'subscriber' : $addons_data['PMUI_Plugin']['pmui_role'][$i],
  1083.                     );     
  1084.                     $logger and call_user_func($logger, sprintf(__('Combine all data for user %s...', 'pmxi_plugin'), $articleData['user_login']));
  1085.                 }
  1086.                 else {                 
  1087.                     $articleData = array(
  1088.                         'post_type' => $post_type,
  1089.                         'post_status' => ("xpath" == $this->options['status']) ? $post_status[$i] : $this->options['status'],
  1090.                         'comment_status' => $this->options['comment_status'],
  1091.                         'ping_status' => $this->options['ping_status'],
  1092.                         'post_title' => (!empty($this->options['is_leave_html'])) ? html_entity_decode($titles[$i]) : $titles[$i],
  1093.                         'post_excerpt' => apply_filters('pmxi_the_excerpt', ((!empty($this->options['is_leave_html'])) ? html_entity_decode($post_excerpt[$i]) : $post_excerpt[$i]), $this->id),
  1094.                         'post_name' => $post_slug[$i],
  1095.                         'post_content' => apply_filters('pmxi_the_content', ((!empty($this->options['is_leave_html'])) ? html_entity_decode($contents[$i]) : $contents[$i]), $this->id),
  1096.                         'post_date' => $dates[$i],
  1097.                         'post_date_gmt' => get_gmt_from_date($dates[$i]),
  1098.                         'post_author' => $post_author[$i],                     
  1099.                         'menu_order' => (int) $menu_order[$i],
  1100.                         'post_parent' => (int) $this->options['parent']
  1101.                     );
  1102.                     $logger and call_user_func($logger, sprintf(__('Combine all data for post `%s`...', 'pmxi_plugin'), $articleData['post_title']));      
  1103.                 }                      
  1104.                
  1105.                 // Re-import Records Matching
  1106.                 $post_to_update = false; $post_to_update_id = false;
  1107.                
  1108.                 // if Auto Matching re-import option selected
  1109.                 if ( "manual" != $this->options['duplicate_matching'] ){
  1110.                    
  1111.                     // find corresponding article among previously imported            
  1112.                     $logger and call_user_func($logger, sprintf(__('Find corresponding article among previously imported for post `%s`...', 'pmxi_plugin'), $articleData['post_title']));
  1113.                     $postRecord->clear();
  1114.                     $postRecord->getBy(array(
  1115.                         'unique_key' => $unique_keys[$i],
  1116.                         'import_id' => $this->id,
  1117.                     ));
  1118.  
  1119.                     if ( ! $postRecord->isEmpty() ) {
  1120.                         $logger and call_user_func($logger, sprintf(__('Duplicate post was founded for post %s with unique key `%s`...', 'pmxi_plugin'), $articleData['post_title'], $unique_keys[$i]));
  1121.                         if ( $this->options['custom_type'] == 'import_users'){
  1122.                             $post_to_update = get_user_by('id', $post_to_update_id = $postRecord->post_id);                        
  1123.                         }
  1124.                         else{
  1125.                             $post_to_update = get_post($post_to_update_id = $postRecord->post_id);
  1126.                         }
  1127.                     }
  1128.                     else{
  1129.                         $logger and call_user_func($logger, sprintf(__('Duplicate post wasn\'t founded with unique key `%s`...', 'pmxi_plugin'), $unique_keys[$i]));
  1130.                     }
  1131.                                                                
  1132.                 // if Manual Matching re-import option seleted
  1133.                 } else {
  1134.                                        
  1135.                     if ('custom field' == $this->options['duplicate_indicator']) {
  1136.                         $custom_duplicate_value = XmlImportParser::factory($xml, $cxpath, $this->options['custom_duplicate_value'], $file)->parse($records); $tmp_files[] = $file;
  1137.                         $custom_duplicate_name = XmlImportParser::factory($xml, $cxpath, $this->options['custom_duplicate_name'], $file)->parse($records); $tmp_files[] = $file;
  1138.                     }
  1139.                     else{
  1140.                         count($titles) and $custom_duplicate_name = $custom_duplicate_value = array_fill(0, count($titles), '');
  1141.                     }
  1142.                    
  1143.                     $logger and call_user_func($logger, sprintf(__('Find corresponding article among database for post `%s`...', 'pmxi_plugin'), $articleData['post_title']));
  1144.                     // handle duplicates according to import settings
  1145.                     if ($duplicates = pmxi_findDuplicates($articleData, $custom_duplicate_name[$i], $custom_duplicate_value[$i], $this->options['duplicate_indicator'])) {                                                         
  1146.                         $duplicate_id = array_shift($duplicates);                      
  1147.                         if ($duplicate_id) {   
  1148.                             $logger and call_user_func($logger, sprintf(__('Duplicate post was founded for post `%s`...', 'pmxi_plugin'), $articleData['post_title']));
  1149.                             if ( $this->options['custom_type'] == 'import_users'){                                                 
  1150.                                 $post_to_update = get_user_by('id', $post_to_update_id = $duplicate_id);
  1151.                             }
  1152.                             else{
  1153.                                 $post_to_update = get_post($post_to_update_id = $duplicate_id);
  1154.                             }
  1155.                         }  
  1156.                         else{
  1157.                             $logger and call_user_func($logger, sprintf(__('Duplicate post wasn\'n founded for post `%s`...', 'pmxi_plugin'), $articleData['post_title']));
  1158.                         }                  
  1159.                     }                  
  1160.                 }
  1161.  
  1162.                 if ( ! empty($specified_records) ) {
  1163.  
  1164.                     if ( ! in_array($created + $updated + $skipped + 1, $specified_records) ){
  1165.  
  1166.                         if ( ! $postRecord->isEmpty() ) $postRecord->set(array('iteration' => $this->iteration))->update();
  1167.  
  1168.                         $skipped++;                                        
  1169.                         $logger and call_user_func($logger, __('<b>SKIPPED</b>: by specified records option', 'pmxi_plugin'));
  1170.                         $logger and !$is_cron and PMXI_Plugin::$session->warnings++;                   
  1171.                         $logger and !$is_cron and PMXI_Plugin::$session->chunk_number++;
  1172.                         $logger and !$is_cron and PMXI_Plugin::$session->save_data();                      
  1173.                         continue;
  1174.                     }                                      
  1175.                 }              
  1176.  
  1177.                 // Duplicate record is founded
  1178.                 if ($post_to_update){
  1179.  
  1180.                     //$logger and call_user_func($logger, sprintf(__('Duplicate record is founded for `%s`', 'pmxi_plugin'), $articleData['post_title']));
  1181.  
  1182.                     // Do not update already existing records option selected
  1183.                     if ("yes" == $this->options['is_keep_former_posts']) { 
  1184.  
  1185.                         if ( ! $postRecord->isEmpty() ) $postRecord->set(array('iteration' => $this->iteration))->update();
  1186.  
  1187.                         do_action('pmxi_do_not_update_existing', $post_to_update_id, $this->id, $this->iteration);                                                                                                                                                                         
  1188.  
  1189.                         $skipped++;
  1190.                         $logger and call_user_func($logger, sprintf(__('<b>SKIPPED</b>: Previously imported record found for `%s`', 'pmxi_plugin'), $articleData['post_title']));
  1191.                         $logger and !$is_cron and PMXI_Plugin::$session->warnings++;                           
  1192.                         $logger and !$is_cron and PMXI_Plugin::$session->chunk_number++;   
  1193.                         $logger and !$is_cron and PMXI_Plugin::$session->save_data();  
  1194.                         continue;
  1195.                     }                  
  1196.  
  1197.                     $articleData['ID'] = $post_to_update_id;                   
  1198.                     // Choose which data to update
  1199.                     if ( $this->options['update_all_data'] == 'no' ){
  1200.  
  1201.                         if ( ! in_array($this->options['custom_type'], array('import_users'))){
  1202.  
  1203.                             // preserve date of already existing article when duplicate is found                   
  1204.                             if ( ! $this->options['is_update_categories'] or ($this->options['is_update_categories'] and $this->options['update_categories_logic'] != "full_update")) {                            
  1205.                                 $logger and call_user_func($logger, sprintf(__('Preserve taxonomies of already existing article for `%s`', 'pmxi_plugin'), $articleData['post_title']));   
  1206.                                 $existing_taxonomies = array();
  1207.                                 foreach (array_keys($taxonomies) as $tx_name) {
  1208.                                     $txes_list = get_the_terms($articleData['ID'], $tx_name);
  1209.                                     if (is_wp_error($txes_list)) {
  1210.                                         $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: Unable to get current taxonomies for article #%d, updating with those read from XML file', 'pmxi_plugin'), $articleData['ID']));
  1211.                                         $logger and !$is_cron and PMXI_Plugin::$session->warnings++;       
  1212.                                     } else {
  1213.                                         $txes_new = array();
  1214.                                         if (!empty($txes_list)):
  1215.                                             foreach ($txes_list as $t) {
  1216.                                                 $txes_new[] = $t->term_taxonomy_id;
  1217.                                             }
  1218.                                         endif;
  1219.                                         $existing_taxonomies[$tx_name][$i] = $txes_new;                            
  1220.                                     }
  1221.                                 }                          
  1222.                             }  
  1223.                                        
  1224.                             if ( ! $this->options['is_update_dates']) { // preserve date of already existing article when duplicate is found
  1225.                                 $articleData['post_date'] = $post_to_update->post_date;
  1226.                                 $articleData['post_date_gmt'] = $post_to_update->post_date_gmt;
  1227.                                 $logger and call_user_func($logger, sprintf(__('Preserve date of already existing article for `%s`', 'pmxi_plugin'), $articleData['post_title']));                             
  1228.                             }
  1229.                             if ( ! $this->options['is_update_status']) { // preserve status and trashed flag
  1230.                                 $articleData['post_status'] = $post_to_update->post_status;
  1231.                                 $logger and call_user_func($logger, sprintf(__('Preserve status of already existing article for `%s`', 'pmxi_plugin'), $articleData['post_title']));                               
  1232.                             }
  1233.                             if ( ! $this->options['is_update_content']){
  1234.                                 $articleData['post_content'] = $post_to_update->post_content;
  1235.                                 $logger and call_user_func($logger, sprintf(__('Preserve content of already existing article for `%s`', 'pmxi_plugin'), $articleData['post_title']));                              
  1236.                             }
  1237.                             if ( ! $this->options['is_update_title']){
  1238.                                 $articleData['post_title'] = $post_to_update->post_title;      
  1239.                                 $logger and call_user_func($logger, sprintf(__('Preserve title of already existing article for `%s`', 'pmxi_plugin'), $articleData['post_title']));                                                                    
  1240.                             }
  1241.                             if ( ! $this->options['is_update_slug']){
  1242.                                 $articleData['post_name'] = $post_to_update->post_name;        
  1243.                                 $logger and call_user_func($logger, sprintf(__('Preserve slug of already existing article for `%s`', 'pmxi_plugin'), $articleData['post_title']));                                                                 
  1244.                             }
  1245.                             if ( ! $this->options['is_update_excerpt']){
  1246.                                 $articleData['post_excerpt'] = $post_to_update->post_excerpt;
  1247.                                 $logger and call_user_func($logger, sprintf(__('Preserve excerpt of already existing article for `%s`', 'pmxi_plugin'), $articleData['post_title']));                                                                              
  1248.                             }                                      
  1249.                             if ( ! $this->options['is_update_menu_order']){
  1250.                                 $articleData['menu_order'] = $post_to_update->menu_order;
  1251.                                 $logger and call_user_func($logger, sprintf(__('Preserve menu order of already existing article for `%s`', 'pmxi_plugin'), $articleData['post_title']));                               
  1252.                             }
  1253.                             if ( ! $this->options['is_update_parent']){
  1254.                                 $articleData['post_parent'] = $post_to_update->post_parent;
  1255.                                 $logger and call_user_func($logger, sprintf(__('Preserve post parent of already existing article for `%s`', 'pmxi_plugin'), $articleData['post_title']));                              
  1256.                             }
  1257.                             if ( ! $this->options['is_update_author']){
  1258.                                 $articleData['post_author'] = $post_to_update->post_author;
  1259.                                 $logger and call_user_func($logger, sprintf(__('Preserve post author of already existing article for `%s`', 'pmxi_plugin'), $articleData['post_title']));
  1260.                             }
  1261.                         }
  1262.                         else {
  1263.                             if ( ! $this->options['is_update_first_name'] ) $articleData['first_name'] = $post_to_update->first_name;
  1264.                             if ( ! $this->options['is_update_last_name'] ) $articleData['last_name'] = $post_to_update->last_name;
  1265.                             if ( ! $this->options['is_update_role'] ) unset($articleData['role']);
  1266.                             if ( ! $this->options['is_update_nickname'] ) $articleData['nickname'] = get_user_meta($post_to_update->ID, 'nickname', true);
  1267.                             if ( ! $this->options['is_update_description'] ) $articleData['description'] = get_user_meta($post_to_update->ID, 'description', true);
  1268.                             if ( ! $this->options['is_update_login'] ) $articleData['user_login'] = $post_to_update->user_login;
  1269.                             if ( ! $this->options['is_update_password'] ) unset($articleData['user_pass']);
  1270.                             if ( ! $this->options['is_update_nicename'] ) $articleData['user_nicename'] = $post_to_update->user_nicename;
  1271.                             if ( ! $this->options['is_update_email'] ) $articleData['user_email'] = $post_to_update->user_email;
  1272.                             if ( ! $this->options['is_update_registered'] ) $articleData['user_registered'] = $post_to_update->user_registered;
  1273.                             if ( ! $this->options['is_update_display_name'] ) $articleData['display_name'] = $post_to_update->display_name;
  1274.                             if ( ! $this->options['is_update_url'] ) $articleData['user_url'] = $post_to_update->user_url;
  1275.                         }
  1276.  
  1277.                         $logger and call_user_func($logger, sprintf(__('Applying filter `pmxi_article_data` for `%s`', 'pmxi_plugin'), $articleData['post_title']));   
  1278.                         $articleData = apply_filters('pmxi_article_data', $articleData, $this, $post_to_update);
  1279.                                                                
  1280.                     }
  1281.  
  1282.                     if ( ! in_array($this->options['custom_type'], array('import_users'))){
  1283.  
  1284.                         if ( $this->options['update_all_data'] == 'yes' or ( $this->options['update_all_data'] == 'no' and $this->options['is_update_attachments'])) {
  1285.                             $logger and call_user_func($logger, sprintf(__('Deleting attachments for `%s`', 'pmxi_plugin'), $articleData['post_title']));                              
  1286.                             wp_delete_attachments($articleData['ID'], true, 'files');
  1287.                         }
  1288.                         // handle obsolete attachments (i.e. delete or keep) according to import settings
  1289.                         if ( $this->options['update_all_data'] == 'yes' or ( $this->options['update_all_data'] == 'no' and $this->options['is_update_images'] and $this->options['update_images_logic'] == "full_update")){
  1290.                             $logger and call_user_func($logger, sprintf(__('Deleting images for `%s`', 'pmxi_plugin'), $articleData['post_title']));                               
  1291.                             wp_delete_attachments($articleData['ID'], ( $this->options['download_images'] == 'yes' ), 'images');
  1292.                         }
  1293.  
  1294.                     }
  1295.                 }
  1296.                 elseif ( ! $postRecord->isEmpty() ){
  1297.                    
  1298.                     // existing post not found though it's track was found... clear the leftover, plugin will continue to treat record as new
  1299.                     $postRecord->clear();
  1300.                    
  1301.                 }                  
  1302.                
  1303.                 // no new records are created. it will only update posts it finds matching duplicates for
  1304.                 if ( ! $this->options['create_new_records'] and empty($articleData['ID'])){
  1305.                    
  1306.                     if ( ! $postRecord->isEmpty() ) $postRecord->set(array('iteration' => $this->iteration))->update();
  1307.  
  1308.                     $logger and call_user_func($logger, __('<b>SKIPPED</b>: by do not create new posts option.', 'pmxi_plugin'));
  1309.                     $logger and !$is_cron and PMXI_Plugin::$session->warnings++;                               
  1310.                     $logger and !$is_cron and PMXI_Plugin::$session->chunk_number++;
  1311.                     $skipped++;    
  1312.                     $logger and !$is_cron and PMXI_Plugin::$session->save_data();  
  1313.                     continue;
  1314.                 }
  1315.                
  1316.                 // cloak urls with `WP Wizard Cloak` if corresponding option is set
  1317.                 if ( ! empty($this->options['is_cloak']) and class_exists('PMLC_Plugin')) {
  1318.                     if (preg_match_all('%<a\s[^>]*href=(?(?=")"([^"]*)"|(?(?=\')\'([^\']*)\'|([^\s>]*)))%is', $articleData['post_content'], $matches, PREG_PATTERN_ORDER)) {
  1319.                         $hrefs = array_unique(array_merge(array_filter($matches[1]), array_filter($matches[2]), array_filter($matches[3])));
  1320.                         foreach ($hrefs as $url) {
  1321.                             if (preg_match('%^\w+://%i', $url)) { // mask only links having protocol
  1322.                                 // try to find matching cloaked link among already registered ones
  1323.                                 $list = new PMLC_Link_List(); $linkTable = $list->getTable();
  1324.                                 $rule = new PMLC_Rule_Record(); $ruleTable = $rule->getTable();
  1325.                                 $dest = new PMLC_Destination_Record(); $destTable = $dest->getTable();
  1326.                                 $list->join($ruleTable, "$ruleTable.link_id = $linkTable.id")
  1327.                                     ->join($destTable, "$destTable.rule_id = $ruleTable.id")
  1328.                                     ->setColumns("$linkTable.*")
  1329.                                     ->getBy(array(
  1330.                                         "$linkTable.destination_type =" => 'ONE_SET',
  1331.                                         "$linkTable.is_trashed =" => 0,
  1332.                                         "$linkTable.preset =" => '',
  1333.                                         "$linkTable.expire_on =" => '0000-00-00',
  1334.                                         "$ruleTable.type =" => 'ONE_SET',
  1335.                                         "$destTable.weight =" => 100,
  1336.                                         "$destTable.url LIKE" => $url,
  1337.                                     ), NULL, 1, 1)->convertRecords();
  1338.                                 if ($list->count()) { // matching link found
  1339.                                     $link = $list[0];
  1340.                                 } else { // register new cloaked link
  1341.                                     global $wpdb;
  1342.                                     $slug = max(
  1343.                                         intval($wpdb->get_var("SELECT MAX(CONVERT(name, SIGNED)) FROM $linkTable")),
  1344.                                         intval($wpdb->get_var("SELECT MAX(CONVERT(slug, SIGNED)) FROM $linkTable")),
  1345.                                         0
  1346.                                     );
  1347.                                     $i = 0; do {
  1348.                                         is_int(++$slug) and $slug > 0 or $slug = 1;
  1349.                                         $is_slug_found = ! intval($wpdb->get_var("SELECT COUNT(*) FROM $linkTable WHERE name = '$slug' OR slug = '$slug'"));
  1350.                                     } while( ! $is_slug_found and $i++ < 100000);
  1351.                                     if ($is_slug_found) {
  1352.                                         $link = new PMLC_Link_Record(array(
  1353.                                             'name' => strval($slug),
  1354.                                             'slug' => strval($slug),
  1355.                                             'header_tracking_code' => '',
  1356.                                             'footer_tracking_code' => '',
  1357.                                             'redirect_type' => '301',
  1358.                                             'destination_type' => 'ONE_SET',
  1359.                                             'preset' => '',
  1360.                                             'forward_url_params' => 1,
  1361.                                             'no_global_tracking_code' => 0,
  1362.                                             'expire_on' => '0000-00-00',
  1363.                                             'created_on' => date('Y-m-d H:i:s'),
  1364.                                             'is_trashed' => 0,
  1365.                                         ));
  1366.                                         $link->insert();
  1367.                                         $rule = new PMLC_Rule_Record(array(
  1368.                                             'link_id' => $link->id,
  1369.                                             'type' => 'ONE_SET',
  1370.                                             'rule' => '',
  1371.                                         ));
  1372.                                         $rule->insert();
  1373.                                         $dest = new PMLC_Destination_Record(array(
  1374.                                             'rule_id' => $rule->id,
  1375.                                             'url' => $url,
  1376.                                             'weight' => 100,
  1377.                                         ));
  1378.                                         $dest->insert();
  1379.                                     } else {
  1380.                                         $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: Unable to create cloaked link for %s', 'pmxi_plugin'), $url));
  1381.                                         $logger and !$is_cron and PMXI_Plugin::$session->warnings++;
  1382.                                         $link = NULL;
  1383.                                     }
  1384.                                 }
  1385.                                 if ($link) { // cloaked link is found or created for url
  1386.                                     $articleData['post_content'] = preg_replace('%' . preg_quote($url, '%') . '(?=([\s\'"]|$))%i', $link->getUrl(), $articleData['post_content']);
  1387.                                 }
  1388.                             }
  1389.                         }
  1390.                     }
  1391.                 }      
  1392.  
  1393.                 // insert article being imported       
  1394.                 if ( ! in_array($this->options['custom_type'], array('import_users'))){                    
  1395.                     if (empty($articleData['ID'])){
  1396.                         $logger and call_user_func($logger, sprintf(__('<b>CREATING</b> `%s` `%s`', 'pmxi_plugin'), $articleData['post_title'], $custom_type_details->labels->singular_name));
  1397.                     }
  1398.                     else{
  1399.                         $logger and call_user_func($logger, sprintf(__('<b>UPDATING</b> `%s` `%s`', 'pmxi_plugin'), $articleData['post_title'], $custom_type_details->labels->singular_name));
  1400.                     }
  1401.  
  1402.                     $pid = ($this->options['is_fast_mode']) ? pmxi_insert_post($articleData, true) : wp_insert_post($articleData, true);
  1403.                 }
  1404.                 else{
  1405.                     $pid = (empty($articleData['ID'])) ? wp_insert_user( $articleData ) : wp_update_user( $articleData );
  1406.                     $articleData['post_title'] = $articleData['user_login'];
  1407.                 }
  1408.                
  1409.                 if (is_wp_error($pid)) {
  1410.                     $logger and call_user_func($logger, __('<b>ERROR</b>', 'pmxi_plugin') . ': ' . $pid->get_error_message());
  1411.                     $logger and !$is_cron and PMXI_Plugin::$session->errors++;
  1412.                 } else {                                       
  1413.                                                            
  1414.                     if ("manual" != $this->options['duplicate_matching'] or empty($articleData['ID'])){                    
  1415.                         // associate post with import                                              
  1416.                         $postRecord->isEmpty() and $postRecord->set(array(
  1417.                             'post_id' => $pid,
  1418.                             'import_id' => $this->id,
  1419.                             'unique_key' => $unique_keys[$i],
  1420.                             'product_key' => (($post_type == "product" and PMXI_Admin_Addons::get_addon('PMWI_Plugin')) ? $addons_data['PMWI_Plugin']['single_product_ID'][$i] : '')
  1421.                         ))->insert();
  1422.  
  1423.                         $postRecord->set(array('iteration' => $this->iteration))->update();                    
  1424.  
  1425.                         $logger and call_user_func($logger, sprintf(__('Associate post `%s` with current import ...', 'pmxi_plugin'), $articleData['post_title']));
  1426.                     }
  1427.  
  1428.                     // [post format]
  1429.                     if ( current_theme_supports( 'post-formats' ) && post_type_supports( $post_type, 'post-formats' ) ){                       
  1430.                         set_post_format($pid, $this->options['post_format'] );                     
  1431.                         $logger and call_user_func($logger, sprintf(__('Associate post `%s` with post format %s ...', 'pmxi_plugin'), $articleData['post_title'], (!empty($this->options['post_format'])) ? $this->options['post_format'] : 'Standart'));
  1432.                     }
  1433.                     // [/post format]
  1434.                    
  1435.                     // [custom fields]                 
  1436.                     if (empty($articleData['ID']) or $this->options['update_all_data'] == 'yes' or ($this->options['update_all_data'] == 'no' and $this->options['is_update_custom_fields']) or ($this->options['update_all_data'] == 'no' and $this->options['is_update_attributes'] and $post_type == "product" and class_exists('PMWI_Plugin'))) {                                                                          
  1437.  
  1438.                         $show_log = ( ! empty($serialized_meta) );
  1439.  
  1440.                         $show_log and $logger and call_user_func($logger, __('<b>CUSTOM FIELDS:</b>', 'pmxi_plugin'));
  1441.  
  1442.                         // Delete all meta keys
  1443.                         if ( ! empty($articleData['ID']) ) {
  1444.  
  1445.                             // Get all existing meta keys                      
  1446.                             $existing_meta_keys = array();
  1447.  
  1448.                             if ( $this->options['custom_type'] == 'import_users'){
  1449.                                 foreach (get_user_meta($pid, '') as $cur_meta_key => $cur_meta_val) $existing_meta_keys[] = $cur_meta_key;
  1450.                             }
  1451.                             else{
  1452.                                 foreach (get_post_meta($pid, '') as $cur_meta_key => $cur_meta_val) $existing_meta_keys[] = $cur_meta_key;
  1453.                             }
  1454.                             /*$import_entry = ( $this->options['custom_type'] == 'import_users') ? 'user' : 'post';
  1455.                             $meta_table = _get_meta_table( $import_entry );*/
  1456.                             // delete keys which are no longer correspond to import settings                                                               
  1457.                             foreach ($existing_meta_keys as $cur_meta_key) {
  1458.                                
  1459.                                 // Do not delete post meta for features image
  1460.                                 if ( in_array($cur_meta_key, array('_thumbnail_id','_product_image_gallery')) ) continue;                                                              
  1461.  
  1462.                                 $field_to_delete = true;                               
  1463.  
  1464.                                 // apply addons filters
  1465.                                 if ( ! apply_filters('pmxi_custom_field_to_delete', $field_to_delete, $pid, $post_type, $this->options, $cur_meta_key) ) continue;
  1466.  
  1467.                                 // Update all Custom Fields is defined
  1468.                                 if ($this->options['update_all_data'] == 'yes' or ($this->options['update_all_data'] == 'no' and $this->options['is_update_custom_fields'] and $this->options['update_custom_fields_logic'] == "full_update")) {
  1469.                                    
  1470.                                     //$this->wpdb->query($this->wpdb->prepare("DELETE FROM $meta_table WHERE `" . $import_entry . "_id` = $pid AND `meta_key` = %s", $cur_meta_key));
  1471.                                     if ( $this->options['custom_type'] == 'import_users'){
  1472.                                         delete_user_meta($pid, $cur_meta_key);
  1473.                                     }
  1474.                                     else{
  1475.                                         delete_post_meta($pid, $cur_meta_key);
  1476.                                     }
  1477.                                    
  1478.                                     $show_log and $logger and call_user_func($logger, sprintf(__('- Custom field %s has been deleted for `%s` attempted to `update all custom fields` setting ...', 'pmxi_plugin'), $cur_meta_key, $articleData['post_title']));
  1479.                                 }
  1480.                                 // Update only these Custom Fields, leave the rest alone
  1481.                                 elseif ($this->options['update_all_data'] == 'no' and $this->options['is_update_custom_fields'] and $this->options['update_custom_fields_logic'] == "only"){
  1482.                                     if (!empty($this->options['custom_fields_list']) and is_array($this->options['custom_fields_list']) and in_array($cur_meta_key, $this->options['custom_fields_list'])){
  1483.                                        
  1484.                                         //$this->wpdb->query($this->wpdb->prepare("DELETE FROM $meta_table WHERE `" . $import_entry . "_id` = $pid AND `meta_key` = %s", $cur_meta_key));
  1485.                                         if ( $this->options['custom_type'] == 'import_users'){
  1486.                                             delete_user_meta($pid, $cur_meta_key);
  1487.                                         }
  1488.                                         else{
  1489.                                             delete_post_meta($pid, $cur_meta_key);
  1490.                                         }
  1491.  
  1492.                                     }
  1493.                                     $show_log and $logger and call_user_func($logger, sprintf(__('- Custom field %s has been deleted for `%s` attempted to `update only these custom fields: %s, leave rest alone` setting ...', 'pmxi_plugin'), $cur_meta_key, $articleData['post_title'], implode(',', $this->options['custom_fields_list'])));
  1494.                                 }
  1495.                                 // Leave these fields alone, update all other Custom Fields
  1496.                                 elseif ($this->options['update_all_data'] == 'no' and $this->options['is_update_custom_fields'] and $this->options['update_custom_fields_logic'] == "all_except"){
  1497.                                     if ( empty($this->options['custom_fields_list']) or ! in_array($cur_meta_key, $this->options['custom_fields_list'])){
  1498.                                        
  1499.                                         //$this->wpdb->query($this->wpdb->prepare("DELETE FROM $meta_table WHERE `" . $import_entry . "_id` = $pid AND `meta_key` = %s", $cur_meta_key));
  1500.                                         if ( $this->options['custom_type'] == 'import_users'){
  1501.                                             delete_user_meta($pid, $cur_meta_key);
  1502.                                         }
  1503.                                         else{
  1504.                                             delete_post_meta($pid, $cur_meta_key);
  1505.                                         }
  1506.  
  1507.                                     }
  1508.                                     $show_log and $logger and call_user_func($logger, sprintf(__('- Custom field %s has been deleted for `%s` attempted to `leave these fields alone: %s, update all other Custom Fields` setting ...', 'pmxi_plugin'), $cur_meta_key, $articleData['post_title'], implode(',', $this->options['custom_fields_list'])));
  1509.                                 }
  1510.                                
  1511.                             }
  1512.                         }                      
  1513.  
  1514.                         $encoded_meta = array();                       
  1515.                        
  1516.                         if ( ! empty($serialized_meta)){
  1517.  
  1518.                             foreach ($serialized_meta as $m_key => $values) {
  1519.                                
  1520.                                 if (!empty($articleData['ID'])){
  1521.                                                                    
  1522.                                     if ($this->options['update_all_data'] != 'yes'){
  1523.  
  1524.                                         $field_to_update = false;
  1525.  
  1526.                                         if ($this->options['is_update_custom_fields'] and $this->options['update_custom_fields_logic'] == "only" and ! empty($this->options['custom_fields_list']) and is_array($this->options['custom_fields_list']) and in_array($m_key, $this->options['custom_fields_list']) ) $field_to_update = true;
  1527.                                         if ($this->options['is_update_custom_fields'] and $this->options['update_custom_fields_logic'] == "all_except" and ( empty($this->options['custom_fields_list']) or ! in_array($m_key, $this->options['custom_fields_list']) )) $field_to_update = true;
  1528.                                        
  1529.                                         if ( $this->options['update_custom_fields_logic'] == "full_update" ) $field_to_update = true;                                  
  1530.  
  1531.                                         // apply addons filters
  1532.                                         $field_to_update = apply_filters('pmxi_custom_field_to_update', $field_to_update, $post_type, $this->options, $m_key);                                 
  1533.  
  1534.                                         if ( ! $field_to_update ) {
  1535.                                             $logger and call_user_func($logger, sprintf(__('- Custom field `%s` has been skipped attempted to record matching options ...', 'pmxi_plugin'), $m_key));
  1536.                                             continue;                                      
  1537.                                         }
  1538.  
  1539.                                     }
  1540.  
  1541.                                 }
  1542.                                
  1543.                                 $cf_value = apply_filters('pmxi_custom_field', (is_serialized($values[$i])) ? unserialize($values[$i]) : $values[$i], $this->id);
  1544.                                
  1545.                                 //$this->pushmeta($pid, $m_key, $cf_value);                            
  1546.                                
  1547.                                 if ( $this->options['custom_type'] == 'import_users'){
  1548.                                     update_user_meta($pid, $m_key, $cf_value);
  1549.                                 }
  1550.                                 else{
  1551.                                     update_post_meta($pid, $m_key, $cf_value);
  1552.                                 }
  1553.  
  1554.                                 $logger and call_user_func($logger, sprintf(__('- Custom field `%s` has been updated with value `%s` for post `%s` ...', 'pmxi_plugin'), $m_key, maybe_serialize($cf_value), $articleData['post_title']));
  1555.                                 $logger and call_user_func($logger, __('- <b>ACTION</b>: pmxi_update_post_meta', 'pmxi_plugin'));
  1556.                                 do_action( 'pmxi_update_post_meta', $pid, $m_key, (is_serialized($values[$i])) ? unserialize($values[$i]) : $values[$i]); // hook that was triggered after post meta data updated  
  1557.                            
  1558.                             }  
  1559.  
  1560.                             //$this->executeSQL();
  1561.                         }                          
  1562.                     }
  1563.                     // [/custom fields]
  1564.  
  1565.                     // [addons import]
  1566.  
  1567.                     // prepare data for import
  1568.                     $importData = array(
  1569.                         'pid' => $pid,
  1570.                         'i' => $i,
  1571.                         'import' => $this,
  1572.                         'articleData' => $articleData,
  1573.                         'xml' => $xml,
  1574.                         'is_cron' => $is_cron,
  1575.                         'logger' => $logger,
  1576.                         'xpath_prefix' => $xpath_prefix
  1577.                     );
  1578.  
  1579.                     // deligate operation to addons
  1580.                     foreach (PMXI_Admin_Addons::get_active_addons() as $class){                        
  1581.                         if (class_exists($class)){
  1582.                             if ( method_exists($addons[$class], 'import') ) $addons[$class]->import($importData);  
  1583.                         }
  1584.                         else{
  1585.                             $import_func = $class . '_import';                         
  1586.                             if (function_exists($import_func)) call_user_func($import_func, $importData, $addons_data[$class]);
  1587.                         }
  1588.                     }
  1589.                    
  1590.                     // [/addons import]
  1591.  
  1592.                     // Page Template
  1593.                     if ('post' != $articleData['post_type'] and !empty($this->options['page_template'])) update_post_meta($pid, '_wp_page_template', $this->options['page_template']);
  1594.                    
  1595.                     // [featured image]
  1596.                     if ( ! empty($uploads) and false === $uploads['error'] and (empty($articleData['ID']) or $this->options['update_all_data'] == "yes" or ( $this->options['update_all_data'] == "no" and $this->options['is_update_images']))) {
  1597.                        
  1598.                         if (!empty($featured_images[$i])){
  1599.  
  1600.                             $targetDir = $uploads['path'];
  1601.                             $targetUrl = $uploads['url'];
  1602.  
  1603.                             $logger and call_user_func($logger, __('<b>IMAGES:</b>', 'pmxi_plugin'));
  1604.  
  1605.                             if ( ! @is_writable($targetDir) ){
  1606.  
  1607.                                 $logger and call_user_func($logger, sprintf(__('<b>ERROR</b>: Target directory %s is not writable', 'pmxi_plugin'), $targetDir));
  1608.  
  1609.                             }
  1610.                             else{
  1611.  
  1612.                                 require_once(ABSPATH . 'wp-admin/includes/image.php');                     
  1613.                                
  1614.                                 $success_images = false;   
  1615.                                 $gallery_attachment_ids = array();                                                                         
  1616.                                 $imgs = array();
  1617.  
  1618.                                 $featured_delim = ( "yes" == $this->options['download_images'] ) ? $this->options['download_featured_delim'] : $this->options['featured_delim'];
  1619.  
  1620.                                 $line_imgs = explode("\n", $featured_images[$i]);
  1621.                                 if ( ! empty($line_imgs) )
  1622.                                     foreach ($line_imgs as $line_img)
  1623.                                         $imgs = array_merge($imgs, ( ! empty($featured_delim) ) ? str_getcsv($line_img, $featured_delim) : array($line_img) );                             
  1624.                                                        
  1625.                                 if (!empty($imgs)) {                                           
  1626.  
  1627.                                     if ( $this->options['set_image_meta_title'] ){     
  1628.                                         $img_titles = array();                                 
  1629.                                         $line_img_titles = explode("\n", $image_meta_titles[$i]);
  1630.                                         if ( ! empty($line_img_titles) )
  1631.                                             foreach ($line_img_titles as $line_img_title)
  1632.                                                 $img_titles = array_merge($img_titles, ( ! empty($this->options['image_meta_title_delim']) ) ? str_getcsv($line_img_title, $this->options['image_meta_title_delim']) : array($line_img_title) );
  1633.            
  1634.                                     }
  1635.                                     if ( $this->options['set_image_meta_caption'] ){                               
  1636.                                         $img_captions = array();                                   
  1637.                                         $line_img_captions = explode("\n", $image_meta_captions[$i]);
  1638.                                         if ( ! empty($line_img_captions) )
  1639.                                             foreach ($line_img_captions as $line_img_caption)
  1640.                                                 $img_captions = array_merge($img_captions, ( ! empty($this->options['image_meta_caption_delim']) ) ? str_getcsv($line_img_caption, $this->options['image_meta_caption_delim']) : array($line_img_caption) );
  1641.  
  1642.                                     }
  1643.                                     if ( $this->options['set_image_meta_alt'] ){                               
  1644.                                         $img_alts = array();                                   
  1645.                                         $line_img_alts = explode("\n", $image_meta_alts[$i]);
  1646.                                         if ( ! empty($line_img_alts) )
  1647.                                             foreach ($line_img_alts as $line_img_alt)
  1648.                                                 $img_alts = array_merge($img_alts, ( ! empty($this->options['image_meta_alt_delim']) ) ? str_getcsv($line_img_alt, $this->options['image_meta_alt_delim']) : array($line_img_alt) );
  1649.  
  1650.                                     }
  1651.                                     if ( $this->options['set_image_meta_description'] ){                               
  1652.                                         $img_descriptions = array();                                   
  1653.                                         $line_img_descriptions = explode("\n", $image_meta_alts[$i]);
  1654.                                         if ( ! empty($line_img_descriptions) )
  1655.                                             foreach ($line_img_descriptions as $line_img_description)
  1656.                                                 $img_descriptions = array_merge($img_descriptions, ( ! empty($this->options['image_meta_description_delim']) ) ? str_getcsv($line_img_description, $this->options['image_meta_description_delim']) : array($line_img_description) );
  1657.  
  1658.                                     }                                      
  1659.  
  1660.                                     foreach ($imgs as $k => $img_url) { if (empty($img_url)) continue;                                                                                                         
  1661.  
  1662.                                         $url = str_replace(" ", "%20", trim($img_url));
  1663.                                         $bn = preg_replace('/[\\?|&].*/', '', basename($url));
  1664.                                        
  1665.                                         if ( "yes" == $this->options['download_images'] and ! empty($auto_extensions[$i]) and preg_match('%^(jpg|jpeg|png|gif)$%i', $auto_extensions[$i])){
  1666.                                             $img_ext = $auto_extensions[$i];
  1667.                                         }
  1668.                                         else {
  1669.                                             $img_ext = pmxi_getExtensionFromStr($url);                                 
  1670.                                             $default_extension = pmxi_getExtension($bn);                                                                                                   
  1671.  
  1672.                                             if ($img_ext == "") $img_ext = pmxi_get_remote_image_ext($url);    
  1673.                                         }
  1674.  
  1675.                                         $logger and call_user_func($logger, sprintf(__('- Importing image `%s` for `%s` ...', 'pmxi_plugin'), $img_url, $articleData['post_title']));
  1676.  
  1677.                                         // generate local file name
  1678.                                         $image_name = urldecode(($this->options['auto_rename_images'] and "" != $auto_rename_images[$i]) ? sanitize_file_name(($img_ext) ? str_replace("." . $default_extension, "", $auto_rename_images[$i]) : $auto_rename_images[$i]) : sanitize_file_name((($img_ext) ? str_replace("." . $default_extension, "", $bn) : $bn))) . (("" != $img_ext) ? '.' . $img_ext : '');                                                                                                                                            
  1679.                                            
  1680.                                         // if wizard store image data to custom field                                  
  1681.                                         $create_image = false;
  1682.                                         $download_image = true;
  1683.  
  1684.                                         if (base64_decode($url, true) !== false){
  1685.                                             $img = @imagecreatefromstring(base64_decode($url));                                    
  1686.                                             if($img)
  1687.                                             {  
  1688.                                                 $logger and call_user_func($logger, __('- Founded base64_encoded image', 'pmxi_plugin'));
  1689.  
  1690.                                                 $image_filename = md5(time()) . '.jpg';
  1691.                                                 $image_filepath = $targetDir . '/' . $image_filename;
  1692.                                                 imagejpeg($img, $image_filepath);
  1693.                                                 if( ! ($image_info = @getimagesize($image_filepath)) or ! in_array($image_info[2], array(IMAGETYPE_GIF, IMAGETYPE_JPEG, IMAGETYPE_PNG))) {
  1694.                                                     $logger and call_user_func($logger, sprintf(__('- <b>WARNING</b>: File %s is not a valid image and cannot be set as featured one', 'pmxi_plugin'), $image_filepath));
  1695.                                                     $logger and !$is_cron and PMXI_Plugin::$session->warnings++;
  1696.                                                 } else {
  1697.                                                     $create_image = true;                                          
  1698.                                                 }
  1699.                                             }
  1700.                                         }
  1701.                                         else {                                     
  1702.                                            
  1703.                                             $image_filename = wp_unique_filename($targetDir, $image_name);
  1704.                                             $image_filepath = $targetDir . '/' . $image_filename;
  1705.                                            
  1706.                                             $logger and call_user_func($logger, sprintf(__('- Image `%s` will be saved with name `%s` ...', 'pmxi_plugin'), $img_url, $image_filename));
  1707.  
  1708.                                             // keep existing and add newest images
  1709.                                             if ( ! empty($articleData['ID']) and $this->options['is_update_images'] and $this->options['update_images_logic'] == "add_new" and $this->options['update_all_data'] == "no"){                                                                                                                                                                         
  1710.                                                
  1711.                                                 $logger and call_user_func($logger, __('- Keep existing and add newest images ...', 'pmxi_plugin'));
  1712.  
  1713.                                                 $attachment_imgs = get_posts( array(
  1714.                                                     'post_type' => 'attachment',
  1715.                                                     'posts_per_page' => -1,
  1716.                                                     'post_parent' => $pid,                                             
  1717.                                                 ) );
  1718.  
  1719.                                                 if ( $attachment_imgs ) {
  1720.                                                     foreach ( $attachment_imgs as $attachment_img ) {                                                  
  1721.                                                         if ($attachment_img->guid == $targetUrl . '/' . $image_name){
  1722.                                                             $download_image = false;
  1723.                                                             $success_images = true;
  1724.                                                             if ( ! has_post_thumbnail($pid) and $this->options['is_featured'] )
  1725.                                                                 set_post_thumbnail($pid, $attachment_img->ID);
  1726.                                                             elseif ( ! in_array($attachment_img->ID, $gallery_attachment_ids))
  1727.                                                                 $gallery_attachment_ids[] = $attachment_img->ID;   
  1728.  
  1729.                                                             $logger and call_user_func($logger, sprintf(__('- <b>Image SKIPPED</b>: The image %s is always exists for the `%s`', 'pmxi_plugin'), basename($attachment_img->guid), $articleData['post_title']));                        
  1730.                                                         }
  1731.                                                     }                                              
  1732.                                                 }
  1733.  
  1734.                                             }
  1735.  
  1736.                                             if ($download_image){                                          
  1737.  
  1738.                                                 // do not download images
  1739.                                                 if ( "yes" != $this->options['download_images'] ){                                                 
  1740.  
  1741.                                                     $image_filename = $image_name;
  1742.                                                     $image_filepath = $targetDir . '/' . $image_filename;                                                                                                                                                                                                                                      
  1743.                                                        
  1744.                                                     $wpai_uploads = $uploads['basedir'] . '/wpallimport/files/';
  1745.                                                     $wpai_image_path = $wpai_uploads . str_replace('%20', ' ', $url);
  1746.  
  1747.                                                     $logger and call_user_func($logger, sprintf(__('- Searching for existing image `%s` in `%s` folder', 'pmxi_plugin'), $wpai_image_path, $wpai_uploads));
  1748.  
  1749.                                                     if ( @file_exists($wpai_image_path) and @copy( $wpai_image_path, $image_filepath )){
  1750.                                                         $download_image = false;                                                                               
  1751.                                                         if( ! ($image_info = @getimagesize($image_filepath)) or ! in_array($image_info[2], array(IMAGETYPE_GIF, IMAGETYPE_JPEG, IMAGETYPE_PNG))) {
  1752.                                                             $logger and call_user_func($logger, sprintf(__('- <b>WARNING</b>: File %s is not a valid image and cannot be set as featured one', 'pmxi_plugin'), $image_filepath));
  1753.                                                             $logger and !$is_cron and PMXI_Plugin::$session->warnings++;
  1754.                                                             @unlink($image_filepath);
  1755.                                                         } else {
  1756.                                                             $create_image = true;                                          
  1757.                                                             $logger and call_user_func($logger, sprintf(__('- Image `%s` has been successfully founded', 'pmxi_plugin'), $wpai_image_path));
  1758.                                                         }
  1759.                                                     }                                                  
  1760.                                                 }  
  1761.  
  1762.                                                 if ($download_image){
  1763.                                                    
  1764.                                                     $logger and call_user_func($logger, sprintf(__('- Downloading image from `%s`', 'pmxi_plugin'), $url));
  1765.  
  1766.                                                     $request = get_file_curl($url, $image_filepath);
  1767.  
  1768.                                                     if ( (is_wp_error($request) or $request === false) and ! @file_put_contents($image_filepath, @file_get_contents($url))) {
  1769.                                                         @unlink($image_filepath); // delete file since failed upload may result in empty file created
  1770.                                                     } elseif( ($image_info = @getimagesize($image_filepath)) and in_array($image_info[2], array(IMAGETYPE_GIF, IMAGETYPE_JPEG, IMAGETYPE_PNG))) {
  1771.                                                         $create_image = true;      
  1772.                                                         $logger and call_user_func($logger, sprintf(__('- Image `%s` has been successfully downloaded', 'pmxi_plugin'), $url));                                
  1773.                                                     }                                              
  1774.                                                    
  1775.                                                     if ( ! $create_image ){
  1776.  
  1777.                                                         $url = str_replace(" ", "%20", trim(pmxi_convert_encoding($img_url)));
  1778.                                                        
  1779.                                                         $request = get_file_curl($url, $image_filepath);
  1780.  
  1781.                                                         if ( (is_wp_error($request) or $request === false) and ! @file_put_contents($image_filepath, @file_get_contents($url))) {
  1782.                                                             $logger and call_user_func($logger, sprintf(__('- <b>WARNING</b>: File %s cannot be saved locally as %s', 'pmxi_plugin'), $url, $image_filepath));
  1783.                                                             $logger and !$is_cron and PMXI_Plugin::$session->warnings++;
  1784.                                                             @unlink($image_filepath); // delete file since failed upload may result in empty file created                                      
  1785.                                                         } elseif( ! ($image_info = @getimagesize($image_filepath)) or ! in_array($image_info[2], array(IMAGETYPE_GIF, IMAGETYPE_JPEG, IMAGETYPE_PNG))) {
  1786.                                                             $logger and call_user_func($logger, sprintf(__('- <b>WARNING</b>: File %s is not a valid image and cannot be set as featured one', 'pmxi_plugin'), $url));
  1787.                                                             $logger and !$is_cron and PMXI_Plugin::$session->warnings++;
  1788.                                                             @unlink($image_filepath);
  1789.                                                         } else {
  1790.                                                             $create_image = true;  
  1791.                                                             $logger and call_user_func($logger, sprintf(__('- Image `%s` has been successfully downloaded', 'pmxi_plugin'), $url));                                            
  1792.                                                         }
  1793.                                                     }
  1794.                                                 }
  1795.                                             }
  1796.                                         }
  1797.  
  1798.                                         if ($create_image){
  1799.                                            
  1800.                                             $logger and call_user_func($logger, sprintf(__('- Creating an attachment for image `%s`', 'pmxi_plugin'), $targetUrl . '/' . $image_filename));
  1801.  
  1802.                                             $attachment = array(
  1803.                                                 'post_mime_type' => image_type_to_mime_type($image_info[2]),
  1804.                                                 'guid' => $targetUrl . '/' . $image_filename,
  1805.                                                 'post_title' => $image_filename,
  1806.                                                 'post_content' => '',
  1807.                                                 'post_author' => $post_author[$i],
  1808.                                             );
  1809.                                             if (($image_meta = wp_read_image_metadata($image_filepath))) {
  1810.                                                 if (trim($image_meta['title']) && ! is_numeric(sanitize_title($image_meta['title'])))
  1811.                                                     $attachment['post_title'] = $image_meta['title'];
  1812.                                                 if (trim($image_meta['caption']))
  1813.                                                     $attachment['post_content'] = $image_meta['caption'];
  1814.                                             }
  1815.  
  1816.                                             $attid = ($this->options['is_fast_mode']) ? pmxi_insert_attachment($attachment, $image_filepath, $pid) : wp_insert_attachment($attachment, $image_filepath, $pid);                                     
  1817.  
  1818.                                             if (is_wp_error($attid)) {
  1819.                                                 $logger and call_user_func($logger, __('- <b>WARNING</b>', 'pmxi_plugin') . ': ' . $attid->get_error_message());
  1820.                                                 $logger and !$is_cron and PMXI_Plugin::$session->warnings++;
  1821.                                             } else {
  1822.                                                 // you must first include the image.php file
  1823.                                                 // for the function wp_generate_attachment_metadata() to work
  1824.                                                 require_once(ABSPATH . 'wp-admin/includes/image.php');
  1825.                                                 wp_update_attachment_metadata($attid, wp_generate_attachment_metadata($attid, $image_filepath));                                                                                           
  1826.                                                                                            
  1827.                                                 $update_attachment_meta = array();
  1828.                                                 if ( $this->options['set_image_meta_title'] and ! empty($img_titles[$k]) ) $update_attachment_meta['post_title'] = $img_titles[$k];
  1829.                                                 if ( $this->options['set_image_meta_caption'] and ! empty($img_captions[$k]) ) $update_attachment_meta['post_excerpt'] =  $img_captions[$k];                               
  1830.                                                 if ( $this->options['set_image_meta_description'] and ! empty($img_descriptions[$k]) ) $update_attachment_meta['post_content'] =  $img_descriptions[$k];
  1831.                                                 if ( $this->options['set_image_meta_alt'] and ! empty($img_alts[$k]) ) update_post_meta($attid, '_wp_attachment_image_alt', $img_alts[$k]);
  1832.                                                
  1833.                                                 if ( ! empty($update_attachment_meta)) $this->wpdb->update( $this->wpdb->posts, $update_attachment_meta, array('ID' => $attid) );                                                              
  1834.                                                
  1835.                                                 $logger and call_user_func($logger, __('- <b>ACTION</b>: pmxi_gallery_image', 'pmxi_plugin'));                                                                                         
  1836.                                                 do_action( 'pmxi_gallery_image', $pid, $attid, $image_filepath);
  1837.  
  1838.                                                 $success_images = true;
  1839.                                                 if ( ! has_post_thumbnail($pid) and $this->options['is_featured'] )
  1840.                                                     set_post_thumbnail($pid, $attid);                                          
  1841.                                                 elseif ( ! in_array($attid, $gallery_attachment_ids))
  1842.                                                     $gallery_attachment_ids[] = $attid;    
  1843.  
  1844.                                                 $logger and call_user_func($logger, sprintf(__('- Attachment has been successfully created for image `%s`', 'pmxi_plugin'), $targetUrl . '/' . $image_filename));                                          
  1845.                                             }
  1846.                                         }                                                                      
  1847.                                     }                                  
  1848.                                 }                          
  1849.                                 // Set product gallery images
  1850.                                 if ( $post_type == "product" and !empty($gallery_attachment_ids) )
  1851.                                     update_post_meta($pid, '_product_image_gallery', implode(',', $gallery_attachment_ids));
  1852.                                 $shandora_prefix = "shandora_";
  1853.                                 if( function_exists( 'bon_get_prefix') ) {
  1854.                                 $shandora_prefix = bon_get_prefix();
  1855.                                 if( empty( $shandora_prefix ) ) {
  1856.                                 $shandora_prefix = "shandora_";
  1857.                                 }
  1858.                                 }
  1859.                                 // Set product gallery images
  1860.                                 if ( ($post_type == "listing" || $post_type == "car-listing") and !empty($gallery_attachment_ids))
  1861.                                                                     update_post_meta($pid, $shandora_prefix . 'listing_gallery', implode(',', $gallery_attachment_ids));
  1862.                                 // Create entry as Draft if no images are downloaded successfully
  1863.                                 if ( ! $success_images and "yes" == $this->options['create_draft'] ) {                             
  1864.                                     $this->wpdb->update( $this->wpdb->posts, array('post_status' => 'draft'), array('ID' => $pid) );
  1865.                                     $logger and call_user_func($logger, sprintf(__('- Post `%s` saved as Draft, because no images are downloaded successfully', 'pmxi_plugin'), $articleData['post_title']));
  1866.                                 }
  1867.                             }
  1868.                         }
  1869.                         else{                          
  1870.                             // Create entry as Draft if no images are downloaded successfully
  1871.                             if ( "yes" == $this->options['create_draft'] ){
  1872.                                 $this->wpdb->update( $this->wpdb->posts, array('post_status' => 'draft'), array('ID' => $pid) );
  1873.                                 $logger and call_user_func($logger, sprintf(__('Post `%s` saved as Draft, because no images are downloaded successfully', 'pmxi_plugin'), $articleData['post_title']));
  1874.                             }
  1875.                         }
  1876.                     }
  1877.                     // [/featured image]
  1878.  
  1879.                     // [attachments]
  1880.                     if ( ! empty($uploads) and false === $uploads['error'] and !empty($attachments[$i]) and (empty($articleData['ID']) or $this->options['update_all_data'] == "yes" or ($this->options['update_all_data'] == "no" and $this->options['is_update_attachments']))) {
  1881.  
  1882.                         $targetDir = $uploads['path'];
  1883.                         $targetUrl = $uploads['url'];
  1884.  
  1885.                         $logger and call_user_func($logger, __('<b>ATTACHMENTS:</b>', 'pmxi_plugin'));
  1886.  
  1887.                         if ( ! @is_writable($targetDir) ){
  1888.                             $logger and call_user_func($logger, sprintf(__('- <b>ERROR</b>: Target directory %s is not writable', 'pmxi_plugin'), trim($targetDir)));
  1889.                         }
  1890.                         else{
  1891.                             // you must first include the image.php file
  1892.                             // for the function wp_generate_attachment_metadata() to work
  1893.                             require_once(ABSPATH . 'wp-admin/includes/image.php');
  1894.  
  1895.                             if ( ! is_array($attachments[$i]) ) $attachments[$i] = array($attachments[$i]);
  1896.  
  1897.                             $logger and call_user_func($logger, sprintf(__('- Importing attachments for `%s` ...', 'pmxi_plugin'), $articleData['post_title']));
  1898.  
  1899.                             foreach ($attachments[$i] as $attachment) { if ("" == $attachment) continue;
  1900.                                
  1901.                                 $atchs = str_getcsv($attachment, $this->options['atch_delim']);
  1902.  
  1903.                                 if ( ! empty($atchs) ) {
  1904.  
  1905.                                     foreach ($atchs as $atch_url) { if (empty($atch_url)) continue;    
  1906.  
  1907.                                         $atch_url = str_replace(" ", "%20", trim($atch_url));                          
  1908.  
  1909.                                         $attachment_filename = wp_unique_filename($targetDir, urldecode(basename(parse_url(trim($atch_url), PHP_URL_PATH))));                                      
  1910.                                         $attachment_filepath = $targetDir . '/' . sanitize_file_name($attachment_filename);
  1911.  
  1912.                                         $logger and call_user_func($logger, sprintf(__('- Filename for attachment was generated as %s', 'pmxi_plugin'), $attachment_filename));
  1913.                                        
  1914.                                         $request = get_file_curl(trim($atch_url), $attachment_filepath);
  1915.                                                                
  1916.                                         if ( (is_wp_error($request) or $request === false)  and ! @file_put_contents($attachment_filepath, @file_get_contents(trim($atch_url)))) {                                             
  1917.                                             $logger and call_user_func($logger, sprintf(__('- <b>WARNING</b>: Attachment file %s cannot be saved locally as %s', 'pmxi_plugin'), trim($atch_url), $attachment_filepath));
  1918.                                             is_wp_error($request) and $logger and call_user_func($logger, sprintf(__('- <b>WP Error</b>: %s', 'pmxi_plugin'), $request->get_error_message()));
  1919.                                             $logger and !$is_cron and PMXI_Plugin::$session->warnings++;
  1920.                                             unlink($attachment_filepath); // delete file since failed upload may result in empty file created                                              
  1921.                                         } elseif( ! $wp_filetype = wp_check_filetype(basename($attachment_filename), null )) {
  1922.                                             $logger and call_user_func($logger, sprintf(__('- <b>WARNING</b>: Can\'t detect attachment file type %s', 'pmxi_plugin'), trim($atch_url)));
  1923.                                             $logger and !$is_cron and PMXI_Plugin::$session->warnings++;
  1924.                                         } else {
  1925.                                             $logger and call_user_func($logger, sprintf(__('- File %s has been successfully downloaded', 'pmxi_plugin'), $atch_url));
  1926.                                             $attachment_data = array(
  1927.                                                 'guid' => $targetUrl . '/' . basename($attachment_filepath),
  1928.                                                 'post_mime_type' => $wp_filetype['type'],
  1929.                                                 'post_title' => preg_replace('/\.[^.]+$/', '', basename($attachment_filepath)),
  1930.                                                 'post_content' => '',
  1931.                                                 'post_status' => 'inherit',
  1932.                                                 'post_author' => $post_author[$i],
  1933.                                             );
  1934.                                             $attach_id = ($this->options['is_fast_mode']) ? pmxi_insert_attachment( $attachment_data, $attachment_filepath, $pid ) : wp_insert_attachment( $attachment_data, $attachment_filepath, $pid );                                             
  1935.  
  1936.                                             if (is_wp_error($attach_id)) {
  1937.                                                 $logger and call_user_func($logger, __('- <b>WARNING</b>', 'pmxi_plugin') . ': ' . $pid->get_error_message());
  1938.                                                 $logger and !$is_cron and PMXI_Plugin::$session->warnings++;
  1939.                                             } else {                                           
  1940.                                                 wp_update_attachment_metadata($attach_id, wp_generate_attachment_metadata($attach_id, $attachment_filepath));                                          
  1941.                                                 $logger and call_user_func($logger, sprintf(__('- Attachment has been successfully created for post `%s`', 'pmxi_plugin'), $articleData['post_title']));
  1942.                                                 $logger and call_user_func($logger, __('- <b>ACTION</b>: pmxi_attachment_uploaded', 'pmxi_plugin'));
  1943.                                                 do_action( 'pmxi_attachment_uploaded', $pid, $attach_id, $attachment_filepath);
  1944.                                             }                                      
  1945.                                         }                                                              
  1946.                                     }
  1947.                                     $shandora_prefix = "shandora_";
  1948.                                                     if( function_exists( 'bon_get_prefix') ) {
  1949.                                                         $shandora_prefix = bon_get_prefix();
  1950.                                                         if( empty( $shandora_prefix ) ) {
  1951.                                                             $shandora_prefix = "shandora_";
  1952.                                                         }
  1953.                                                     }
  1954.                                                     // Set product gallery images
  1955.                                                     if ( ($post_type == "listing" || $post_type == "car-listing") and !empty($gallery_attachment_ids))
  1956.                                                         update_post_meta($pid, $shandora_prefix . 'listing_gallery', implode(',', $gallery_attachment_ids));
  1957.                                 }
  1958.                             }
  1959.                         }
  1960.                     }
  1961.                     // [/attachments]
  1962.                    
  1963.                     // [custom taxonomies]
  1964.                     if ( ! empty($taxonomies) ){
  1965.  
  1966.                         $logger and call_user_func($logger, __('<b>TAXONOMIES:</b>', 'pmxi_plugin'));  
  1967.  
  1968.                         $custom_type = get_post_type_object( $this->options['custom_type'] );  
  1969.  
  1970.                         foreach ($taxonomies as $tx_name => $txes) {                               
  1971.  
  1972.                             // Skip updating product attributes
  1973.                             if ( PMXI_Admin_Addons::get_addon('PMWI_Plugin') and strpos($tx_name, "pa_") === 0 ) continue;
  1974.  
  1975.                             if ( empty($articleData['ID']) or $this->options['update_all_data'] == "yes" or ( $this->options['update_all_data'] == "no" and $this->options['is_update_categories'] )) {
  1976.                                
  1977.                                 $logger and call_user_func($logger, sprintf(__('- Importing taxonomy `%s` ...', 'pmxi_plugin'), $tx_name));
  1978.  
  1979.                                 if ( ! empty($this->options['tax_logic'][$tx_name]) and $this->options['tax_logic'][$tx_name] == 'hierarchical' and ! empty($this->options['tax_hierarchical_logic'][$tx_name]) and $this->options['tax_hierarchical_logic'][$tx_name] == 'entire'){
  1980.                                     $logger and call_user_func($logger, sprintf(__('- Auto-nest enabled with separator `%s` ...', 'pmxi_plugin'), ( ! empty($this->options['tax_hierarchical_delim'][$tx_name]) ? $this->options['tax_hierarchical_delim'][$tx_name] : ',')));
  1981.                                 }
  1982.  
  1983.                                 if (!empty($articleData['ID'])){
  1984.                                     if ($this->options['update_all_data'] == "no" and $this->options['update_categories_logic'] == "all_except" and !empty($this->options['taxonomies_list'])
  1985.                                         and is_array($this->options['taxonomies_list']) and in_array($tx_name, $this->options['taxonomies_list'])){
  1986.                                             $logger and call_user_func($logger, sprintf(__('- %s %s `%s` has been skipped attempted to `Leave these taxonomies alone, update all others`...', 'pmxi_plugin'), $custom_type->labels->singular_name, $tx_name, $single_tax['name']));
  1987.                                             continue;
  1988.                                         }      
  1989.                                     if ($this->options['update_all_data'] == "no" and $this->options['update_categories_logic'] == "only" and ((!empty($this->options['taxonomies_list'])
  1990.                                         and is_array($this->options['taxonomies_list']) and ! in_array($tx_name, $this->options['taxonomies_list'])) or empty($this->options['taxonomies_list']))){
  1991.                                             $logger and call_user_func($logger, sprintf(__('- %s %s `%s` has been skipped attempted to `Update only these taxonomies, leave the rest alone`...', 'pmxi_plugin'), $custom_type->labels->singular_name, $tx_name, $single_tax['name']));
  1992.                                             continue;
  1993.                                         }
  1994.                                 }                              
  1995.  
  1996.                                 $assign_taxes = array();
  1997.  
  1998.                                 if ($this->options['update_categories_logic'] == "add_new" and !empty($existing_taxonomies[$tx_name][$i])){
  1999.                                     $assign_taxes = $existing_taxonomies[$tx_name][$i];
  2000.                                     unset($existing_taxonomies[$tx_name][$i]);
  2001.                                 }
  2002.                                 elseif(!empty($existing_taxonomies[$tx_name][$i])){
  2003.                                     unset($existing_taxonomies[$tx_name][$i]);
  2004.                                 }
  2005.  
  2006.                                 // create term if not exists                               
  2007.                                 if ( ! empty($txes[$i]) ):
  2008.                                     foreach ($txes[$i] as $key => $single_tax) {
  2009.                                         $is_created_term = false;
  2010.                                         if (is_array($single_tax) and ! empty($single_tax['name'])){                                                                                                                       
  2011.  
  2012.                                             $parent_id = (!empty($single_tax['parent'])) ? pmxi_recursion_taxes($single_tax['parent'], $tx_name, $txes[$i], $key) : '';
  2013.                                            
  2014.                                             $term = term_exists($single_tax['name'], $tx_name, (int)$parent_id);       
  2015.                                            
  2016.                                             if ( empty($term) and !is_wp_error($term) ){
  2017.                                                 $term = term_exists(htmlspecialchars($single_tax['name']), $tx_name, (int)$parent_id);     
  2018.                                                 if ( empty($term) and !is_wp_error($term) ){
  2019.                                                     $term_attr = array('parent'=> (!empty($parent_id)) ? $parent_id : 0);
  2020.                                                     $term = wp_insert_term(
  2021.                                                         $single_tax['name'], // the term
  2022.                                                         $tx_name, // the taxonomy
  2023.                                                         $term_attr
  2024.                                                     );
  2025.                                                     if ( ! is_wp_error($term) ){
  2026.                                                         $is_created_term = true;
  2027.                                                         if ( empty($parent_id) ){
  2028.                                                             $logger and call_user_func($logger, sprintf(__('- Creating parent %s %s `%s` ...', 'pmxi_plugin'), $custom_type->labels->singular_name, $tx_name, $single_tax['name']));   
  2029.                                                         }
  2030.                                                         else{
  2031.                                                             $logger and call_user_func($logger, sprintf(__('- Creating child %s %s for %s named `%s` ...', 'pmxi_plugin'), $custom_type->labels->singular_name, $tx_name, (is_array($single_tax['parent']) ? $single_tax['parent']['name'] : $single_tax['parent']), $single_tax['name']));    
  2032.                                                         }
  2033.                                                     }
  2034.                                                 }
  2035.                                             }                                          
  2036.                                            
  2037.                                             if ( is_wp_error($term) ){                                 
  2038.                                                 $logger and call_user_func($logger, sprintf(__('- <b>WARNING</b>: `%s`', 'pmxi_plugin'), $term->get_error_message()));
  2039.                                                 $logger and !$is_cron and PMXI_Plugin::$session->warnings++;
  2040.                                             }
  2041.                                             elseif ( ! empty($term)) {                                             
  2042.                                                 $cat_id = $term['term_id'];
  2043.                                                 if ($cat_id and $single_tax['assign'])
  2044.                                                 {
  2045.                                                     $term = get_term_by('id', $cat_id, $tx_name);
  2046.                                                     if (!in_array($term->slug, $assign_taxes)) $assign_taxes[] = $term->term_taxonomy_id;      
  2047.                                                     if (!$is_created_term){                                                    
  2048.                                                         if ( empty($parent_id) ){                                                          
  2049.                                                             $logger and call_user_func($logger, sprintf(__('- Attempted to create parent %s %s `%s`, duplicate detected. Importing %s to existing `%s` %s, ID %d, slug `%s` ...', 'pmxi_plugin'), $custom_type->labels->singular_name, $tx_name, $single_tax['name'], $custom_type->labels->singular_name, $term->name, $tx_name, $term->term_id, $term->slug));   
  2050.                                                         }
  2051.                                                         else{                                                          
  2052.                                                             $logger and call_user_func($logger, sprintf(__('- Attempted to create child %s %s `%s`, duplicate detected. Importing %s to existing `%s` %s, ID %d, slug `%s` ...', 'pmxi_plugin'), $custom_type->labels->singular_name, $tx_name, $single_tax['name'], $custom_type->labels->singular_name, $term->name, $tx_name, $term->term_id, $term->slug));
  2053.                                                         }  
  2054.                                                     }
  2055.                                                 }                                  
  2056.                                             }                                  
  2057.                                         }
  2058.                                     }              
  2059.                                 endif;                                     
  2060.                                
  2061.                                 // associate taxes with post                               
  2062.                                 $this->associate_terms($pid, ( empty($assign_taxes) ? false : $assign_taxes ), $tx_name, $logger); 
  2063.                                
  2064.                             }
  2065.                         }
  2066.                         if ( ! empty($existing_taxonomies) and $this->options['update_all_data'] == "no" and ($this->options['is_update_categories'] and $this->options['update_categories_logic'] != 'full_update') or !$this->options['is_update_categories']) {
  2067.                            
  2068.                             foreach ($existing_taxonomies as $tx_name => $txes) {
  2069.                                 // Skip updating product attributes
  2070.                                 if ( PMXI_Admin_Addons::get_addon('PMWI_Plugin') and strpos($tx_name, "pa_") === 0 ) continue;
  2071.  
  2072.                                 if (!empty($txes[$i]))                                 
  2073.                                     $this->associate_terms($pid, $txes[$i], $tx_name, $logger);                                
  2074.                             }
  2075.                         }
  2076.                     }                  
  2077.                     // [/custom taxonomies]                                    
  2078.  
  2079.                     if (empty($articleData['ID'])) {                                                                                                               
  2080.                         $logger and call_user_func($logger, sprintf(__('<b>CREATED</b> `%s` `%s` (ID: %s)', 'pmxi_plugin'), $articleData['post_title'], $custom_type_details->labels->singular_name, $pid));
  2081.                     } else {                       
  2082.                         $logger and call_user_func($logger, sprintf(__('<b>UPDATED</b> `%s` `%s` (ID: %s)', 'pmxi_plugin'), $articleData['post_title'], $custom_type_details->labels->singular_name, $pid));
  2083.                     }
  2084.  
  2085.                     // [addons import]
  2086.  
  2087.                     // prepare data for import
  2088.                     $importData = array(
  2089.                         'pid' => $pid,                     
  2090.                         'import' => $this,                     
  2091.                         'logger' => $logger                    
  2092.                     );
  2093.  
  2094.                     // deligate operation to addons
  2095.                     foreach (PMXI_Admin_Addons::get_active_addons() as $class){
  2096.                         if (class_exists($class)){
  2097.                             if ( method_exists($addons[$class], 'saved_post') ) $addons[$class]->saved_post($importData);  
  2098.                         }
  2099.                         else{
  2100.                             $saved_func = $class . '_saved_post';
  2101.                             if (function_exists($saved_func)) call_user_func($saved_func, $importData);
  2102.                         }
  2103.                     }
  2104.                    
  2105.                     // [/addons import]                                    
  2106.                     $logger and call_user_func($logger, __('<b>ACTION</b>: pmxi_saved_post', 'pmxi_plugin'));
  2107.                     do_action( 'pmxi_saved_post', $pid); // hook that was triggered immediately after post saved
  2108.                    
  2109.                     if (empty($articleData['ID'])) $created++; else $updated++;                    
  2110.  
  2111.                     if ( ! $is_cron and "default" == $this->options['import_processing'] ){
  2112.                         $processed_records = $created + $updated + $skipped + PMXI_Plugin::$session->errors;
  2113.                         $logger and call_user_func($logger, sprintf(__('<span class="processing_info"><span class="created_count">%s</span><span class="updated_count">%s</span><span class="percents_count">%s</span></span>', 'pmxi_plugin'), $created, $updated, ceil(($processed_records/$this->count) * 100)));
  2114.                     }
  2115.                                                                                    
  2116.                 }              
  2117.                 $logger and call_user_func($logger, __('<b>ACTION</b>: pmxi_after_post_import', 'pmxi_plugin'));
  2118.                 do_action('pmxi_after_post_import', $this->id);
  2119.  
  2120.                 $logger and !$is_cron and PMXI_Plugin::$session->chunk_number++;
  2121.             }          
  2122.  
  2123.             wp_cache_flush();                      
  2124.  
  2125.             $this->set(array(      
  2126.                 'imported' => $created + $updated, 
  2127.                 'created'  => $created,
  2128.                 'updated'  => $updated,
  2129.                 'skipped'  => $skipped,
  2130.                 'last_activity' => date('Y-m-d H:i:s')             
  2131.             ))->update();
  2132.            
  2133.             if ( ! $is_cron ){
  2134.  
  2135.                 PMXI_Plugin::$session->save_data();
  2136.  
  2137.                 $records_count = $this->created + $this->updated + $this->skipped + PMXI_Plugin::$session->errors;
  2138.  
  2139.                 $is_import_complete = ($records_count == $this->count);                    
  2140.  
  2141.                 // Delete posts that are no longer present in your file
  2142.                 if ( $is_import_complete and ! empty($this->options['is_delete_missing']) and $this->options['duplicate_matching'] == 'auto') {
  2143.  
  2144.                     $logger and call_user_func($logger, __('Removing previously imported posts which are no longer actual...', 'pmxi_plugin'));
  2145.                     $postList = new PMXI_Post_List();                                  
  2146.  
  2147.                     $missing_ids = array();
  2148.                     $missingPosts = $postList->getBy(array('import_id' => $this->id, 'iteration !=' => $this->iteration));
  2149.  
  2150.                     if ( ! $missingPosts->isEmpty() ):
  2151.                        
  2152.                         foreach ($missingPosts as $missingPost) {
  2153.                        
  2154.                             $missing_ids[] = $missingPost['post_id'];
  2155.  
  2156.                             // Instead of deletion, set Custom Field
  2157.                             if ($this->options['is_update_missing_cf']){
  2158.                                 update_post_meta( $missingPost['post_id'], $this->options['update_missing_cf_name'], $this->options['update_missing_cf_value'] );
  2159.                                 $logger and call_user_func($logger, sprintf(__('Instead of deletion post `%s`, set Custom Field `%s` to value `%s`', 'pmxi_plugin'), $articleData['post_title'], $this->options['update_missing_cf_name'], $this->options['update_missing_cf_value']));
  2160.                             }
  2161.  
  2162.                             // Instead of deletion, change post status to Draft
  2163.                             if ($this->options['set_missing_to_draft']){
  2164.                                 $this->wpdb->update( $this->wpdb->posts, array('post_status' => 'draft'), array('ID' => $missingPost['post_id']) );                            
  2165.                                 $logger and call_user_func($logger, sprintf(__('Instead of deletion, change post `%s` status to Draft', 'pmxi_plugin'), $articleData['post_title']));
  2166.                             }
  2167.  
  2168.                             // Delete posts that are no longer present in your file
  2169.                             if ( ! $this->options['is_update_missing_cf'] and ! $this->options['set_missing_to_draft']){
  2170.  
  2171.                                 // Remove attachments
  2172.                                 $logger and call_user_func($logger, __('Deleting attachments...', 'pmxi_plugin'));
  2173.                                 empty($this->options['is_keep_attachments']) and wp_delete_attachments($missingPost['post_id'], true, 'files');                    
  2174.                                 // Remove images
  2175.                                 $logger and call_user_func($logger, __('Deleting images...', 'pmxi_plugin'));
  2176.                                 empty($this->options['is_keep_imgs']) and wp_delete_attachments($missingPost['post_id'], ($this->options['download_images'] == 'yes'));
  2177.                                
  2178.                                 $logger and call_user_func($logger, sprintf(__('Deleting post `%s` from pmxi_posts table', 'pmxi_plugin'), $missingPost['post_id']));          
  2179.                                 if ( ! empty($missingPost['id'])){                                 
  2180.                                     // Delete record form pmxi_posts                                               
  2181.                                     $missingRecord = new PMXI_Post_Record();
  2182.                                     $missingRecord->getById($missingPost['id'])->delete();                     
  2183.                                 }
  2184.                                 else {                                 
  2185.                                     $sql = "DELETE FROM " . PMXI_Plugin::getInstance()->getTablePrefix() . "posts WHERE post_id = " . $missingPost['post_id'] . " AND import_id = " . $missingPost['import_id'];
  2186.                                     $this->wpdb->query(
  2187.                                         $this->wpdb->prepare($sql, '')
  2188.                                     ); 
  2189.                                 }
  2190.  
  2191.                                 // Clear post's relationships
  2192.                                 if ( $post_type != "import_users" ) wp_delete_object_term_relationships($missingPost['post_id'], get_object_taxonomies('' != $this->options['custom_type'] ? $this->options['custom_type'] : 'post'));
  2193.  
  2194.                             }
  2195.                                                            
  2196.                         }
  2197.  
  2198.                     endif;                         
  2199.  
  2200.                     // Delete posts from database
  2201.                     if (!empty($missing_ids) && is_array($missing_ids) and ! $this->options['is_update_missing_cf'] and ! $this->options['set_missing_to_draft']){                                                                 
  2202.                        
  2203.                         $logger and call_user_func($logger, __('<b>ACTION</b>: pmxi_delete_post', 'pmxi_plugin'));
  2204.                         do_action('pmxi_delete_post', $missing_ids);       
  2205.  
  2206.                         if ( $this->options['custom_type'] == "import_users" ){
  2207.                             $sql = "delete a,b
  2208.                             FROM ".$this->wpdb->users." a
  2209.                             LEFT JOIN ".$this->wpdb->usermeta." b ON ( a.ID = b.user_id )                                      
  2210.                             WHERE a.ID IN (".implode(',', $missing_ids).");";
  2211.                         }
  2212.                         else {
  2213.                             $sql = "delete a,b,c
  2214.                             FROM ".$this->wpdb->posts." a
  2215.                             LEFT JOIN ".$this->wpdb->term_relationships." b ON ( a.ID = b.object_id )
  2216.                             LEFT JOIN ".$this->wpdb->postmeta." c ON ( a.ID = c.post_id )              
  2217.                             WHERE a.ID IN (".implode(',', $missing_ids).");";
  2218.                         }                      
  2219.  
  2220.                         $logger and call_user_func($logger, __('Deleting posts from database', 'pmxi_plugin'));
  2221.                         $this->wpdb->query(
  2222.                             $this->wpdb->prepare($sql, '')
  2223.                         );                     
  2224.  
  2225.                         $this->set(array('deleted' => count($missing_ids)))->update();         
  2226.                     }                              
  2227.  
  2228.                 }
  2229.  
  2230.                 // Set out of stock status for missing records [Woocommerce add-on option]
  2231.                 if ( $is_import_complete and empty($this->options['is_delete_missing']) and $post_type == "product" and class_exists('PMWI_Plugin') and !empty($this->options['missing_records_stock_status'])) {
  2232.  
  2233.                     $logger and call_user_func($logger, __('Update stock status previously imported posts which are no longer actual...', 'pmxi_plugin'));
  2234.                     $postList = new PMXI_Post_List();              
  2235.                     $missingPosts = $postList->getBy(array('import_id' => $this->id, 'iteration !=' => $this->iteration));
  2236.                     if ( ! $missingPosts->isEmpty() ){
  2237.                         foreach ($missingPosts as $missingPost) {
  2238.                             update_post_meta( $missingPost['post_id'], '_stock_status', 'outofstock' );
  2239.                             update_post_meta( $missingPost['post_id'], '_stock', 0 );
  2240.                         }
  2241.                     }
  2242.                 }  
  2243.             }      
  2244.            
  2245.         } catch (XmlImportException $e) {
  2246.             $logger and call_user_func($logger, __('<b>ERROR</b>', 'pmxi_plugin') . ': ' . $e->getMessage());
  2247.             $logger and !$is_cron and PMXI_Plugin::$session->errors++; 
  2248.         }              
  2249.        
  2250.         $logger and $is_import_complete and call_user_func($logger, __('Cleaning temporary data...', 'pmxi_plugin'));
  2251.         foreach ($tmp_files as $file) { // remove all temporary files created
  2252.             @unlink($file);
  2253.         }
  2254.        
  2255.         if (($is_cron or $is_import_complete) and $this->options['is_delete_source']) {
  2256.             $logger and call_user_func($logger, __('Deleting source XML file...', 'pmxi_plugin'));         
  2257.  
  2258.             // Delete chunks
  2259.             foreach (PMXI_Helper::safe_glob($uploads['basedir'] . '/wpallimport/temp/pmxi_chunk_*', PMXI_Helper::GLOB_RECURSE | PMXI_Helper::GLOB_PATH) as $filePath) {
  2260.                 $logger and call_user_func($logger, __('Deleting chunks files...', 'pmxi_plugin'));
  2261.                 @file_exists($filePath) and pmxi_remove_source($filePath, false);      
  2262.             }
  2263.  
  2264.             if ($this->type != "ftp"){
  2265.                 if ( ! @unlink($this->path)) {
  2266.                     $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: Unable to remove %s', 'pmxi_plugin'), $this->path));
  2267.                 }
  2268.             }
  2269.             else{
  2270.                 $file_path_array = PMXI_Helper::safe_glob($this->path, PMXI_Helper::GLOB_NODIR | PMXI_Helper::GLOB_PATH);
  2271.                 if (!empty($file_path_array)){
  2272.                     foreach ($file_path_array as $path) {
  2273.                         if ( ! @unlink($path)) {
  2274.                             $logger and call_user_func($logger, sprintf(__('<b>WARNING</b>: Unable to remove %s', 'pmxi_plugin'), $path));
  2275.                         }
  2276.                     }
  2277.                 }
  2278.             }
  2279.         }
  2280.  
  2281.         if ( ! $is_cron and $is_import_complete ){
  2282.  
  2283.             $this->set(array(
  2284.                 'processing' => 0, // unlock cron requests 
  2285.                 'triggered' => 0,
  2286.                 'queue_chunk_number' => 0,             
  2287.                 'registered_on' => date('Y-m-d H:i:s'),
  2288.                 'iteration' => ++$this->iteration
  2289.             ))->update();
  2290.  
  2291.             $logger and call_user_func($logger, 'Done');           
  2292.         }
  2293.        
  2294.         remove_filter('user_has_cap', array($this, '_filter_has_cap_unfiltered_html')); kses_init(); // return any filtering rules back if they has been disabled for import procedure
  2295.        
  2296.         return $this;
  2297.     }  
  2298.  
  2299.     protected function pushmeta($pid, $meta_key, $meta_value){
  2300.  
  2301.         if (empty($meta_key)) return;      
  2302.  
  2303.         $this->post_meta_to_insert[] = array(
  2304.             'meta_key' => $meta_key,
  2305.             'meta_value' => $meta_value,
  2306.             'pid' => $pid
  2307.         );     
  2308.  
  2309.     }
  2310.  
  2311.     protected function executeSQL(){
  2312.        
  2313.         $import_entry = ( $this->options['custom_type'] == 'import_users') ? 'user' : 'post';
  2314.  
  2315.         // prepare bulk SQL query
  2316.         $meta_table = _get_meta_table( $import_entry );
  2317.        
  2318.         if ( $this->post_meta_to_insert ){         
  2319.             $values = array();
  2320.             $already_added = array();
  2321.            
  2322.             foreach (array_reverse($this->post_meta_to_insert) as $key => $value) {
  2323.                 if ( ! empty($value['meta_key']) and ! in_array($value['pid'] . '-' . $value['meta_key'], $already_added) ){
  2324.                     $already_added[] = $value['pid'] . '-' . $value['meta_key'];                       
  2325.                     $values[] = '(' . $value['pid'] . ',"' . $value['meta_key'] . '",\'' . maybe_serialize($value['meta_value']) .'\')';                       
  2326.                 }
  2327.             }
  2328.            
  2329.             $this->wpdb->query("INSERT INTO $meta_table (`" . $import_entry . "_id`, `meta_key`, `meta_value`) VALUES " . implode(',', $values));
  2330.             $this->post_meta_to_insert = array();
  2331.         }  
  2332.     }
  2333.    
  2334.     public function _filter_has_cap_unfiltered_html($caps)
  2335.     {
  2336.         $caps['unfiltered_html'] = true;
  2337.         return $caps;
  2338.     }      
  2339.    
  2340.     protected function associate_terms($pid, $assign_taxes, $tx_name, $logger){
  2341.        
  2342.         $terms = wp_get_object_terms( $pid, $tx_name );
  2343.         $term_ids = array();        
  2344.  
  2345.         if ( ! empty($terms) ){
  2346.             if ( ! is_wp_error( $terms ) ) {               
  2347.                 foreach ($terms as $term_info) {
  2348.                     $term_ids[] = $term_info->term_taxonomy_id;
  2349.                     $this->wpdb->query(  $this->wpdb->prepare("UPDATE {$this->wpdb->term_taxonomy} SET count = count - 1 WHERE term_taxonomy_id = %d", $term_info->term_taxonomy_id) );
  2350.                 }              
  2351.                 $in_tt_ids = "'" . implode( "', '", $term_ids ) . "'";
  2352.                 $this->wpdb->query( $this->wpdb->prepare( "DELETE FROM {$this->wpdb->term_relationships} WHERE object_id = %d AND term_taxonomy_id IN ($in_tt_ids)", $pid ) );
  2353.             }
  2354.         }
  2355.  
  2356.         if (empty($assign_taxes)) return;
  2357.  
  2358.         foreach ($assign_taxes as $tt) {
  2359.             $this->wpdb->insert( $this->wpdb->term_relationships, array( 'object_id' => $pid, 'term_taxonomy_id' => $tt ) );
  2360.             $this->wpdb->query( "UPDATE {$this->wpdb->term_taxonomy} SET count = count + 1 WHERE term_taxonomy_id = $tt" );
  2361.         }
  2362.  
  2363.         $values = array();
  2364.         $term_order = 0;
  2365.         foreach ( $assign_taxes as $tt )                                       
  2366.             $values[] = $this->wpdb->prepare( "(%d, %d, %d)", $pid, $tt, ++$term_order);
  2367.                                            
  2368.  
  2369.         if ( $values ){
  2370.             if ( false === $this->wpdb->query( "INSERT INTO {$this->wpdb->term_relationships} (object_id, term_taxonomy_id, term_order) VALUES " . join( ',', $values ) . " ON DUPLICATE KEY UPDATE term_order = VALUES(term_order)" ) ){
  2371.                 $logger and call_user_func($logger, __('<b>ERROR</b> Could not insert term relationship into the database', 'pmxi_plugin') . ': '. $this->wpdb->last_error);
  2372.                 $logger and PMXI_Plugin::$session['pmxi_import']['errors'] = ++PMXI_Plugin::$session->data['pmxi_import']['errors'];
  2373.             }
  2374.         }                                  
  2375.  
  2376.         wp_cache_delete( $pid, $tx_name . '_relationships' );
  2377.     }
  2378.  
  2379.     /**
  2380.      * Clear associations with posts
  2381.      * @param bool[optional] $keepPosts When set to false associated wordpress posts will be deleted as well
  2382.      * @return PMXI_Import_Record
  2383.      * @chainable
  2384.      */
  2385.     public function deletePosts($keepPosts = TRUE) {
  2386.         $post = new PMXI_Post_List();      
  2387.         if ( ! $keepPosts) {                               
  2388.             $ids = array();
  2389.             foreach ($post->getBy('import_id', $this->id)->convertRecords() as $p) {               
  2390.                 // Remove attachments
  2391.                 empty($this->options['is_keep_attachments']) and wp_delete_attachments($p->post_id, true, 'files');
  2392.                 // Remove images
  2393.                 empty($this->options['is_keep_imgs']) and wp_delete_attachments($p->post_id, ($this->options['download_images'] == 'yes'));            
  2394.                 $ids[] = $p->post_id;
  2395.             }
  2396.  
  2397.             if ( ! empty($ids) ){
  2398.  
  2399.                 foreach ($ids as $id) {
  2400.                     do_action('pmxi_delete_post', $id);
  2401.                     if ( $this->options['custom_type'] != 'import_users' ) wp_delete_object_term_relationships($id, get_object_taxonomies('' != $this->options['custom_type'] ? $this->options['custom_type'] : 'post'));
  2402.                 }
  2403.  
  2404.                 if ( $this->options['custom_type'] == 'import_users' ){
  2405.                     $sql = "delete a,b
  2406.                     FROM ".$this->wpdb->users." a
  2407.                     LEFT JOIN ".$this->wpdb->usermeta." b ON ( a.ID = b.user_id )                  
  2408.                     WHERE a.ID IN (".implode(',', $ids).");";
  2409.                 }
  2410.                 else {
  2411.                     $sql = "delete a,b,c
  2412.                     FROM ".$this->wpdb->posts." a
  2413.                     LEFT JOIN ".$this->wpdb->term_relationships." b ON ( a.ID = b.object_id )
  2414.                     LEFT JOIN ".$this->wpdb->postmeta." c ON ( a.ID = c.post_id )
  2415.                     LEFT JOIN ".$this->wpdb->posts." d ON ( a.ID = d.post_parent )
  2416.                     WHERE a.ID IN (".implode(',', $ids).");";
  2417.                 }
  2418.  
  2419.                 $this->wpdb->query(
  2420.                     $this->wpdb->prepare($sql, '')
  2421.                 );             
  2422.                
  2423.             }          
  2424.         }
  2425.        
  2426.         $this->wpdb->query($this->wpdb->prepare('DELETE FROM ' . $post->getTable() . ' WHERE import_id = %s', $this->id));
  2427.  
  2428.         return $this;
  2429.     }
  2430.     /**
  2431.      * Delete associated files
  2432.      * @return PMXI_Import_Record
  2433.      * @chainable
  2434.      */
  2435.     public function deleteFiles() {
  2436.         $fileList = new PMXI_File_List();
  2437.         foreach($fileList->getBy('import_id', $this->id)->convertRecords() as $f) {
  2438.             if ( @file_exists($f->path) ){
  2439.                 pmxi_remove_source($f->path);              
  2440.             }
  2441.             $f->delete();
  2442.         }
  2443.         return $this;
  2444.     }
  2445.     /**
  2446.      * Delete associated history logs
  2447.      * @return PMXI_Import_Record
  2448.      * @chainable
  2449.      */
  2450.     public function deleteHistories(){
  2451.         $historyList = new PMXI_History_List();
  2452.         foreach ($historyList->getBy('import_id', $this->id)->convertRecords() as $h) {
  2453.             $h->delete();
  2454.         }
  2455.         return $this;
  2456.     }
  2457.     /**
  2458.      * Delete associated sub imports
  2459.      * @return PMXI_Import_Record
  2460.      * @chainable
  2461.      */
  2462.     public function deleteChildren($keepPosts = TRUE){
  2463.         $importList = new PMXI_Import_List();
  2464.         foreach ($importList->getBy('parent_import_id', $this->id)->convertRecords() as $i) {
  2465.             $i->delete($keepPosts);
  2466.         }
  2467.         return $this;
  2468.     }  
  2469.     /**
  2470.      * @see parent::delete()
  2471.      * @param bool[optional] $keepPosts When set to false associated wordpress posts will be deleted as well
  2472.      */
  2473.     public function delete($keepPosts = TRUE) {
  2474.         $this->deletePosts($keepPosts)->deleteFiles()->deleteHistories()->deleteChildren($keepPosts);
  2475.        
  2476.         return parent::delete();
  2477.     }
  2478.    
  2479. }
Add Comment
Please, Sign In to add comment