/**
  * @param shopProduct $product
  * @param string|array $tags
  * @return array
  */
 public function setData(shopProduct $product, $tags)
 {
     $product_id = $product->getId();
     if (!is_array($tags)) {
         $tags = explode(',', $tags);
     }
     $tag_model = new shopTagModel();
     $tag_ids = $tag_model->getIds($tags);
     $old_tag_ids = $this->query("SELECT tag_id FROM " . $this->table . "\n            WHERE product_id = i:id", array('id' => $product_id))->fetchAll(null, true);
     // find new tags to add
     $add_tag_ids = array_diff($tag_ids, $old_tag_ids);
     if ($add_tag_ids) {
         $this->multipleInsert(array('product_id' => $product_id, 'tag_id' => $add_tag_ids));
         $tag_model->incCounters($add_tag_ids);
     }
     // find tags to remove
     $remove_tag_ids = array_diff($old_tag_ids, $tag_ids);
     if ($remove_tag_ids) {
         $this->deleteByField(array('product_id' => $product_id, 'tag_id' => $remove_tag_ids));
         $tag_model->incCounters($remove_tag_ids, -1);
     }
     if ($add_tag_ids || $remove_tag_ids) {
         if ($cache = wa()->getCache()) {
             $cache->delete('tags');
         }
     }
     // return new tags
     return $this->getData($product);
 }
 public function execute()
 {
     $id = $this->get('id', true);
     $product_model = new shopProductModel();
     $data = $product_model->getById($id);
     if (!$data) {
         throw new waAPIException('invalid_param', 'Product not found', 404);
     }
     $this->response = $data;
     $p = new shopProduct($data);
     if ($p['image_id']) {
         $this->response['image_url'] = shopImage::getUrl(array('product_id' => $id, 'id' => $p['image_id'], 'ext' => $p['ext']), wa('shop')->getConfig()->getImageSize('default'), true);
     }
     $this->response['skus'] = array_values($p->skus);
     foreach ($this->response['skus'] as &$sku) {
         $stocks = array();
         foreach ($sku['stock'] as $stock_id => $count) {
             $stocks[] = array('id' => $stock_id, 'count' => $count);
         }
         unset($sku['stock']);
         $sku['stocks'] = $stocks;
     }
     unset($sku);
     $this->response['categories'] = array_values($p->categories);
     $this->response['images'] = array_values($p->getImages('thumb', true));
     $this->response['features'] = array();
     foreach ($p->features as $f => $v) {
         if (is_array($v)) {
             $this->response['features'][$f] = array_values($v);
         } else {
             $this->response['features'][$f] = (string) $v;
         }
     }
 }
 protected function save($type)
 {
     $value = waRequest::post($type);
     $product = new shopProduct($this->product_id);
     $product->save(array($type => $value));
     if ($value != 2) {
         $related_model = new shopProductRelatedModel();
         $related_model->deleteByField(array('product_id' => $this->product_id, 'type' => $type));
     }
 }
 public function execute()
 {
     $product_id = $this->get('product_id', true);
     $product_model = new shopProductModel();
     $product = $product_model->getById($product_id);
     if (!$product) {
         throw new waAPIException('invalid_param', 'Product not found', 404);
     }
     $p = new shopProduct($product);
     $this->response = array_values($p->getImages('thumb', true));
     $this->response['_element'] = 'image';
 }
 public function execute()
 {
     $id = $this->get('id', true);
     $product = $this->getProduct($id);
     $data = waRequest::post();
     if (isset($data['type_id'])) {
         $this->checkRights($data['type_id']);
     }
     $this->checkSku($data);
     $p = new shopProduct($product);
     if ($p->save($data, true, $errors)) {
         $_GET['id'] = $p->getId();
         $method = new shopProductGetInfoMethod();
         $this->response = $method->getResponse(true);
     } else {
         throw new waAPIException('server_error', implode(",\n", $errors), 500);
     }
 }
 public function execute()
 {
     $data = waRequest::post();
     $exclude = array('id', 'sku_type');
     foreach ($exclude as $k) {
         if (isset($data[$k])) {
             unset($data[$k]);
         }
     }
     $this->post("name", true);
     $this->post("skus", true);
     $this->checkSku($data);
     // check access rights
     $this->checkRights($this->post("type_id", true));
     $p = new shopProduct();
     if ($p->save($data, true, $errors)) {
         $_GET['id'] = $p->getId();
         $method = new shopProductGetInfoMethod();
         $this->response = $method->getResponse(true);
     } else {
         throw new waAPIException('server_error', implode(",\n", $errors), 500);
     }
 }
 public function execute()
 {
     $id = waRequest::get('id', 0, waRequest::TYPE_INT);
     if (!$id) {
         throw new waException("Unknown product");
     }
     $product = new shopProduct($id);
     $sizes = $this->getConfig()->getImageSizes('system');
     $images = $product->getImages($sizes);
     $param = waRequest::get('param', array(), waRequest::TYPE_ARRAY_INT);
     $image_id = !empty($param[0]) ? $param[0] : 0;
     if (isset($images[$image_id])) {
         $image = $images[$image_id];
         if ($image['size']) {
             $image['size'] = waFiles::formatSize($image['size'], '%0.2f', 'B,KB,MB,GB');
         }
         $this->setTemplate('ProductImage');
         $images = array_values($images);
         array_unshift($images, null);
         array_push($images, null);
         $offset = 0;
         foreach ($images as $k => $img) {
             if ($image['id'] == $img['id']) {
                 $offset = $k;
             }
         }
         $next = $images[$offset + 1];
         $image['dimensions'] = shopImage::getThumbDimensions($image, $sizes['big']);
         $this->view->assign(array('image' => $image, 'next' => $next, 'offset' => $offset, 'original_exists' => file_exists(shopImage::getOriginalPath($image)), 'photostream' => waRequest::get('ps', array())));
     }
     $this->view->assign(array('sizes' => $sizes, 'images' => $images, 'count' => count($images) - 2, 'product_id' => $id, 'product' => $product));
     /**
      * @event backend_product_edit
      * @return array[string][string]string $return[%plugin_id%]['images'] html output
      */
     $this->view->assign('backend_product_edit', wa()->event('backend_product_edit', $product));
 }
 protected function save(waRequestFile $file)
 {
     if (!$this->model) {
         $this->model = new shopProductSkusModel();
     }
     $field = array('id' => waRequest::post('sku_id', null, waRequest::TYPE_INT), 'product_id' => waRequest::post('product_id', null, waRequest::TYPE_INT));
     $data = array('file_size' => $file->size, 'file_name' => $file->name);
     $this->model->updateByField($field, $data);
     $file_path = shopProduct::getPath($field['product_id'], "sku_file/{$field['id']}." . pathinfo($file->name, PATHINFO_EXTENSION));
     if (file_exists($file_path) && !is_writable($file_path) || !file_exists($file_path) && !waFiles::create($file_path)) {
         $data = array('file_size' => 0, 'file_name' => '');
         $this->model->updateByField($field, $data);
         throw new waException(sprintf("The insufficient file write permissions for the %s folder.", substr($file_path, strlen($this->getConfig()->getRootPath()))));
     }
     $file->moveTo($file_path);
     return array('name' => $file->name, 'size' => waFiles::formatSize($file->size));
 }
