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; } } }
public function execute() { $hash = $this->get('hash'); $collection = new shopProductsCollection($hash); $offset = waRequest::get('offset', 0, 'int'); if ($offset < 0) { throw new waAPIException('invalid_param', 'Param offset must be greater than or equal to zero'); } $limit = waRequest::get('limit', 100, 'int'); if ($limit < 0) { throw new waAPIException('invalid_param', 'Param limit must be greater than or equal to zero'); } if ($limit > 1000) { throw new waAPIException('invalid_param', 'Param limit must be less or equal 1000'); } $this->response['count'] = $collection->count(); $this->response['offset'] = $offset; $this->response['limit'] = $limit; $this->response['products'] = array_values($collection->getProducts('*', $offset, $limit)); $image_size = wa('shop')->getConfig()->getImageSize('thumb'); foreach ($this->response['products'] as &$p) { if ($p['image_id']) { $p['image_url'] = shopImage::getUrl(array('id' => $p['image_id'], 'product_id' => $p['id'], 'ext' => $p['ext']), $image_size, true); } } unset($p); }
protected function save(waRequestFile $file) { $product_id = waRequest::post('product_id', null, waRequest::TYPE_INT); $product_model = new shopProductModel(); if (!$product_model->checkRights($product_id)) { throw new waException(_w("Access denied")); } // check image if (!($image = $file->waImage())) { throw new waException('Incorrect image'); } $image_changed = false; /** * Extend upload proccess * Make extra workup * @event image_upload */ $event = wa()->event('image_upload', $image); if ($event) { foreach ($event as $plugin_id => $result) { if ($result) { $image_changed = true; } } } if (!$this->model) { $this->model = new shopProductImagesModel(); } $data = array('product_id' => $product_id, 'upload_datetime' => date('Y-m-d H:i:s'), 'width' => $image->width, 'height' => $image->height, 'size' => $file->size, 'original_filename' => basename($file->name), 'ext' => $file->extension); $image_id = $data['id'] = $this->model->add($data); if (!$image_id) { throw new waException("Database error"); } /** * @var shopConfig $config */ $config = $this->getConfig(); $image_path = shopImage::getPath($data); if (file_exists($image_path) && !is_writable($image_path) || !file_exists($image_path) && !waFiles::create($image_path)) { $this->model->deleteById($image_id); throw new waException(sprintf("The insufficient file write permissions for the %s folder.", substr($image_path, strlen($config->getRootPath())))); } if ($image_changed) { $image->save($image_path); // save original $original_file = shopImage::getOriginalPath($data); if ($config->getOption('image_save_original') && $original_file) { $file->moveTo($original_file); } } else { $file->moveTo($image_path); } unset($image); // free variable shopImage::generateThumbs($data, $config->getImageSizes()); return array('id' => $image_id, 'name' => $file->name, 'type' => $file->type, 'size' => $file->size, 'url_thumb' => shopImage::getUrl($data, $config->getImageSize('thumb')), 'url_crop' => shopImage::getUrl($data, $config->getImageSize('crop')), 'url_crop_small' => shopImage::getUrl($data, $config->getImageSize('crop_small')), 'description' => ''); }
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() { $id = $this->get('id', true); $images_model = new shopProductImagesModel(); $image = $images_model->getById($id); if (!$image) { throw new waAPIException('invalid_param', 'Product image not found', 404); } $this->response = $image; $size = waRequest::get('size', wa('shop')->getConfig()->getImageSize('thumb')); $this->response['url_thumb'] = shopImage::getUrl($image, $size, true); }
public function workup(&$product, $sku_stocks) { if (!$product['image_id']) { $product['url_crop_small'] = null; } else { $product['url_crop_small'] = shopImage::getUrl(array('id' => $product['image_id'], 'product_id' => $product['id'], 'ext' => $product['ext']), $this->getConfig()->getImageSize('crop_small')); } // aggregated stocks count icon for product $product['icon'] = shopHelper::getStockCountIcon($product['count'], null, true); foreach ($product['skus'] as &$sku) { $this->workupSku($sku, $sku_stocks); } unset($sku); }
public function execute() { $app_settings_model = new waAppSettingsModel(); $query = waRequest::get('term'); $count = $app_settings_model->get($this->plugin_id, 'autocomplete_count'); $collection = new shopProductsCollection('search/query=' . $query); $products = $collection->getProducts('*', 0, $count); $result = array(); foreach ($products as $product) { $size = $app_settings_model->get($this->plugin_id, 'img_size'); $product['value'] = $product['name']; $product['price_str'] = shop_currency($product['price']); $product['img_url'] = $product['image_id'] ? shopImage::getUrl(array('id' => $product['image_id'], 'product_id' => $product['id'], 'filename' => $product['image_filename'], 'ext' => $product['ext']), $size) : ''; array_push($result, $product); } $this->response = $result; }
public function getImages($product_id, $sizes = array(), $key = 'id', $absolute = false) { if (empty($product_id)) { return array(); } if (!$sizes) { $sizes = array('crop' => wa('shop')->getConfig()->getImageSize('crop')); } else { if (is_numeric($sizes)) { $sizes = array($sizes => $sizes); } elseif (is_string($sizes)) { $sizes = array((string) $sizes => wa('shop')->getConfig()->getImageSize((string) $sizes)); foreach ($sizes as $k => $s) { if ($s === null) { $sizes[$k] = $k; } } } } if ($key != 'product_id') { $key = 'id'; } $where = $this->getWhereByField('product_id', $product_id); $images = array(); foreach ($this->query("SELECT * FROM {$this->table} WHERE {$where} ORDER BY product_id, sort") as $image) { $image['edit_datetime_ts'] = $image['edit_datetime'] ? strtotime($image['edit_datetime']) : null; if (!empty($sizes)) { foreach ($sizes as $name => $size) { $image['url_' . $name] = shopImage::getUrl($image, $size, $absolute); } } if ($key == 'id') { $images[$image['id']] = $image; } else { $images[$image['product_id']][$image['id']] = $image; } } return $images; }
public function execute() { $offset = waRequest::get('offset', 0, waRequest::TYPE_INT); $total_count = waRequest::get('total_count', null, waRequest::TYPE_INT); $lazy = waRequest::get('lazy', false, waRequest::TYPE_INT); $product_reivews_model = new shopProductReviewsModel(); $reviews_per_page = $this->getConfig()->getOption('reviews_per_page_total'); /* $reviews = $product_reivews_model->getList( $offset, $reviews_per_page, array('is_new' => true) ); */ $reviews = $product_reivews_model->getList('*,is_new,contact,product', array('offset' => $offset, 'limit' => $reviews_per_page)); // TODO: move to model $product_ids = array(); foreach ($reviews as $review) { $product_ids[] = $review['product_id']; } $product_ids = array_unique($product_ids); $product_model = new shopProductModel(); $products = $product_model->getByField('id', $product_ids, 'id'); $image_size = wa()->getConfig()->getImageSize('crop_small'); foreach ($reviews as &$review) { if (isset($products[$review['product_id']])) { $product = $products[$review['product_id']]; $review['product_name'] = $product['name']; if ($product['image_id']) { $review['product_url_crop_small'] = shopImage::getUrl(array('id' => $product['image_id'], 'product_id' => $product['id'], 'ext' => $product['ext']), $image_size); } else { $review['product_url_crop_small'] = null; } } } $this->view->assign(array('total_count' => $total_count ? $total_count : $product_reivews_model->countAll(), 'count' => count($reviews), 'offset' => $offset, 'reviews' => $reviews, 'current_author' => shopProductReviewsModel::getAuthorInfo(wa()->getUser()->getId()), 'reply_allowed' => true, 'lazy' => $lazy, 'sidebar_counters' => array('new' => $product_reivews_model->countNew(!$offset)))); }
private function workupList(&$data, $fields, $escape) { $extract_contact_info = false; foreach (explode(',', $fields) as $field) { if ($field == 'contact') { $contact_ids = array(); foreach ($data as $item) { if ($item['contact_id']) { $contact_ids[] = $item['contact_id']; } } $contact_ids = array_unique($contact_ids); $contacts = self::getAuthorInfo($contact_ids); foreach ($data as &$item) { $author = array('name' => $item['name'], 'email' => $item['email'], 'site' => $item['site']); $item['author'] = array_merge($author, isset($contacts[$item['contact_id']]) ? $contacts[$item['contact_id']] : array()); if ($escape) { $item['author']['name'] = htmlspecialchars($item['author']['name']); } } unset($item); } if ($field == 'is_new') { $this->checkForNew($data); } if ($field == 'product') { $product_ids = array(); foreach ($data as $item) { $product_ids[] = $item['product_id']; } $product_ids = array_unique($product_ids); $product_model = new shopProductModel(); $products = $product_model->getByField('id', $product_ids, 'id'); $image_size = wa()->getConfig()->getImageSize('crop_small'); foreach ($data as &$item) { if (isset($products[$item['product_id']])) { $product = $products[$item['product_id']]; $item['product_name'] = $product['name']; if ($product['image_id']) { $item['product_url_crop_small'] = shopImage::getUrl(array('id' => $product['image_id'], 'product_id' => $product['id'], 'ext' => $product['ext']), $image_size); } else { $item['product_url_crop_small'] = null; } } } } } foreach ($data as &$item) { // recursive workuping if (!empty($item['comments'])) { $this->extendItems($item['comments'], $options); } } unset($item); }
private function workupProducts(&$products = array(), $escape) { // Names of fields that must be converted to float values $float = array('min_price', 'max_price', 'total_sales', 'base_price_selectable', 'rating', 'price', 'compare_price'); foreach ($products as &$p) { foreach ($float as $field) { if (isset($p[$field])) { $p[$field] = (double) $p[$field]; } } if ($this->is_frontend && $p['compare_price'] && $p['compare_price'] <= $p['price']) { $p['compare_price'] = 0; } // escape if ($escape) { $p['name'] = htmlspecialchars($p['name']); $p['url'] = htmlspecialchars($p['url']); } } unset($p); if (!empty($this->options['params'])) { $product_params_model = new shopProductParamsModel(); $rows = $product_params_model->getByField('product_id', array_keys($products), true); foreach ($rows as $row) { $products[$row['product_id']]['params'][$row['name']] = $row['value']; } } if ($this->post_fields) { $ids = array_keys($products); foreach ($this->post_fields as $table => $fields) { if ($table == '_internal') { if ($this->is_frontend && waRequest::param('url_type') == 2) { $cat_ids = array(); foreach ($products as &$p) { if (!empty($p['category_id'])) { $cat_ids[] = $p['category_id']; } } $cat_ids = array_unique($cat_ids); if ($cat_ids) { $categories = $this->getModel('category')->getById($cat_ids); foreach ($products as &$p) { if (!empty($p['category_id'])) { $p['category_url'] = $categories[$p['category_id']]['full_url']; } } } } foreach ($fields as $i => $f) { if ($f == 'images' || $f == 'image') { if ($f == 'images') { $product_images_model = new shopProductImagesModel(); $product_images = $product_images_model->getImages($ids, 'thumb', 'product_id'); foreach ($product_images as $product_id => $images) { $products[$product_id]['images'] = $images; } } elseif ($f == 'image') { $thumb_size = wa('shop')->getConfig()->getImageSize('thumb'); $big_size = wa('shop')->getConfig()->getImageSize('big'); foreach ($products as &$p) { if ($p['image_id']) { $tmp = array('id' => $p['image_id'], 'product_id' => $p['id'], 'ext' => $p['ext']); $p['image']['thumb_url'] = shopImage::getUrl($tmp, $thumb_size, isset($this->options['absolute']) ? $this->options['absolute'] : false); $p['image']['big_url'] = shopImage::getUrl($tmp, $big_size, isset($this->options['absolute']) ? $this->options['absolute'] : false); } } } } elseif ($f == 'frontend_url') { foreach ($products as &$p) { $route_params = array('product_url' => $p['url']); if (isset($p['category_url'])) { $route_params['category_url'] = $p['category_url']; } elseif (isset($this->info['hash']) && $this->info['hash'] == 'category') { if (isset($this->info['subcategories']) && $this->info['id'] != $p['category_id']) { if (isset($this->info['subcategories'][$p['category_id']])) { $route_params['category_url'] = $this->info['subcategories'][$p['category_id']]['full_url']; } } else { $route_params['category_url'] = $this->info['full_url']; } } $p['frontend_url'] = wa()->getRouteUrl('shop/frontend/product', $route_params); } unset($p); } } } } } }
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() { $id = waRequest::get('id', null, waRequest::TYPE_INT); if (!$id) { throw new waException("Unknown image"); } $direction = waRequest::post('direction', 'left', waRequest::TYPE_STRING_TRIM); if (!isset($this->angles[$direction])) { throw new waException("Can't rotate image"); } $product_images_model = new shopProductImagesModel(); $image = $product_images_model->getById($id); if (!$image) { throw new waException("Unknown image"); } // check rights $product_model = new shopProductModel(); if (!$product_model->checkRights($image['product_id'])) { throw new waException(_w("Access denied")); } $image_path = shopImage::getPath($image); $paths = array(); try { $result_image_path = preg_replace('/(\\.[^\\.]+)$/', '.result$1', $image_path); $backup_image_path = preg_replace('/(\\.[^\\.]+)$/', '.backup$1', $image_path); $paths[] = $result_image_path; if ($this->rotate($image_path, $result_image_path, $this->angles[$direction])) { $count = 0; while (!file_exists($result_image_path) && ++$count < 5) { sleep(1); } if (!file_exists($result_image_path)) { throw new waException(_w("Error while rotate. I/O error")); } if (!waFiles::move($image_path, $backup_image_path)) { throw new waException(_w("Error while rotate. Operation canceled")); } $paths[] = $backup_image_path; if (!waFiles::move($result_image_path, $image_path)) { if (!waFiles::move($backup_image_path, $image_path)) { throw new waException(_w("Error while rotate. Original file corupted but backuped")); } throw new waException(_w("Error while rotate. Operation canceled")); } $datetime = date('Y-m-d H:i:s'); $data = array('edit_datetime' => $datetime, 'width' => $image['height'], 'height' => $image['width']); $product_images_model->updateById($id, $data); $image = array_merge($image, $data); $thumb_dir = shopImage::getThumbsPath($image); $back_thumb_dir = preg_replace('@(/$|$)@', '.back$1', $thumb_dir, 1); $paths[] = $back_thumb_dir; waFiles::delete($back_thumb_dir); if (!(waFiles::move($thumb_dir, $back_thumb_dir) || waFiles::delete($back_thumb_dir)) && !waFiles::delete($thumb_dir)) { throw new waException(_w("Error while rebuild thumbnails")); } $config = $this->getConfig(); try { shopImage::generateThumbs($image, $config->getImageSizes()); } catch (Exception $e) { waLog::log($e->getMessage()); } $this->response = $image; $edit_datetime_ts = strtotime($image['edit_datetime']); $this->response['url_big'] = shopImage::getUrl($image, $config->getImageSize('big')) . '?' . $edit_datetime_ts; $this->response['url_crop'] = shopImage::getUrl($image, $config->getImageSize('crop')) . '?' . $edit_datetime_ts; } foreach ($paths as $path) { waFiles::delete($path); } } catch (Exception $e) { foreach ($paths as $path) { waFiles::delete($path); } throw $e; } }
public function execute() { $id = waRequest::post('id', null, waRequest::TYPE_INT); if (!$id) { throw new waException("Can't restore image"); } $product_images_model = new shopProductImagesModel(); $image = $product_images_model->getById($id); if (!$image) { throw new waException("Can't restore image"); } // check rights $product_model = new shopProductModel(); if (!$product_model->checkRights($image['product_id'])) { throw new waException(_w("Access denied")); } $original_image_path = shopImage::getOriginalPath($image); if (!wa('shop')->getConfig()->getOption('image_save_original') || !file_exists($original_image_path)) { throw new waException("Can't restore image. Original image doesn't exist"); } $image_path = shopImage::getPath($image); $paths = array(); try { $backup_image_path = preg_replace('/(\\.[^\\.]+)$/', '.backup$1', $image_path); if (!waFiles::move($image_path, $backup_image_path)) { throw new waException("Error while restore. Operation canceled"); } $paths[] = $backup_image_path; if (!waFiles::move($original_image_path, $image_path)) { if (!waFiles::move($backup_image_path, $image_path)) { throw new waException("Error while restore. Current file corupted but backuped"); } throw new waException("Error while restore. Operation canceled"); } $data = $this->getData($image_path); $product_images_model->updateById($id, $data); $image = array_merge($image, $data); $thumb_dir = shopImage::getThumbsPath($image); $back_thumb_dir = preg_replace('@(/$|$)@', '.back$1', $thumb_dir, 1); $paths[] = $back_thumb_dir; waFiles::delete($back_thumb_dir); // old backups if (!(waFiles::move($thumb_dir, $back_thumb_dir) || waFiles::delete($back_thumb_dir)) && !waFiles::delete($thumb_dir)) { throw new waException(_w("Error while rebuild thumbnails")); } /** * @var shopConfig $config */ $config = $this->getConfig(); try { shopImage::generateThumbs($image, $config->getImageSizes()); } catch (Exception $e) { waLog::log($e->getMessage()); } $this->response = $image; $edit_datetime_ts = strtotime($image['edit_datetime']); $this->response['url_big'] = shopImage::getUrl($image, $config->getImageSize('big')) . '?' . $edit_datetime_ts; $this->response['url_crop'] = shopImage::getUrl($image, $config->getImageSize('crop')) . '?' . $edit_datetime_ts; foreach ($paths as $path) { waFiles::delete($path); } } catch (Exception $e) { foreach ($paths as $path) { waFiles::delete($path); } throw $e; } }
/** * @param string $field * @param mixed $value * @param array $info * @param array $data * @param null $sku_data * @return mixed|string */ private function format($field, $value, $info = array(), $data = array(), $sku_data = null) { /** * @todo cpa field */ /** * <yml_catalog> * <shop> * <currencies> * <categories> * <local_delivery_cost> * <offers> * <picture> * <description> и <name> * <delivery>, <pickup> и <store> * <adult> * <barcode> * <cpa> TODO * <rec> * <param> (name,unit,value) * <vendor> */ static $currency_model; static $size; switch ($field) { case 'group_id': if ($value === 'auto') { if (!empty($data['market_category'])) { $value = $this->plugin()->isGroupedCategory($data['market_category']) ? $data['id'] : null; } else { $info['format'] = false; } } break; case 'market_category': //it's product constant field //TODO verify it break; case 'name': if (!empty($sku_data['name']) && !empty($data['name']) && $sku_data['name'] != $data['name']) { $value = sprintf('%s (%s)', $value, $sku_data['name']); } $value = preg_replace('/<br\\/?\\s*>/', "\n", $value); $value = preg_replace("/[\r\n]+/", "\n", $value); $value = strip_tags($value); $value = trim($value); if (mb_strlen($value) > 255) { $value = mb_substr($value, 0, 252) . '...'; } break; case 'description': $value = preg_replace('/<br\\/?\\s*>/', "\n", $value); $value = preg_replace("/[\r\n]+/", "\n", $value); $value = strip_tags($value); $value = trim($value); if (mb_strlen($value) > 512) { $value = mb_substr($value, 0, 509) . '...'; } break; case 'barcode': //может содержать несколько элементов $value = preg_replace('@\\D+@', '', $value); if (!in_array(strlen($value), array(8, 12, 13))) { $value = null; } break; case 'sales_notes': $value = trim($value); if (mb_strlen($value) > 50) { $value = mb_substr($value, 0, 50); } break; case 'typePrefix': $model = new shopTypeModel(); if ($type = $model->getById($value)) { $value = $type['name']; } break; case 'url': //max 512 $value = preg_replace_callback('@([^\\[\\]a-zA-Z\\d_/-\\?=%&,\\.]+)@i', array(__CLASS__, 'rawurlencode'), $value); if ($this->data['utm']) { $value .= (strpos($value, '?') ? '&' : '?') . $this->data['utm']; } $value = 'http://' . ifempty($this->data['base_url'], 'localhost') . $value; break; case 'oldprice': if (empty($value) || empty($this->data['export']['compare_price'])) { $value = null; break; } case 'price': if (!$currency_model) { $currency_model = new shopCurrencyModel(); } if ($sku_data) { if (!in_array($data['currency'], $this->data['currency'])) { $value = $currency_model->convert($value, $data['currency'], $this->data['primary_currency']); $data['currency'] = $this->data['primary_currency']; } } else { if (!in_array($data['currency'], $this->data['currency'])) { #value in default currency if ($this->data['default_currency'] != $this->data['primary_currency']) { $value = $currency_model->convert($value, $this->data['default_currency'], $this->data['primary_currency']); } $data['currency'] = $this->data['primary_currency']; } elseif ($this->data['default_currency'] != $data['currency']) { $value = $currency_model->convert($value, $this->data['default_currency'], $data['currency']); } } break; case 'currencyId': if (!in_array($value, $this->data['currency'])) { $value = $this->data['primary_currency']; } break; case 'rate': if (!in_array($value, array('CB', 'CBRF', 'NBU', 'NBK'))) { $info['format'] = '%0.4f'; } break; case 'available': if (!empty($sku_data) && isset($sku_data['available']) && empty($sku_data['available'])) { $value = 'false'; } if (is_object($value)) { switch (get_class($value)) { case 'shopBooleanValue': /** * @var $value shopBooleanValue */ $value = $value->value ? 'true' : 'false'; break; } } $value = ($value <= 0 || $value === 'false' || empty($value)) && $value !== null && $value !== 'true' ? 'false' : 'true'; break; case 'store': case 'pickup': case 'delivery': case 'adult ': if (is_object($value)) { switch (get_class($value)) { case 'shopBooleanValue': /** * @var $value shopBooleanValue */ $value = $value->value ? 'true' : 'false'; break; } } $value = empty($value) || $value === 'false' ? 'false' : 'true'; break; case 'picture': //max 512 $values = array(); $limit = 10; if (!empty($sku_data['image_id'])) { $value = array(ifempty($value[$sku_data['image_id']])); } while (is_array($value) && ($image = array_shift($value)) && $limit--) { if (!$size) { $shop_config = wa('shop')->getConfig(); /** * @var $shop_config shopConfig */ $size = $shop_config->getImageSize('big'); } $values[] = 'http://' . ifempty($this->data['base_url'], 'localhost') . shopImage::getUrl($image, $size); } $value = $values; break; case 'page_extent': $value = max(1, intval($value)); break; case 'seller_warranty': case 'manufacturer_warranty': case 'expiry': /** * ISO 8601, например: P1Y2M10DT2H30M */ $pattern = '@P((\\d+S)?(\\d+M)(\\d+D)?)?(T(\\d+H)?(\\d+M)(\\d+S)?)?@'; $class = is_object($value) ? get_class($value) : false; switch ($class) { case 'shopBooleanValue': /** * @var $value shopBooleanValue */ $value = $value->value ? 'true' : 'false'; break; case 'shopDimensionValue': /** * @var $value shopDimensionValue */ $value = $value->convert('s', false); /** * @var $value int */ if (empty($value)) { $value = 'false'; } else { $value = $this->formatCustom($value, 'ISO8601'); } break; default: $value = (string) $value; if (empty($value) || $value == 'false') { $value = 'false'; } elseif (preg_match('@^\\d+$@', trim($value))) { $value = $this->formatCustom(intval($value) * 3600 * 24, 'ISO8601'); } elseif (!preg_match($pattern, $value)) { $value = 'true'; } break; } break; case 'year': if (empty($value)) { $value = null; } break; case 'ISBN': /** * @todo verify format * Код книги, если их несколько, то указываются через запятую. * Форматы ISBN и SBN проверяются на корректность. Валидация кодов происходит не только по длине, * также проверяется контрольная цифра (check-digit) – последняя цифра кода должна согласовываться * с остальными цифрами по определенной формуле. При разбиении ISBN на части при помощи дефиса * (например, 978-5-94878-004-7) код проверяется на соответствие дополнительным требованиям к * количеству цифр в каждой из частей. * Необязательный элемент. **/ break; case 'recording_length': /** * Время звучания задается в формате mm.ss (минуты.секунды). **/ if (is_object($value)) { switch (get_class($value)) { case 'shopDimensionValue': /** * @var $value shopDimensionValue */ $value = $value->convert('s', false); break; default: $value = (int) $value; break; } } $value = sprintf('%02d.%02d', floor($value / 60), $value % 60); break; case 'weight': /** * Элемент предназначен для указания веса товара. Вес указывается в килограммах с учетом упаковки. * Формат элемента: положительное число с точностью 0.001, разделитель целой и дробной части — точка. * При указании более высокой точности значение автоматически округляется следующим способом: * — если 4-ый знак после разделителя меньше 5, то 3-й знак сохраняется, а все последующие обнуляются; * — если 4-ый знак после разделителя больше или равен 5, то 3-й знак увеличивается на единицу, а все последующие обнуляются. **/ if (is_object($value)) { switch (get_class($value)) { case 'shopDimensionValue': /** * @var $value shopDimensionValue */ if ($value->type == 'weight') { $value = $value->convert('kg', '%0.3f'); } break; default: $value = floatval($value); break; } } else { $value = floatval($value); } break; case 'dimensions': /** * * Элемент предназначен для указания габаритов товара (длина, ширина, высота) в упаковке. Размеры указываются в сантиметрах. * Формат элемента: три положительных числа с точностью 0.001, разделитель целой и дробной части — точка. Числа должны быть разделены символом «/» без пробелов. * При указании более высокой точности значение автоматически округляется следующим способом: * — если 4-ый знак после разделителя меньше 5, то 3-й знак сохраняется, а все последующие обнуляются; * — если 4-ый знак после разделителя больше или равен 5, то 3-й знак увеличивается на единицу, а все последующие обнуляются. **/ /** * @todo use cm * */ $parsed_value = array(); $class = is_object($value) ? get_class($value) : false; switch ($class) { case 'shopCompositeValue': /** * @var $value shopCompositeValue */ for ($i = 0; $i < 3; $i++) { $value_item = $value[$i]; $class_item = is_object($value_item) ? get_class($value_item) : false; switch ($class_item) { case 'shopDimensionValue': /** * @var $value_item shopDimensionValue */ if ($value_item->type == '3d.length') { $parsed_value[] = $value_item->convert('cm', '%0.4f'); } else { $parsed_value[] = sprintf('%0.4f', (string) $value_item); } break; default: $parsed_value[] = sprintf('%0.4f', (string) $value_item); break; } } break; default: $parsed_value = array_map('floatval', explode(':', preg_replace('@[^\\d\\.,]+@', ':', $value), 3)); break; } foreach ($parsed_value as &$p) { $p = str_replace(',', '.', sprintf('%0.4f', $p)); unset($p); } $value = implode('/', $parsed_value); break; case 'age': /** * @todo * unit="year": 0, 6, 12, 16, 18 * unit="month": 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 */ if (is_object($value)) { switch (get_class($value)) { case 'shopDimensionValue': /** * @var $value shopDimensionValue */ if ($value->type == 'time') { $value = $value->convert('month', false); } break; default: $value = intval($value); break; } } else { /** * @var $value shopDimensionValue */ if (preg_match('@^(year|month)s?:(\\d+)$@', trim($value), $matches)) { $value = array('unit' => $matches[1], 'value' => intval($matches[2])); } else { $value = intval($value); } } if (!is_array($value)) { if ($value > 12) { $value = array('unit' => 'year', 'value' => floor($value / 12)); } else { $value = array('unit' => 'month', 'value' => intval($value)); } } break; case 'country_of_origin': /** * @todo * @see http://partner.market.yandex.ru/pages/help/Countries.pdf */ break; case 'local_delivery_cost': if ($value !== '') { $value = max(0, floatval($value)); } break; case 'days': $value = max(1, intval($value)); break; case 'dataTour': /** * @todo * Даты заездов. * Необязательный элемент. Элемент <offer> может содержать несколько элементов <dataTour>. **/ break; case 'hotel_stars': /** * @todo * Звезды отеля. * Необязательный элемент. **/ break; case 'room': /** * @todo * Тип комнаты (SNG, DBL, ...). * Необязательный элемент. **/ break; case 'meal': /** * @todo * Тип питания (All, HB, ...). * Необязательный элемент. **/ break; case 'date': /** * @todo * Дата и время сеанса. Указываются в формате ISO 8601: YYYY-MM-DDThh:mm. **/ break; case 'hall': /** * @todo * max 512 * Ссылка на изображение с планом зала. **/ //plan - property break; case 'param': $unit = null; $name = ifset($info['source_name'], ''); if ($value instanceof shopDimensionValue) { $unit = $value->unit_name; $value = $value->format('%s'); } elseif (is_array($value)) { $_value = reset($value); if ($_value instanceof shopDimensionValue) { $unit = $_value->unit_name; $values = array(); foreach ($value as $_value) { /** * @var shopDimensionValue $_value */ $values[] = $_value->convert($unit, '%s'); } $value = implode(', ', $values); } else { if (preg_match('@^(.+)\\s*\\(([^\\)]+)\\)\\s*$@', $name, $matches)) { //feature name based unit $unit = $matches[2]; $name = $matches[1]; } $value = implode(', ', $value); } } elseif (preg_match('@^(.+)\\s*\\(([^\\)]+)\\)\\s*$@', $name, $matches)) { //feature name based unit $unit = $matches[2]; $name = $matches[1]; } $value = trim((string) $value); if (in_array($value, array(null, false, ''), true)) { $value = null; } else { $value = array('name' => $name, 'unit' => $unit, 'value' => trim((string) $value)); } break; } $format = ifempty($info['format'], '%s'); if (is_array($value)) { /** * @var $value array */ reset($value); if (key($value) == 0) { foreach ($value as &$item) { $item = str_replace(' ', ' ', $item); $item = str_replace('&', '&', $item); $item = $this->sprintf($format, $item); } unset($item); } if (!in_array($field, array('email', 'picture', 'dataTour', 'additional', 'barcode', 'param', 'related_offer'))) { $value = implode(', ', $value); } } elseif ($value !== null) { /** * @var $value string */ $value = str_replace(' ', ' ', $value); $value = str_replace('&', '&', $value); $value = $this->sprintf($format, $value); } return $value; }
/** * Get aggregated data about placing products(skus) in stocks * * @see getProductStocks * * @param int|array $product_id * @param string $order * @return array */ public function getProductStocksByProductId($product_id, $order = 'desc') { if (!$product_id) { return array(); } $product_ids = (array) $product_id; $product_ids_str = implode(',', $product_ids); $order = $order == 'desc' || $order == 'DESC' ? 'DESC' : 'ASC'; // necessary models $stock_model = new shopStockModel(); $product_images_model = new shopProductImagesModel(); // stock ids of items ordered by sort $stock_ids = array_keys($stock_model->getAll('id')); // get products $sql = "\n SELECT id, name, count, image_id\n FROM {$this->table}\n WHERE id IN ( {$product_ids_str} )\n ORDER BY count {$order}\n "; $data = array(); $image_ids = array(); foreach ($this->query($sql) as $item) { $data[$item['id']] = array('id' => $item['id'], 'name' => $item['name'], 'url_crop_small' => null, 'count' => $item['count'], 'skus' => array(), 'stocks' => array()); if ($item['image_id'] != null) { $image_ids[] = $item['image_id']; } } if (!$data) { return array(); } $product_ids = array_keys($data); $product_ids_str = implode(',', $product_ids); $images = $product_images_model->getByField('id', $image_ids, 'product_id'); $size = wa()->getConfig()->getImageSize('crop_small'); // get for skus number of stocks in which it presents $sql = "\n SELECT sk.id, COUNT(sk.id) num_of_stocks\n FROM shop_product_skus sk\n JOIN shop_product_stocks st ON sk.id = st.sku_id\n WHERE sk.product_id IN ( {$product_ids_str} )\n GROUP BY sk.id\n "; $num_of_stocks = $this->query($sql)->fetchAll('id', true); // get info about skus and stocks $sql = "SELECT\n sk.product_id,\n sk.id AS sku_id,\n sk.name AS sku_name,\n sk.count,\n\n pst.stock_id,\n pst.count AS stock_count\n FROM shop_product_skus sk\n LEFT JOIN shop_product_stocks pst ON pst.sku_id = sk.id\n WHERE sk.product_id IN ( {$product_ids_str} )\n ORDER BY sk.product_id, sk.count {$order}, sk.id"; $stocks_count = count($stock_ids); // temporary aggragating info about stocks $sku_stocks = array(); if ($stocks_count) { $sku_stocks = array_fill(0, $stocks_count, array()); } $sku_id = 0; $product_id = 0; $p_product = null; foreach ($this->query($sql) as $item) { // another product if ($product_id != $item['product_id']) { $product_id = $item['product_id']; $p_product =& $data[$product_id]; if (isset($images[$product_id])) { $p_product['url_crop_small'] = shopImage::getUrl($images[$product_id], $size); } } // another sku if ($sku_id != $item['sku_id']) { $sku_id = $item['sku_id']; $p_product['skus'][$sku_id] = array('id' => $sku_id, 'name' => $item['sku_name'], 'count' => $item['count'], 'num_of_stocks' => isset($num_of_stocks[$sku_id]) ? $num_of_stocks[$sku_id] : 0); } // aggregate info about stocks if ($item['stock_id'] !== null) { $sku_stocks[$item['stock_id']][$sku_id] = $item['stock_count']; } } // lay out stocks info if (!empty($sku_stocks)) { foreach ($data as &$product) { foreach ($stock_ids as $stock_id) { foreach ($product['skus'] as $sku_id => $sku) { $product['stocks'][$stock_id][$sku_id] = array('id' => $sku_id, 'name' => $sku['name'], 'count' => isset($sku_stocks[$stock_id][$sku_id]) ? $sku_stocks[$stock_id][$sku_id] : null, 'num_of_stocks' => $sku['num_of_stocks']); } } } unset($product); } return $data; }
public function productImgUrl($product, $size) { if (!$product['image_id']) { return ''; } return shopImage::getUrl(array('product_id' => $product['id'], 'id' => $product['image_id'], 'ext' => $product['ext']), $size); }
private function workupItems(&$item, $sku_stocks) { $size = $this->getCropSize(); if (empty($item['image_id'])) { $item['url_crop_small'] = null; } else { $item['url_crop_small'] = shopImage::getUrl(array('id' => $item['image_id'], 'product_id' => $item['id'], 'ext' => $item['ext']), $size); } // aggregated stocks count icon for product if (empty($item['fake'])) { $item['icon'] = shopHelper::getStockCountIcon($item['count'], null, true); } foreach ($item['skus'] as &$sku) { if (empty($sku['fake'])) { // detaled stocks count icon for sku if (empty($sku_stocks[$sku['id']])) { $sku['icon'] = shopHelper::getStockCountIcon($sku['count'], null, true); } else { $icons = array(); foreach ($sku_stocks[$sku['id']] as $stock_id => $stock) { $icon =& $icons[$stock_id]; $icon = shopHelper::getStockCountIcon($stock['count'], $stock_id) . " "; $icon .= $stock['count'] . " "; $icon .= "<span class='small'>@" . htmlspecialchars($stock['name']) . "</span>"; unset($icon); } //$sku['icon'] = implode(', ', $icons); $sku['icon'] = shopHelper::getStockCountIcon($sku['count'], null, true); $sku['icons'] = $icons; } } } unset($sku); }