Esempio n. 1
0
 /**
  * Creates a new product object or a product object corresponding to existing product.
  *
  * @param int|array $data Product id or product data array
  */
 public function __construct($data = array())
 {
     $this->model = new shopProductModel();
     if (is_array($data)) {
         $this->data = $data;
     } elseif ($data) {
         $this->data = $this->model->getById($data);
     }
 }
 public function getProduct($product_id)
 {
     if ($this->product === null) {
         $this->product = $this->product_model->getById($product_id);
         if (!$this->product) {
             throw new waException(_w("Unknown product"), 404);
         }
     }
     return $this->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;
         }
     }
 }
 public function execute()
 {
     $id = waRequest::get('id', null, waRequest::TYPE_INT);
     $product_model = new shopProductModel();
     $product = $product_model->getById($id);
     if (!$product) {
         throw new waException(_w("Unknown product"));
     }
     $service_id = $this->getServiceId();
     $model = $this->getModel();
     $services = $model->getServices($id);
     if ($service_id !== 0) {
         if (!empty($services)) {
             if (!$service_id || !isset($services[$service_id])) {
                 $service = reset($services);
                 $service_id = $service['id'];
             }
         }
     }
     if (!$service_id) {
         $this->assign(array('product' => $product));
         return;
     }
     $this->assign(array('service' => $this->getModel()->getProductServiceFullInfo($product['id'], $service_id), 'product' => $product, 'services' => $services, 'count' => $this->getModel()->countServices($product['id'])));
 }
Esempio n. 5
0
 public static function prepareSkus($skus = array(), $contact_id = null, $currency = null)
 {
     $app_settings_model = new waAppSettingsModel();
     if ($app_settings_model->get(self::$plugin_id, 'status') && shopPrice::getDomainSetting('status')) {
         $category_ids = self::getUserCategoryId($contact_id);
         $domain_hash = shopPrice::getRouteHash();
         $params = array('domain_hash' => $domain_hash, 'category_id' => $category_ids);
         $price_model = new shopPricePluginModel();
         $prices = $price_model->getPriceByParams($params, true);
         if ($prices) {
             foreach ($skus as &$sku) {
                 foreach ($prices as $price) {
                     $price_field = "price_plugin_{$price['id']}";
                     if (!empty($sku[$price_field]) && $sku[$price_field] > 0) {
                         //if (!empty($sku['unconverted_currency']) && !empty($sku['currency'])) {
                         //    $sku['price'] = shop_currency($sku[$price_field], $sku['unconverted_currency'], $sku['currency'], false);
                         //} else {
                         if (!$currency) {
                             $sku['price'] = $sku[$price_field];
                         } else {
                             $product_model = new shopProductModel();
                             $product = $product_model->getById($sku['product_id']);
                             $sku['price'] = shop_currency($sku[$price_field], $product['currency'], $currency, false);
                         }
                         //}
                         break;
                     }
                 }
             }
             unset($sku);
         }
     }
     return $skus;
 }