Example #9
0
 public function delete(array $product_ids)
 {
     if (wa()->getEnv() !== 'cli') {
         $delete_ids = $this->filterAllowedProductIds($product_ids);
     } else {
         $delete_ids = $product_ids;
     }
     // remove files
     foreach ($delete_ids as $product_id) {
         try {
             waFiles::delete(shopProduct::getPath($product_id, null, false));
             waFiles::delete(shopProduct::getPath($product_id, null, true));
         } catch (waException $e) {
         }
     }
     if (empty($delete_ids)) {
         return false;
     }
     $params = array('ids' => $delete_ids);
     /**
      * @event product_delete
      * @param array [string]mixed $params
      * @param array [string]array $params['ids'] Array of IDs of deleted product entries
      * @return void
      */
     wa()->event('product_delete', $params);
     // remove from related models
     foreach (array(new shopProductFeaturesModel(), new shopProductImagesModel(), new shopProductReviewsModel(), new shopProductServicesModel(), new shopProductSkusModel(), new shopProductStocksModel(), new shopProductStocksLogModel(), new shopProductTagsModel(), new shopCategoryProductsModel(), new shopSetProductsModel(), new shopSearchIndexModel(), new shopProductFeaturesSelectableModel(), new shopProductParamsModel(), new shopCartItemsModel()) as $model) {
         $model->deleteByProducts($delete_ids);
     }
     $type_ids = $this->select('DISTINCT `type_id`')->where($this->getWhereByField($this->id, $delete_ids))->fetchAll('type_id');
     // remove records
     if ($this->deleteById($delete_ids)) {
         $type_model = new shopTypeModel();
         $type_model->recount(array_keys($type_ids));
         if ($cache = wa('shop')->getCache()) {
             $cache->deleteGroup('sets');
         }
         return $delete_ids;
     }
     return false;
 }
