public function featuresSelectableAction() { $model = new waModel(); $product_features_selectable_model = new shopProductFeaturesSelectableModel(); // delete unbinded old values in shop_product_features_selectable $sql = "SELECT DISTINCT ps.product_id, pf.feature_id FROM `shop_product_skus` ps\n JOIN `shop_product_features` pf ON ps.product_id = pf.product_id AND ps.id = pf.sku_id\n LEFT JOIN `shop_product_features_selectable` fs ON fs.product_id = pf.product_id AND fs.feature_id = pf.feature_id AND fs.value_id = pf.feature_value_id\n WHERE ps.virtual = 1 AND fs.value_id IS NULL"; foreach ($model->query($sql)->fetchAll() as $key) { $product_features_selectable_model->deleteByField($key); } // insert new actual values in shop_product_features_selectable $sql = "SELECT DISTINCT ps.product_id, pf.feature_id, pf.feature_value_id AS value_id FROM `shop_product_skus` ps\n JOIN `shop_product_features` pf ON ps.product_id = pf.product_id AND ps.id = pf.sku_id\n LEFT JOIN `shop_product_features_selectable` fs ON fs.product_id = pf.product_id AND fs.feature_id = pf.feature_id AND fs.value_id = pf.feature_value_id\n WHERE ps.virtual = 1 AND fs.value_id IS NULL"; foreach ($model->query($sql)->fetchAll() as $item) { $product_features_selectable_model->insert($item); } echo "OK"; }
private function bindToProducts($feature, $values) { if (is_array($feature)) { $feature_id = $feature['id']; } else { $feature_id = (int) $feature; $feature = $this->feature_model->getById($feature_id); } $is_multidimensional = $this->isMultidimensional($feature); // bind products with values of new feature foreach ($values as $v) { if ($feature['type'] !== 'boolean') { if (isset($v['original_id'])) { $new_id = $v['original_id']; } else { $new_id = $v['id']; } if (isset($v['original_id'])) { $old_id = -$v['id']; } else { $old_id = -$v['insert_id']; } } else { $old_id = -$v['id']; $new_id = $v['value']; } if (!$is_multidimensional) { $key = array('feature_id' => $feature_id, 'feature_value_id' => $old_id); $value = array('feature_value_id' => $new_id); } else { $key = array('feature_id' => $v['feature_id'], 'feature_value_id' => $old_id); $value = array('feature_value_id' => $new_id); } $this->product_features_model->updateByField($key, $value); $key['value_id'] = $key['feature_value_id']; unset($key['feature_value_id']); $value['value_id'] = $value['feature_value_id']; unset($value['feature_value_id']); $this->product_features_selectable_model->updateByField($key, $value); } }
/** * @param array $options * @return shopProduct * @throws waException */ public function duplicate($options = array()) { if (!$this->checkRights()) { throw new waRightsException('Access denied'); } $data = $this->data; $skip = array('id', 'create_datetime', 'id_1c', 'rating', 'rating_count', 'total_sales', 'image_id', 'contact_id', 'ext', 'count', 'sku_count'); foreach ($skip as $field) { if (isset($data[$field])) { unset($data[$field]); } } $duplicate = new shopProduct(); $this->getStorage(null); $sku_files = array(); $sku_images = array(); $ignore_select = true; foreach (self::$data_storages as $key => $i) { $raw = $this->getStorage($key)->getData($this); switch ($key) { case 'features_selectable': $storage_data = array(); if (!$ignore_select) { if ($this->sku_type == shopProductModel::SKU_TYPE_SELECTABLE) { if (!is_array($raw)) { $raw = array(); } foreach ($raw as $id => $f) { if (!empty($f['selected'])) { foreach ($f['values'] as $value_id => &$value) { if (!empty($value['selected'])) { $value = array('id' => $value_id); } else { unset($f['values'][$value_id]); } } $storage_data[$id] = $f; } } } } break; case 'skus': $storage_data = array(); $i = 0; foreach ($raw as $sku_id => $sku) { if (!empty($sku['virtual']) || $ignore_select) { if ($file_path = shopProductSkusModel::getPath($sku)) { $sku_files[$sku['id']] = array('file_name' => $sku['file_name'], 'file_description' => $sku['file_description'], 'file_size' => $sku['file_size'], 'file_path' => $file_path); } if (!empty($sku['image_id'])) { $sku_images[$sku['id']] = $sku['image_id']; } foreach (array('id', 'id_1c', 'product_id', 'image_id', 'file_name', 'file_size', 'file_description') as $field) { if (isset($sku[$field])) { unset($sku[$field]); } } $storage_data[--$i] = $sku; } } break; case 'tags': $storage_data = array_values($raw); break; case 'categories': $storage_data = array_keys($raw); break; default: $storage_data = $raw; break; } $duplicate->{$key} = $storage_data; } $counter = 0; $data['url'] = shopHelper::genUniqueUrl($this->url, $this->model, $counter); $data['name'] = $this->name . sprintf('(%d)', $counter ? $counter : 1); $duplicate->save($data); $product_id = $duplicate->getId(); $sku_map = array_combine(array_keys($this->skus), array_keys($duplicate->skus)); $config = wa('shop')->getConfig(); $image_thumbs_on_demand = $config->getOption('image_thumbs_on_demand'); /** * @var shopConfig $config */ if ($this->pages) { $product_pages_model = new shopProductPagesModel(); foreach ($this->pages as $page) { unset($page['id']); unset($page['create_time']); unset($page['update_datetime']); unset($page['create_contact_id']); $page['product_id'] = $duplicate->getId(); $product_pages_model->add($page); } } #duplicate images $product_skus_model = new shopProductSkusModel(); $images_model = new shopProductImagesModel(); $images = $images_model->getByField('product_id', $this->getId(), $images_model->getTableId()); $callback = create_function('$a, $b', 'return (max(-1, min(1, $a["sort"] - $b["sort"])));'); usort($images, $callback); foreach ($images as $id => $image) { $source_path = shopImage::getPath($image); $original_file = shopImage::getOriginalPath($image); $image['product_id'] = $duplicate->getId(); if ($sku_id = array_search($image['id'], $sku_images)) { $sku_id = $sku_map[$sku_id]; } unset($image['id']); try { if ($image['id'] = $images_model->add($image, $id == $this->image_id)) { waFiles::copy($source_path, shopImage::getPath($image)); if (file_exists($original_file)) { waFiles::copy($original_file, shopImage::getOriginalPath($image)); } if ($sku_id) { $product_skus_model->updateById($sku_id, array('image_id' => $image['id'])); } if (!$image_thumbs_on_demand) { shopImage::generateThumbs($image, $config->getImageSizes()); //TODO use dummy copy with rename files } } } catch (waDbException $ex) { //just ignore it waLog::log('Error during copy product: ' . $ex->getMessage(), 'shop.log'); } catch (waException $ex) { if (!empty($image['id'])) { $images_model->deleteById($image['id']); } waLog::log('Error during copy product: ' . $ex->getMessage(), 'shop.log'); } } foreach ($sku_files as $sku_id => $data) { $source_path = $data['file_path']; unset($data['file_path']); $sku_id = $sku_map[$sku_id]; $sku = array_merge($duplicate->skus[$sku_id], $data); $product_skus_model->updateById($sku_id, $data); $target_path = shopProductSkusModel::getPath($sku); try { waFiles::copy($source_path, $target_path); } catch (waException $ex) { $data = array('file_name' => '', 'file_description' => '', 'file_size' => 0); $product_skus_model->updateById($sku_id, $data); print $ex->getMessage(); } } $product_features_model = new shopProductFeaturesModel(); $skus_features = $product_features_model->getSkuFeatures($this->id); $skus_features_data = array(); foreach ($skus_features as $sku_id => $features) { $sku_id = $sku_map[$sku_id]; foreach ($features as $feature_id => $feature_value_id) { $skus_features_data[] = compact('product_id', 'sku_id', 'feature_id', 'feature_value_id'); } } if ($skus_features_data) { $product_features_model->multipleInsert($skus_features_data); } if ($this->sku_type == shopProductModel::SKU_TYPE_SELECTABLE) { $product_features_selectable_model = new shopProductFeaturesSelectableModel(); if ($features_selectable = $product_features_selectable_model->getByField('product_id', $this->id, true)) { foreach ($features_selectable as &$feature_selectable) { $feature_selectable['product_id'] = $product_id; } unset($feature_selectable); $product_features_selectable_model->multipleInsert($features_selectable); } } $product_services_model = new shopProductServicesModel(); if ($services = $product_services_model->getByField('product_id', $this->id, true)) { foreach ($services as &$service) { unset($service['id']); $service['product_id'] = $product_id; $service['sku_id'] = ifset($sku_map[$service['sku_id']]); unset($service); } $product_services_model->multipleInsert($services); } $product_related_model = new shopProductRelatedModel(); if ($related = $product_related_model->getByField('product_id', $this->id, true)) { foreach ($related as &$row) { $row['product_id'] = $product_id; } unset($row); $product_related_model->multipleInsert($related); } $params = array('product' => &$this, 'duplicate' => &$duplicate); /** * @wa-event product_duplicate */ wa()->event('product_duplicate', $params); return $duplicate; }
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]; }
public function execute() { $category = $this->getCategory(); $this->addCanonical(); // breadcrumbs $root_category_id = $category['id']; if ($category['parent_id']) { $breadcrumbs = array(); $path = array_reverse($this->getModel()->getPath($category['id'])); $root_category = reset($path); $root_category_id = $root_category['id']; foreach ($path as $row) { $breadcrumbs[] = array('url' => wa()->getRouteUrl('/frontend/category', array('category_url' => waRequest::param('url_type') == 1 ? $row['url'] : $row['full_url'])), 'name' => $row['name']); } if ($breadcrumbs) { $this->view->assign('breadcrumbs', $breadcrumbs); } } $this->view->assign('root_category_id', $root_category_id); // sort if ($category['type'] == shopCategoryModel::TYPE_DYNAMIC && !$category['sort_products']) { $category['sort_products'] = 'create_datetime DESC'; } if ($category['sort_products'] && !waRequest::get('sort')) { $sort = explode(' ', $category['sort_products']); $this->view->assign('active_sort', $sort[0] == 'count' ? 'stock' : $sort[0]); } elseif (!$category['sort_products'] && !waRequest::get('sort')) { $this->view->assign('active_sort', ''); } $this->view->assign('category', $category); // products $collection = new shopProductsCollection('category/' . $category['id']); // filters if ($category['filter']) { $filter_ids = explode(',', $category['filter']); $feature_model = new shopFeatureModel(); $features = $feature_model->getById(array_filter($filter_ids, 'is_numeric')); if ($features) { $features = $feature_model->getValues($features); } $category_value_ids = $collection->getFeatureValueIds(); $filters = array(); foreach ($filter_ids as $fid) { if ($fid == 'price') { $range = $collection->getPriceRange(); if ($range['min'] != $range['max']) { $filters['price'] = array('min' => shop_currency($range['min'], null, null, false), 'max' => shop_currency($range['max'], null, null, false)); } } elseif (isset($features[$fid]) && isset($category_value_ids[$fid])) { $filters[$fid] = $features[$fid]; $min = $max = $unit = null; foreach ($filters[$fid]['values'] as $v_id => $v) { if (!in_array($v_id, $category_value_ids[$fid])) { unset($filters[$fid]['values'][$v_id]); } else { if ($v instanceof shopRangeValue) { $begin = $this->getFeatureValue($v->begin); if ($min === null || $begin < $min) { $min = $begin; } $end = $this->getFeatureValue($v->end); if ($max === null || $end > $max) { $max = $end; if ($v->end instanceof shopDimensionValue) { $unit = $v->end->unit; } } } else { $tmp_v = $this->getFeatureValue($v); if ($min === null || $tmp_v < $min) { $min = $tmp_v; } if ($max === null || $tmp_v > $max) { $max = $tmp_v; if ($v instanceof shopDimensionValue) { $unit = $v->unit; } } } } } if (!$filters[$fid]['selectable'] && ($filters[$fid]['type'] == 'double' || substr($filters[$fid]['type'], 0, 6) == 'range.' || substr($filters[$fid]['type'], 0, 10) == 'dimension.')) { if ($min == $max) { unset($filters[$fid]); } else { $type = preg_replace('/^[^\\.]*\\./', '', $filters[$fid]['type']); if ($type != 'double') { $filters[$fid]['base_unit'] = shopDimension::getBaseUnit($type); $filters[$fid]['unit'] = shopDimension::getUnit($type, $unit); if ($filters[$fid]['base_unit']['value'] != $filters[$fid]['unit']['value']) { $dimension = shopDimension::getInstance(); $min = $dimension->convert($min, $type, $filters[$fid]['unit']['value']); $max = $dimension->convert($max, $type, $filters[$fid]['unit']['value']); } } $filters[$fid]['min'] = $min; $filters[$fid]['max'] = $max; } } } } $this->view->assign('filters', $filters); $this->setCollection($collection); // fix prices $products = $this->view->getVars('products'); $product_ids = array(); foreach ($products as $p_id => $p) { if ($p['sku_count'] > 1) { $product_ids[] = $p_id; } } if ($product_ids) { $min_price = $max_price = null; $tmp = array(); foreach ($filters as $fid => $f) { if ($fid == 'price') { $min_price = waRequest::get('price_min'); if (!empty($min_price)) { $min_price = (double) $min_price; } else { $min_price = null; } $max_price = waRequest::get('price_max'); if (!empty($max_price)) { $max_price = (double) $max_price; } else { $max_price = null; } } else { $fvalues = waRequest::get($f['code']); if ($fvalues && !isset($fvalues['min']) && !isset($fvalues['max'])) { $tmp[$fid] = $fvalues; } } } $product_skus = array(); if ($tmp) { $pf_model = new shopProductFeaturesModel(); $product_skus = $pf_model->getSkusByFeatures($product_ids, $tmp); } elseif ($min_price || $max_price) { $ps_model = new shopProductSkusModel(); $rows = $ps_model->getByField('product_id', $product_ids, true); foreach ($rows as $row) { $product_skus[$row['product_id']][] = $row; } } $default_currency = $this->getConfig()->getCurrency(true); if ($product_skus) { foreach ($product_skus as $product_id => $skus) { $currency = $products[$product_id]['currency']; usort($skus, array($this, 'sortSkus')); $k = 0; if ($min_price || $max_price) { foreach ($skus as $i => $sku) { if ($min_price) { $tmp_price = shop_currency($min_price, true, $currency, false); if ($sku['price'] < $tmp_price) { continue; } } if ($max_price) { $tmp_price = shop_currency($max_price, true, $currency, false); if ($sku['price'] > $tmp_price) { continue; } } $k = $i; break; } } $sku = $skus[$k]; if ($products[$product_id]['sku_id'] != $sku['id']) { $products[$product_id]['sku_id'] = $sku['id']; $products[$product_id]['frontend_url'] .= '?sku=' . $sku['id']; $products[$product_id]['price'] = shop_currency($sku['price'], $currency, $default_currency, false); $products[$product_id]['compare_price'] = shop_currency($sku['compare_price'], $currency, $default_currency, false); } } $this->view->assign('products', $products); } } } else { $this->setCollection($collection); } //отображение дополнительных размеров $products = $this->view->getVars('products'); $product_features_model = new shopProductFeaturesSelectableModel(); foreach ($products as &$p) { $sku_features = $product_features_model->getByProduct($p['id']); $sizes = $sku_features[3]; if (!$sizes) { $p['sizes'] = array(); continue; } $pf_names = $product_features_model->query("SELECT `id`, `value` FROM shop_feature_values_varchar where `id` IN (" . implode(',', $sizes) . ') ORDER BY `sort`;')->fetchAll(); foreach ($pf_names as $key => $val) { $sizes[$val['id']] = $val['value']; } $p['sizes'] = $pf_names; } //отображение всех картинок foreach ($products as &$p) { $images_full = shopViewHelper::images($p['id']); if (isset($images_full[$p['id']])) { $p['image_ids'] = array_keys($images_full[$p['id']]); } } $this->view->assign('products', $products); // set meta $title = $category['meta_title'] ? $category['meta_title'] : $category['name']; wa()->getResponse()->setTitle($title); wa()->getResponse()->setMeta('keywords', $category['meta_keywords']); wa()->getResponse()->setMeta('description', $category['meta_description']); /** * @event frontend_category * @return array[string]string $return[%plugin_id%] html output for category */ $this->view->assign('frontend_category', wa()->event('frontend_category', $category)); $this->setThemeTemplate('category.html'); }