Esempio n. 6
0
 /**
  * Amount of affiliation points given order worths.
  * @param array|int $order_or_id
  * @param float $credit_rate
  * @return float
  */
 public static function calculateBonus($order_or_id, $credit_rate = null)
 {
     if (!self::isEnabled()) {
         return 0;
     }
     if ($credit_rate === null) {
         $credit_rate = wa()->getSetting('affiliate_credit_rate', 0, 'shop');
     }
     if (!$credit_rate) {
         return 0;
     }
     if (wa_is_int($order_or_id)) {
         $om = new shopOrderModel();
         $order = $om->getOrder($order_or_id);
     } else {
         $order = $order_or_id;
     }
     // Convert order total from order currency to default currency
     $curm = new shopCurrencyModel();
     $order_currency = isset($order['currency']) ? $order['currency'] : null;
     $def_cur = wa('shop')->getConfig()->getCurrency(true);
     $affiliatable_total = $curm->convert($order['total'] - ifset($order['shipping'], 0), ifempty($order_currency, $def_cur), $def_cur);
     $product_types = wa()->getSetting('affiliate_product_types', '', 'shop');
     if (!empty($product_types)) {
         //
         // When affiliation program is enabled for certain product types only,
         // we need to calculate total afiliatable amount from order items.
         //
         $product_types = array_fill_keys(explode(',', $product_types), true);
         // Make sure order data contains items
         if (empty($order['items']) && !empty($order['id'])) {
             $oim = new shopOrderItemsModel();
             $order['items'] = $oim->getItems($order['id']);
         }
         if (empty($order['items']) || !is_array($order['items'])) {
             return 0;
         }
         // Fetch product info
         $product_ids = array();
         foreach ($order['items'] as $i) {
             $product_ids[$i['product_id']] = true;
         }
         $pm = new shopProductModel();
         $products = $pm->getById(array_keys($product_ids));
         // Calculate total value of affiliatable order items
         $items_total = 0;
         foreach ($order['items'] as $i) {
             $p = $products[$i['product_id']];
             $type_id = $p['type_id'];
             if ($i['type'] == 'product' && $type_id && !empty($product_types[$type_id])) {
                 $items_total += $curm->convert($i['price'] * $i['quantity'], ifempty($p['currency'], $def_cur), $def_cur);
             }
         }
         if ($affiliatable_total > $items_total) {
             $affiliatable_total = $items_total;
         }
     }
     return $affiliatable_total / $credit_rate;
 }
 protected function getProduct($id)
 {
     $product_model = new shopProductModel();
     $product = $product_model->getById($id);
     if (!$product) {
         throw new waAPIException('invalid_param', 'Product not found', 404);
     }
     $this->checkRights($product['type_id']);
     return $product;
 }
 public function execute()
 {
     // get id of product and check existing
     $id = waRequest::get('id', null, waRequest::TYPE_INT);
     $product_model = new shopProductModel();
     $product = $product_model->getById($id);
     if (!$product) {
         throw new waException(_w("Unkown product"));
     }
     $this->product_id = $id;
     parent::execute();
 }
 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()
 {
     $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);
     }
     $product_pages_model = new shopProductPagesModel();
     $this->response = $product_pages_model->getByProductId($product_id);
     $this->response['_element'] = 'page';
 }
 public function checkProductRights($product_id)
 {
     $product_model = new shopProductModel();
     $product = $product_model->getById($product_id);
     if (!$product) {
         throw new waAPIException('invalid_param', 'Product not found', 404);
     }
     if (!$this->getRights('type.all') || !$this->getRights('type.' . $product['type_id'])) {
         throw new waAPIException('access_denied', 500);
     }
     return true;
 }
 public function execute()
 {
     $product_id = waRequest::get('product_id', null, waRequest::TYPE_INT);
     $product_model = new shopProductModel();
     $product = $product_model->getById($product_id);
     if (!$product) {
         throw new waException(_w("Unknown product"), 404);
     }
     $id = waRequest::get('id', null, waRequest::TYPE_INT);
     $page = $this->getPage($id);
     $url = rtrim(wa()->getRouteUrl('/frontend/productPage', array('product_url' => $product['url'], 'page_url' => ''), true), '/');
     $this->view->assign(array('url' => $url, 'preview_hash' => $this->getPreviewHash(), 'page' => $page, 'lang' => substr(wa()->getLocale(), 0, 2), 'product_id' => $product_id));
 }
 public function execute()
 {
     $product_model = new shopProductModel();
     $id = waRequest::get('id', null, waRequest::TYPE_INT);
     $product = $product_model->getById($id);
     if (!$product) {
         $this->errors[] = _w("Unknown product");
         return;
     }
     if (!$product_model->checkRights($product)) {
         throw new waException(_w("Access denied"));
     }
     $product_model->updateById($id, array('badge' => null));
 }
 public function getServices($product_id, $sku_id)
 {
     $product_model = new shopProductModel();
     $product = $product_model->getById($product_id);
     $type_service_model = new shopTypeServicesModel();
     $service_ids = $type_service_model->getServiceIds($product['type_id']);
     $sql = "SELECT v.*, ps.price p_price, ps.status, ps.sku_id, s.currency FROM shop_service_variants v\n                LEFT JOIN shop_product_services ps ON v.id = ps.service_variant_id AND ps.product_id = i:product_id\n                JOIN shop_service s ON v.service_id = s.id\n                WHERE " . ($service_ids ? "v.service_id IN (i:service_ids) OR " : '') . "\n                ps.product_id = i:product_id OR ps.sku_id = i:sku_id\n                ORDER BY ps.sku_id";
     $product_services_model = new shopProductServicesModel();
     $rows = $product_services_model->query($sql, array('service_ids' => $service_ids, 'product_id' => $product_id, 'sku_id' => $sku_id))->fetchAll();
     $services = array();
     foreach ($rows as $row) {
         $services[$row['service_id']][$row['id']] = array('name' => $row['name'], 'price' => $row['p_price'] ? $row['p_price'] : $row['price'], 'currency' => $row['currency']);
     }
     return $services;
 }
 public function execute()
 {
     $id = waRequest::get('id', null, waRequest::TYPE_INT);
     $product_model = new shopProductModel();
     $product = $product_model->getById($id);
     if (!$product) {
         throw new waException(_w("Unkown product"));
     }
     $offset = waRequest::get('offset', 0, waRequest::TYPE_INT);
     $total_count = waRequest::get('total_count', null, waRequest::TYPE_INT);
     $lazy = waRequest::get('lazy');
     $order = waRequest::get('order', 'default', waRequest::TYPE_STRING_TRIM);
     $order = isset($this->orders[$order]) ? $order : 'default';
     $product_reviews_model = new shopProductReviewsModel();
     $reviews = $product_reviews_model->getFullTree($id, $offset, $this->getConfig()->getOption('reviews_per_page_product'), $this->orders[$order], array('is_new' => true));
     $this->view->assign(array('product' => $product, 'reviews' => $reviews, 'offset' => $offset, 'total_count' => $total_count ? $total_count : $product_reviews_model->count($id), 'reply_allowed' => true, 'lazy' => $lazy, 'current_author' => shopProductReviewsModel::getAuthorInfo(wa()->getUser()->getId()), 'count' => count($reviews), 'id' => $id, 'order' => $order, 'sidebar_counters' => array('new' => $product_reviews_model->countNew())));
 }
 public function execute()
 {
     $product_id = $this->get('product_id');
     $product_model = new shopProductModel();
     $product = $product_model->getById($product_id);
     if (!$product) {
         throw new waAPIException('invalid_param', 'Product not found', 404);
     }
     $skus_model = new shopProductSkusModel();
     $skus = $skus_model->getData(new shopProduct($product));
     foreach ($skus as &$sku) {
         $sku['currency'] = $product['currency'];
         $sku['primary_price'] = (double) $sku['primary_price'];
     }
     unset($sku);
     $this->response = array_values($skus);
     $this->response['_element'] = 'sku';
 }
 public function execute()
 {
     $product_model = new shopProductModel();
     $id = waRequest::get('id', null, waRequest::TYPE_INT);
     $product = $product_model->getById($id);
     if (!$product) {
         throw new waException(_w("Unknown product"));
     }
     if (!$product_model->checkRights($product)) {
         throw new waException(_w("Access denied"));
     }
     $code = waRequest::post('code', null, waRequest::TYPE_STRING_TRIM);
     if (!$code) {
         throw new waException(_w("Empty code"));
     }
     $product_model->updateById($id, array('badge' => $code));
     $badges = shopProductModel::badges();
     $this->response = isset($badges[$code]) ? $badges[$code]['code'] : $code;
 }
 public function execute()
 {
     $sku_id = waRequest::post('sku_id', 0, waRequest::TYPE_INT);
     if (!$sku_id) {
         $this->setError(_w("Error when delete: unknown sku"));
     }
     $product_id = waRequest::post('product_id', 0, waRequest::TYPE_INT);
     if (!$product_id) {
         $this->setError(_w("Error when delete: unknown product"));
     }
     $product_skus_model = new shopProductSkusModel();
     if (!$product_skus_model->delete($sku_id)) {
         $this->setError(_w("Error when delete"));
     }
     $product_model = new shopProductModel();
     $product = $product_model->getById($product_id);
     if (!$product) {
         $this->setError(_w("Error when delete"));
     }
     $this->response = $product;
 }
 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);
     }
     $parent_id = waRequest::get('parent_id');
     $reviews_model = new shopProductReviewsModel();
     $reviews = $reviews_model->getTree($parent_id, waRequest::get('depth', null, 'int'), 'product_id = ' . (int) $product_id);
     $stack = array();
     $result = array();
     foreach ($reviews as $r) {
         $r['comments'] = array();
         // Number of stack items
         $l = count($stack);
         // Check if we're dealing with different levels
         while ($l > 0 && $stack[$l - 1]['depth'] >= $r['depth']) {
             array_pop($stack);
             $l--;
         }
         // Stack is empty (we are inspecting the root)
         if ($l == 0) {
             // Assigning the root node
             $i = count($result);
             $result[$i] = $r;
             $stack[] =& $result[$i];
         } else {
             // Add node to parent
             $i = count($stack[$l - 1]['comments']);
             $stack[$l - 1]['comments'][$i] = $r;
             $stack[] =& $stack[$l - 1]['comments'][$i];
         }
     }
     $this->response = $result;
     $this->response['_element'] = 'review';
 }