Example #10
0
 /**
  * @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;
 }
 /**
  *
  * @param array $data
  * @return shopProduct
  */
 private function findProduct(&$data)
 {
     static $currencies;
     static $model;
     static $sku_model;
     /**
      * @var shopTypeFeaturesModel $type_features_model
      */
     static $type_features_model;
     if (empty($model)) {
         $model = new shopProductModel();
     }
     if (empty($currencies)) {
         $currencies = array();
         $config = wa()->getConfig();
         /**
          * @var shopConfig $config
          */
         $c = $config->getCurrency();
         $currencies[$c] = $c;
         foreach ($config->getCurrencies() as $row) {
             $currencies[$row['code']] = $row['code'];
         }
     }
     if (!empty($data['skus'][-1]['stock'])) {
         $per_stock = false;
         $stock =& $data['skus'][-1]['stock'];
         foreach ($stock as $id => &$count) {
             if ($count === '') {
                 $count = null;
             } else {
                 $count = intval($count);
                 if ($id) {
                     $per_stock = true;
                 }
             }
         }
         unset($count);
         if ($per_stock) {
             if (isset($stock[0])) {
                 unset($stock[0]);
             }
         } else {
             $count = ifset($stock[0]);
             $stock = array(0 => $count);
         }
         unset($stock);
     }
     $stack = ifset($this->data['map'][self::STAGE_CATEGORY], array());
     $category_id = end($stack);
     if (!$category_id) {
         $category_id = null;
     }
     $primary = $this->data['primary'];
     $fields = false;
     if (empty($primary)) {
         $keys = explode(':', $this->data['secondary']);
         if (empty($sku_model)) {
             $sku_model = new shopProductSkusModel();
         }
         $sku_fields = array(end($keys) => self::getData($data, $keys));
         //hack for empty SKU code ???
         if (false && reset($sku_fields) === '' && $this->data['extra_secondary']) {
             $extra_keys = explode(':', $this->data['extra_secondary']);
             $sku_fields[end($extra_keys)] = self::getData($data, $this->data['extra_secondary']);
         }
         if ($sku = $sku_model->getByField($sku_fields)) {
             $fields = array('category_id' => $category_id, 'id' => $sku['product_id']);
         }
     } elseif (!empty($primary)) {
         $fields = array('category_id' => $category_id, $primary => ifset($data[$primary], ''));
     }
     if ($fields && $this->data['ignore_category']) {
         unset($fields['category_id']);
     }
     $key = 'p';
     if ($fields && ($current_data = $model->getByField($fields))) {
         $product = new shopProduct($current_data['id']);
         $data['type_id'] = ifempty($current_data['type_id'], $this->data['type_id']);
         if (!empty($current_data['tax_id'])) {
             $data['tax_id'] = $current_data['tax_id'];
         }
         if (isset($data['currency']) && !isset($currencies[$data['currency']])) {
             $this->data['processed_count'][self::STAGE_PRODUCT]['currency']++;
             $data['currency'] = reset($currencies);
         }
         if (!empty($data['skus'])) {
             $data['sku_id'] = ifempty($current_data['sku_id'], -1);
         }
         foreach ($product->skus as $sku_id => $current_sku) {
             if (empty($data['skus'][$sku_id])) {
                 if (!count($current_sku['stock']) && $current_sku['count'] !== null) {
                     $current_sku['stock'][0] = $current_sku['count'];
                 }
                 $data['skus'][$sku_id] = $current_sku;
             }
         }
         $key .= ':u:' . $product->getId();
     } else {
         $product = new shopProduct();
         if ($category_id) {
             $data['categories'] = array($category_id);
         }
         $data['currency'] = ifempty($data['currency'], reset($currencies));
         if (!isset($currencies[$data['currency']])) {
             $this->data['processed_count'][self::STAGE_PRODUCT]['currency']++;
             $data['currency'] = reset($currencies);
         }
         if (!empty($data['skus'])) {
             $sku = reset($data['skus']);
             $data['sku_id'] = key($data['skus']);
             if (!isset($sku['available'])) {
                 $sku['available'] = true;
                 $data['skus'][$data['sku_id']] = $sku;
             }
         }
         $key .= ':i:' . $this->getKey($fields);
     }
     if (!empty($data['features'])) {
         foreach ($data['features'] as $feature => &$values) {
             if (is_array($values)) {
             } elseif (preg_match('/^<\\{(.*)\\}>$/', $values, $matches)) {
                 if (!isset($data['features_selectable'])) {
                     $data['features_selectable'] = array();
                 }
                 if ($values = explode(',', $matches[1])) {
                     foreach ($values as &$value) {
                         if (preg_match('@^(.+)=([\\+\\-]?(\\d+|\\.\\d+|\\d\\.\\d))$@', $value, $matches)) {
                             $value = array('value' => trim($matches[1]), 'price' => $matches[2]);
                         } else {
                             $value = array('value' => trim($value));
                         }
                         unset($value);
                     }
                     $data['features_selectable'][$feature] = array('values' => $values);
                     if (!empty($this->data['virtual_sku_stock']) && isset($data['skus'][-1]['stock'])) {
                         $stock = $data['skus'][-1]['stock'];
                         switch ($this->data['virtual_sku_stock']) {
                             case 'distribute':
                                 if (is_array($stock)) {
                                     foreach ($stock as &$stock_item) {
                                         $stock_item = $stock_item / count($values);
                                         unset($stock_item);
                                     }
                                 } else {
                                     $stock = $stock / count($values);
                                 }
                                 $data['features_selectable'][$feature]['stock'] = $stock;
                                 break;
                             case 'set':
                                 $data['features_selectable'][$feature]['stock'] = $stock;
                                 break;
                         }
                     }
                     $product->sku_type = shopProductModel::SKU_TYPE_SELECTABLE;
                     if (isset($data['skus'][-1])) {
                         if (!isset($data['base_price_selectable'])) {
                             $data['base_price_selectable'] = ifset($data['skus'][-1]['price']);
                         }
                         if (!isset($data['purchase_price_selectable'])) {
                             $data['purchase_price_selectable'] = ifset($data['skus'][-1]['purchase_price']);
                         }
                         if (!isset($data['compare_price_selectable'])) {
                             $data['compare_price_selectable'] = ifset($data['skus'][-1]['compare_price']);
                         }
                     }
                     unset($data['skus']);
                 }
                 unset($data['features'][$feature]);
             } elseif (preg_match('/^\\{(.*)\\}$/', $values, $matches)) {
                 $values = explode(',', $matches[1]);
             }
         }
         unset($values);
     }
     $this->findTax($data);
     $access = $this->findType($data);
     if ($access) {
         $access = !$product->type_id || in_array($product->type_id, $this->data['types']);
     }
     if ($access) {
         $product->__hash = $key;
         foreach ($this->data['new_features'] as $code => &$feature) {
             if (isset($data['features'][$code]) || isset($data['features_selectable'][$code])) {
                 if ($data['type_id'] && !in_array($data['type_id'], $feature['types'])) {
                     if (empty($type_features_model)) {
                         $type_features_model = new shopTypeFeaturesModel();
                     }
                     $type_features_model->updateByFeature($feature['id'], array($data['type_id']), false);
                     $feature['types'][] = $data['type_id'];
                 }
             }
             unset($feature);
         }
     }
     return $access ? $product : null;
 }
