public function execute() { if (!$this->getUser()->getRights('shop', 'settings')) { throw new waRightsException(_w('Access denied')); } if ($features = waRequest::post('feature')) { $model = new shopFeatureModel(); $type_features_model = new shopTypeFeaturesModel(); foreach ($features as $feature_id => &$feature) { $feature['id'] = $model->save($feature, $feature_id); if ($feature['selectable']) { $feature['values'] = $model->setValues($feature, $feature['values']); } $feature['types'] = $type_features_model->updateByFeature($feature['id'], $feature['types']); if ($feature_id < $feature['id']) { $feature['sort'] = array(); foreach ($feature['types'] as $type) { $feature['sort'][$type] = $type_features_model->move(array('feature_id' => $feature['id'], 'type_id' => $type), null, $type); } } } unset($feature); shopFeatureModel::appendTypeNames($features); } $this->response = $features; }
private function initImport() { $name = basename(waRequest::post('file')); if (empty($name)) { throw new waException('Empty import filename'); } $config = wa('shop')->getConfig(); /** * @var shopConfig $config ; */ //TODO detect emulate & type of control $file = wa()->getTempPath('csv/upload/' . $name); $this->data['emulate'] = waRequest::post('emulate') ? array() : null; $this->data['rights'] = $this->getUser()->getRights('shop', 'settings'); $this->data['new_features'] = array(); $this->data['currencies'] = $config->getCurrencies(); $this->data['type_id'] = waRequest::post('type_id', null, waRequest::TYPE_INT); if ($this->data['type_id'] && !in_array($this->data['type_id'], $this->data['types'])) { $this->data['type_id'] = reset($this->data['types']); } $map = waRequest::post('csv_map'); if ($this->emulate()) { $this->reader = shopCsvReader::snapshot($file); if (!$this->reader) { throw new waException('CSV file not found'); } $this->reader->rewind(); } else { /*, waRequest::post('encoding', 'utf-8')*/ //after upload encoding converted into utf-8 $this->reader = new shopCsvReader($file, waRequest::post('delimiter', ';')); $header = $this->reader->header(); foreach ($map as $id => &$target) { if (preg_match('@^f\\+:(.+)$@', $target, $matches)) { if ($this->data['rights']) { $id = preg_replace('@\\D.*$@', '', $id); $feature = array('name' => ifset($header[$id], 'csv feature'), 'type' => shopFeatureModel::TYPE_VARCHAR, 'multiple' => 0, 'selectable' => 0); list($feature['type'], $feature['multiple'], $feature['selectable']) = explode(':', $matches[1]); $feature['type'] = preg_replace('@([^\\.]+\\.)\\1@', '$1', $feature['type']); if (empty($feature_model)) { $feature_model = new shopFeatureModel(); } if (empty($type_features_model)) { $type_features_model = new shopTypeFeaturesModel(); } $feature['id'] = $feature_model->save($feature); if ($this->data['type_id']) { $type_features_model->updateByFeature($feature['id'], array($this->data['type_id']), false); } $target = 'features:' . $feature['code']; $this->data['new_features'][$feature['code']] = array('id' => $feature['id'], 'types' => (array) $this->data['type_id']); } else { unset($map[$id]); } } } unset($target); } $map = array_flip($map); $this->reader->setMap($map); $this->data['file'] = serialize($this->reader); $this->data['primary'] = waRequest::post('primary', 'name'); $this->data['secondary'] = waRequest::post('secondary', 'skus:-1:sku'); $this->data['extra_secondary'] = false; switch ($this->data['secondary']) { case 'skus:-1:sku': if (isset($map['skus:-1:name']) && intval($map['skus:-1:name']) >= 0) { $this->data['extra_secondary'] = 'skus:-1:name'; } break; case 'skus:-1:name': if (isset($map['skus:-1:sku']) && intval($map['skus:-1:sku']) >= 0) { $this->data['extra_secondary'] = 'skus:-1:sku'; } break; } $upload_app = waRequest::post('upload_app', 'shop', waRequest::TYPE_STRING_TRIM); if ($upload_app != 'site') { $upload_app = 'shop'; } $this->data['upload_path'] = preg_replace('@[\\\\/]+$@', '/', waRequest::post('upload_path', 'upload/images/') . '/'); $this->data['upload_path'] = preg_replace('@(^|/)(\\.\\.)/@', '$1/', $this->data['upload_path']); if (waSystem::getSetting('csv.upload_path') != $this->data['upload_path']) { $app_settings = new waAppSettingsModel(); $app_settings->set('shop', 'csv.upload_path', $this->data['upload_path']); } $this->data['virtual_sku_stock'] = waRequest::post('virtual_sku_stock', '', waRequest::TYPE_STRING_TRIM); if ($upload_app == 'site') { $this->data['upload_path'] = wa()->getDataPath($this->data['upload_path'], true, 'site'); } else { $this->data['upload_path'] = wa()->getDataPath($this->data['upload_path'], false, 'shop'); } if (waSystem::getSetting('csv.upload_app') != $upload_app) { if (empty($app_settings)) { $app_settings = new waAppSettingsModel(); } $app_settings->set('shop', 'csv.upload_app', $upload_app); } $this->data['ignore_category'] = !!waRequest::post('ignore_category', 0, waRequest::TYPE_INT); if (!in_array($this->data['primary'], array('name', 'url', 'null'))) { throw new waException(_w('Invalid primary field')); } if ($this->data['primary'] == 'null') { $this->data['primary'] = null; } if (!in_array($this->data['secondary'], array('skus:-1:sku', 'skus:-1:name'))) { throw new waException(_w('Invalid secondary field')); } $current = $this->reader->current(); if (!empty($this->data['primary']) && self::getData($current, $this->data['primary']) === null) { throw new waException(_w('Empty primary CSV column')); } if (empty($this->data['primary']) && self::getData($current, $this->data['secondary']) === null) { throw new waException(_w('Empty secondary CSV column')); } $this->data['count'] = array(self::STAGE_FILE => $this->reader ? $this->reader->size() : null, self::STAGE_CATEGORY => null, self::STAGE_PRODUCT => null, self::STAGE_SKU => null, self::STAGE_IMAGE => null); }
/** * @param $template_id * @param bool $extend * @return array|null * @throws waException */ public function insertTemplate($template_id, $extend = false) { $types = self::getTemplates(); $feature_model = new shopFeatureModel(); $type_features_model = new shopTypeFeaturesModel(); $type = null; if (!empty($types[$template_id])) { $type = $types[$template_id]; $type['sort'] = $this->select('MAX(sort)+1 as max_sort')->fetchField('max_sort'); $type['id'] = $this->insert($type); if ($type['id'] && !empty($type['features'])) { foreach ($type['features'] as $code => &$feature) { $feature += array('type' => 'varchar', 'selectable' => false, 'multiple' => false); $feature['types'] = array($type['id']); $feature['name'] = ifempty(self::$translate[$feature['name']], $feature['name']); $feature['code'] = $code; $id = null; if ($data = $feature_model->getByField('code', $code)) { if ($feature['type'] == $data['type'] && $feature['selectable'] == $data['selectable'] && $feature['multiple'] == $data['multiple']) { $id = $data['id']; } } $feature['id'] = $feature_model->save($feature, $id); if ($feature['id']) { if (!empty($feature['selectable']) && !empty($feature['values'])) { foreach ($feature['values'] as &$value) { if (is_string($value)) { $value = ifempty(self::$translate[$value], $value); } elseif (isset($value['value'])) { $value['value'] = ifempty(self::$translate[$value['value']], $value['value']); } } unset($value); $feature['values'] = $feature_model->setValues($feature, $feature['values'], false, true); } $feature['types'] = $type_features_model->updateByFeature($feature['id'], $feature['types'], false); if ($id && $extend) { //TODO get exists feature values //$feature_model->getFeatureValues($feature); $feature['types'] = array_keys($type_features_model->getByField('feature_id', $feature['id'], 'type_id')); } } unset($feature); } if ($extend) { shopFeatureModel::appendTypeNames($type['features']); } } } return $type; }
/** * @see shopProductStorageInterface::setData() * @param shopProduct $product current product object * @param array [string] mixed $data new product feature values */ public function setData(shopProduct $product, $data) { $product_id = $product->getId(); $feature_model = new shopFeatureModel(); $codes = array_keys($data); $features = $feature_model->getByCode($codes); /** * composite fields workaround */ $composite_codes = array(); foreach ($data as $code => $value) { if (!preg_match('/\\.[0-3]$/', $code) && isset($features[$code]) && preg_match('/^([23])d\\./', $features[$code]['type'], $matches)) { $n = $matches[1]; $pattern = '/^' . implode('\\s*[×xX\\*]?\\s*', array_fill(0, $n, '([^\\s]+)')) . '(\\s+.+)?$/u'; if (preg_match($pattern, trim($value), $matches)) { $unit = ifset($matches[$n + 1]); for ($i = 0; $i < $n; $i++) { $c_code = $code . '.' . $i; $data[$c_code] = $matches[$i + 1] . $unit; $composite_codes[] = $c_code; } unset($features[$code]); } else { /** * invalid complex feature format */ } unset($data[$code]); } } if ($composite_codes) { $features += $feature_model->getByCode($composite_codes); } $features_map = array(); foreach ($features as $code => $f) { $features_map[$f['id']] =& $features[$code]; } $current = array(); $rows = $this->getByField(array('product_id' => $product_id, 'sku_id' => null), true); foreach ($rows as $row) { $id = $row['feature_id']; if (isset($features_map[$id])) { $f = $features_map[$id]; $code = $f['code']; if (empty($f['multiple'])) { $current[$code] = intval($row['feature_value_id']); } else { if (!isset($current[$code])) { $current[$code] = array(); } $current[$code][] = intval($row['feature_value_id']); } } else { //obsolete data } } $add = $delete = array(); foreach ($data as $code => $value) { if (isset($features[$code])) { $f =& $features[$code]; if (is_array($value)) { $empty = isset($value['value']) && $value['value'] === ''; if (!$empty && isset($value['value']) && is_array($value['value'])) { foreach ($value['value'] as $key => $v) { if ($v === '') { unset($value['value'][$key]); } } $empty = count($value['value']) == 0; } if (!$empty && !isset($value['value'])) { foreach ($value as $key => $v) { if ($v === '') { unset($value[$key]); } } $empty = count($value) == 0; } } else { $empty = $value === ''; } if ($empty) { //delete it if (isset($current[$code])) { $delete[$f['id']] = $current[$code]; } } else { if (is_array($value) && preg_match('/^(.+\\.)[12]$/', $code, $matches) && isset($data[$matches[1] . '0'])) { $value = array_merge($data[$matches[1] . '0'], $value); } $id = $feature_model->getValueId($f, $value, true); if (isset($current[$code])) { if (empty($f['multiple'])) { if ($current[$code] != $id) { $delete[$f['id']] = $current[$code]; $add[$f['id']] = $id; } } else { $delete[$f['id']] = array_diff($current[$code], (array) $id); if (empty($delete[$f['id']])) { unset($delete[$f['id']]); } $add[$f['id']] = array_diff((array) $id, $current[$code]); if (empty($add[$f['id']])) { unset($add[$f['id']]); } } } else { $add[$f['id']] = $id; } } } elseif (!empty($value) && is_array($value)) { //it's a new feature if (!empty($value) && (ifset($value['type']) == shopFeatureModel::TYPE_BOOLEAN || !empty($value['value']))) { $f = array('name' => $value['name'], 'type' => $value['type'], 'types' => $value['types']); $f['id'] = $feature_model->save($f); $type_features_model = new shopTypeFeaturesModel(); $type_features_model->updateByFeature($f['id'], $f['types']); if ($value['value'] !== '') { $add[$f['id']] = $feature_model->getValueId($f, $value['value'], true); } } } } foreach ($features as $code => $f) { if (empty($data[$code]) && !empty($current[$code])) { $delete[$f['id']] = $current[$code]; } } foreach ($delete as $feature_id => $value_id) { $this->deleteByField(array('product_id' => $product_id, 'sku_id' => null, 'feature_id' => $feature_id, 'feature_value_id' => $value_id)); } foreach ($add as $feature_id => $value_id) { $this->multipleInsert(array('product_id' => $product_id, 'feature_id' => $feature_id, 'feature_value_id' => $value_id)); } }