Esempio n. 20
0
 private function recalcProductRating($product_id, $rate, $inc = true)
 {
     if ($rate <= 0) {
         return;
     }
     $product_model = new shopProductModel();
     $product = $product_model->getById($product_id);
     if ($inc) {
         $update = array('rating' => ($product['rating'] * $product['rating_count'] + $rate) / ($product['rating_count'] + 1), 'rating_count' => $product['rating_count'] + 1);
     } else {
         $update = array('rating' => ($product['rating'] * $product['rating_count'] - $rate) / ($product['rating_count'] - 1), 'rating_count' => $product['rating_count'] - 1);
     }
     $product_model->updateById($product_id, $update);
 }
Esempio n. 21
0
 public function setData(shopProduct $product, $data)
 {
     $primary_currency = wa()->getConfig()->getCurrency();
     $sort = 0;
     $default_sku_id = null;
     $result = array();
     foreach ($data as $sku_id => $sku) {
         $sku['sort'] = ++$sort;
         if (empty($sku['available'])) {
             $sku['available'] = 0;
         }
         if (isset($sku['price'])) {
             if ($product->currency == $primary_currency) {
                 $sku['primary_price'] = $sku['price'];
             } else {
                 $sku['primary_price'] = $this->convertPrice($sku['price'], $product->currency);
             }
         }
         $sku['product_id'] = $product->id;
         $sku = $this->updateSku($sku_id > 0 ? $sku_id : 0, $sku, false, $product);
         $result[$sku['id']] = $sku;
         if (!empty($sku['features'])) {
             foreach ($sku['features'] as $code => $value) {
                 if (!isset($features)) {
                     $features = $product->features;
                 }
                 if (!isset($features[$code])) {
                     $features[$code] = array();
                 }
                 if (is_array($features[$code])) {
                     if (is_array($value)) {
                         if (isset($value['id'])) {
                             if (!isset($features[$code][$value['id']])) {
                                 $features[$code][$value['id']] = $value['value'];
                             }
                         }
                     } else {
                         $features[$code][] = $value;
                     }
                 }
             }
         }
         if ($product->sku_id == $sku_id) {
             $default_sku_id = $sku['id'];
         }
     }
     $model = new shopProductModel();
     if ($default_sku_id === null && $result) {
         $default_sku_id = current(array_keys($result));
     }
     $model->updateById($product->id, array('sku_id' => $default_sku_id));
     $model->correct($product->id);
     $product_data = $model->getById($product->id);
     $product->min_price = $product_data['min_price'];
     $product->max_price = $product_data['max_price'];
     $product->price = $product_data['price'];
     $product->compare_price = $product_data['compare_price'];
     $product->count = $product_data['count'];
     $product->sku_count = count($data);
     $product->sku_id = $default_sku_id;
     if (isset($features)) {
         $product->features = $features;
     }
     return $result;
 }