Example #12
0
 public static function getPath($sku)
 {
     return empty($sku['file_name']) ? null : shopProduct::getPath($sku['product_id'], "sku_file/{$sku['id']}." . pathinfo($sku['file_name'], PATHINFO_EXTENSION));
 }
Example #13
0
 /**
  * Returns URL of a product image. 
  * 
  * @param array $image Key-value image data object
  * @param string $size Size value string (e.g., '200x0', '96x96', etc.)
  * @param bool $absolute Whether absolute URL must be returned
  * @return string
  */
 public static function getUrl($image, $size = null, $absolute = false)
 {
     $path = shopProduct::getFolder($image['product_id']) . "/{$image['product_id']}/images/{$image['id']}/{$image['id']}.{$size}.{$image['ext']}";
     if (waSystemConfig::systemOption('mod_rewrite')) {
         return wa()->getDataUrl($path, true, 'shop', $absolute);
     } else {
         if (file_exists(wa()->getDataPath($path, true, 'shop'))) {
             return wa()->getDataUrl($path, true, 'shop', $absolute);
         } else {
             $path = str_replace('products/', 'products/thumb.php/', $path);
             return wa()->getDataUrl($path, true, 'shop', $absolute);
         }
     }
 }
 public function deleteByProducts(array $product_ids, $hard = false)
 {
     if ($hard) {
         foreach ($product_ids as $product_id) {
             waFiles::delete(shopProduct::getPath($product_id, 'images', false));
             waFiles::delete(shopProduct::getPath($product_id, 'images', true));
         }
     }
     $this->deleteByField('product_id', $product_ids);
 }
 /**
  * @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));
     }
 }
 public function execute()
 {
     $update = waRequest::post('update');
     // just update one or any field of product
     if ($update) {
         $this->update($update);
         return;
     }
     $data = waRequest::post('product');
     $id = empty($data['id']) || !intval($data['id']) ? null : $data['id'];
     if (!$id && isset($data['id'])) {
         unset($data['id']);
     }
     # edit product info - check rights
     $product_model = new shopProductModel();
     if ($id) {
         if (!$product_model->checkRights($id)) {
             throw new waRightsException(_w("Access denied"));
         }
     } else {
         if (!$product_model->checkRights($data)) {
             throw new waRightsException(_w("Access denied"));
         }
     }
     $skus = waRequest::post('skus', array());
     if (isset($data['skus'])) {
         foreach ($skus as $s_id => $s) {
             if (isset($data['skus'][$s_id])) {
                 $data['skus'][$s_id] += $s;
             } else {
                 $data['skus'][$s_id] = $s;
             }
         }
     } else {
         $data['skus'] = $skus;
     }
     if (empty($data['categories'])) {
         $data['categories'] = array();
     }
     if (empty($data['tags'])) {
         $data['tags'] = array();
     }
     if (empty($data['features_selectable'])) {
         $data['features_selectable'] = array();
     }
     # verify sku_type before save
     if ($data['type_id']) {
         $features_model = new shopFeatureModel();
         if ($features_model->isTypeMultipleSelectable($data['type_id'])) {
             if ($data['sku_type'] == shopProductModel::SKU_TYPE_SELECTABLE) {
                 if (empty($data['features_selectable'])) {
                     throw new waException(_w("Check at least one feature value"));
                 }
             }
         } else {
             $data['sku_type'] = shopProductModel::SKU_TYPE_FLAT;
         }
     } else {
         $data['sku_type'] = shopProductModel::SKU_TYPE_FLAT;
     }
     if ($data['sku_type'] == shopProductModel::SKU_TYPE_FLAT) {
         $data['features_selectable'] = array();
     }
     try {
         $product = new shopProduct($id);
         // for logging changes in stocks
         shopProductStocksLogModel::setContext(shopProductStocksLogModel::TYPE_PRODUCT);
         if ($product->save($data, true, $this->errors)) {
             $features_counts = null;
             if ($product->sku_type == shopProductModel::SKU_TYPE_SELECTABLE) {
                 $features_counts = array();
                 foreach ($product->features_selectable as $f) {
                     if (isset($f['selected'])) {
                         $features_counts[] = $f['selected'];
                     } else {
                         $features_counts[] = count($f['values']);
                     }
                 }
                 $features_total_count = array_product($features_counts);
                 $this->response['features_selectable_strings'] = array('options' => implode(' x ', $features_counts) . ' ' . _w('option', 'options', $features_total_count), 'skus' => _w('%d SKU in total', '%d SKUs in total', $features_total_count));
             }
             shopProductStocksLogModel::clearContext();
             if ($id) {
                 $this->logAction('product_edit', $id);
             } else {
                 $this->logAction('product_add', $product->getId());
             }
             $this->response['id'] = $product->getId();
             $this->response['name'] = $product->name;
             $this->response['url'] = $product->url;
             $this->response['frontend_urls'] = $this->getUrl($product);
             $this->response['raw'] = $this->workupData($product->getData());
             $sales_rate = waRequest::post('sales_rate', 0, waRequest::TYPE_STRING_TRIM);
             $sales_rate = (double) str_replace(',', '.', $sales_rate);
             $runout = $product->getRunout($sales_rate);
             if (!empty($runout['product'])) {
                 $runout['product']['date_str'] = wa_date("humandate", $runout['product']['date']);
                 $runout['product']['days_str'] = _w('%d day', '%d days', $runout['product']['days']);
                 if ($runout['product']['days'] < 3 * 365 && $runout['product']['days'] > 0) {
                     $runout['product_str'] = sprintf(_w('Based on last 30 days sales dynamic (%d items of %s sold during last 30 days), you will run out of %s in <strong>%d days</strong> (on %s)'), $sales_rate * 30, $product->name, $product->name, $runout['product']['days'], wa_date("humandate", $runout['product']['date']));
                 }
             } else {
                 $runout['product'] = new stdClass();
                 /* {} */
             }
             if (!empty($runout['sku'])) {
                 foreach ($runout['sku'] as &$sk_r) {
                     if (empty($sk_r['stock'])) {
                         $sk_r['date_str'] = wa_date("humandate", $sk_r['date']);
                         $sk_r['days_str'] = _w('%d day', '%d days', $sk_r['days']);
                     } else {
                         foreach ($sk_r['stock'] as &$st_r) {
                             $st_r['date_str'] = wa_date("humandate", $st_r['date']);
                             $st_r['days_str'] = _w('%d day', '%d days', $st_r['days']);
                         }
                     }
                 }
                 unset($sk_r, $st_r);
             } else {
                 $runout['sku'] = new stdClass();
                 /* {} */
             }
             $this->response['raw']['runout'] = $runout;
             $this->response['storefront_map'] = $product_model->getStorefrontMap($product->id);
         }
     } catch (Exception $ex) {
         $this->setError($ex->getMessage());
     }
 }
