/** * Receives a notification from a publisher object * * @param \Aimeos\MW\Observer\Publisher\Iface $order Shop basket instance implementing publisher interface * @param string $action Name of the action to listen for * @param mixed $value Object or value changed in publisher * @throws \Aimeos\MShop\Plugin\Provider\Exception if checks fail * @return bool true if checks succeed */ public function update(\Aimeos\MW\Observer\Publisher\Iface $order, $action, $value = null) { if (!$order instanceof \Aimeos\MShop\Order\Item\Base\Iface) { $msg = $this->getContext()->getI18n()->dt('mshop', 'Object is not of required type "%1$s"'); throw new \Aimeos\MShop\Plugin\Exception(sprintf($msg, '\\Aimeos\\MShop\\Order\\Item\\Base\\Iface')); } if ($value & \Aimeos\MShop\Order\Item\Base\Base::PARTS_ADDRESS) { $problems = array(); $availableAddresses = $order->getAddresses(); foreach ($this->getItemBase()->getConfig() as $type => $value) { if ($value == true && !isset($availableAddresses[$type])) { $problems[$type] = 'available.none'; } if ($value !== null && $value !== '' && $value == false && isset($availableAddresses[$type])) { $problems[$type] = 'available.notallowed'; } } if (count($problems) > 0) { $code = array('address' => $problems); $msg = $this->getContext()->getI18n()->dt('mshop', 'Checks for available addresses in basket failed'); throw new \Aimeos\MShop\Plugin\Provider\Exception($msg, -1, null, $code); } } return true; }
/** * Receives a notification from a publisher object * * @param \Aimeos\MW\Observer\Publisher\Iface $order Shop basket instance implementing publisher interface * @param string $action Name of the action to listen for * @param mixed $value Object or value changed in publisher * @throws \Aimeos\MShop\Plugin\Provider\Exception if an error occurs * @return bool true if subsequent plugins should be processed */ public function update(\Aimeos\MW\Observer\Publisher\Iface $order, $action, $value = null) { if (!$order instanceof \Aimeos\MShop\Order\Item\Base\Iface) { $msg = $this->getContext()->getI18n()->dt('mshop', 'Object is not of required type "%1$s"'); throw new \Aimeos\MShop\Plugin\Exception(sprintf($msg, '\\Aimeos\\MShop\\Order\\Item\\Base\\Iface')); } $context = $this->getContext(); $services = $order->getServices(); $addresses = $order->getAddresses(); if (($userid = $context->getUserId()) !== null && (bool) $this->getConfigValue('autofill.useorder', false) === true && (empty($addresses) || empty($services))) { $orderManager = \Aimeos\MShop\Factory::createManager($context, 'order'); $search = $orderManager->createSearch(); $search->setConditions($search->compare('==', 'order.base.customerid', $userid)); $search->setSortations(array($search->sort('-', 'order.ctime'))); $search->setSlice(0, 1); $result = $orderManager->searchItems($search); if (($item = reset($result)) !== false) { $this->setAddresses($order, $item); $this->setServices($order, $item); } } $this->setAddressDefault($order); $this->setServicesDefault($order); return true; }
/** * Receives a notification from a publisher object * * @param \Aimeos\MW\Observer\Publisher\Iface $order Shop basket instance implementing publisher interface * @param string $action Name of the action to listen for * @param mixed $value Object or value changed in publisher */ public function update(\Aimeos\MW\Observer\Publisher\Iface $order, $action, $value = null) { if (!$order instanceof \Aimeos\MShop\Order\Item\Base\Iface) { $msg = $this->getContext()->getI18n()->dt('mshop', 'Object is not of required type "%1$s"'); throw new \Aimeos\MShop\Plugin\Exception(sprintf($msg, '\\Aimeos\\MShop\\Order\\Item\\Base\\Iface')); } $notAvailable = array(); if (self::$lock === false) { self::$lock = true; $couponManager = \Aimeos\MShop\Factory::createManager($this->getContext(), 'coupon'); foreach ($order->getCoupons() as $code => $products) { $search = $couponManager->createSearch(true); $expr = array($search->compare('==', 'coupon.code.code', $code), $search->getConditions()); $search->setConditions($search->combine('&&', $expr)); $search->setSlice(0, 1); $results = $couponManager->searchItems($search); if (($couponItem = reset($results)) !== false) { $couponProvider = $couponManager->getProvider($couponItem, $code); $couponProvider->updateCoupon($order); } else { $notAvailable[$code] = 'coupon.gone'; } } self::$lock = false; } if (count($notAvailable) > 0) { $codes = array('coupon' => $notAvailable); $msg = $this->getContext()->getI18n()->dt('mshop', 'Coupon in basket is not available any more'); throw new \Aimeos\MShop\Plugin\Provider\Exception($msg, -1, null, $codes); } return true; }
/** * Receives a notification from a publisher object * * @param \Aimeos\MW\Observer\Publisher\Iface $order Shop basket instance implementing publisher interface * @param string $action Name of the action to listen for * @param mixed $value Object or value changed in publisher * @throws \Aimeos\MShop\Plugin\Provider\Exception if checks fail * @return bool true if checks succeed */ public function update(\Aimeos\MW\Observer\Publisher\Iface $order, $action, $value = null) { $class = '\\Aimeos\\MShop\\Order\\Item\\Base\\Iface'; if (!$order instanceof $class) { throw new \Aimeos\MShop\Plugin\Order\Exception(sprintf('Object is not of required type "%1$s"', $class)); } if (!($value & \Aimeos\MShop\Order\Item\Base\Base::PARTS_PRODUCT)) { return true; } $attrIds = $prodCodes = $changedProducts = array(); $orderProducts = $order->getProducts(); foreach ($orderProducts as $pos => $item) { if ($item->getFlags() & \Aimeos\MShop\Order\Item\Base\Product\Base::FLAG_IMMUTABLE) { unset($orderProducts[$pos]); } $prodCodes[] = $item->getProductCode(); foreach ($item->getAttributes() as $ordAttrItem) { if (($id = $ordAttrItem->getAttributeId()) != '') { $attrIds[$id] = null; } } } $attributes = $this->getAttributes(array_keys($attrIds)); $prodMap = $this->getProducts($prodCodes); foreach ($orderProducts as $pos => $orderProduct) { $refPrices = array(); // fetch prices of articles/sub-products if (isset($prodMap[$orderProduct->getProductCode()])) { $refPrices = $prodMap[$orderProduct->getProductCode()]->getRefItems('price', 'default', 'default'); } $orderPosPrice = $orderProduct->getPrice(); $price = $this->getPrice($orderProduct, $refPrices, $attributes, $pos); if ($orderPosPrice->compare($price) === false) { $orderProduct->setPrice($price); $order->deleteProduct($pos); $order->addProduct($orderProduct, $pos); $changedProducts[$pos] = 'price.changed'; } } if (count($changedProducts) > 0) { $code = array('product' => $changedProducts); $msg = sprintf('Please have a look at the prices of the products in your basket'); throw new \Aimeos\MShop\Plugin\Provider\Exception($msg, -1, null, $code); } return true; }
/** * Receives a notification from a publisher object * * @param \Aimeos\MW\Observer\Publisher\Iface $order Shop basket instance implementing publisher interface * @param string $action Name of the action to listen for * @param mixed $value Object or value changed in publisher */ public function update(\Aimeos\MW\Observer\Publisher\Iface $order, $action, $value = null) { if (!$order instanceof \Aimeos\MShop\Order\Item\Base\Iface) { $msg = $this->getContext()->getI18n()->dt('mshop', 'Object is not of required type "%1$s"'); throw new \Aimeos\MShop\Plugin\Exception(sprintf($msg, '\\Aimeos\\MShop\\Order\\Item\\Base\\Iface')); } $config = $this->getItemBase()->getConfig(); if (!isset($config['threshold'])) { return true; } try { $delivery = $order->getService('delivery'); } catch (\Aimeos\MShop\Order\Exception $oe) { // no delivery item available yet return true; } $this->checkThreshold($order, $delivery->getPrice(), $config['threshold']); return true; }
/** * Receives a notification from a publisher object * * @param \Aimeos\MW\Observer\Publisher\Iface $order Shop basket instance implementing publisher interface * @param string $action Name of the action to listen for * @param mixed $value Object or value changed in publisher * @throws \Aimeos\MShop\Plugin\Provider\Exception if checks fail * @return bool true if checks succeed */ public function update(\Aimeos\MW\Observer\Publisher\Iface $order, $action, $value = null) { if (!$order instanceof \Aimeos\MShop\Order\Item\Base\Iface) { $msg = $this->getContext()->getI18n()->dt('mshop', 'Object is not of required type "%1$s"'); throw new \Aimeos\MShop\Plugin\Exception(sprintf($msg, '\\Aimeos\\MShop\\Order\\Item\\Base\\Iface')); } if (!($value & \Aimeos\MShop\Order\Item\Base\Base::PARTS_PRODUCT)) { return true; } $productIds = array(); foreach ($order->getProducts() as $pr) { $productIds[] = $pr->getProductId(); } $productManager = \Aimeos\MShop\Factory::createManager($this->getContext(), 'product'); $search = $productManager->createSearch(); $search->setConditions($search->compare('==', 'product.id', $productIds)); $checkItems = $productManager->searchItems($search); $notAvailable = array(); $now = date('Y-m-d H-i-s'); foreach ($order->getProducts() as $position => $orderProduct) { if (!array_key_exists($orderProduct->getProductId(), $checkItems)) { $notAvailable[$position] = 'gone.notexist'; continue; } $product = $checkItems[$orderProduct->getProductId()]; if ($product->getStatus() <= 0) { $notAvailable[$position] = 'gone.status'; continue; } $start = $product->getDateStart(); $end = $product->getDateEnd(); if ($start !== null && $start >= $now || $end !== null && $now > $end) { $notAvailable[$position] = 'gone.timeframe'; } } if (count($notAvailable) > 0) { $code = array('product' => $notAvailable); $msg = $this->getContext()->getI18n()->dt('mshop', 'Products in basket not available'); throw new \Aimeos\MShop\Plugin\Provider\Exception($msg, -1, null, $code); } return true; }
/** * Receives a notification from a publisher object * * @param \Aimeos\MW\Observer\Publisher\Iface $order Shop basket instance implementing publisher interface * @param string $action Name of the action to listen for * @param mixed $value Object or value changed in publisher * @throws \Aimeos\MShop\Plugin\Provider\Exception if checks fail * @return bool true if checks succeed */ public function update(\Aimeos\MW\Observer\Publisher\Iface $order, $action, $value = null) { if (!$order instanceof \Aimeos\MShop\Order\Item\Base\Iface) { $msg = $this->getContext()->getI18n()->dt('mshop', 'Object is not of required type "%1$s"'); throw new \Aimeos\MShop\Plugin\Exception(sprintf($msg, '\\Aimeos\\MShop\\Order\\Item\\Base\\Iface')); } if (!($value & \Aimeos\MShop\Order\Item\Base\Base::PARTS_PRODUCT)) { return true; } $context = $this->getContext(); $outOfStock = $productQuantities = $positions = array(); $siteConfig = $context->getLocale()->getSite()->getConfig(); foreach ($order->getProducts() as $position => $pr) { $productQuantities[$pr->getProductId()] = $pr->getQuantity(); $positions[$pr->getProductId()] = $position; } $stockManager = \Aimeos\MShop\Factory::createManager($context, 'product/stock'); $search = $stockManager->createSearch(); $expr = array($search->compare('==', 'product.stock.parentid', array_keys($productQuantities))); if (isset($siteConfig['repository'])) { $expr[] = $search->compare('==', 'product.stock.warehouse.code', $siteConfig['warehouse']); } $search->setConditions($search->combine('&&', $expr)); $checkItems = $stockManager->searchItems($search); foreach ($checkItems as $checkItem) { $parentid = $checkItem->getParentId(); $stocklevel = $checkItem->getStocklevel(); if ($stocklevel !== null && $stocklevel < $productQuantities[$parentid]) { $outOfStock[$positions[$parentid]] = 'stock.notenough'; } } if (count($outOfStock) > 0) { $code = array('product' => $outOfStock); $msg = $this->getContext()->getI18n()->dt('mshop', 'Products out of stock'); throw new \Aimeos\MShop\Plugin\Provider\Exception($msg, -1, null, $code); } return true; }
/** * Receives a notification from a publisher object * * @param \Aimeos\MW\Observer\Publisher\Iface $order Shop basket instance implementing publisher interface * @param string $action Name of the action to listen for * @param mixed $value Object or value changed in publisher * @throws \Aimeos\MShop\Plugin\Provider\Exception if checks fail * @return bool true if checks succeed */ public function update(\Aimeos\MW\Observer\Publisher\Iface $order, $action, $value = null) { if (!$order instanceof \Aimeos\MShop\Order\Item\Base\Iface) { $msg = $this->getContext()->getI18n()->dt('mshop', 'Object is not of required type "%1$s"'); throw new \Aimeos\MShop\Plugin\Exception(sprintf($msg, '\\Aimeos\\MShop\\Order\\Item\\Base\\Iface')); } if (!($value & \Aimeos\MShop\Order\Item\Base\Base::PARTS_PRODUCT)) { return true; } $context = $this->getContext(); /** mshop/plugin/provider/order/complete/disable * Disables the basket limits check * * If the BasketLimits plug-in is enabled, it enforces the configured * limits before customers or anyone on behalf of them can continue the * checkout process. * * This option enables e.g. call center agents to place orders which * doesn't satisfy all requirements. It may be useful if you want to * allow them to send free or replacements for lost or damaged products. * * @param boolean True to disable the check, false to keep it enabled * @category Developer * @category User * @since 2014.03 */ if ($context->getConfig()->get('mshop/plugin/provider/order/complete/disable', false)) { return true; } $count = 0; $sum = \Aimeos\MShop\Factory::createManager($context, 'price')->createItem(); foreach ($order->getProducts() as $product) { $sum->addItem($product->getPrice(), $product->getQuantity()); $count += $product->getQuantity(); } $this->checkLimits($sum, $count); return true; }
/** * Receives a notification from a publisher object * * @param \Aimeos\MW\Observer\Publisher\Iface $order Shop basket instance implementing publisher interface * @param string $action Name of the action to listen for * @param mixed $value Object or value changed in publisher * @throws \Aimeos\MShop\Plugin\Provider\Exception if checks fail * @return bool true if checks succeed */ public function update(\Aimeos\MW\Observer\Publisher\Iface $order, $action, $value = null) { $class = '\\Aimeos\\MShop\\Order\\Item\\Base\\Iface'; if (!$order instanceof $class) { throw new \Aimeos\MShop\Plugin\Exception(sprintf('Object is not of required type "%1$s"', $class)); } $ids = array(); $context = $this->getContext(); $services = $order->getServices(); if (count($order->getProducts()) === 0) { $priceManager = \Aimeos\MShop\Factory::createManager($context, 'price'); foreach ($services as $type => $service) { $service->setPrice($priceManager->createItem()); } return true; } foreach ($services as $type => $service) { $ids[$type] = $service->getServiceId(); } $serviceManager = \Aimeos\MShop\Factory::createManager($context, 'service'); $search = $serviceManager->createSearch(true); $expr = array($search->compare('==', 'service.id', $ids), $search->getConditions()); $search->setConditions($search->combine('&&', $expr)); $result = $serviceManager->searchItems($search, array('price')); foreach ($services as $type => $service) { if (isset($result[$service->getServiceId()])) { $provider = $serviceManager->getProvider($result[$service->getServiceId()]); if ($provider->isAvailable($order)) { $service->setPrice($provider->calcPrice($order)); $order->setService($service, $type); continue; } } $order->deleteService($type); } return true; }
/** * Receives a notification from a publisher object * * @param \Aimeos\MW\Observer\Publisher\Iface $order Shop basket instance implementing publisher interface * @param string $action Name of the action to listen for * @param mixed $value Object or value changed in publisher * @throws \Aimeos\MShop\Plugin\Provider\Exception if checks fail * @return bool true if checks succeed */ public function update(\Aimeos\MW\Observer\Publisher\Iface $order, $action, $value = null) { $class = '\\Aimeos\\MShop\\Order\\Item\\Base\\Iface'; if (!$order instanceof $class) { throw new \Aimeos\MShop\Plugin\Exception(sprintf('Object is not of required type "%1$s"', $class)); } if ($value & \Aimeos\MShop\Order\Item\Base\Base::PARTS_SERVICE) { $problems = array(); $availableServices = $order->getServices(); foreach ($this->getItemBase()->getConfig() as $type => $value) { if ($value == true && !isset($availableServices[$type])) { $problems[$type] = 'available.none'; } if ($value !== null && $value !== '' && $value == false && isset($availableServices[$type])) { $problems[$type] = 'available.notallowed'; } } if (count($problems) > 0) { $code = array('service' => $problems); throw new \Aimeos\MShop\Plugin\Provider\Exception(sprintf('Checks for available service items in basket failed'), -1, null, $code); } } return true; }
/** * Receives a notification from a publisher object * * @param \Aimeos\MW\Observer\Publisher\Iface $order Shop basket instance implementing publisher interface * @param string $action Name of the action to listen for * @param mixed $value Object or value changed in publisher */ public function update(\Aimeos\MW\Observer\Publisher\Iface $order, $action, $value = null) { $class = '\\Aimeos\\MShop\\Order\\Item\\Base\\Iface'; if (!$order instanceof $class) { throw new \Aimeos\MShop\Plugin\Exception(sprintf('Object is not of required type "%1$s"', $class)); } $config = $this->getItemBase()->getConfig(); if (!isset($config['threshold'])) { return true; } try { $delivery = $order->getService('delivery'); } catch (\Aimeos\MShop\Order\Exception $oe) { // no delivery item available yet return true; } $price = $delivery->getPrice(); $currency = $price->getCurrencyId(); if (!isset($config['threshold'][$currency])) { return true; } $sum = \Aimeos\MShop\Factory::createManager($this->getContext(), 'price')->createItem(); foreach ($order->getProducts() as $product) { $sum->addItem($product->getPrice(), $product->getQuantity()); } if ($sum->getValue() + $sum->getRebate() >= $config['threshold'][$currency] && $price->getCosts() > '0.00') { $price->setRebate($price->getCosts()); $price->setCosts('0.00'); } else { if ($sum->getValue() + $sum->getRebate() < $config['threshold'][$currency] && $price->getRebate() > '0.00') { $price->setCosts($price->getRebate()); $price->setRebate('0.00'); } } return true; }
/** * Subscribes itself to a publisher. * * @param \Aimeos\MW\Observer\Publisher\Iface $p Object implementing publisher interface */ public function register(\Aimeos\MW\Observer\Publisher\Iface $p) { $p->addListener($this, 'addProduct.after'); }