Esempio n. 22
0
 public function execute()
 {
     $this->getResponse()->addHeader("Cache-Control", "no-store, no-cache, must-revalidate");
     $this->getResponse()->addHeader("Expires", date("r"));
     if (waRequest::method() == 'post') {
         $data = wa()->getStorage()->get('shop/checkout', array());
         if ($coupon_code = waRequest::post('coupon_code')) {
             $data['coupon_code'] = $coupon_code;
         } elseif (isset($data['coupon_code'])) {
             unset($data['coupon_code']);
         }
         if (($use = waRequest::post('use_affiliate')) !== null) {
             if ($use) {
                 $data['use_affiliate'] = 1;
             } elseif (isset($data['use_affiliate'])) {
                 unset($data['use_affiliate']);
             }
         }
         if ($coupon_code || $use) {
             wa()->getStorage()->set('shop/checkout', $data);
             wa()->getStorage()->remove('shop/cart');
         }
     }
     $cart_model = new shopCartItemsModel();
     $cart = new shopCart();
     $code = $cart->getCode();
     $errors = array();
     if (waRequest::post('checkout')) {
         $saved_quantity = $cart_model->select('id,quantity')->where("type='product' AND code = s:code", array('code' => $code))->fetchAll('id');
         $quantity = waRequest::post('quantity');
         foreach ($quantity as $id => $q) {
             if ($q != $saved_quantity[$id]) {
                 $cart->setQuantity($id, $q);
             }
         }
         $not_available_items = $cart_model->getNotAvailableProducts($code, !wa()->getSetting('ignore_stock_count'));
         foreach ($not_available_items as $row) {
             if ($row['sku_name']) {
                 $row['name'] .= ' (' . $row['sku_name'] . ')';
             }
             if ($row['available']) {
                 $errors[$row['id']] = sprintf(_w('Only %d pcs of %s are available, and you already have all of them in your shopping cart.'), $row['count'], $row['name']);
             } else {
                 $errors[$row['id']] = _w('Oops! %s is not available for purchase at the moment. Please remove this product from your shopping cart to proceed.');
             }
         }
         if (!$errors) {
             $this->redirect(wa()->getRouteUrl('/frontend/checkout'));
         }
     }
     $this->setThemeTemplate('cart.html');
     $items = $cart_model->where('code= ?', $code)->order('parent_id')->fetchAll('id');
     $product_ids = $sku_ids = $service_ids = $type_ids = array();
     foreach ($items as $item) {
         $product_ids[] = $item['product_id'];
         $sku_ids[] = $item['sku_id'];
     }
     $product_ids = array_unique($product_ids);
     $sku_ids = array_unique($sku_ids);
     $product_model = new shopProductModel();
     if (waRequest::param('url_type') == 2) {
         $products = $product_model->getWithCategoryUrl($product_ids);
     } else {
         $products = $product_model->getById($product_ids);
     }
     $sku_model = new shopProductSkusModel();
     $skus = $sku_model->getByField('id', $sku_ids, 'id');
     $image_model = new shopProductImagesModel();
     $delete_items = array();
     foreach ($items as $item_id => &$item) {
         if (!isset($skus[$item['sku_id']])) {
             unset($items[$item_id]);
             $delete_items[] = $item_id;
             continue;
         }
         if ($item['type'] == 'product') {
             $item['product'] = $products[$item['product_id']];
             $sku = $skus[$item['sku_id']];
             if ($sku['image_id'] && $sku['image_id'] != $item['product']['image_id']) {
                 $img = $image_model->getById($sku['image_id']);
                 if ($img) {
                     $item['product']['image_id'] = $sku['image_id'];
                     $item['product']['ext'] = $img['ext'];
                 }
             }
             $item['sku_name'] = $sku['name'];
             $item['sku_code'] = $sku['sku'];
             $item['price'] = $sku['price'];
             $item['compare_price'] = $sku['compare_price'];
             $item['currency'] = $item['product']['currency'];
             $type_ids[] = $item['product']['type_id'];
             if (isset($errors[$item_id])) {
                 $item['error'] = $errors[$item_id];
                 if (strpos($item['error'], '%s') !== false) {
                     $item['error'] = sprintf($item['error'], $item['product']['name'] . ($item['sku_name'] ? ' (' . $item['sku_name'] . ')' : ''));
                 }
             }
         }
     }
     unset($item);
     if ($delete_items) {
         $cart_model->deleteByField(array('code' => $code, 'id' => $delete_items));
     }
     $type_ids = array_unique($type_ids);
     // get available services for all types of products
     $type_services_model = new shopTypeServicesModel();
     $rows = $type_services_model->getByField('type_id', $type_ids, true);
     $type_services = array();
     foreach ($rows as $row) {
         $service_ids[] = $row['service_id'];
         $type_services[$row['type_id']][$row['service_id']] = true;
     }
     // get services for all products
     $product_services_model = new shopProductServicesModel();
     $rows = $product_services_model->getByProducts($product_ids);
     $product_services = $sku_services = array();
     foreach ($rows as $row) {
         if ($row['sku_id'] && !in_array($row['sku_id'], $sku_ids)) {
             continue;
         }
         $service_ids[] = $row['service_id'];
         if (!$row['sku_id']) {
             $product_services[$row['product_id']][$row['service_id']]['variants'][$row['service_variant_id']] = $row;
         }
         if ($row['sku_id']) {
             $sku_services[$row['sku_id']][$row['service_id']]['variants'][$row['service_variant_id']] = $row;
         }
     }
     $service_ids = array_unique($service_ids);
     $service_model = new shopServiceModel();
     $variant_model = new shopServiceVariantsModel();
     $services = $service_model->getByField('id', $service_ids, 'id');
     foreach ($services as &$s) {
         unset($s['id']);
     }
     unset($s);
     $rows = $variant_model->getByField('service_id', $service_ids, true);
     foreach ($rows as $row) {
         $services[$row['service_id']]['variants'][$row['id']] = $row;
         unset($services[$row['service_id']]['variants'][$row['id']]['id']);
     }
     foreach ($items as $item_id => $item) {
         if ($item['type'] == 'product') {
             $p = $item['product'];
             $item_services = array();
             // services from type settings
             if (isset($type_services[$p['type_id']])) {
                 foreach ($type_services[$p['type_id']] as $service_id => &$s) {
                     $item_services[$service_id] = $services[$service_id];
                 }
             }
             // services from product settings
             if (isset($product_services[$item['product_id']])) {
                 foreach ($product_services[$item['product_id']] as $service_id => $s) {
                     if (!isset($s['status']) || $s['status']) {
                         if (!isset($item_services[$service_id])) {
                             $item_services[$service_id] = $services[$service_id];
                         }
                         // update variants
                         foreach ($s['variants'] as $variant_id => $v) {
                             if ($v['status']) {
                                 if ($v['price'] !== null) {
                                     $item_services[$service_id]['variants'][$variant_id]['price'] = $v['price'];
                                 }
                             } else {
                                 unset($item_services[$service_id]['variants'][$variant_id]);
                             }
                         }
                     } elseif (isset($item_services[$service_id])) {
                         // remove disabled service
                         unset($item_services[$service_id]);
                     }
                 }
             }
             // services from sku settings
             if (isset($sku_services[$item['sku_id']])) {
                 foreach ($sku_services[$item['sku_id']] as $service_id => $s) {
                     if (!isset($s['status']) || $s['status']) {
                         // update variants
                         foreach ($s['variants'] as $variant_id => $v) {
                             if ($v['status']) {
                                 if ($v['price'] !== null) {
                                     $item_services[$service_id]['variants'][$variant_id]['price'] = $v['price'];
                                 }
                             } else {
                                 unset($item_services[$service_id]['variants'][$variant_id]);
                             }
                         }
                     } elseif (isset($item_services[$service_id])) {
                         // remove disabled service
                         unset($item_services[$service_id]);
                     }
                 }
             }
             foreach ($item_services as $s_id => &$s) {
                 if (!$s['variants']) {
                     unset($item_services[$s_id]);
                     continue;
                 }
                 if ($s['currency'] == '%') {
                     foreach ($s['variants'] as $v_id => $v) {
                         $s['variants'][$v_id]['price'] = $v['price'] * $item['price'] / 100;
                     }
                     $s['currency'] = $item['currency'];
                 }
                 if (count($s['variants']) == 1) {
                     $v = reset($s['variants']);
                     $s['price'] = $v['price'];
                     unset($s['variants']);
                 }
             }
             unset($s);
             uasort($item_services, array('shopServiceModel', 'sortServices'));
             $items[$item_id]['services'] = $item_services;
         } else {
             $items[$item['parent_id']]['services'][$item['service_id']]['id'] = $item['id'];
             if (isset($item['service_variant_id'])) {
                 $items[$item['parent_id']]['services'][$item['service_id']]['variant_id'] = $item['service_variant_id'];
             }
             unset($items[$item_id]);
         }
     }
     foreach ($items as $item_id => $item) {
         $price = shop_currency($item['price'] * $item['quantity'], $item['currency'], null, false);
         if (isset($item['services'])) {
             foreach ($item['services'] as $s) {
                 if (!empty($s['id'])) {
                     if (isset($s['variants'])) {
                         $price += shop_currency($s['variants'][$s['variant_id']]['price'] * $item['quantity'], $s['currency'], null, false);
                     } else {
                         $price += shop_currency($s['price'] * $item['quantity'], $s['currency'], null, false);
                     }
                 }
             }
         }
         $items[$item_id]['full_price'] = $price;
     }
     $total = $cart->total(false);
     $order = array('total' => $total, 'items' => $items);
     $order['discount'] = $discount = shopDiscounts::calculate($order);
     $order['total'] = $total = $total - $order['discount'];
     $data = wa()->getStorage()->get('shop/checkout');
     $this->view->assign('cart', array('items' => $items, 'total' => $total, 'count' => $cart->count()));
     $this->view->assign('coupon_code', isset($data['coupon_code']) ? $data['coupon_code'] : '');
     if (shopAffiliate::isEnabled()) {
         $affiliate_bonus = 0;
         if ($this->getUser()->isAuth()) {
             $customer_model = new shopCustomerModel();
             $customer = $customer_model->getById($this->getUser()->getId());
             $affiliate_bonus = $customer ? round($customer['affiliate_bonus'], 2) : 0;
         }
         $this->view->assign('affiliate_bonus', $affiliate_bonus);
         $use = !empty($data['use_affiliate']);
         $this->view->assign('use_affiliate', $use);
         if ($use) {
             $discount -= shop_currency(shopAffiliate::convertBonus($order['params']['affiliate_bonus']), $this->getConfig()->getCurrency(true), null, false);
             $this->view->assign('used_affiliate_bonus', $order['params']['affiliate_bonus']);
         }
         $order['currency'] = $this->getConfig()->getCurrency(false);
         $add_affiliate_bonus = shopAffiliate::calculateBonus($order);
         $this->view->assign('add_affiliate_bonus', round($add_affiliate_bonus, 2));
     }
     $this->view->assign('discount', $discount);
     /**
      * @event frontend_cart
      * @return array[string]string $return[%plugin_id%] html output
      */
     $this->view->assign('frontend_cart', wa()->event('frontend_cart'));
     $this->getResponse()->setTitle(_w('Cart'));
     $checkout_flow = new shopCheckoutFlowModel();
     $checkout_flow->add(array('code' => $code, 'step' => 0, 'description' => null));
 }
 public function execute($data = null)
 {
     $order_model = new shopOrderModel();
     $order = $order_model->getById($data['id']);
     $subtotal = 0;
     $services = $products = array();
     foreach ($data['items'] as $item) {
         if ($item['service_id']) {
             $services[] = $item['service_id'];
         } else {
             $products[] = $item['product_id'];
         }
     }
     $service_model = new shopServiceModel();
     $product_model = new shopProductModel();
     $services = $service_model->getById($services);
     $products = $product_model->getById($products);
     foreach ($data['items'] as &$item) {
         $item['currency'] = $order['currency'];
         $item['price'] = $this->price($item['price']);
         if ($item['service_id']) {
             $item['service'] = $services[$item['service_id']];
         } else {
             $item['product'] = $products[$item['product_id']];
         }
         $subtotal += $item['price'] * $item['quantity'];
     }
     unset($item);
     foreach (array('shipping', 'discount') as $k) {
         if (!isset($data[$k])) {
             $data[$k] = 0;
         }
     }
     $contact = new waContact($order['contact_id']);
     $shipping_address = $contact->getFirst('address.shipping');
     if (!$shipping_address) {
         $shipping_address = $contact->getFirst('address');
     }
     $shipping_address = $shipping_address ? $shipping_address['data'] : array();
     $billing_address = $contact->getFirst('address.billing');
     if (!$billing_address) {
         $billing_address = $contact->getFirst('address');
     }
     $billing_address = $billing_address ? $billing_address['data'] : array();
     $discount_rate = $subtotal ? $data['discount'] / $subtotal : 0;
     $taxes = shopTaxes::apply($data['items'], array('shipping' => $shipping_address, 'billing' => $billing_address, 'discount_rate' => $discount_rate), $order['currency']);
     $tax = $tax_included = 0;
     foreach ($taxes as $t) {
         if (isset($t['sum'])) {
             $tax += $t['sum'];
         }
         if (isset($t['sum_included'])) {
             $tax_included += $t['sum_included'];
         }
     }
     $data['tax'] = $tax_included + $tax;
     $data['total'] = $subtotal + $tax + $this->price($data['shipping']) - $this->price($data['discount']);
     // for logging changes in stocks
     shopProductStocksLogModel::setContext(shopProductStocksLogModel::TYPE_ORDER, 'Order %s was edited', array('order_id' => $data['id']));
     // update
     $order_model->update($data, $data['id']);
     $log_model = new waLogModel();
     $log_model->add('order_edit', $data['id']);
     shopProductStocksLogModel::clearContext();
     if (!empty($data['params'])) {
         $params_model = new shopOrderParamsModel();
         $params_model->set($data['id'], $data['params'], false);
     }
     return true;
 }
 public static function checkCart(&$cart = null)
 {
     $error = false;
     $cart = new shopCart();
     $code = $cart->getCode();
     $view = wa()->getView();
     if (!wa()->getSetting('ignore_stock_count')) {
         $cart_model = new shopCartItemsModel();
         $sku_model = new shopProductSkusModel();
         $product_model = new shopProductModel();
         $items = $cart->items(false);
         foreach ($items as &$item) {
             if (!isset($item['product_id'])) {
                 $sku = $sku_model->getById($item['sku_id']);
                 $product = $product_model->getById($sku['product_id']);
             } else {
                 $product = $product_model->getById($item['product_id']);
                 if (isset($item['sku_id'])) {
                     $sku = $sku_model->getById($item['sku_id']);
                 } else {
                     if (isset($item['features'])) {
                         $product_features_model = new shopProductFeaturesModel();
                         $sku_id = $product_features_model->getSkuByFeatures($product['id'], $item['features']);
                         if ($sku_id) {
                             $sku = $sku_model->getById($sku_id);
                         } else {
                             $sku = null;
                         }
                     } else {
                         $sku = $sku_model->getById($product['sku_id']);
                         if (!$sku['available']) {
                             $sku = $sku_model->getByField(array('product_id' => $product['id'], 'available' => 1));
                         }
                         if (!$sku) {
                             $item['error'] = _w('This product is not available for purchase');
                             $error = true;
                         }
                     }
                 }
             }
             $quantity = $item['quantity'];
             $c = $cart_model->countSku($code, $sku['id']);
             if ($sku['count'] !== null && $c + $quantity > $sku['count']) {
                 $quantity = $sku['count'] - $c;
                 $name = $product['name'] . ($sku['name'] ? ' (' . $sku['name'] . ')' : '');
                 if ($quantity < 0) {
                     $item['error'] = sprintf(_w('Only %d pcs of %s are available, and you already have all of them in your shopping cart.'), $sku['count'], $name);
                     $error = true;
                 }
             }
         }
         unset($item);
         foreach ($items as $item_id => $item) {
             $price = shop_currency($item['price'] * $item['quantity'], $item['currency'], null, false);
             if (isset($item['services'])) {
                 foreach ($item['services'] as $s) {
                     if (!empty($s['id'])) {
                         if (isset($s['variants'])) {
                             $price += shop_currency($s['variants'][$s['variant_id']]['price'] * $item['quantity'], $s['currency'], null, false);
                         } else {
                             $price += shop_currency($s['price'] * $item['quantity'], $s['currency'], null, false);
                         }
                     }
                 }
             }
             $items[$item_id]['full_price'] = $price;
         }
         $cart = array('items' => $items, 'total' => $cart->total(false), 'count' => $cart->count());
     }
     return $error;
 }
 public function execute()
 {
     $code = waRequest::cookie('shop_cart');
     if (!$code) {
         $code = md5(uniqid(time(), true));
         // header for IE
         wa()->getResponse()->addHeader('P3P', 'CP="NOI ADM DEV COM NAV OUR STP"');
         // set cart cookie
         wa()->getResponse()->setCookie('shop_cart', $code, time() + 30 * 86400, null, '', false, true);
     }
     $this->cart = new shopCart($code);
     $this->cart_model = new shopCartItemsModel();
     $data = waRequest::post();
     $this->is_html = waRequest::request('html');
     // add service
     if (isset($data['parent_id'])) {
         $this->addService($data);
         return;
     }
     // add sku
     $sku_model = new shopProductSkusModel();
     $product_model = new shopProductModel();
     if (!isset($data['product_id'])) {
         $sku = $sku_model->getById($data['sku_id']);
         $product = $product_model->getById($sku['product_id']);
     } else {
         $product = $product_model->getById($data['product_id']);
         if (isset($data['sku_id'])) {
             $sku = $sku_model->getById($data['sku_id']);
         } else {
             if (isset($data['features'])) {
                 $product_features_model = new shopProductFeaturesModel();
                 $sku_id = $product_features_model->getSkuByFeatures($product['id'], $data['features']);
                 if ($sku_id) {
                     $sku = $sku_model->getById($sku_id);
                 } else {
                     $sku = null;
                 }
             } else {
                 $sku = $sku_model->getById($product['sku_id']);
                 if (!$sku['available']) {
                     $sku = $sku_model->getByField(array('product_id' => $product['id'], 'available' => 1));
                 }
                 if (!$sku) {
                     $this->errors = _w('This product is not available for purchase');
                     return;
                 }
             }
         }
     }
     $quantity = waRequest::post('quantity', 1);
     if ($product && $sku) {
         // check quantity
         if (!wa()->getSetting('ignore_stock_count')) {
             $c = $this->cart_model->countSku($code, $sku['id']);
             if ($sku['count'] !== null && $c + $quantity > $sku['count']) {
                 $quantity = $sku['count'] - $c;
                 $name = $product['name'] . ($sku['name'] ? ' (' . $sku['name'] . ')' : '');
                 if (!$quantity) {
                     $this->errors = sprintf(_w('Only %d pcs of %s are available, and you already have all of them in your shopping cart.'), $sku['count'], $name);
                     return;
                 } else {
                     $this->response['error'] = sprintf(_w('Only %d pcs of %s are available, and you already have all of them in your shopping cart.'), $sku['count'], $name);
                 }
             }
         }
         $services = waRequest::post('services', array());
         if ($services) {
             $variants = waRequest::post('service_variant');
             $temp = array();
             $service_ids = array();
             foreach ($services as $service_id) {
                 if (isset($variants[$service_id])) {
                     $temp[$service_id] = $variants[$service_id];
                 } else {
                     $service_ids[] = $service_id;
                 }
             }
             if ($service_ids) {
                 $service_model = new shopServiceModel();
                 $temp_services = $service_model->getById($service_ids);
                 foreach ($temp_services as $row) {
                     $temp[$row['id']] = $row['variant_id'];
                 }
             }
             $services = $temp;
         }
         $item_id = null;
         $item = $this->cart_model->getItemByProductAndServices($code, $product['id'], $sku['id'], $services);
         if ($item) {
             $item_id = $item['id'];
             $this->cart->setQuantity($item_id, $item['quantity'] + $quantity);
         }
         if (!$item_id) {
             $data = array('create_datetime' => date('Y-m-d H:i:s'), 'product_id' => $product['id'], 'sku_id' => $sku['id'], 'quantity' => $quantity, 'type' => 'product');
             if ($services) {
                 $data_services = array();
                 foreach ($services as $service_id => $variant_id) {
                     $data_services[] = array('service_id' => $service_id, 'service_variant_id' => $variant_id);
                 }
             } else {
                 $data_services = array();
             }
             $item_id = $this->cart->addItem($data, $data_services);
         }
         if (waRequest::isXMLHttpRequest()) {
             $this->response['item_id'] = $item_id;
             $this->response['total'] = $this->currencyFormat($this->cart->total());
             $this->response['discount'] = $this->currencyFormat($this->cart->discount());
             $this->response['count'] = $this->cart->count();
         } else {
             $this->redirect(waRequest::server('HTTP_REFERER'));
         }
     } else {
         throw new waException('product not found');
     }
 }