Example #17
0
 public function crossSelling($product_id, $limit = 5, $available_only = false, $key = false)
 {
     if (!is_numeric($limit)) {
         $key = $available_only;
         $available_only = $limit;
         $limit = 5;
     }
     if (is_string($available_only)) {
         $key = $available_only;
         $available_only = false;
     }
     if (!$product_id) {
         return array();
     }
     if (is_array($product_id)) {
         if ($key) {
             foreach ($product_id as &$r) {
                 $r = $r[$key];
             }
             unset($r);
         }
         $product_model = new shopProductModel();
         $sql = "SELECT p.* FROM  shop_product p JOIN shop_type t ON p.type_id = t.id\n            WHERE (p.id IN (i:id)) AND (t.cross_selling !=  '' OR p.cross_selling = 2)\n            ORDER BY RAND() LIMIT 1";
         $p = $product_model->query($sql, array('id' => $product_id))->fetchAssoc();
         $p = new shopProduct($p);
         $result = $p->crossSelling($limit, $available_only);
         foreach ($result as $p_id => $pr) {
             if (in_array($p_id, $product_id)) {
                 unset($result[$p_id]);
             }
         }
         return $result;
     } else {
         $p = new shopProduct($product_id);
         return $p->crossSelling($limit, $available_only);
     }
 }
 /**
  * Daten fuer Produktbereiche aufbereiten
  *
  * @param array $hParams      Parameter für shopProduct::readEntry und Assigns
  * @return array
  */
 protected static function includeProductCompare($hParams = array())
 {
     if (array_key_exists('settings_file', $hParams)) {
         $sSettingsFile = $hParams['settings_file'] ? $hParams['settings_file'] : 'products';
         unset($hParams['settings_file']);
         $hParams['shop_settings'] = Settings::get($sSettingsFile);
     }
     // Einstellungen dem Renderer zuweisen
     $sSettingsAssignName = null;
     if (array_key_exists('assign_settings', $hParams)) {
         $sSettingsAssignName = $hParams['assign_settings'];
         Renderer::assign($sSettingsAssignName, $hParams['shop_settings']);
         unset($hParams['assign_settings']);
     }
     // Produkt-IDs setzen
     if (!array_key_exists('peid', $hParams)) {
         $hParams['peid'] = $hParams['shop_settings']['products']['peid'];
     }
     // Daten für Vergleiche formatieren
     $hParams['return_shopformat'] = 1;
     // Daten auslesen und zurückgeben
     return shopProduct::readEntry($hParams);
 }
 public function addNewProduct($data)
 {
     $product = new shopProduct();
     $product->save($data);
     return $product->getId();
 }
