public function execute()
 {
     $product_features_model = new shopProductFeaturesModel();
     $this->view->assign('sku_id', $sku_id = waRequest::get('sku_id', 0, waRequest::TYPE_INT));
     $this->view->assign('product_id', $product_id = waRequest::get('product_id', 0, waRequest::TYPE_INT));
     $this->view->assign('product', $product = new shopProduct($product_id));
     if ($sku_id < 0) {
         $sku = array('image_id' => '', 'available' => 1, 'purchase_price' => null, 'compare_price' => null);
     } elseif (isset($product->skus[$sku_id])) {
         $sku = $product->skus[$sku_id];
     } else {
         throw new waException("SKU not found", 404);
     }
     $this->view->assign('sku', $sku);
     //$this->view->assign('features', $features_model->getByType($product->type_id, 'code', true));
     $this->view->assign('features', $this->getFeatures($product));
     $this->view->assign('sku_features', $product_features_model->getValues($product_id, -$sku_id));
 }
 private function stepExportProduct(&$current_stage, &$count, &$processed)
 {
     static $products;
     static $product_feature_model;
     static $feature_model;
     static $tags_model;
     static $size;
     if (!$products) {
         $offset = $current_stage[self::STAGE_PRODUCT] - ifset($this->data['map'][self::STAGE_PRODUCT], 0);
         $fields = '*';
         if (!empty($this->data['options']['images'])) {
             $fields .= ', images';
         }
         $products = $this->getCollection()->getProducts($fields, $offset, 50, false);
     }
     $chunk = 5;
     $non_sku_fields = array('summary', 'meta_title', 'meta_keywords', 'meta_description', 'description', 'sort', 'tags', 'images');
     while ($chunk-- > 0 && ($product = reset($products))) {
         $exported = false;
         /* check rights per product type && settlement options */
         $rights = empty($product['type_id']) || in_array($product['type_id'], $this->data['types']);
         $category_id = isset($product['category_id']) ? intval($product['category_id']) : null;
         /* check category match*/
         $category_match = !$this->data['export_category'] || $category_id === $this->data['map'][self::STAGE_CATEGORY];
         if ($rights && $category_match) {
             $shop_product = new shopProduct($product);
             if (!empty($this->data['options']['features'])) {
                 if (!isset($product['features'])) {
                     if (!$product_feature_model) {
                         $product_feature_model = new shopProductFeaturesModel();
                     }
                     $product['features'] = $product_feature_model->getValues($product['id']);
                 }
                 foreach ($product['features'] as $code => &$feature) {
                     if (!empty($this->data['composite_features'][$code])) {
                         $feature = str_replace('×', 'x', $feature);
                     }
                     unset($feature);
                 }
             }
             if (!isset($product['tags'])) {
                 if (!$tags_model) {
                     $tags_model = new shopProductTagsModel();
                 }
                 $product['tags'] = implode(',', $tags_model->getTags($product['id']));
             }
             if (!empty($this->data['options']['images'])) {
                 if (isset($product['images'])) {
                     if (!$size) {
                         /**
                          * @var shopConfig $config
                          */
                         $config = $this->getConfig();
                         $size = $config->getImageSize('big');
                     }
                     foreach ($product['images'] as &$image) {
                         $image = 'http://' . ifempty($this->data['base_url'], 'localhost') . shopImage::getUrl($image, $size);
                     }
                     $product['images'] = array_values($product['images']);
                 }
             }
             $product['type_name'] = $shop_product->type['name'];
             $skus = $shop_product->skus;
             if (false && $product['sku_id']) {
                 #default SKU reorder
                 if (isset($skus[$product['sku_id']])) {
                     $sku = $skus[$product['sku_id']];
                     $sku['stock'][0] = $sku['count'];
                     $product['skus'] = array(-1 => $sku);
                     unset($skus[$product['sku_id']]);
                 }
                 $this->writer->write($product);
                 if (!empty($this->data['options']['images'])) {
                     if (isset($product['images'])) {
                         $processed[self::STAGE_IMAGE] += count($product['images']);
                     }
                 }
                 $exported = true;
                 if (!empty($this->data['options']['features'])) {
                     unset($product['features']);
                 }
             }
             if (!empty($product['tax_id'])) {
                 $product['tax_name'] = ifset($this->data['taxes'][$product['tax_id']]);
             }
             if (!isset($product['features'])) {
                 $product['features'] = array();
             }
             foreach ($skus as $sku_id => $sku) {
                 if ($exported) {
                     foreach ($non_sku_fields as $field) {
                         if (isset($product[$field])) {
                             unset($product[$field]);
                         }
                     }
                 }
                 $sku['stock'][0] = $sku['count'];
                 if (!empty($this->data['options']['features'])) {
                     $sku['features'] = $product_feature_model->getValues($product['id'], -$sku_id);
                     if ($product['sku_type'] == shopProductModel::SKU_TYPE_SELECTABLE) {
                         if (!$exported) {
                             $features_selectable_model = new shopProductFeaturesSelectableModel();
                             if ($selected = $features_selectable_model->getByProduct($product['id'])) {
                                 if (!$feature_model) {
                                     $feature_model = new shopFeatureModel();
                                 }
                                 $features = $feature_model->getById(array_keys($selected));
                                 $enclosure = $this->writer->enclosure;
                                 $pattern = sprintf("/(?:%s|%s|%s)/", preg_quote(',', '/'), preg_quote($enclosure, '/'), preg_quote($enclosure, '/'));
                                 foreach ($features as $feature_id => $feature) {
                                     $values = shopFeatureModel::getValuesModel($feature['type'])->getValues(array('feature_id' => $feature_id, 'id' => $selected[$feature_id]));
                                     if (!empty($values[$feature['id']])) {
                                         $f_values = $values[$feature['id']];
                                         if (!isset($product['features'])) {
                                             $product['features'] = array();
                                         }
                                         if (isset($sku['features'][$feature['code']])) {
                                             array_unshift($f_values, (string) $sku['features'][$feature['code']]);
                                         }
                                         foreach ($f_values as &$value) {
                                             if (preg_match($pattern, $value)) {
                                                 $value = $enclosure . str_replace($enclosure, $enclosure . $enclosure, $value) . $enclosure;
                                             }
                                             unset($value);
                                         }
                                         $f_values = array_unique($f_values);
                                         $product['features'][$feature['code']] = '<{' . implode(',', $f_values) . '}>';
                                     }
                                 }
                             }
                             $virtual_product = $product;
                             if (isset($skus[$product['sku_id']])) {
                                 $virtual_product['skus'] = array(-1 => $skus[$product['sku_id']]);
                             } else {
                                 $virtual_product['skus'] = array(-1 => $sku);
                             }
                             $virtual_product['skus'][-1]['stock'] = array(0 => $product['count']);
                             $this->writer->write($virtual_product);
                         }
                         $product['features'] = $sku['features'];
                     } else {
                         if (!$exported) {
                             foreach ($product['features'] as $code => &$values) {
                                 if (isset($sku['features'][$code])) {
                                     $values = array_unique(array_merge($values, $sku['features'][$code]));
                                 }
                                 unset($values);
                             }
                         } else {
                             $product['features'] = $sku['features'];
                         }
                     }
                 }
                 $product['skus'] = array(-1 => $sku);
                 $this->writer->write($product);
                 if (isset($product['images'])) {
                     $processed[self::STAGE_IMAGE] += count($product['images']);
                 }
                 $exported = true;
                 ++$current_stage[self::STAGE_SKU];
                 ++$processed[self::STAGE_SKU];
             }
         } elseif (count($products) > 1) {
             ++$chunk;
         }
         array_shift($products);
         ++$current_stage[self::STAGE_PRODUCT];
         if ($exported) {
             ++$processed[self::STAGE_PRODUCT];
         }
     }
     return $current_stage[self::STAGE_PRODUCT] < $count[self::STAGE_PRODUCT];
 }
 private function getValue(&$product, $sku, $field, $info)
 {
     static $features_model;
     $value = null;
     list($source, $param) = explode(':', $info['source'], 2);
     switch ($source) {
         case 'field':
             $value = isset($product[$param]) ? $product[$param] : null;
             if (!empty($this->data['export']['sku'])) {
                 switch ($param) {
                     case 'id':
                         if (!empty($sku['id']) && $sku['id'] != $product['sku_id']) {
                             $value .= 's' . $sku['id'];
                         }
                         break;
                     case 'frontend_url':
                         if (!empty($sku['id']) && $sku['id'] != $product['sku_id']) {
                             if (strpos($value, '?')) {
                                 $value .= '&sku=' . $sku['id'];
                             } else {
                                 $value .= '?sku=' . $sku['id'];
                             }
                         }
                         break;
                     case 'file_name':
                         if (!empty($sku)) {
                             $value = empty($sku[$param]) ? null : 'true';
                         } else {
                             $value = empty($value) ? null : 'true';
                         }
                         break;
                     case 'price':
                     case 'count':
                     case 'sku':
                     case 'group_id':
                     case 'compare_price':
                         $value = ifset($sku[$param], $value);
                         break;
                 }
             }
             $value = $this->format($field, $value, $info, $product, $sku);
             break;
         case 'value':
         case 'text':
             $value = $this->format($field, $param, $info);
             break;
         case 'feature':
             if (!isset($product['features'])) {
                 if (!$features_model) {
                     $features_model = new shopProductFeaturesModel();
                 }
                 $product['features'] = $features_model->getValues($product['id'], ifset($sku['id']));
             }
             $value = $this->format($field, ifempty($product['features'][$param]), $info, $product, $sku);
             break;
         case 'function':
             switch ($param) {
                 case 'prepaid':
                     $source = array('source' => 'field:count');
                     if ($this->getValue($product, $sku, 'available', $source) === 'false') {
                         $value = 'Заказ товара по предоплате';
                     }
                     break;
                 case 'group_category':
                     break;
                 case 'group_market_category':
                     break;
             }
             break;
     }
     return $value;
 }