public function execute()
 {
     $app_settings_model = new waAppSettingsModel();
     $settings = $app_settings_model->get(array('shop', 'yoss'));
     if ($settings['status'] === 'on') {
         $query = waRequest::post('query', '', waRequest::TYPE_STRING_TRIM);
         $page = waRequest::post('page', 1, 'int');
         $result = array();
         $result['products'] = array();
         $result['product_count'] = 0;
         $collection = new shopProductsCollection('search/query=' . $query);
         $product_limit = $settings['product_limit'];
         if (!$product_limit) {
             $product_limit = $this->getConfig()->getOption('products_per_page');
         }
         $products = $collection->getProducts('*', ($page - 1) * $product_limit, $product_limit);
         if ($products) {
             $brands = array();
             $categories = array();
             $feature_model = new shopFeatureModel();
             $result['searh_all_url'] = wa()->getRouteUrl('/frontend/search/query=') . '?query=' . $query;
             foreach ($products as $p) {
                 $brand_feature = $feature_model->getByCode('brand');
                 $brand = '';
                 if ($brand_feature) {
                     $feature_value_model = $feature_model->getValuesModel($brand_feature['type']);
                     $product_brands = $feature_value_model->getProductValues($p['id'], $brand_feature['id']);
                     $brands = array();
                     foreach ($product_brands as $k => $v) {
                         $brand_id = $feature_value_model->getValueId($brand_feature['id'], $v);
                         $brands[] = array('id' => $brand_id, 'brand' => '<a href="' . wa()->getRouteUrl('shop/frontend/brand', array('brand' => str_replace('%2F', '/', urlencode($v)))) . '">' . $v . '</a>');
                     }
                 }
                 $category_model = new shopCategoryModel();
                 $category = $category_model->getById($p['category_id']);
                 $res_category = '';
                 if ($category) {
                     $res_category = '<a href="' . wa()->getRouteUrl('/frontend/category', array('category_url' => $category['full_url'])) . '">' . $category['name'] . '</a>';
                 }
                 $result['products'][] = array("name" => $p['name'], "url" => $p['frontend_url'], "image" => $p['image_id'] ? "<img src='" . shopImage::getUrl(array("product_id" => $p['id'], "id" => $p['image_id'], "ext" => $p['ext']), "48x48") . "' />" : "", "price" => shop_currency_html($p['price'], true), "brands" => $brands, "category" => $res_category);
             }
             $product_model = new shopProductModel();
             $product_count = $collection->count();
             $result['product_count'] = $product_count;
             if ($product_count > ($page - 1) * $product_limit + $product_limit) {
                 $result['next_page'] = $page + 1;
             } else {
                 $result['next_page'] = false;
             }
         }
         $this->response = $result;
     } else {
         $this->response = false;
     }
 }
 public function execute()
 {
     $items = waRequest::post('items');
     $product_ids = array();
     foreach ($items as $i) {
         $product_ids[] = $i['product_id'];
     }
     $product_ids = array_unique($product_ids);
     $feature_model = new shopFeatureModel();
     $f = $feature_model->getByCode('weight');
     if (!$f) {
         $values = array();
     } else {
         $values_model = $feature_model->getValuesModel($f['type']);
         $values = $values_model->getProductValues($product_ids, $f['id']);
     }
     $contact = $this->getContact();
     $shipping_address = $contact->getFirst('address.shipping');
     if ($shipping_address) {
         $shipping_address = $shipping_address['data'];
     }
     $shipping_items = array();
     foreach ($items as $i) {
         if (isset($values['skus'][$i['sku_id']])) {
             $w = $values['skus'][$i['sku_id']];
         } else {
             $w = isset($values[$i['product_id']]) ? $values[$i['product_id']] : 0;
         }
         $shipping_items[] = array('name' => '', 'price' => $i['price'], 'quantity' => $i['quantity'], 'weight' => $w);
     }
     $order_id = waRequest::post('order_id');
     if ($order_id) {
         $order_model = new shopOrderModel();
         $order_info = $order_model->getById($order_id);
         $currency = $order_info['currency'];
     } else {
         $currency = $this->getConfig()->getCurrency();
     }
     $total = waRequest::post('subtotal') - waRequest::post('discount');
     $order = array('currency' => $currency, 'contact' => $contact, 'items' => $items, 'total' => waRequest::post('subtotal'));
     if ($order_id) {
         $order['id'] = $order_info['id'];
     }
     $this->response['discount'] = shopDiscounts::calculate($order_info);
     $this->response['shipping_methods'] = shopHelper::getShippingMethods($shipping_address, $shipping_items, array('currency' => $currency, 'total_price' => $total));
     // for saving order in js
     $this->response['shipping_method_ids'] = array_keys($this->response['shipping_methods']);
 }
 /**
  * Filters collection products by specified conditions. 
  * 
  * @param array $data Product filtering conditions:
  *     'in_stock_only'     => whether only products with positive or unlimited stock count must be returned
  *     'price_min'         => minimum price limit
  *     'price_max'         => maximum price limit
  *     '%feature_code%'    => feature value
  */
 public function filters($data)
 {
     if ($this->filtered) {
         return;
     }
     $delete = array('page', 'sort', 'order');
     foreach ($delete as $k) {
         if (isset($data[$k])) {
             unset($data[$k]);
         }
     }
     $config = wa('shop')->getConfig();
     if (isset($data['in_stock_only'])) {
         $this->where[] = '(p.count > 0 OR p.count IS NULL)';
     }
     if (isset($data['price_min']) && $data['price_min'] !== '') {
         $this->where[] = 'p.max_price >= ' . $this->toFloat(shop_currency($data['price_min'], true, $config->getCurrency(true), false));
         unset($data['price_min']);
     }
     if (isset($data['price_max']) && $data['price_max'] !== '') {
         $this->where[] = 'p.min_price <= ' . $this->toFloat(shop_currency($data['price_max'], true, $config->getCurrency(true), false));
         unset($data['price_max']);
     }
     $feature_model = new shopFeatureModel();
     $features = $feature_model->getByField('code', array_keys($data), 'code');
     foreach ($data as $feature_code => $values) {
         if (!is_array($values)) {
             if ($values === '') {
                 continue;
             }
             $values = array($values);
         }
         if (isset($features[$feature_code])) {
             if (isset($values['min']) || isset($values['max']) || isset($values['unit'])) {
                 if (ifset($values['min'], '') === '' && ifset($values['max'], '') === '') {
                     continue;
                 } else {
                     $unit = ifset($values['unit']);
                     $min = $max = null;
                     if (isset($values['min'])) {
                         $min = $values['min'];
                         if ($unit) {
                             $min = shopDimension::getInstance()->convert($min, $features[$feature_code]['type'], null, $unit);
                         }
                     }
                     if (isset($values['max'])) {
                         $max = $values['max'];
                         if ($unit) {
                             $max = shopDimension::getInstance()->convert($max, $features[$feature_code]['type'], null, $unit);
                         }
                     }
                     $fm = $feature_model->getValuesModel($features[$feature_code]['type']);
                     $values = $fm->getValueIdsByRange($features[$feature_code]['id'], $min, $max);
                 }
             } else {
                 foreach ($values as &$v) {
                     $v = (int) $v;
                 }
             }
             if ($values) {
                 $this->addJoin('shop_product_features', 'p.id = :table.product_id AND :table.feature_id = ' . (int) $features[$feature_code]['id'], ':table.feature_value_id IN (' . implode(',', $values) . ')');
                 $this->group_by = 'p.id';
             } else {
                 $this->where[] = '0';
             }
         }
     }
     $this->filtered = true;
 }
 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];
 }
 /**
  * @param int $id
  * @param array $data
  * @param bool $correct
  * @param shopProduct $product
  * @return array
  */
 protected function updateSku($id = 0, $data, $correct = true, shopProduct $product = null)
 {
     /**
      * @var shopProductStocksModel $stocks_model
      */
     static $stocks_model;
     /**
      * @var bool $multi_stock
      */
     static $multi_stock = null;
     /**
      * @var shopFeatureModel $feature_model
      */
     static $feature_model;
     /**
      * @var shopProductFeaturesModel $product_features_model
      */
     static $product_features_model;
     if (isset($data['price'])) {
         $data['price'] = $this->castValue('double', $data['price']);
     }
     if (isset($data['purchase_price'])) {
         $data['purchase_price'] = $this->castValue('double', $data['purchase_price']);
     }
     if (isset($data['compare_price'])) {
         $data['compare_price'] = $this->castValue('double', $data['compare_price']);
     }
     if ($id > 0) {
         if ($product && (!isset($data['virtual']) || !empty($data['virtual']))) {
             #check changes for virtual SKU
             $virtual_sku_defaults = array('price' => $product->base_price_selectable, 'purchase_price' => $product->purchase_price_selectable, 'compare_price' => $product->compare_price_selectable, 'count' => 0);
             $virtual = null;
             foreach ($virtual_sku_defaults as $field => $default) {
                 if (isset($data[$field])) {
                     $value = $data[$field];
                     if (is_array($value)) {
                         $value = max($value);
                     }
                     if ($value != $default) {
                         if ($virtual === null) {
                             $virtual = isset($product->skus[$id]) && !empty($product->skus[$id]['virtual']);
                         }
                         if ($virtual) {
                             $data['virtual'] = 0;
                             $virtual = false;
                         }
                         if (!$virtual) {
                             break;
                         }
                     }
                 }
             }
         }
         if (empty($data['eproduct']) && !empty($data['file_name'])) {
             $file_path = shopProduct::getPath($data['product_id'], "sku_file/{$id}." . pathinfo($data['file_name'], PATHINFO_EXTENSION));
             waFiles::delete($file_path);
             $data['file_name'] = '';
             $data['file_description'] = '';
         } elseif (isset($data['file_name'])) {
             unset($data['file_name']);
         }
         $this->updateById($id, $data);
     } else {
         if (!isset($data['sku'])) {
             $data['sku'] = '';
         }
         $id = $this->insert($data);
     }
     $data['id'] = $id;
     $sku_count = false;
     // if stocking for this sku
     if (isset($data['stock']) && count($data['stock'])) {
         if ($multi_stock === null) {
             $stock_model = new shopStockModel();
             $stocks = $stock_model->getAll($stock_model->getTableId());
             $multi_stock = $stocks ? array_keys($stocks) : false;
         }
         // not multistocking
         if (!$multi_stock || isset($data['stock'][0])) {
             $sku_count = self::castStock($data['stock'][0]);
             unset($data['stock']);
             $this->logCount($data['product_id'], $id, $sku_count);
             // multistocking
         } else {
             $sku_count = 0;
             $missed = array_combine($multi_stock, $multi_stock);
             if (!$stocks_model) {
                 $stocks_model = new shopProductStocksModel();
             }
             // need for track transition from aggregating mode to multistocking mode
             $has_any_stocks = $stocks_model->hasAnyStocks($id);
             if (!$has_any_stocks) {
                 $this->writeOffCount($data['product_id'], $id);
             }
             foreach ($data['stock'] as $stock_id => $count) {
                 if ($stock_id > 0 && isset($missed[$stock_id])) {
                     unset($missed[$stock_id]);
                     $field = array('sku_id' => $id, 'stock_id' => $stock_id, 'product_id' => $data['product_id']);
                     $count = self::castStock($count);
                     $stock = array('count' => $count);
                     if ($count === null) {
                         $sku_count = null;
                     } else {
                         // Once turned into NULL value is not changed
                         if ($sku_count !== null) {
                             $sku_count += $count;
                         }
                     }
                     // there is taking into account stocks log inside this method
                     $stocks_model->set(array_merge($field, $stock));
                     $data['stock'][$stock_id] = $count;
                 }
             }
             //get stock_count for missed stocks
             if ($sku_count !== null && !empty($missed)) {
                 $search = array('stock_id' => $missed, 'sku_id' => $id, 'product_id' => $data['product_id']);
                 foreach ($stocks_model->getByField($search, 'stock_id') as $stock_id => $row) {
                     $count = $row['count'];
                     $data['stock'][$stock_id] = $count;
                     if ($count === null) {
                         $sku_count = null;
                     } else {
                         // Once turned into NULL value is not changed
                         if ($sku_count !== null) {
                             $sku_count += $count;
                         }
                     }
                 }
             }
         }
     }
     if ($sku_count !== false) {
         $data['count'] = $sku_count;
         $this->updateById($id, array('count' => $sku_count));
     }
     if (isset($data['features'])) {
         if (!$feature_model) {
             $feature_model = new shopFeatureModel();
         }
         if (!$product_features_model) {
             $product_features_model = new shopProductFeaturesModel();
         }
         $features = $data['features'];
         $data['features'] = array();
         $skip_values = array('', false, null);
         foreach ($features as $code => $value) {
             if ($feature = $feature_model->getByField('code', $code)) {
                 $model = shopFeatureModel::getValuesModel($feature['type']);
                 $field = array('product_id' => $data['product_id'], 'sku_id' => $id, 'feature_id' => $feature['id']);
                 $product_features_model->deleteByField($field);
                 if (is_array($value)) {
                     if (!empty($value['id'])) {
                         $field['feature_value_id'] = $value['id'];
                     } elseif (isset($value['value']) && !in_array($value['value'], $skip_values, true)) {
                         $field['feature_value_id'] = $model->getId($feature['id'], $code == 'weight' ? $value : $value['value'], $feature['type']);
                     }
                 } elseif (!in_array($value, $skip_values, true)) {
                     $field['feature_value_id'] = $model->getId($feature['id'], $value, $feature['type']);
                     $value = array('value' => $value, 'id' => $field['feature_value_id']);
                 }
                 if (!empty($field['feature_value_id'])) {
                     $product_features_model->insert($field);
                     $data['features'][$code] = $value;
                 }
             } elseif (is_numeric($code) && is_numeric($value)) {
                 if ($feature = $feature_model->getById($code)) {
                     $field = array('product_id' => $data['product_id'], 'sku_id' => $id, 'feature_id' => $code);
                     $product_features_model->deleteByField($field);
                     if (empty($value)) {
                         continue;
                     }
                     $field['feature_value_id'] = $value;
                     $product_features_model->insert($field);
                     $data['features'][$feature['code']] = $feature_model->getValuesModel($feature['type'])->getFeatureValue($value);
                 }
             }
         }
     }
     if ($correct) {
         $product_model = new shopProductModel();
         $product_model->correct($data['product_id']);
     }
     return $data;
 }
 public function getValues($product_id, $lang, $sku_id = null, $type_id = null)
 {
     $sql = "SELECT " . ($type_id ? 'tf.sort, ' : '') . "f.code, f.type, f.multiple, pf.*\n                FROM shop_product_features pf";
     $sql .= " JOIN shop_feature f ON (pf.feature_id = f.id)";
     if ($type_id) {
         $sql .= " LEFT JOIN shop_type_features tf ON ((tf.feature_id = IFNULL(f.parent_id,f.id)) AND (tf.type_id=i:type_id))";
     }
     $sql .= " WHERE pf.product_id = i:id AND ";
     if ($sku_id) {
         if ($sku_id > 0) {
             $sql .= '(pf.sku_id = i:sku_id OR pf.sku_id IS NULL) ORDER BY pf.sku_id';
         } else {
             $sql .= '(pf.sku_id = i:sku_id) ORDER BY pf.sku_id';
             $sku_id = -$sku_id;
         }
     } else {
         $sql .= 'pf.sku_id IS NULL';
     }
     if ($type_id) {
         $sql .= " ORDER BY tf.sort";
     }
     $features = $storages = array();
     $params = array('id' => $product_id, 'sku_id' => $sku_id, 'type_id' => $type_id);
     $data = $this->query($sql, $params);
     $result = array();
     foreach ($data as $row) {
         if ($sku_id && $row['code'] == 'weight' && !$row['sku_id']) {
             continue;
         }
         $features[$row['feature_id']] = array('code' => $row['code'], 'multiple' => $row['multiple']);
         if (preg_match('/^(.+)\\.[0-2]$/', $row['code'], $matches)) {
             $result[$matches[1]] = null;
         } else {
             $result[$row['code']] = null;
         }
         $type = preg_replace('/\\..*$/', '', $row['type']);
         if ($type == shopFeatureModel::TYPE_BOOLEAN) {
             /**
              * @var shopFeatureValuesBooleanModel $model
              */
             $model = shopFeatureModel::getValuesModel($type);
             $values = $model->getValues('id', $row['feature_value_id']);
             $result[$row['code']] = reset($values);
         } elseif ($type == shopFeatureModel::TYPE_DIVIDER) {
             /**
              * @var shopFeatureValuesDividerModel $model
              */
             $model = shopFeatureModel::getValuesModel($type);
             $values = $model->getValues('id', $row['feature_value_id']);
             $result[$row['code']] = reset($values);
         } else {
             if ($sku_id) {
                 $storages[$type][$row['feature_id']] = $row['feature_value_id'];
             } else {
                 $storages[$type][] = $row['feature_value_id'];
             }
         }
     }
     foreach ($storages as $type => $value_ids) {
         $model = shopFeatureModel::getValuesModel($type);
         $feature_values = $model->getValues('id', $value_ids);
         $feature_values_tr = $this->select('id, value')->where('type = ? AND lang = ? AND id IN(?)', $type, $lang, $value_ids)->fetchAll('id', true);
         foreach ($feature_values as $feature_id => $values) {
             foreach ($values as $vid => $value) {
                 if (!empty($feature_values_tr[$vid])) {
                     $values[$vid] = $feature_values_tr[$vid];
                 }
             }
             if (isset($features[$feature_id])) {
                 $f = $features[$feature_id];
                 $result[$f['code']] = $sku_id || empty($f['multiple']) ? reset($values) : $values;
             } else {
                 //obsolete feature value
             }
         }
     }
     /**
      * composite fields workaround
      */
     $composite = array_filter(array_keys($result), create_function('$a', 'return preg_match("/\\.0$/",$a);'));
     foreach ($composite as $code) {
         $code = preg_replace('/\\.0$/', '', $code);
         $result[$code] = new shopCompositeValue($code, $result);
     }
     return $result;
 }
 private function getOrder($order_id)
 {
     $order = $this->order_model->getOrder($order_id, true, true);
     if (!$order) {
         throw new waException("Unknow order", 404);
     }
     $order['shipping_id'] = ifset($order['params']['shipping_id'], '') . '.' . ifset($order['params']['shipping_rate_id'], '');
     $sku_ids = array();
     foreach ($order['items'] as $item) {
         foreach ($item['skus'] as $sku) {
             if (empty($sku['fake'])) {
                 $sku_ids[] = $sku['id'];
             }
         }
     }
     $sku_stocks = $this->getSkuStocks(array_unique($sku_ids));
     $subtotal = 0;
     $product_ids = array();
     foreach ($order['items'] as $i) {
         $product_ids[] = $i['id'];
         $subtotal += $i['item']['price'] * $i['item']['quantity'];
     }
     $order['subtotal'] = $subtotal;
     $product_ids = array_unique($product_ids);
     $feature_model = new shopFeatureModel();
     $f = $feature_model->getByCode('weight');
     if (!$f) {
         $values = array();
     } else {
         $values_model = $feature_model->getValuesModel($f['type']);
         $values = $values_model->getProductValues($product_ids, $f['id']);
     }
     foreach ($order['items'] as &$item) {
         if (isset($values['skus'][$item['item']['sku_id']])) {
             $w = $values['skus'][$item['item']['sku_id']];
         } else {
             $w = isset($values[$item['id']]) ? $values[$item['id']] : 0;
         }
         $this->workupItems($item, $sku_stocks);
         $item['quantity'] = $item['item']['quantity'];
         $item['weight'] = $w;
     }
     unset($item);
     return $order;
 }
 /**
  * Verify input data and get selected base features
  * @param array &$data
  * @return int[int][int] value_id[value_id][feature_id]
  */
 private function getSelectedData(&$data)
 {
     $selected = array();
     $features = array();
     if ($feature_codes = array_keys($data)) {
         $feature_model = new shopFeatureModel();
         $features = $feature_model->getByCode($feature_codes);
     }
     foreach ($data as $code => &$feature) {
         if (!isset($features[$code])) {
             unset($data[$code]);
         } else {
             $feature_id = intval($features[$code]['id']);
             $selected[$feature_id] = array();
             if (!isset($feature['values'])) {
                 $feature = array('values' => $feature);
             }
             $feature['feature_id'] = $feature_id;
             $values = $feature['values'];
             $feature['values'] = array();
             foreach ($values as $value) {
                 if (is_array($value)) {
                     if (isset($value['value']) && empty($value['id'])) {
                         $value['id'] = $feature_model->getValueId($features[$code], $value['value'], true);
                     }
                 } else {
                     $value = array('id' => $value);
                 }
                 $id = $value['id'];
                 if (!isset($value['value'])) {
                     $value['value'] = (string) $feature_model->getValuesModel($features[$code]['type'])->getFeatureValue($id);
                 }
                 $feature['values'][$id] = $value;
                 $selected[$feature_id][$id] = $id;
                 unset($value);
             }
         }
         unset($values);
     }
     ksort($selected, SORT_NUMERIC);
     return $selected;
 }
 private function getOrderItems($items, $weight_unit)
 {
     $product_ids = array();
     foreach ($items as $item) {
         $product_ids[] = $item['product_id'];
     }
     $product_ids = array_unique($product_ids);
     $feature_model = new shopFeatureModel();
     $f = $feature_model->getByCode('weight');
     if (!$f) {
         $values = array();
     } else {
         $values_model = $feature_model->getValuesModel($f['type']);
         $values = $values_model->getProductValues($product_ids, $f['id']);
     }
     $m = null;
     if ($weight_unit) {
         $dimension = shopDimension::getInstance()->getDimension('weight');
         if ($weight_unit != $dimension['base_unit']) {
             $m = $dimension['units'][$weight_unit]['multiplier'];
         }
     }
     foreach ($items as &$item) {
         if ($item['type'] == 'product') {
             if (isset($values['skus'][$item['sku_id']])) {
                 $w = $values['skus'][$item['sku_id']];
             } else {
                 $w = isset($values[$item['product_id']]) ? $values[$item['product_id']] : 0;
             }
             if ($m !== null) {
                 $w = $w / $m;
             }
             $item['weight'] = $w;
         } else {
             $item['weight'] = 0;
         }
     }
     unset($item);
     return $items;
 }
 public function execute()
 {
     $id = waRequest::get('order_id');
     if (!$id) {
         throw new waException("Unknown order", 404);
     }
     $order = $this->getOrder($id);
     if (!$order) {
         $id = shopHelper::decodeOrderId($id);
         $order = $this->getOrder($id);
         if (!$order) {
             throw new waException("Unkown order", 404);
         }
     }
     $product_ids = array();
     foreach ($order['items'] as $item) {
         if ($item['type'] == 'product') {
             $product_ids[] = $item['product_id'];
         }
     }
     $product_ids = array_unique($product_ids);
     $form_id = waRequest::get('form_id');
     if (strpos($form_id, '.')) {
         list($type, $form) = explode('.', $form_id, 2);
     } else {
         $form = null;
         $type = $form_id;
     }
     $order_params_model = new shopOrderParamsModel();
     $params = $order_params_model->get($order['id']);
     $plugin = self::getPlugin($type, ifempty($params[$type . '_id']));
     if ($type == 'shipping') {
         /* add weight info only for shipping modules */
         $feature_model = new shopFeatureModel();
         $f = $feature_model->getByCode('weight');
         if (!$f) {
             $weights = array();
         } else {
             $values_model = $feature_model->getValuesModel($f['type']);
             $weights = $values_model->getProductValues($product_ids, $f['id']);
         }
         if ($weights) {
             $dimension = shopDimension::getInstance()->getDimension('weight');
             $weight_unit = $plugin->allowedWeightUnit();
             $m = null;
             if ($weight_unit != $dimension['base_unit']) {
                 $m = $dimension['units'][$weight_unit]['multiplier'];
             }
             foreach ($order['items'] as &$item) {
                 if ($item['type'] == 'product') {
                     if (isset($weights['skus'][$item['sku_id']])) {
                         $w = $weights['skus'][$item['sku_id']];
                     } else {
                         $w = isset($weights[$item['product_id']]) ? $weights[$item['product_id']] : 0;
                     }
                     if ($m !== null) {
                         $w = $w / $m;
                     }
                     $item['weight'] = $w;
                 }
             }
             unset($item);
         }
     }
     if (!$plugin) {
         throw new waException(_w('Printform not found'), 404);
     }
     print $plugin->displayPrintForm(ifempty($form, $plugin->getId()), shopPayment::getOrderData($order, $plugin));
     exit;
 }
 public function getItems($weight_unit = null)
 {
     $items = array();
     $cart = new shopCart();
     $cart_items = $cart->items();
     $product_ids = $sku_ids = array();
     foreach ($cart_items as $item) {
         $product_ids[] = $item['product_id'];
         $sku_ids[] = $item['sku_id'];
     }
     $feature_model = new shopFeatureModel();
     $f = $feature_model->getByCode('weight');
     if (!$f) {
         $values = array();
     } else {
         $values_model = $feature_model->getValuesModel($f['type']);
         $values = $values_model->getProductValues($product_ids, $f['id']);
     }
     $m = null;
     if ($weight_unit) {
         $dimension = shopDimension::getInstance()->getDimension('weight');
         if ($weight_unit != $dimension['base_unit']) {
             $m = $dimension['units'][$weight_unit]['multiplier'];
         }
     }
     foreach ($cart_items as $item) {
         if (isset($values['skus'][$item['sku_id']])) {
             $w = $values['skus'][$item['sku_id']];
         } else {
             $w = isset($values[$item['product_id']]) ? $values[$item['product_id']] : 0;
         }
         if ($m !== null) {
             $w = $w / $m;
         }
         $items[] = array('name' => $item['name'], 'price' => $item['price'], 'quantity' => $item['quantity'], 'weight' => $w);
     }
     return $items;
 }
 /**
 * @param $data
 * @param array $features строка 1
 строка 2
 * @return string
 */
 public static function getConditionHTML($data, $features = array())
 {
     $result = array();
     foreach ($data as $row) {
         if (empty($row['cond'])) {
             continue;
         }
         if (!empty($row['feature_id'])) {
             if ($features) {
                 $html = $features[$row['feature_id']]['name'];
             } else {
                 $html = $row['feature_name'];
             }
         } else {
             if ($row['feature'] == 'price') {
                 $html = _w('Price');
             } elseif ($row['feature'] == 'tag') {
                 $html = _w('Tags');
             } elseif ($row['feature'] == 'type_id') {
                 $html = _w('Type');
             } else {
                 continue;
             }
         }
         $html .= ' ';
         switch ($row['cond']) {
             case 'between':
                 $v = explode(',', $row['value']);
                 $html .= '<span class="s-plus-minus">' . ($v[1] > 0 ? '+' : '') . $v[1] . '%<br>' . ($v[0] > 0 ? '+' : '') . $v[0] . '%</span>';
                 break;
             case 'contain':
                 $html .= $row['cond'] . ' "' . $row['value'] . '"';
                 break;
             case 'same':
                 $html .= _w('matches base product value');
                 break;
             case 'notsame':
                 $html .= _w('differs from base product value');
                 break;
             case 'all':
             case 'any':
             case 'is':
                 if ($row['cond'] == 'any') {
                     $html .= _w('any of selected values (OR)');
                 } elseif ($row['cond'] == 'all') {
                     $html .= _w('all of selected values (AND)');
                 } else {
                     $html .= _w($row['cond']);
                 }
                 $html .= ' ';
                 if ($row['feature'] == 'type_id') {
                     $type_model = new shopTypeModel();
                     $type = $type_model->getById($row['value']);
                     $html .= $type['name'];
                 } else {
                     $feature_values_model = shopFeatureModel::getValuesModel($features ? $features[$row['feature_id']]['type'] : $row['feature_type']);
                     if (strpos($row['value'], ',') !== false) {
                         $value_ids = explode(',', $row['value']);
                         $values = $feature_values_model->getById($value_ids);
                         foreach ($values as &$v) {
                             $v = $v['value'];
                         }
                         unset($v);
                         $html .= implode(', ', $values);
                     } else {
                         $v = $feature_values_model->getById($row['value']);
                         $html .= $v['value'];
                     }
                 }
                 break;
         }
         $result[] = $html;
     }
     return implode('; ', $result);
 }
 private function setValues($feature, $values)
 {
     if (!$this->isMultidimensional($feature)) {
         return $this->feature_model->setValues($feature, $values, false);
     } else {
         $type = $feature['type'];
         $parts = explode('.', $type);
         $values_model = shopFeatureModel::getValuesModel($parts[1]);
         $children = $this->getChildren($feature);
         $data = array();
         $sort = 0;
         foreach ($values as $id => $value) {
             $val = $value['value'];
             $f_id = $value['feature_id'];
             $row =& $data[];
             $row = $values_model->addValue($f_id, $val, $id, $children[$f_id]['type'], ++$sort);
             $row['feature_id'] = $f_id;
         }
         foreach ($children as $c) {
             $this->feature_model->recount($c);
         }
         return $data;
     }
 }