Example #20
0
 private function getProductInfo($product_id, $sku_id = null, $order_id = null)
 {
     $product = new shopProduct($product_id);
     $data = $product->getData();
     if (!$data) {
         return array();
     }
     $rate = 1;
     $currency_model = $this->getModel('currency');
     if ($order_id) {
         $order = $this->getOrder($order_id);
         $rate = $order['rate'];
     }
     $data['price'] = (double) $currency_model->convertByRate($data['price'], 1, $rate);
     $data['max_price'] = (double) $currency_model->convertByRate($data['max_price'], 1, $rate);
     $data['min_price'] = (double) $currency_model->convertByRate($data['min_price'], 1, $rate);
     $data['skus'] = $product->skus;
     foreach ($data['skus'] as &$sku) {
         $sku['price'] = (double) $currency_model->convertByRate($sku['primary_price'], 1, $rate);
     }
     unset($sku);
     if ($sku_id === null) {
         $sku_id = count($data['skus']) > 1 ? $product->sku_id : null;
     }
     if ($sku_id && isset($data['skus'][$sku_id])) {
         $sku_price = $data['skus'][$sku_id]['price'];
     } else {
         $sku_price = $data['price'];
     }
     $data['services'] = $this->getServices($product_id, $sku_id, $order_id, $sku_price);
     return $data;
 }
Example #21
0
 protected function assignReportsData(shopProduct $product)
 {
     $order_model = new shopOrderModel();
     $sales_total = $order_model->getTotalSalesByProduct($product['id'], $product['currency']);
     $this->view->assign('sales', $sales_total);
     $profit = $sales_total['total'];
     $rows = $order_model->getSalesByProduct($product['id']);
     $date = strtotime(date('Y-m-d') . " -30 day");
     $sales_data = array();
     $i = 0;
     while ($date < time()) {
         $date = date('Y-m-d', $date);
         $sales_data[] = array($i++, isset($rows[$date]) ? (double) $rows[$date] : 0);
         $date = strtotime($date . " +1 day");
     }
     $this->view->assign('sales_plot_data', array($sales_data));
     if (count($product['skus']) > 1) {
         $sku_sales_data = array();
         $rows = $order_model->getTotalSkuSalesByProduct($product['id'], $product['currency']);
         foreach ($rows as $sku_id => $v) {
             $sku_sales_data[] = array($product['skus'][$sku_id]['name'], (double) $v['total']);
             if (!(double) $v['purchase']) {
                 $profit = false;
             } elseif ($profit) {
                 $profit -= $v['purchase'];
             }
         }
         $this->view->assign('sku_plot_data', array($sku_sales_data));
     } else {
         if ((double) $sales_total['purchase']) {
             $profit -= $sales_total['purchase'];
         } else {
             $profit = false;
         }
     }
     if ($profit) {
         $this->view->assign('profit', $profit);
     }
     $runout = array();
     $sales_rate = 0;
     if ($sales_total['quantity'] >= 3) {
         // < 3 means not enough data for proper statistic
         $sales_rate = $sales_total['quantity'] / 30;
         $runout = $product->getRunout($sales_rate);
     }
     $this->view->assign('runout', $runout);
     $this->view->assign('sales_rate', $sales_rate);
     $stocks_log_model = new shopProductStocksLogModel();
     $stocks_log = $stocks_log_model->getList('*,stock_name,sku_name,product_name', array('where' => array('product_id' => $product->id), 'limit' => 5, 'order' => 'datetime DESC'));
     $this->view->assign('stocks_log', $stocks_log);
 }