first commit

This commit is contained in:
2024-11-05 12:22:50 +01:00
commit e5682a3912
19641 changed files with 2948548 additions and 0 deletions

View File

@@ -0,0 +1,428 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
namespace PrestaShop\PrestaShop\Adapter\Presenter;
use ArrayAccess;
use ArrayIterator;
use ArrayObject;
use Countable;
use Doctrine\Common\Util\Inflector;
use Iterator;
use JsonSerializable;
use ReflectionClass;
use ReflectionException;
use ReflectionMethod;
use RuntimeException;
/**
* This class is useful to provide the same behaviour than an array, but which load the result of each key on demand
* (LazyLoading).
*
* Example:
*
* If your want to define the ['addresses'] array access in your lazyArray object, just define the public method
* getAddresses() and add the annotation arrayAccess to it. e.g:
*
* @arrayAccess
*
* @return array
*
* public function getAddresses()
*
* The method name should always be the index name converted to camelCase and prefixed with get. e.g:
*
* ['add_to_cart'] => getAddToCart()
*
* You can also add an array with already defined key to the lazyArray be calling the appendArray function.
* e.g.: you have a $product array containing $product['id'] = 10; $product['url'] = 'foo';
* If you call ->appendArray($product) on the lazyArray, it will define the key ['id'] and ['url'] as well
* for the lazyArray.
* Note if the key already exists as a method, it will be skip. In our example, if getUrl() is defined with the
* annotation @arrayAccess, the $product['url'] = 'foo'; will be ignored
*/
abstract class AbstractLazyArray implements Iterator, ArrayAccess, Countable, JsonSerializable
{
/**
* @var ArrayObject
*/
private $arrayAccessList;
/**
* @var ArrayIterator
*/
private $arrayAccessIterator;
/**
* @var array
*/
private $methodCacheResults = [];
/**
* AbstractLazyArray constructor.
*
* @throws ReflectionException
*/
public function __construct()
{
$this->arrayAccessList = new ArrayObject();
$reflectionClass = new ReflectionClass(get_class($this));
$methods = $reflectionClass->getMethods(ReflectionMethod::IS_PUBLIC);
foreach ($methods as $method) {
$methodDoc = $method->getDocComment();
if (strpos($methodDoc, '@arrayAccess') !== false) {
$this->arrayAccessList[$this->convertMethodNameToIndex($method->getName())] =
[
'type' => 'method',
'value' => $method->getName(),
];
}
}
$this->arrayAccessIterator = $this->arrayAccessList->getIterator();
}
/**
* Make the lazyArray serializable like an array.
*
* @return array
*
* @throws RuntimeException
*/
public function jsonSerialize()
{
$arrayResult = [];
foreach ($this->arrayAccessList as $key => $value) {
$arrayResult[$key] = $this->offsetGet($key);
}
return $arrayResult;
}
/**
* Set array key and values from $array into the LazyArray.
*
* @param array $array
*/
public function appendArray($array)
{
foreach ($array as $key => $value) {
// do not override any existing method
if (!$this->arrayAccessList->offsetExists($key)) {
$this->arrayAccessList->offsetSet(
$key,
[
'type' => 'variable',
'value' => $value,
]
);
}
}
}
/**
* @param mixed $key
* @param \Closure $closure
*/
public function appendClosure($key, \Closure $closure)
{
$this->arrayAccessList->offsetSet(
$key,
[
'type' => 'closure',
'value' => $closure,
]
);
}
/**
* The number of keys defined into the lazyArray.
*
* @return int
*/
public function count()
{
return $this->arrayAccessList->count();
}
/**
* The properties are provided as an array. But callers checking the type of this class (is_object === true)
* think they must use the object syntax.
*
* Check if the index exists inside the lazyArray.
*
* @param string $index
*
* @return bool
*/
public function __isset($index)
{
return $this->offsetExists($index);
}
/**
* The properties are provided as an array. But callers checking the type of this class (is_object === true)
* think they must use the object syntax.
*
* Get the value associated with the $index from the lazyArray.
*
* @param mixed $index
*
* @return mixed
*
* @throws RuntimeException
*/
public function __get($index)
{
return $this->offsetGet($index);
}
/**
* The properties are provided as an array. But callers checking the type of this class (is_object === true)
* think they must use the object syntax.
*
* @param mixed $name
* @param mixed $value
*
* @throws RuntimeException
*/
public function __set($name, $value)
{
$this->offsetSet($name, $value);
}
/**
* The properties are provided as an array. But callers checking the type of this class (is_object === true)
* think they must use the object syntax.
*
* @param mixed $name
*
* @throws RuntimeException
*/
public function __unset($name)
{
$this->offsetUnset($name);
}
/**
* Needed to ensure that any changes to this object won't bleed to other instances
*/
public function __clone()
{
$this->arrayAccessList = clone $this->arrayAccessList;
$this->arrayAccessIterator = clone $this->arrayAccessIterator;
}
/**
* Get the value associated with the $index from the lazyArray.
*
* @param mixed $index
*
* @return mixed
*
* @throws RuntimeException
*/
public function offsetGet($index)
{
if (isset($this->arrayAccessList[$index])) {
$type = $this->arrayAccessList[$index]['type'];
switch ($type) {
case 'method':
$isResultAvailableInCache = (isset($this->methodCacheResults[$index]));
if (!$isResultAvailableInCache) {
$methodName = $this->arrayAccessList[$index]['value'];
$this->methodCacheResults[$index] = $this->{$methodName}();
}
$result = $this->methodCacheResults[$index];
break;
case 'closure':
$isResultAvailableInCache = (isset($this->methodCacheResults[$index]));
if (!$isResultAvailableInCache) {
$methodName = $this->arrayAccessList[$index]['value'];
$this->methodCacheResults[$index] = $methodName();
}
$result = $this->methodCacheResults[$index];
break;
default:
$result = $this->arrayAccessList[$index]['value'];
break;
}
return $result;
}
return [];
}
public function clearMethodCacheResults()
{
$this->methodCacheResults = [];
}
/**
* Check if the index exists inside the lazyArray.
*
* @param mixed $index
*
* @return bool
*/
public function offsetExists($index)
{
return isset($this->arrayAccessList[$index]);
}
/**
* Copy the lazyArray.
*
* @return AbstractLazyArray
*/
public function getArrayCopy()
{
return clone $this;
}
/**
* Get the result associated with the current index.
*
* @return mixed
*
* @throws RuntimeException
*/
public function current()
{
$key = $this->arrayAccessIterator->key();
return $this->offsetGet($key);
}
/**
* Go to the next result inside the lazyArray.
*/
public function next()
{
$this->arrayAccessIterator->next();
}
/**
* Get the key associated with the current index.
*
* @return mixed|string
*/
public function key()
{
return $this->arrayAccessIterator->key();
}
/**
* Check if we are at the end of the lazyArray.
*
* @return bool
*/
public function valid()
{
return $this->arrayAccessIterator->valid();
}
/**
* Go back to the first element of the lazyArray.
*/
public function rewind()
{
$this->arrayAccessIterator->rewind();
}
/**
* Set the keys not present in the given $array to null.
*
* @param array $array
*
* @throws RuntimeException
*/
public function intersectKey($array)
{
$arrayCopy = $this->arrayAccessList->getArrayCopy();
foreach ($arrayCopy as $key => $value) {
if (!array_key_exists($key, $array)) {
$this->offsetUnset($key, true);
}
}
}
/**
* @param mixed $offset
* @param mixed $value
* @param bool $force if set, allow override of an existing method
*
* @throws RuntimeException
*/
public function offsetSet($offset, $value, $force = false)
{
if (!$force && $this->arrayAccessList->offsetExists($offset)) {
$result = $this->arrayAccessList->offsetGet($offset);
if ($result['type'] !== 'variable') {
throw new RuntimeException('Trying to set the index ' . print_r($offset, true) . ' of the LazyArray ' . get_class($this) . ' already defined by a method is not allowed');
}
}
$this->arrayAccessList->offsetSet($offset, [
'type' => 'variable',
'value' => $value,
]);
}
/**
* @param mixed $offset
* @param bool $force if set, allow unset of an existing method
*
* @throws RuntimeException
*/
public function offsetUnset($offset, $force = false)
{
$result = $this->arrayAccessList->offsetGet($offset);
if ($force || $result['type'] === 'variable') {
$this->arrayAccessList->offsetUnset($offset);
} else {
throw new RuntimeException('Trying to unset the index ' . print_r($offset, true) . ' of the LazyArray ' . get_class($this) . ' already defined by a method is not allowed');
}
}
/**
* @param string $methodName
*
* @return string
*/
private function convertMethodNameToIndex($methodName)
{
// remove "get" prefix from the function name
$strippedMethodName = substr($methodName, 3);
return Inflector::tableize($strippedMethodName);
}
}

View File

@@ -0,0 +1,709 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
namespace PrestaShop\PrestaShop\Adapter\Presenter\Cart;
use Cart;
use CartRule;
use Configuration;
use Context;
use Country;
use Hook;
use PrestaShop\PrestaShop\Adapter\Image\ImageRetriever;
use PrestaShop\PrestaShop\Adapter\Presenter\PresenterInterface;
use PrestaShop\PrestaShop\Adapter\Presenter\Product\ProductLazyArray;
use PrestaShop\PrestaShop\Adapter\Presenter\Product\ProductListingLazyArray;
use PrestaShop\PrestaShop\Adapter\Presenter\Product\ProductListingPresenter;
use PrestaShop\PrestaShop\Adapter\Product\PriceFormatter;
use PrestaShop\PrestaShop\Adapter\Product\ProductColorsRetriever;
use PrestaShop\PrestaShop\Core\Product\ProductPresentationSettings;
use Product;
use ProductAssembler;
use Symfony\Component\Translation\TranslatorInterface;
use TaxConfiguration;
use Tools;
class CartPresenter implements PresenterInterface
{
/**
* @var PriceFormatter
*/
private $priceFormatter;
/**
* @var \Link
*/
private $link;
/**
* @var TranslatorInterface
*/
private $translator;
/**
* @var ImageRetriever
*/
private $imageRetriever;
/**
* @var TaxConfiguration
*/
private $taxConfiguration;
/**
* @var ProductPresentationSettings
*/
protected $settings;
/**
* @var ProductAssembler
*/
protected $productAssembler;
public function __construct()
{
$context = Context::getContext();
$this->priceFormatter = new PriceFormatter();
$this->link = $context->link;
$this->translator = $context->getTranslator();
$this->imageRetriever = new ImageRetriever($this->link);
$this->taxConfiguration = new TaxConfiguration();
}
/**
* @return bool
*/
private function includeTaxes()
{
return $this->taxConfiguration->includeTaxes();
}
/**
* @param array $rawProduct
*
* @return ProductLazyArray|ProductListingLazyArray
*/
private function presentProduct(array $rawProduct)
{
$assembledProduct = $this->getProductAssembler()->assembleProduct($rawProduct);
$rawProduct = array_merge($assembledProduct, $rawProduct);
if (isset($rawProduct['attributes']) && is_string($rawProduct['attributes'])) {
$rawProduct['attributes'] = $this->getAttributesArrayFromString($rawProduct['attributes']);
}
$rawProduct['remove_from_cart_url'] = $this->link->getRemoveFromCartURL(
$rawProduct['id_product'],
$rawProduct['id_product_attribute']
);
$rawProduct['up_quantity_url'] = $this->link->getUpQuantityCartURL(
$rawProduct['id_product'],
$rawProduct['id_product_attribute']
);
$rawProduct['down_quantity_url'] = $this->link->getDownQuantityCartURL(
$rawProduct['id_product'],
$rawProduct['id_product_attribute']
);
$rawProduct['update_quantity_url'] = $this->link->getUpdateQuantityCartURL(
$rawProduct['id_product'],
$rawProduct['id_product_attribute']
);
$resetFields = [
'ecotax_rate',
'specific_prices',
'customizable',
'online_only',
'reduction',
'reduction_without_tax',
'new',
'condition',
'pack',
];
foreach ($resetFields as $field) {
if (!array_key_exists($field, $rawProduct)) {
$rawProduct[$field] = '';
}
}
if ($this->includeTaxes()) {
$rawProduct['price_amount'] = $rawProduct['price_wt'];
$rawProduct['price'] = $this->priceFormatter->format($rawProduct['price_wt']);
} else {
$rawProduct['price_amount'] = $rawProduct['price'];
$rawProduct['price'] = $rawProduct['price_tax_exc'] = $this->priceFormatter->format($rawProduct['price']);
}
if ($rawProduct['price_amount'] && $rawProduct['unit_price_ratio'] > 0) {
$rawProduct['unit_price'] = $rawProduct['price_amount'] / $rawProduct['unit_price_ratio'];
}
$rawProduct['total'] = $this->priceFormatter->format(
$this->includeTaxes() ?
$rawProduct['total_wt'] :
$rawProduct['total']
);
$rawProduct['quantity_wanted'] = $rawProduct['cart_quantity'];
$presenter = new ProductListingPresenter(
$this->imageRetriever,
$this->link,
$this->priceFormatter,
new ProductColorsRetriever(),
$this->translator
);
return $presenter->present(
$this->getSettings(),
$rawProduct,
Context::getContext()->language
);
}
/**
* @param array $products
* @param Cart $cart
*
* @return array
*/
public function addCustomizedData(array $products, Cart $cart)
{
return array_map(function ($product) use ($cart) {
$customizations = [];
$data = Product::getAllCustomizedDatas($cart->id, null, true, null, (int) $product['id_customization']);
if (!$data) {
$data = [];
}
$id_product = (int) $product['id_product'];
$id_product_attribute = (int) $product['id_product_attribute'];
if (array_key_exists($id_product, $data)) {
if (array_key_exists($id_product_attribute, $data[$id_product])) {
foreach ($data[$id_product] as $byAddress) {
foreach ($byAddress as $byAddressCustomizations) {
foreach ($byAddressCustomizations as $customization) {
$presentedCustomization = [
'quantity' => $customization['quantity'],
'fields' => [],
'id_customization' => null,
];
foreach ($customization['datas'] as $byType) {
foreach ($byType as $data) {
$field = [];
switch ($data['type']) {
case Product::CUSTOMIZE_FILE:
$field['type'] = 'image';
$field['image'] = $this->imageRetriever->getCustomizationImage(
$data['value']
);
break;
case Product::CUSTOMIZE_TEXTFIELD:
$field['type'] = 'text';
$field['text'] = $data['value'];
break;
default:
$field['type'] = null;
}
$field['label'] = $data['name'];
$field['id_module'] = $data['id_module'];
$presentedCustomization['id_customization'] = $data['id_customization'];
$presentedCustomization['fields'][] = $field;
}
}
$product['up_quantity_url'] = $this->link->getUpQuantityCartURL(
$product['id_product'],
$product['id_product_attribute'],
$presentedCustomization['id_customization']
);
$product['down_quantity_url'] = $this->link->getDownQuantityCartURL(
$product['id_product'],
$product['id_product_attribute'],
$presentedCustomization['id_customization']
);
$product['remove_from_cart_url'] = $this->link->getRemoveFromCartURL(
$product['id_product'],
$product['id_product_attribute'],
$presentedCustomization['id_customization']
);
$product['update_quantity_url'] = $this->link->getUpdateQuantityCartURL(
$product['id_product'],
$product['id_product_attribute'],
$presentedCustomization['id_customization']
);
$presentedCustomization['up_quantity_url'] = $this->link->getUpQuantityCartURL(
$product['id_product'],
$product['id_product_attribute'],
$presentedCustomization['id_customization']
);
$presentedCustomization['down_quantity_url'] = $this->link->getDownQuantityCartURL(
$product['id_product'],
$product['id_product_attribute'],
$presentedCustomization['id_customization']
);
$presentedCustomization['remove_from_cart_url'] = $this->link->getRemoveFromCartURL(
$product['id_product'],
$product['id_product_attribute'],
$presentedCustomization['id_customization']
);
$presentedCustomization['update_quantity_url'] = $product['update_quantity_url'];
$customizations[] = $presentedCustomization;
}
}
}
}
}
usort($customizations, function (array $a, array $b) {
if (
$a['quantity'] > $b['quantity']
|| count($a['fields']) > count($b['fields'])
|| $a['id_customization'] > $b['id_customization']
) {
return -1;
} else {
return 1;
}
});
$product['customizations'] = $customizations;
return $product;
}, $products);
}
/**
* @param Cart $cart
* @param bool $shouldSeparateGifts
*
* @return array
*
* @throws \Exception
*/
public function present($cart, $shouldSeparateGifts = false)
{
if (!is_a($cart, 'Cart')) {
throw new \Exception('CartPresenter can only present instance of Cart');
}
if ($shouldSeparateGifts) {
$rawProducts = $cart->getProductsWithSeparatedGifts();
} else {
$rawProducts = $cart->getProducts(true);
}
$products = array_map([$this, 'presentProduct'], $rawProducts);
$products = $this->addCustomizedData($products, $cart);
$subtotals = [];
$productsTotalExcludingTax = $cart->getOrderTotal(false, Cart::ONLY_PRODUCTS);
$total_excluding_tax = $cart->getOrderTotal(false);
$total_including_tax = $cart->getOrderTotal(true);
$total_discount = $cart->getDiscountSubtotalWithoutGifts($this->includeTaxes());
$totalCartAmount = $cart->getOrderTotal($this->includeTaxes(), Cart::ONLY_PRODUCTS);
$subtotals['products'] = [
'type' => 'products',
'label' => $this->translator->trans('Subtotal', [], 'Shop.Theme.Checkout'),
'amount' => $totalCartAmount,
'value' => $this->priceFormatter->format($totalCartAmount),
];
if ($total_discount) {
$subtotals['discounts'] = [
'type' => 'discount',
'label' => $this->translator->trans('Discount(s)', [], 'Shop.Theme.Checkout'),
'amount' => $total_discount,
'value' => $this->priceFormatter->format($total_discount),
];
} else {
$subtotals['discounts'] = null;
}
if ($cart->gift) {
$giftWrappingPrice = ($cart->getGiftWrappingPrice($this->includeTaxes()) != 0)
? $cart->getGiftWrappingPrice($this->includeTaxes())
: 0;
$subtotals['gift_wrapping'] = [
'type' => 'gift_wrapping',
'label' => $this->translator->trans('Gift wrapping', [], 'Shop.Theme.Checkout'),
'amount' => $giftWrappingPrice,
'value' => ($giftWrappingPrice > 0)
? $this->priceFormatter->convertAndFormat($giftWrappingPrice)
: $this->translator->trans('Free', [], 'Shop.Theme.Checkout'),
];
}
if (!$cart->isVirtualCart()) {
$shippingCost = $cart->getTotalShippingCost(null, $this->includeTaxes());
} else {
$shippingCost = 0;
}
$subtotals['shipping'] = [
'type' => 'shipping',
'label' => $this->translator->trans('Shipping', [], 'Shop.Theme.Checkout'),
'amount' => $shippingCost,
'value' => $this->getShippingDisplayValue($cart, $shippingCost),
];
$subtotals['tax'] = null;
if (Configuration::get('PS_TAX_DISPLAY')) {
$taxAmount = $total_including_tax - $total_excluding_tax;
$subtotals['tax'] = [
'type' => 'tax',
'label' => ($this->includeTaxes())
? $this->translator->trans('Included taxes', [], 'Shop.Theme.Checkout')
: $this->translator->trans('Taxes', [], 'Shop.Theme.Checkout'),
'amount' => $taxAmount,
'value' => $this->priceFormatter->format($taxAmount),
];
}
$totals = [
'total' => [
'type' => 'total',
'label' => $this->translator->trans('Total', [], 'Shop.Theme.Checkout'),
'amount' => $this->includeTaxes() ? $total_including_tax : $total_excluding_tax,
'value' => $this->priceFormatter->format(
$this->includeTaxes() ? $total_including_tax : $total_excluding_tax
),
],
'total_including_tax' => [
'type' => 'total',
'label' => $this->translator->trans('Total (tax incl.)', [], 'Shop.Theme.Checkout'),
'amount' => $total_including_tax,
'value' => $this->priceFormatter->format($total_including_tax),
],
'total_excluding_tax' => [
'type' => 'total',
'label' => $this->translator->trans('Total (tax excl.)', [], 'Shop.Theme.Checkout'),
'amount' => $total_excluding_tax,
'value' => $this->priceFormatter->format($total_excluding_tax),
],
];
$products_count = array_reduce($products, function ($count, $product) {
return $count + $product['quantity'];
}, 0);
$summary_string = $products_count === 1 ?
$this->translator->trans('1 item', [], 'Shop.Theme.Checkout') :
$this->translator->trans('%count% items', ['%count%' => $products_count], 'Shop.Theme.Checkout');
$minimalPurchase = $this->priceFormatter->convertAmount((float) Configuration::get('PS_PURCHASE_MINIMUM'));
Hook::exec('overrideMinimalPurchasePrice', [
'minimalPurchase' => &$minimalPurchase,
]);
// TODO: move it to a common parent, since it's copied in OrderPresenter and ProductPresenter
$labels = [
'tax_short' => ($this->includeTaxes())
? $this->translator->trans('(tax incl.)', [], 'Shop.Theme.Global')
: $this->translator->trans('(tax excl.)', [], 'Shop.Theme.Global'),
'tax_long' => ($this->includeTaxes())
? $this->translator->trans('(tax included)', [], 'Shop.Theme.Global')
: $this->translator->trans('(tax excluded)', [], 'Shop.Theme.Global'),
];
$discounts = $cart->getDiscounts();
$vouchers = $this->getTemplateVarVouchers($cart);
$cartRulesIds = array_flip(array_map(
function ($voucher) {
return $voucher['id_cart_rule'];
},
$vouchers['added']
));
$discounts = array_filter($discounts, function ($discount) use ($cartRulesIds, $cart) {
$voucherCustomerId = (int) $discount['id_customer'];
$voucherIsRestrictedToASingleCustomer = ($voucherCustomerId !== 0);
$voucherIsEmptyCode = empty($discount['code']);
if ($voucherIsRestrictedToASingleCustomer && $cart->id_customer !== $voucherCustomerId && $voucherIsEmptyCode) {
return false;
}
return !array_key_exists($discount['id_cart_rule'], $cartRulesIds);
});
$result = [
'products' => $products,
'totals' => $totals,
'subtotals' => $subtotals,
'products_count' => $products_count,
'summary_string' => $summary_string,
'labels' => $labels,
'id_address_delivery' => $cart->id_address_delivery,
'id_address_invoice' => $cart->id_address_invoice,
'is_virtual' => $cart->isVirtualCart(),
'vouchers' => $vouchers,
'discounts' => $discounts,
'minimalPurchase' => $minimalPurchase,
'minimalPurchaseRequired' => ($productsTotalExcludingTax < $minimalPurchase) ?
$this->translator->trans(
'A minimum shopping cart total of %amount% (tax excl.) is required to validate your order. Current cart total is %total% (tax excl.).',
[
'%amount%' => $this->priceFormatter->format($minimalPurchase),
'%total%' => $this->priceFormatter->format($productsTotalExcludingTax),
],
'Shop.Theme.Checkout'
) :
'',
];
Hook::exec('actionPresentCart',
['presentedCart' => &$result]
);
return $result;
}
/**
* Accepts a cart object with the shipping cost amount and formats the shipping cost display value accordingly.
* If the shipping cost is 0, then we must check if this is because of a free carrier and thus display 'Free' or
* simply because the system was unable to determine shipping cost at this point and thus send an empty string to hide the shipping line.
*
* @param Cart $cart
* @param float $shippingCost
*
* @return string
*/
private function getShippingDisplayValue($cart, $shippingCost)
{
$shippingDisplayValue = '';
// if one of the applied cart rules have free shipping, then the shipping display value is 'Free'
foreach ($cart->getCartRules() as $rule) {
if ($rule['free_shipping'] && !$rule['carrier_restriction']) {
return $this->translator->trans('Free', [], 'Shop.Theme.Checkout');
}
}
if ($shippingCost != 0) {
$shippingDisplayValue = $this->priceFormatter->format($shippingCost);
} else {
$defaultCountry = null;
if (isset(Context::getContext()->cookie->id_country)) {
$defaultCountry = new Country(Context::getContext()->cookie->id_country);
}
$deliveryOptionList = $cart->getDeliveryOptionList($defaultCountry);
if (count($deliveryOptionList) > 0) {
foreach ($deliveryOptionList as $option) {
foreach ($option as $currentCarrier) {
if (isset($currentCarrier['is_free']) && $currentCarrier['is_free'] > 0) {
$shippingDisplayValue = $this->translator->trans('Free', [], 'Shop.Theme.Checkout');
break 2;
}
}
}
}
}
return $shippingDisplayValue;
}
private function getTemplateVarVouchers(Cart $cart)
{
$cartVouchers = $cart->getCartRules();
$vouchers = [];
$cartHasTax = null === $cart->id ? false : $cart::getTaxesAverageUsed($cart);
$freeShippingAlreadySet = false;
foreach ($cartVouchers as $cartVoucher) {
$vouchers[$cartVoucher['id_cart_rule']]['id_cart_rule'] = $cartVoucher['id_cart_rule'];
$vouchers[$cartVoucher['id_cart_rule']]['name'] = $cartVoucher['name'];
$vouchers[$cartVoucher['id_cart_rule']]['code'] = $cartVoucher['code'];
$vouchers[$cartVoucher['id_cart_rule']]['reduction_percent'] = $cartVoucher['reduction_percent'];
$vouchers[$cartVoucher['id_cart_rule']]['reduction_currency'] = $cartVoucher['reduction_currency'];
$vouchers[$cartVoucher['id_cart_rule']]['free_shipping'] = (bool) $cartVoucher['free_shipping'];
// Voucher reduction depending of the cart tax rule
// if $cartHasTax & voucher is tax excluded, set amount voucher to tax included
if ($cartHasTax && $cartVoucher['reduction_tax'] == '0') {
$cartVoucher['reduction_amount'] = $cartVoucher['reduction_amount'] * (1 + $cartHasTax / 100);
}
$vouchers[$cartVoucher['id_cart_rule']]['reduction_amount'] = $cartVoucher['reduction_amount'];
if ($this->cartVoucherHasGiftProductReduction($cartVoucher)) {
$cartVoucher['reduction_amount'] = $cartVoucher['value_real'];
}
$totalCartVoucherReduction = 0;
if (!$this->cartVoucherHasPercentReduction($cartVoucher)
&& !$this->cartVoucherHasAmountReduction($cartVoucher)
&& !$this->cartVoucherHasGiftProductReduction($cartVoucher)) {
$freeShippingOnly = true;
if ($freeShippingAlreadySet) {
unset($vouchers[$cartVoucher['id_cart_rule']]);
continue;
} else {
$freeShippingAlreadySet = true;
}
} else {
$freeShippingOnly = false;
$totalCartVoucherReduction = $this->includeTaxes() ? $cartVoucher['value_real'] : $cartVoucher['value_tax_exc'];
}
// when a voucher has only a shipping reduction, the value displayed must be "Free Shipping"
if ($freeShippingOnly) {
$cartVoucher['reduction_formatted'] = $this->translator->trans(
'Free shipping',
[],
'Admin.Shipping.Feature'
);
} else {
$cartVoucher['reduction_formatted'] = '-' . $this->priceFormatter->format($totalCartVoucherReduction);
}
$vouchers[$cartVoucher['id_cart_rule']]['reduction_formatted'] = $cartVoucher['reduction_formatted'];
$vouchers[$cartVoucher['id_cart_rule']]['delete_url'] = $this->link->getPageLink(
'cart',
true,
null,
[
'deleteDiscount' => $cartVoucher['id_cart_rule'],
'token' => Tools::getToken(false),
]
);
}
return [
'allowed' => (int) CartRule::isFeatureActive(),
'added' => $vouchers,
];
}
/**
* @param array $cartVoucher
*
* @return bool
*/
private function cartVoucherHasFreeShipping($cartVoucher)
{
return !empty($cartVoucher['free_shipping']);
}
/**
* @param array $cartVoucher
*
* @return bool
*/
private function cartVoucherHasPercentReduction($cartVoucher)
{
return isset($cartVoucher['reduction_percent'])
&& $cartVoucher['reduction_percent'] > 0
&& $cartVoucher['reduction_amount'] == '0.00';
}
/**
* @param array $cartVoucher
*
* @return bool
*/
private function cartVoucherHasAmountReduction($cartVoucher)
{
return isset($cartVoucher['reduction_amount']) && $cartVoucher['reduction_amount'] > 0;
}
/**
* @param array $cartVoucher
*
* @return bool
*/
private function cartVoucherHasGiftProductReduction($cartVoucher)
{
return !empty($cartVoucher['gift_product']);
}
/**
* Receives a string containing a list of attributes affected to the product and returns them as an array.
*
* @param string $attributes
*
* @return array Converted attributes in an array
*/
protected function getAttributesArrayFromString($attributes)
{
$separator = Configuration::get('PS_ATTRIBUTE_ANCHOR_SEPARATOR');
$pattern = '/(?>(?P<attribute>[^:]+:[^:]+)' . $separator . '+(?!' . $separator . '([^:' . $separator . '])+:))/';
$attributesArray = [];
$matches = [];
if (!preg_match_all($pattern, $attributes . $separator, $matches)) {
return $attributesArray;
}
foreach ($matches['attribute'] as $attribute) {
list($key, $value) = explode(':', $attribute);
$attributesArray[trim($key)] = ltrim($value);
}
return $attributesArray;
}
protected function getSettings(): ProductPresentationSettings
{
if ($this->settings === null) {
$this->settings = new ProductPresentationSettings();
$this->settings->catalog_mode = Configuration::isCatalogMode();
$this->settings->catalog_mode_with_prices = (int) Configuration::get('PS_CATALOG_MODE_WITH_PRICES');
$this->settings->include_taxes = $this->includeTaxes();
$this->settings->allow_add_variant_to_cart_from_listing = (int) Configuration::get('PS_ATTRIBUTE_CATEGORY_DISPLAY');
$this->settings->stock_management_enabled = Configuration::get('PS_STOCK_MANAGEMENT');
$this->settings->showPrices = Configuration::showPrices();
$this->settings->showLabelOOSListingPages = (bool) Configuration::get('PS_SHOW_LABEL_OOS_LISTING_PAGES');
}
return $this->settings;
}
protected function getProductAssembler(): ProductAssembler
{
if ($this->productAssembler === null) {
$this->productAssembler = new ProductAssembler(Context::getContext());
}
return $this->productAssembler;
}
}

View File

@@ -0,0 +1,149 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
namespace PrestaShop\PrestaShop\Adapter\Presenter\Module;
use Currency;
use Exception;
use Hook;
use Module as LegacyModule;
use PrestaShop\PrestaShop\Adapter\Module\Module;
use PrestaShop\PrestaShop\Adapter\Presenter\PresenterInterface;
use PrestaShop\PrestaShop\Adapter\Product\PriceFormatter;
use PrestaShop\PrestaShop\Core\Addon\AddonsCollection;
class ModulePresenter implements PresenterInterface
{
/**
* @var Currency
*/
private $currency;
/** @var PriceFormatter */
private $priceFormatter;
public function __construct(Currency $currency, PriceFormatter $priceFormatter)
{
$this->currency = $currency;
$this->priceFormatter = $priceFormatter;
}
/**
* @param Module $module
*
* @return array
*/
public function present($module)
{
if (!($module instanceof Module)) {
throw new Exception('ModulePresenter can only present instance of Module');
}
$attributes = $module->attributes->all();
$attributes['picos'] = $this->addPicos($attributes);
$attributes['price'] = $this->getModulePrice($attributes['price']);
$attributes['starsRate'] = str_replace('.', '', round($attributes['avgRate'] * 2) / 2); // Round to the nearest 0.5
$moduleInstance = $module->getInstance();
if ($moduleInstance instanceof LegacyModule) {
$attributes['multistoreCompatibility'] = $moduleInstance->getMultistoreCompatibility();
}
$result = [
'attributes' => $attributes,
'disk' => $module->disk->all(),
'database' => $module->database->all(),
];
Hook::exec('actionPresentModule',
['presentedModule' => &$result]
);
return $result;
}
private function getModulePrice($prices)
{
$iso_code = $this->currency->iso_code;
if (array_key_exists($iso_code, $prices)) {
$prices['displayPrice'] = $this->priceFormatter->convertAndFormat($prices[$iso_code]);
$prices['raw'] = $prices[$iso_code];
} else {
$prices['displayPrice'] = '$' . $prices['USD'];
$prices['raw'] = $prices['USD'];
}
return $prices;
}
/**
* Transform a collection of addons as a simple array of data.
*
* @param AddonsCollection|array $modules
*
* @return array
*/
public function presentCollection($modules)
{
$presentedProducts = [];
foreach ($modules as $name => $product) {
$presentedProducts[$name] = $this->present($product);
}
return $presentedProducts;
}
/**
* Generate the list of small icons to be displayed near the module name.
*
* @param array $attributes Attributes of presented module
*
* @return array
*/
private function addPicos(array $attributes)
{
$picos = [];
// PrestaTrust display
if (!empty($attributes['prestatrust']) && !empty($attributes['prestatrust']->pico)) {
$text = '';
$class = '';
if (isset($attributes['prestatrust']->status)) {
$text = $attributes['prestatrust']->status ? 'OK' : 'KO';
$class = $attributes['prestatrust']->status ? 'text-success' : 'text-warning';
}
$picos['prestatrust'] = [
'img' => $attributes['prestatrust']->pico,
'label' => 'prestatrust',
'text' => $text,
'class' => $class,
];
}
return $picos;
}
}

View File

@@ -0,0 +1,77 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Presenter\Module;
use PrestaShop\PrestaShop\Adapter\Module\PaymentModuleListProvider;
use PrestaShop\PrestaShop\Adapter\Presenter\PresenterInterface;
/**
* Class PaymentModulesPresenter is responsible for presenting payment modules.
*/
class PaymentModulesPresenter
{
/**
* @var PresenterInterface
*/
private $modulePresenter;
/**
* @var PaymentModuleListProvider
*/
private $paymentModuleListProvider;
/**
* @param PresenterInterface $modulePresenter
* @param PaymentModuleListProvider $paymentModuleListProvider
*/
public function __construct(
PresenterInterface $modulePresenter,
PaymentModuleListProvider $paymentModuleListProvider
) {
$this->modulePresenter = $modulePresenter;
$this->paymentModuleListProvider = $paymentModuleListProvider;
}
/**
* Get presented payment modules.
*
* @return array
*/
public function present(): array
{
$installedModules = $this->paymentModuleListProvider->getPaymentModuleList();
$paymentModulesToDisplay = [];
foreach ($installedModules as $module) {
$paymentModulesToDisplay[] = $this->modulePresenter->present($module);
}
return $paymentModulesToDisplay;
}
}

View File

@@ -0,0 +1,105 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
namespace PrestaShop\PrestaShop\Adapter\Presenter\Object;
use Exception;
use Hook;
use ObjectModel;
use PrestaShop\PrestaShop\Adapter\Presenter\PresenterInterface;
use Product;
class ObjectPresenter implements PresenterInterface
{
/**
* @param ObjectModel $object
*
* @return array
*
* @throws Exception
*/
public function present($object)
{
if (!($object instanceof ObjectModel)) {
throw new Exception('ObjectPresenter can only present ObjectModel classes');
}
$presentedObject = [];
$fields = $object::$definition['fields'];
foreach ($fields as $fieldName => $null) {
$presentedObject[$fieldName] = $object->{$fieldName};
}
if ($object instanceof Product) {
$presentedObject['ecotax_tax_inc'] = $object->getEcotax(null, true, true);
}
$presentedObject['id'] = $object->id;
$mustRemove = ['deleted', 'active'];
foreach ($mustRemove as $fieldName) {
if (isset($presentedObject[$fieldName])) {
unset($presentedObject[$fieldName]);
}
}
$this->filterHtmlContent($object::$definition['table'], $presentedObject, $object->getHtmlFields());
return $presentedObject;
}
/**
* Execute filterHtml hook for html Content for objectPresenter.
*
* @param string $type
* @param ObjectModel $presentedObject
* @param array $htmlFields
*/
private function filterHtmlContent($type, &$presentedObject, $htmlFields)
{
if (!empty($htmlFields) && is_array($htmlFields)) {
$filteredHtml = Hook::exec(
'filterHtmlContent',
[
'type' => $type,
'htmlFields' => $htmlFields,
'object' => $presentedObject,
],
null,
false,
true,
false,
null,
true
);
if (!empty($filteredHtml['object'])) {
$presentedObject = $filteredHtml['object'];
}
}
}
}

View File

@@ -0,0 +1,257 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
namespace PrestaShop\PrestaShop\Adapter\Presenter\Order;
use Cart;
use Configuration;
use Context;
use Currency;
use HistoryController;
use Order;
use PrestaShop\PrestaShop\Adapter\Presenter\AbstractLazyArray;
use PrestaShop\PrestaShop\Core\Localization\Locale;
use PrestaShopBundle\Translation\TranslatorComponent;
use PrestaShopException;
use Tools;
class OrderDetailLazyArray extends AbstractLazyArray
{
/**
* @var Locale
*/
private $locale;
/**
* @var Order
*/
private $order;
/**
* @var Context
*/
private $context;
/**
* @var TranslatorComponent
*/
private $translator;
/**
* OrderDetailLazyArray constructor.
*
* @param Order $order
*/
public function __construct(Order $order)
{
$this->order = $order;
$this->context = Context::getContext();
$this->translator = Context::getContext()->getTranslator();
$this->locale = $this->context->getCurrentLocale();
parent::__construct();
}
/**
* @arrayAccess
*
* @return int
*/
public function getId()
{
return $this->order->id;
}
/**
* @arrayAccess
*
* @return string
*/
public function getReference()
{
return $this->order->reference;
}
/**
* @arrayAccess
*
* @return string
*
* @throws PrestaShopException
*/
public function getOrderDate()
{
return Tools::displayDate($this->order->date_add, null, false);
}
/**
* @arrayAccess
*
* @return string
*/
public function getDetailsUrl()
{
return $this->context->link->getPageLink('order-detail', true, null, 'id_order=' . $this->order->id);
}
/**
* @arrayAccess
*
* @return mixed
*/
public function getReorderUrl()
{
return HistoryController::getUrlToReorder((int) $this->order->id, $this->context);
}
/**
* @arrayAccess
*
* @return mixed
*/
public function getInvoiceUrl()
{
return HistoryController::getUrlToInvoice($this->order, $this->context);
}
/**
* @arrayAccess
*
* @return string
*/
public function getGiftMessage()
{
return nl2br($this->order->gift_message);
}
/**
* @arrayAccess
*
* @return int
*/
public function getIsReturnable()
{
return (int) $this->order->isReturnable();
}
/**
* @arrayAccess
*
* @return string
*/
public function getPayment()
{
return $this->order->payment;
}
/**
* @arrayAccess
*
* @return string
*/
public function getModule()
{
return $this->order->module;
}
/**
* @arrayAccess
*
* @return bool
*/
public function getRecyclable()
{
return (bool) $this->order->recyclable;
}
/**
* @arrayAccess
*
* @return bool
*/
public function getIsValid()
{
return $this->order->valid;
}
/**
* @arrayAccess
*
* @return bool
*/
public function getIsVirtual()
{
$cart = new Cart($this->order->id_cart);
return $cart->isVirtualCart();
}
/**
* @arrayAccess
*
* @return array
*/
public function getShipping()
{
$order = $this->order;
$shippingList = $order->getShipping();
$orderShipping = [];
foreach ($shippingList as $shippingId => $shipping) {
if (isset($shipping['carrier_name']) && $shipping['carrier_name']) {
$orderShipping[$shippingId] = $shipping;
$orderShipping[$shippingId]['shipping_date'] =
Tools::displayDate($shipping['date_add'], null, false);
$orderShipping[$shippingId]['shipping_weight'] =
($shipping['weight'] > 0) ? sprintf('%.3f', $shipping['weight']) . ' ' .
Configuration::get('PS_WEIGHT_UNIT') : '-';
$shippingCost =
(!$order->getTaxCalculationMethod()) ? $shipping['shipping_cost_tax_excl']
: $shipping['shipping_cost_tax_incl'];
$orderShipping[$shippingId]['shipping_cost'] =
($shippingCost > 0) ? $this->locale->formatPrice($shippingCost, (Currency::getIsoCodeById((int) $order->id_currency)))
: $this->translator->trans('Free', [], 'Shop.Theme.Checkout');
$tracking_line = '-';
if ($shipping['tracking_number']) {
if ($shipping['url']) {
$tracking_line = '<a href="' . str_replace(
'@',
$shipping['tracking_number'],
$shipping['url']
) . '" target="_blank">' . $shipping['tracking_number'] . '</a>';
} else {
$tracking_line = $shipping['tracking_number'];
}
}
$orderShipping[$shippingId]['tracking'] = $tracking_line;
}
}
return $orderShipping;
}
}

View File

@@ -0,0 +1,468 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
namespace PrestaShop\PrestaShop\Adapter\Presenter\Order;
use Address;
use AddressFormat;
use Carrier;
use Cart;
use Configuration;
use Context;
use Currency;
use CustomerMessage;
use Doctrine\Common\Annotations\AnnotationException;
use Order;
use OrderReturn;
use PrestaShop\PrestaShop\Adapter\Presenter\AbstractLazyArray;
use PrestaShop\PrestaShop\Adapter\Presenter\Cart\CartPresenter;
use PrestaShop\PrestaShop\Adapter\Presenter\Object\ObjectPresenter;
use PrestaShop\PrestaShop\Adapter\Product\PriceFormatter;
use PrestaShopBundle\Translation\TranslatorComponent;
use PrestaShopException;
use ProductDownload;
use ReflectionException;
use TaxConfiguration;
use Tools;
class OrderLazyArray extends AbstractLazyArray
{
/** @var CartPresenter */
private $cartPresenter;
/** @var ObjectPresenter */
private $objectPresenter;
/** @var PriceFormatter */
private $priceFormatter;
/** @var TranslatorComponent */
private $translator;
/** @var TaxConfiguration */
private $taxConfiguration;
/** @var Order */
private $order;
/** @var OrderSubtotalLazyArray */
private $subTotals;
/**
* OrderArray constructor.
*
* @throws AnnotationException
* @throws ReflectionException
*/
public function __construct(Order $order)
{
$this->order = $order;
$this->cartPresenter = new CartPresenter();
$this->objectPresenter = new ObjectPresenter();
$this->priceFormatter = new PriceFormatter();
$this->translator = Context::getContext()->getTranslator();
$this->taxConfiguration = new TaxConfiguration();
$this->subTotals = new OrderSubtotalLazyArray($this->order);
parent::__construct();
}
/**
* @arrayAccess
*
* @return mixed
*/
public function getTotals()
{
$amounts = $this->getAmounts();
return $amounts['totals'];
}
/**
* @arrayAccess
*
* @return int
*/
public function getIdAddressInvoice()
{
return $this->order->id_address_invoice;
}
/**
* @arrayAccess
*
* @return int
*/
public function getIdAddressDelivery()
{
return $this->order->id_address_delivery;
}
/**
* @arrayAccess
*
* @return mixed
*/
public function getSubtotals()
{
return $this->subTotals;
}
/**
* @arrayAccess
*
* @return int
*/
public function getProductsCount()
{
return count($this->getProducts());
}
/**
* @arrayAccess
*
* @return mixed
*
* @throws PrestaShopException
*/
public function getShipping()
{
$details = $this->getDetails();
return $details['shipping'];
}
/**
* @arrayAccess
*
* @return array
*/
public function getProducts()
{
$order = $this->order;
$cart = new Cart($order->id_cart);
$orderProducts = $order->getProducts();
$cartProducts = $this->cartPresenter->present($cart);
$orderPaid = $order->getCurrentOrderState() && $order->getCurrentOrderState()->paid;
$includeTaxes = $this->includeTaxes();
foreach ($orderProducts as &$orderProduct) {
// Use data from OrderDetail in case that the Product has been deleted
$orderProduct['name'] = $orderProduct['product_name'];
$orderProduct['quantity'] = $orderProduct['product_quantity'];
$orderProduct['id_product'] = $orderProduct['product_id'];
$orderProduct['id_product_attribute'] = $orderProduct['product_attribute_id'];
$productPrice = $includeTaxes ? 'product_price_wt' : 'product_price';
$totalPrice = $includeTaxes ? 'total_wt' : 'total_price';
$orderProduct['price'] = $this->priceFormatter->format(
$orderProduct[$productPrice],
Currency::getCurrencyInstance((int) $order->id_currency)
);
$orderProduct['total'] = $this->priceFormatter->format(
$orderProduct[$totalPrice],
Currency::getCurrencyInstance((int) $order->id_currency)
);
if ($orderPaid && $orderProduct['is_virtual']) {
$id_product_download = ProductDownload::getIdFromIdProduct($orderProduct['product_id']);
$product_download = new ProductDownload($id_product_download);
if ($product_download->display_filename != '') {
$orderProduct['download_link'] =
$product_download->getTextLink(false, $orderProduct['download_hash'])
. '&id_order=' . (int) $order->id
. '&secure_key=' . $order->secure_key;
}
}
foreach ($cartProducts['products'] as $cartProduct) {
if (($cartProduct['id_product'] === $orderProduct['id_product'])
&& ($cartProduct['id_product_attribute'] === $orderProduct['id_product_attribute'])
) {
if (isset($cartProduct['attributes'])) {
$orderProduct['attributes'] = $cartProduct['attributes'];
} else {
$orderProduct['attributes'] = [];
}
$orderProduct['cover'] = $cartProduct['cover'];
$orderProduct['default_image'] = $cartProduct['default_image'];
$orderProduct['unit_price_full'] = $cartProduct['unit_price_full'];
break;
}
}
OrderReturn::addReturnedQuantity($orderProducts, $order->id);
}
$orderProducts = $this->cartPresenter->addCustomizedData($orderProducts, $cart);
return $orderProducts;
}
/**
* @arrayAccess
*
* @return array
*/
public function getAmounts()
{
$order = $this->order;
$amounts['subtotals'] = $this->subTotals;
$amounts['totals'] = [];
$amount = $this->includeTaxes() ? $order->total_paid : $order->total_paid_tax_excl;
$amounts['totals']['total'] = [
'type' => 'total',
'label' => $this->translator->trans('Total', [], 'Shop.Theme.Checkout'),
'amount' => $amount,
'value' => $this->priceFormatter->format($amount, Currency::getCurrencyInstance((int) $order->id_currency)),
];
$amounts['totals']['total_paid'] = [
'type' => 'total_paid',
'label' => $this->translator->trans('Total paid', [], 'Shop.Theme.Checkout'),
'amount' => $order->total_paid_real,
'value' => $this->priceFormatter->format(
$order->total_paid_real,
Currency::getCurrencyInstance((int) $order->id_currency)
),
];
$amounts['totals']['total_including_tax'] = [
'type' => 'total_including_tax',
'label' => $this->translator->trans('Total (tax incl.)', [], 'Shop.Theme.Checkout'),
'amount' => $order->total_paid_tax_incl,
'value' => $this->priceFormatter->format(
$order->total_paid_tax_incl,
Currency::getCurrencyInstance((int) $order->id_currency)
),
];
$amounts['totals']['total_excluding_tax'] = [
'type' => 'total_excluding_tax',
'label' => $this->translator->trans('Total (tax excl.)', [], 'Shop.Theme.Checkout'),
'amount' => $order->total_paid_tax_excl,
'value' => $this->priceFormatter->format(
$order->total_paid_tax_excl,
Currency::getCurrencyInstance((int) $order->id_currency)
),
];
return $amounts;
}
/**
* @arrayAccess
*
* @return OrderDetailLazyArray
*/
public function getDetails()
{
return new OrderDetailLazyArray($this->order);
}
/**
* @arrayAccess
*
* @return array
*/
public function getHistory()
{
$order = $this->order;
$orderHistory = [];
$context = Context::getContext();
$historyList = $order->getHistory($context->language->id, false, true);
foreach ($historyList as $historyId => $history) {
// HistoryList only contains order states that are not hidden to customers, the last visible order state,
// that is to say the one we get in the first iteration
if ($historyId === array_key_first($historyList)) {
$historyId = 'current';
}
$orderHistory[$historyId] = $history;
$orderHistory[$historyId]['history_date'] = Tools::displayDate($history['date_add'], null, false);
$orderHistory[$historyId]['contrast'] = (Tools::getBrightness($history['color']) > 128) ? 'dark' : 'bright';
}
if (!isset($orderHistory['current'])) {
$orderHistory['current'] = $this->getDefaultHistory();
}
return $orderHistory;
}
/**
* @arrayAccess
*
* @return array
*/
public function getMessages()
{
$order = $this->order;
$messages = [];
$customerMessages = CustomerMessage::getMessagesByOrderId((int) $order->id, false);
foreach ($customerMessages as $cmId => $customerMessage) {
$messages[$cmId] = $customerMessage;
$messages[$cmId]['message'] = nl2br($customerMessage['message']);
$messages[$cmId]['message_date'] = Tools::displayDate($customerMessage['date_add'], null, true);
if (isset($customerMessage['elastname']) && $customerMessage['elastname']) {
$messages[$cmId]['name'] = $customerMessage['efirstname'] . ' ' . $customerMessage['elastname'];
} elseif ($customerMessage['clastname']) {
$messages[$cmId]['name'] = $customerMessage['cfirstname'] . ' ' . $customerMessage['clastname'];
} else {
$messages[$cmId]['name'] = Configuration::get('PS_SHOP_NAME');
}
}
return $messages;
}
/**
* @arrayAccess
*
* @return array
*/
public function getCarrier()
{
$order = $this->order;
$carrier = new Carrier((int) $order->id_carrier, (int) $order->getAssociatedLanguage()->getId());
$orderCarrier = $this->objectPresenter->present($carrier);
$orderCarrier['name'] = ($carrier->name == '0') ? Configuration::get('PS_SHOP_NAME') : $carrier->name;
$orderCarrier['delay'] = $carrier->delay;
return $orderCarrier;
}
/**
* @arrayAccess
*
* @return array
*/
public function getAddresses()
{
$order = $this->order;
$orderAddresses = [
'delivery' => [],
'invoice' => [],
];
$addressDelivery = new Address((int) $order->id_address_delivery);
$addressInvoice = new Address((int) $order->id_address_invoice);
if (!$order->isVirtual()) {
$orderAddresses['delivery'] = $this->objectPresenter->present($addressDelivery);
$orderAddresses['delivery']['formatted'] =
AddressFormat::generateAddress($addressDelivery, [], '<br />');
}
$orderAddresses['invoice'] = $this->objectPresenter->present($addressInvoice);
$orderAddresses['invoice']['formatted'] = AddressFormat::generateAddress($addressInvoice, [], '<br />');
return $orderAddresses;
}
/**
* @arrayAccess
*
* @return string
*/
public function getFollowUp()
{
$order = $this->order;
$carrier = $this->getCarrier();
if (!empty($carrier['url']) && !empty($order->shipping_number)) {
return str_replace('@', $order->shipping_number, $carrier['url']);
}
return '';
}
/**
* @arrayAccess
*
* @return array
*/
public function getLabels()
{
return [
'tax_short' => ($this->includeTaxes())
? $this->translator->trans('(tax incl.)', [], 'Shop.Theme.Global')
: $this->translator->trans('(tax excl.)', [], 'Shop.Theme.Global'),
'tax_long' => ($this->includeTaxes())
? $this->translator->trans('(tax included)', [], 'Shop.Theme.Global')
: $this->translator->trans('(tax excluded)', [], 'Shop.Theme.Global'),
];
}
/**
* @return bool|mixed
*/
private function includeTaxes()
{
return $this->taxConfiguration->includeTaxes();
}
/**
* @return array
*/
private function getDefaultHistory()
{
return [
'id_order_state' => '',
'invoice' => '',
'send_email' => '',
'module_name' => '',
'color' => '',
'unremovable' => '',
'hidden' => '',
'loggable' => '',
'delivery' => '',
'shipped' => '',
'paid' => '',
'pdf_invoice' => '',
'pdf_delivery' => '',
'deleted' => '',
'id_order_history' => '',
'id_employee' => '',
'id_order' => '',
'date_add' => '',
'employee_firstname' => '',
'employee_lastname' => '',
'ostate_name' => '',
'history_date' => '',
'contrast' => '',
];
}
}

View File

@@ -0,0 +1,57 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
namespace PrestaShop\PrestaShop\Adapter\Presenter\Order;
use Exception;
use Hook;
use Order;
use PrestaShop\PrestaShop\Adapter\Presenter\PresenterInterface;
class OrderPresenter implements PresenterInterface
{
/**
* @param Order $order
*
* @return OrderLazyArray
*
* @throws Exception
*/
public function present($order)
{
if (!($order instanceof Order)) {
throw new Exception('OrderPresenter can only present instance of Order');
}
$orderLazyArray = new OrderLazyArray($order);
Hook::exec('actionPresentOrder',
['presentedOrder' => &$orderLazyArray]
);
return $orderLazyArray;
}
}

View File

@@ -0,0 +1,145 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
namespace PrestaShop\PrestaShop\Adapter\Presenter\Order;
use Link;
use PrestaShop\PrestaShop\Adapter\Presenter\AbstractLazyArray;
use PrestaShopException;
use Tools;
class OrderReturnLazyArray extends AbstractLazyArray
{
/**
* @var string
*/
private $prefix;
/**
* @var Link
*/
private $link;
/** @var array */
private $orderReturn;
/**
* OrderReturnLazyArray constructor.
*
* @param string $prefix
* @param Link $link
* @param array $orderReturn
*
* @throws \ReflectionException
*/
public function __construct($prefix, Link $link, array $orderReturn)
{
$this->prefix = $prefix;
$this->link = $link;
$this->orderReturn = $orderReturn;
parent::__construct();
$this->appendArray($orderReturn);
}
/**
* @arrayAccess
*
* @return mixed
*/
public function getId()
{
return $this->orderReturn['id_order_return'];
}
/**
* @arrayAccess
*
* @return string
*/
public function getDetailsUrl()
{
return $this->link->getPageLink(
'order-detail',
true,
null,
'id_order=' . (int) $this->orderReturn['id_order']
);
}
/**
* @arrayAccess
*
* @return string
*/
public function getReturnUrl()
{
return $this->link->getPageLink(
'order-return',
true,
null,
'id_order_return=' . (int) $this->orderReturn['id_order_return']
);
}
/**
* @arrayAccess
*
* @return string
*/
public function getReturnNumber()
{
return $this->prefix . sprintf('%06d', $this->orderReturn['id_order_return']);
}
/**
* @arrayAccess
*
* @return string
*
* @throws PrestaShopException
*/
public function getReturnDate()
{
return Tools::displayDate($this->orderReturn['date_add'], null, false);
}
/**
* @arrayAccess
*
* @return string
*/
public function getPrintUrl()
{
return ($this->orderReturn['state'] == 2)
? $this->link->getPageLink(
'pdf-order-return',
true,
null,
'id_order_return=' . (int) $this->orderReturn['id_order_return']
)
: '';
}
}

View File

@@ -0,0 +1,79 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
namespace PrestaShop\PrestaShop\Adapter\Presenter\Order;
use Exception;
use Hook;
use Link;
use PrestaShop\PrestaShop\Adapter\Presenter\PresenterInterface;
class OrderReturnPresenter implements PresenterInterface
{
/**
* @var string
*/
private $prefix;
/**
* @var Link
*/
private $link;
/**
* OrderReturnPresenter constructor.
*
* @param string $prefix
* @param Link $link
*/
public function __construct($prefix, Link $link)
{
$this->prefix = $prefix;
$this->link = $link;
}
/**
* @param array $orderReturn
*
* @return OrderReturnLazyArray
*
* @throws \ReflectionException
*/
public function present($orderReturn)
{
if (!is_array($orderReturn)) {
throw new Exception('orderReturnPresenter can only present order_return passed as array');
}
$orderReturnLazyArray = new OrderReturnLazyArray($this->prefix, $this->link, $orderReturn);
Hook::exec('actionPresentOrderReturn',
['presentedOrderReturn' => &$orderReturnLazyArray]
);
return $orderReturnLazyArray;
}
}

View File

@@ -0,0 +1,224 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
namespace PrestaShop\PrestaShop\Adapter\Presenter\Order;
use Cart;
use Configuration;
use Context;
use Currency;
use Order;
use PrestaShop\PrestaShop\Adapter\Presenter\AbstractLazyArray;
use PrestaShop\PrestaShop\Adapter\Product\PriceFormatter;
use PrestaShopBundle\Translation\TranslatorComponent;
use TaxConfiguration;
class OrderSubtotalLazyArray extends AbstractLazyArray
{
/** @var Order */
private $order;
/** @var Context */
private $context;
/** @var TaxConfiguration */
private $taxConfiguration;
/** @var PriceFormatter */
private $priceFormatter;
/** @var bool */
private $includeTaxes;
/** @var TranslatorComponent */
private $translator;
/**
* OrderSubtotalLazyArray constructor.
*
* @param Order $order
*/
public function __construct(Order $order)
{
$this->context = Context::getContext();
$this->taxConfiguration = new TaxConfiguration();
$this->includeTaxes = $this->includeTaxes();
$this->priceFormatter = new PriceFormatter();
$this->translator = Context::getContext()->getTranslator();
$this->order = $order;
parent::__construct();
}
/**
* @arrayAccess
*
* @return array
*/
public function getProducts()
{
$totalProducts = ($this->includeTaxes) ? $this->order->total_products_wt : $this->order->total_products;
return [
'type' => 'products',
'label' => $this->translator->trans('Subtotal', [], 'Shop.Theme.Checkout'),
'amount' => $totalProducts,
'value' => $this->priceFormatter->format(
$totalProducts,
Currency::getCurrencyInstance((int) $this->order->id_currency)
),
];
}
/**
* @arrayAccess
*
* @return array
*/
public function getDiscounts()
{
$discountAmount = ($this->includeTaxes)
? $this->order->total_discounts_tax_incl
: $this->order->total_discounts_tax_excl;
if ((float) $discountAmount) {
return [
'type' => 'discount',
'label' => $this->translator->trans('Discount', [], 'Shop.Theme.Checkout'),
'amount' => $discountAmount,
'value' => $this->priceFormatter->format(
$discountAmount,
Currency::getCurrencyInstance((int) $this->order->id_currency)
),
];
}
return [
'type' => 'discount',
'label' => null,
'amount' => null,
'value' => '',
];
}
/**
* @arrayAccess
*
* @return array
*/
public function getShipping()
{
$cart = new Cart($this->order->id_cart);
if (!$cart->isVirtualCart()) {
$shippingCost = ($this->includeTaxes)
? $this->order->total_shipping_tax_incl : $this->order->total_shipping_tax_excl;
return [
'type' => 'shipping',
'label' => $this->translator->trans('Shipping and handling', [], 'Shop.Theme.Checkout'),
'amount' => $shippingCost,
'value' => $shippingCost != 0 ? $this->priceFormatter->format(
$shippingCost,
Currency::getCurrencyInstance((int) $this->order->id_currency)
)
: $this->translator->trans('Free', [], 'Shop.Theme.Checkout'),
];
}
return [
'type' => 'shipping',
'label' => null,
'amount' => null,
'value' => '',
];
}
/**
* @arrayAccess
*
* @return array
*/
public function getTax()
{
if (!Configuration::get('PS_TAX_DISPLAY')) {
return [
'type' => 'tax',
'label' => null,
'amount' => null,
'value' => '',
];
}
$tax = $this->order->total_paid_tax_incl - $this->order->total_paid_tax_excl;
return [
'type' => 'tax',
'label' => $this->translator->trans('Tax', [], 'Shop.Theme.Checkout'),
'amount' => $tax,
'value' => $this->priceFormatter->format(
$tax,
Currency::getCurrencyInstance((int) $this->order->id_currency)
),
];
}
/**
* @arrayAccess
*
* @return array
*/
public function getGiftWrapping()
{
if ($this->order->gift) {
$giftWrapping = ($this->includeTaxes)
? $this->order->total_wrapping_tax_incl
: $this->order->total_wrapping_tax_excl;
return [
'type' => 'gift_wrapping',
'label' => $this->translator->trans('Gift wrapping', [], 'Shop.Theme.Checkout'),
'amount' => $giftWrapping,
'value' => $this->priceFormatter->format(
$giftWrapping,
Currency::getCurrencyInstance((int) $this->order->id_currency)
),
];
}
return [
'type' => 'gift_wrapping',
'label' => null,
'amount' => null,
'value' => '',
];
}
/**
* @return bool
*/
private function includeTaxes()
{
return $this->taxConfiguration->includeTaxes();
}
}

View File

@@ -0,0 +1,37 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
namespace PrestaShop\PrestaShop\Adapter\Presenter;
interface PresenterInterface
{
/**
* @param mixed $object
*
* @return array|AbstractLazyArray
*/
public function present($object);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,67 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
namespace PrestaShop\PrestaShop\Adapter\Presenter\Product;
use PrestaShop\PrestaShop\Core\Product\ProductPresentationSettings;
class ProductListingLazyArray extends ProductLazyArray
{
/**
* @arrayAccess
*
* @return string|null
*/
public function getAddToCartUrl()
{
if ($this->product['id_product_attribute'] != 0 && !$this->settings->allow_add_variant_to_cart_from_listing) {
return null;
}
if ($this->product['customizable'] == 2 || !empty($this->product['customization_required'])) {
return null;
}
return parent::getAddToCartUrl();
}
/**
* @param array $product
* @param ProductPresentationSettings $settings
*
* @return bool
*/
protected function shouldEnableAddToCartButton(array $product, ProductPresentationSettings $settings)
{
if (isset($product['attributes'])
&& count($product['attributes']) > 0
&& !$settings->allow_add_variant_to_cart_from_listing) {
return false;
}
return parent::shouldEnableAddToCartButton($product, $settings);
}
}

View File

@@ -0,0 +1,66 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
namespace PrestaShop\PrestaShop\Adapter\Presenter\Product;
use Hook;
use Language;
use PrestaShop\PrestaShop\Core\Product\ProductPresentationSettings;
class ProductListingPresenter extends ProductPresenter
{
/**
* @param ProductPresentationSettings $settings
* @param array $product
* @param Language $language
*
* @return ProductLazyArray|ProductListingLazyArray
*
* @throws \ReflectionException
*/
public function present(
ProductPresentationSettings $settings,
array $product,
Language $language
) {
$productListingLazyArray = new ProductListingLazyArray(
$settings,
$product,
$language,
$this->imageRetriever,
$this->link,
$this->priceFormatter,
$this->productColorsRetriever,
$this->translator
);
Hook::exec('actionPresentProductListing',
['presentedProduct' => &$productListingLazyArray]
);
return $productListingLazyArray;
}
}

View File

@@ -0,0 +1,119 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
namespace PrestaShop\PrestaShop\Adapter\Presenter\Product;
use Hook;
use Language;
use Link;
use PrestaShop\PrestaShop\Adapter\Configuration;
use PrestaShop\PrestaShop\Adapter\HookManager;
use PrestaShop\PrestaShop\Adapter\Image\ImageRetriever;
use PrestaShop\PrestaShop\Adapter\Product\PriceFormatter;
use PrestaShop\PrestaShop\Adapter\Product\ProductColorsRetriever;
use PrestaShop\PrestaShop\Core\Product\ProductPresentationSettings;
use Symfony\Component\Translation\TranslatorInterface;
class ProductPresenter
{
/**
* @var Configuration
*/
protected $configuration;
/**
* @var HookManager
*/
protected $hookManager;
/**
* @var ImageRetriever
*/
protected $imageRetriever;
/**
* @var Link
*/
protected $link;
/**
* @var PriceFormatter
*/
protected $priceFormatter;
/**
* @var ProductColorsRetriever
*/
protected $productColorsRetriever;
/**
* @var TranslatorInterface
*/
protected $translator;
public function __construct(
ImageRetriever $imageRetriever,
Link $link,
PriceFormatter $priceFormatter,
ProductColorsRetriever $productColorsRetriever,
TranslatorInterface $translator,
HookManager $hookManager = null,
Configuration $configuration = null
) {
$this->imageRetriever = $imageRetriever;
$this->link = $link;
$this->priceFormatter = $priceFormatter;
$this->productColorsRetriever = $productColorsRetriever;
$this->translator = $translator;
$this->hookManager = $hookManager ?? new HookManager();
$this->configuration = $configuration ?? new Configuration();
}
public function present(
ProductPresentationSettings $settings,
array $product,
Language $language
) {
$productLazyArray = new ProductLazyArray(
$settings,
$product,
$language,
$this->imageRetriever,
$this->link,
$this->priceFormatter,
$this->productColorsRetriever,
$this->translator,
$this->hookManager,
$this->configuration
);
Hook::exec('actionPresentProduct',
['presentedProduct' => &$productLazyArray]
);
return $productLazyArray;
}
}

View File

@@ -0,0 +1,115 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product;
use PrestaShop\PrestaShop\Adapter\Product\Repository\ProductSupplierRepository;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\ValueObject\CombinationId;
use PrestaShop\PrestaShop\Core\Domain\Product\Supplier\ProductSupplier as ProductSupplierDTO;
use PrestaShop\PrestaShop\Core\Domain\Product\Supplier\QueryResult\ProductSupplierForEditing;
use PrestaShop\PrestaShop\Core\Domain\Product\Supplier\QueryResult\ProductSupplierInfo;
use PrestaShop\PrestaShop\Core\Domain\Product\ValueObject\ProductId;
use ProductSupplier;
/**
* Holds reusable methods for ProductSupplier related query/command handlers
*/
abstract class AbstractProductSupplierHandler
{
/**
* @var ProductSupplierRepository
*/
protected $productSupplierRepository;
/**
* @param ProductSupplierRepository $productSupplierRepository
*/
public function __construct(
ProductSupplierRepository $productSupplierRepository
) {
$this->productSupplierRepository = $productSupplierRepository;
}
/**
* @param ProductId $productId
* @param CombinationId|null $combinationId
*
* @return array<int, ProductSupplierInfo>
*/
protected function getProductSuppliersInfo(ProductId $productId, ?CombinationId $combinationId = null): array
{
$productSuppliersInfo = $this->productSupplierRepository->getProductSuppliersInfo($productId, $combinationId);
$suppliersInfo = [];
foreach ($productSuppliersInfo as $productSupplierInfo) {
$supplierId = (int) $productSupplierInfo['id_supplier'];
$suppliersInfo[] = new ProductSupplierInfo(
$productSupplierInfo['name'],
$supplierId,
new ProductSupplierForEditing(
(int) $productSupplierInfo['id_product_supplier'],
(int) $productSupplierInfo['id_product'],
(int) $productSupplierInfo['id_supplier'],
$productSupplierInfo['product_supplier_reference'],
$productSupplierInfo['product_supplier_price_te'],
(int) $productSupplierInfo['id_currency'],
(int) $productSupplierInfo['id_product_attribute']
)
);
}
return $suppliersInfo;
}
/**
* Loads ProductSupplier object model with data from DTO.
*
* @param ProductId $productId
* @param ProductSupplierDTO $productSupplierDTO
* @param CombinationId|null $combinationId
*
* @return ProductSupplier
*/
protected function loadEntityFromDTO(ProductId $productId, ProductSupplierDTO $productSupplierDTO, ?CombinationId $combinationId = null): ProductSupplier
{
if ($productSupplierDTO->getProductSupplierId()) {
$productSupplier = $this->productSupplierRepository->get($productSupplierDTO->getProductSupplierId());
} else {
$productSupplier = new ProductSupplier();
}
$productSupplier->id_product = $productId->getValue();
$productSupplier->id_product_attribute = $combinationId ? $combinationId->getValue() : CombinationId::NO_COMBINATION;
$productSupplier->id_supplier = $productSupplierDTO->getSupplierId()->getValue();
$productSupplier->id_currency = $productSupplierDTO->getCurrencyId()->getValue();
$productSupplier->product_supplier_reference = $productSupplierDTO->getReference();
$productSupplier->product_supplier_price_te = $productSupplierDTO->getPriceTaxExcluded();
return $productSupplier;
}
}

View File

@@ -0,0 +1,472 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
namespace PrestaShop\PrestaShop\Adapter\Product;
use AppKernel;
use Configuration;
use Context;
use Currency;
use Db;
use DbQuery;
use Doctrine\ORM\EntityManager;
use Hook;
use PrestaShop\PrestaShop\Adapter\Admin\AbstractAdminQueryBuilder;
use PrestaShop\PrestaShop\Adapter\ImageManager;
use PrestaShop\PrestaShop\Adapter\Validate;
use PrestaShopBundle\Entity\AdminFilter;
use PrestaShopBundle\Service\DataProvider\Admin\ProductInterface;
use Product;
use Psr\Cache\CacheItemPoolInterface;
use StockAvailable;
use Tools;
/**
* Data provider for new Architecture, about Product object model.
*
* This class will provide data from DB / ORM about Products for the Admin interface.
* This is an Adapter that works with the Legacy code and persistence behaviors.
*/
class AdminProductDataProvider extends AbstractAdminQueryBuilder implements ProductInterface
{
/**
* @var EntityManager
*/
private $entityManager;
/**
* @var ImageManager
*/
private $imageManager;
/**
* @var CacheItemPoolInterface
*/
private $cache;
public function __construct(
EntityManager $entityManager,
ImageManager $imageManager,
CacheItemPoolInterface $cache
) {
$this->entityManager = $entityManager;
$this->imageManager = $imageManager;
$this->cache = $cache;
}
/**
* {@inheritdoc}
*/
public function getPersistedFilterParameters()
{
$employee = Context::getContext()->employee;
$employeeId = $employee->id ?: 0;
$cachedFilters = $this->cache->getItem("app.product_filters_${employeeId}");
if (!$cachedFilters->isHit()) {
$shop = Context::getContext()->shop;
$filter = $this->entityManager->getRepository('PrestaShopBundle:AdminFilter')->findOneBy([
'employee' => $employeeId,
'shop' => $shop->id ?: 0,
'controller' => 'ProductController',
'action' => 'catalogAction',
]);
/** @var $filter AdminFilter */
if (null === $filter) {
$filters = AdminFilter::getProductCatalogEmptyFilter();
} else {
$filters = $filter->getProductCatalogFilter();
}
$cachedFilters->set($filters);
$this->cache->save($cachedFilters);
}
return $cachedFilters->get();
}
/**
* {@inheritdoc}
*/
public function isCategoryFiltered()
{
$filters = $this->getPersistedFilterParameters();
return !empty($filters['filter_category']) && $filters['filter_category'] > 0;
}
/**
* {@inheritdoc}
*/
public function isColumnFiltered()
{
$filters = $this->getPersistedFilterParameters();
foreach ($filters as $filterKey => $filterValue) {
if (strpos($filterKey, 'filter_column_') === 0 && $filterValue !== '') {
return true; // break at first column filter found
}
}
return false;
}
/**
* {@inheritdoc}
*/
public function persistFilterParameters(array $parameters)
{
$employee = Context::getContext()->employee;
$shop = Context::getContext()->shop;
$filter = $this->entityManager->getRepository('PrestaShopBundle:AdminFilter')->findOneBy([
'employee' => $employee->id ?: 0,
'shop' => $shop->id ?: 0,
'controller' => 'ProductController',
'action' => 'catalogAction',
]);
if (!$filter) {
$filter = new AdminFilter();
$filter->setEmployee($employee->id ?: 0)->setShop($shop->id ?: 0)->setController('ProductController')->setAction('catalogAction');
}
$filter->setProductCatalogFilter($parameters);
$this->entityManager->persist($filter);
// if each filter is == '', then remove item from DB :)
if (count(array_diff($filter->getProductCatalogFilter(), [''])) == 0) {
$this->entityManager->remove($filter);
}
$this->entityManager->flush();
//Flush cache
$employee = Context::getContext()->employee;
$employeeId = $employee->id ?: 0;
$this->cache->deleteItem("app.product_filters_${employeeId}");
}
/**
* {@inheritdoc}
*/
public function combinePersistentCatalogProductFilter($paramsIn = [], $avoidPersistence = false)
{
// retrieve persisted filter parameters
$persistedParams = $this->getPersistedFilterParameters();
// merge with new values
$paramsOut = array_merge($persistedParams, (array) $paramsIn);
// persist new values
if (!$avoidPersistence) {
$this->persistFilterParameters($paramsOut);
}
// return new values
return $paramsOut;
}
/**
* {@inheritdoc}
*/
public function getCatalogProductList(
$offset,
$limit,
$orderBy,
$sortOrder,
$post = [],
$avoidPersistence = false,
$formatCldr = true
) {
$offset = (int) $offset;
$limit = (int) $limit;
$orderBy = Validate::isOrderBy($orderBy) ? $orderBy : 'id_product';
$sortOrder = Validate::isOrderWay($sortOrder) ? $sortOrder : 'desc';
$filterParams = $this->combinePersistentCatalogProductFilter(array_merge(
$post,
['last_offset' => $offset, 'last_limit' => $limit, 'last_orderBy' => $orderBy, 'last_sortOrder' => $sortOrder]
), $avoidPersistence);
$filterParams = AdminFilter::sanitizeFilterParameters($filterParams);
$showPositionColumn = $this->isCategoryFiltered();
if ($orderBy == 'position_ordering' && $showPositionColumn) {
foreach ($filterParams as $key => $param) {
if (strpos($key, 'filter_column_') === 0) {
$filterParams[$key] = '';
}
}
}
if ($orderBy == 'position_ordering') {
$orderBy = 'position';
}
$idShop = Context::getContext()->shop->id;
$idLang = Context::getContext()->language->id;
$sqlSelect = [
'id_product' => ['table' => 'p', 'field' => 'id_product', 'filtering' => ' %s '],
'reference' => ['table' => 'p', 'field' => 'reference', 'filtering' => self::FILTERING_LIKE_BOTH],
'price' => ['table' => 'sa', 'field' => 'price', 'filtering' => ' %s '],
'id_shop_default' => ['table' => 'p', 'field' => 'id_shop_default'],
'is_virtual' => ['table' => 'p', 'field' => 'is_virtual'],
'name' => ['table' => 'pl', 'field' => 'name', 'filtering' => self::FILTERING_LIKE_BOTH],
'link_rewrite' => ['table' => 'pl', 'field' => 'link_rewrite', 'filtering' => self::FILTERING_LIKE_BOTH],
'active' => ['table' => 'sa', 'field' => 'active', 'filtering' => self::FILTERING_EQUAL_NUMERIC],
'shopname' => ['table' => 'shop', 'field' => 'name'],
'id_image' => ['table' => 'image_shop', 'field' => 'id_image'],
'name_category' => ['table' => 'cl', 'field' => 'name', 'filtering' => self::FILTERING_LIKE_BOTH],
'price_final' => '0',
'nb_downloadable' => ['table' => 'pd', 'field' => 'nb_downloadable'],
'sav_quantity' => ['table' => 'sav', 'field' => 'quantity', 'filtering' => ' %s '],
'badge_danger' => ['select' => 'IF(sav.`quantity`<=0, 1, 0)', 'filtering' => 'IF(sav.`quantity`<=0, 1, 0) = %s'],
];
$sqlTable = [
'p' => 'product',
'pl' => [
'table' => 'product_lang',
'join' => 'LEFT JOIN',
'on' => 'pl.`id_product` = p.`id_product` AND pl.`id_lang` = ' . $idLang . ' AND pl.`id_shop` = ' . $idShop,
],
'sav' => [
'table' => 'stock_available',
'join' => 'LEFT JOIN',
'on' => 'sav.`id_product` = p.`id_product` AND sav.`id_product_attribute` = 0' .
StockAvailable::addSqlShopRestriction(null, $idShop, 'sav'),
],
'sa' => [
'table' => 'product_shop',
'join' => 'JOIN',
'on' => 'p.`id_product` = sa.`id_product` AND sa.id_shop = ' . $idShop,
],
'cl' => [
'table' => 'category_lang',
'join' => 'LEFT JOIN',
'on' => 'sa.`id_category_default` = cl.`id_category` AND cl.`id_lang` = ' . $idLang . ' AND cl.id_shop = ' . $idShop,
],
'c' => [
'table' => 'category',
'join' => 'LEFT JOIN',
'on' => 'c.`id_category` = cl.`id_category`',
],
'shop' => [
'table' => 'shop',
'join' => 'LEFT JOIN',
'on' => 'shop.id_shop = ' . $idShop,
],
'image_shop' => [
'table' => 'image_shop',
'join' => 'LEFT JOIN',
'on' => 'image_shop.`id_product` = p.`id_product` AND image_shop.`cover` = 1 AND image_shop.id_shop = ' . $idShop,
],
'i' => [
'table' => 'image',
'join' => 'LEFT JOIN',
'on' => 'i.`id_image` = image_shop.`id_image`',
],
'pd' => [
'table' => 'product_download',
'join' => 'LEFT JOIN',
'on' => 'pd.`id_product` = p.`id_product`',
],
];
$sqlWhere = ['AND', 1];
$sqlOrder = [$orderBy . ' ' . $sortOrder];
if ($orderBy != 'id_product') {
$sqlOrder[] = 'id_product asc'; // secondary order by (useful when ordering by active, quantity, price, etc...)
}
$sqlLimit = $offset . ', ' . $limit;
// Column 'position' added if filtering by category
if ($showPositionColumn) {
$filteredCategoryId = (int) $filterParams['filter_category'];
$sqlSelect['position'] = ['table' => 'cp', 'field' => 'position'];
$sqlTable['cp'] = [
'table' => 'category_product',
'join' => 'INNER JOIN',
'on' => 'cp.`id_product` = p.`id_product` AND cp.`id_category` = ' . $filteredCategoryId,
];
} elseif ($orderBy == 'position') {
// We do not show position column, so we do not join the table, so we do not order by position!
$sqlOrder = ['id_product ASC'];
}
$sqlGroupBy = [];
// exec legacy hook but with different parameters (retro-compat < 1.7 is broken here)
Hook::exec('actionAdminProductsListingFieldsModifier', [
'_ps_version' => AppKernel::VERSION,
'sql_select' => &$sqlSelect,
'sql_table' => &$sqlTable,
'sql_where' => &$sqlWhere,
'sql_group_by' => &$sqlGroupBy,
'sql_order' => &$sqlOrder,
'sql_limit' => &$sqlLimit,
]);
foreach ($filterParams as $filterParam => $filterValue) {
if (!$filterValue && $filterValue !== '0') {
continue;
}
if (strpos($filterParam, 'filter_column_') === 0) {
$filterValue = Db::getInstance()->escape($filterValue, in_array($filterParam, [
'filter_column_id_product',
'filter_column_sav_quantity',
'filter_column_price',
]), true);
$field = substr($filterParam, 14); // 'filter_column_' takes 14 chars
if (isset($sqlSelect[$field]['table'])) {
$sqlWhere[] = $sqlSelect[$field]['table'] . '.`' . $sqlSelect[$field]['field'] . '` ' . sprintf($sqlSelect[$field]['filtering'], $filterValue);
} else {
$sqlWhere[] = '(' . sprintf($sqlSelect[$field]['filtering'], $filterValue) . ')';
}
}
// for 'filter_category', see next if($showPositionColumn) block.
}
$sqlWhere[] = 'state = ' . Product::STATE_SAVED;
// exec legacy hook but with different parameters (retro-compat < 1.7 is broken here)
Hook::exec('actionAdminProductsListingFieldsModifier', [
'_ps_version' => AppKernel::VERSION,
'sql_select' => &$sqlSelect,
'sql_table' => &$sqlTable,
'sql_where' => &$sqlWhere,
'sql_group_by' => &$sqlGroupBy,
'sql_order' => &$sqlOrder,
'sql_limit' => &$sqlLimit,
]);
$sql = $this->compileSqlQuery($sqlSelect, $sqlTable, $sqlWhere, $sqlGroupBy, $sqlOrder, $sqlLimit);
$products = Db::getInstance()->executeS($sql, true, false);
$total = Db::getInstance()->executeS('SELECT FOUND_ROWS();', true, false);
$total = $total[0]['FOUND_ROWS()'];
// post treatment
$currency = new Currency(Configuration::get('PS_CURRENCY_DEFAULT'));
$localeCldr = Tools::getContextLocale(Context::getContext());
foreach ($products as &$product) {
$product['total'] = $total; // total product count (filtered)
$product['price_final'] = Product::getPriceStatic(
$product['id_product'],
true,
null,
Context::getContext()->getComputingPrecision(),
null,
false,
false,
1,
true,
null,
null,
null,
$nothing,
true,
true
);
if ($formatCldr) {
$product['price'] = $localeCldr->formatPrice($product['price'], $currency->iso_code);
$product['price_final'] = $localeCldr->formatPrice($product['price_final'], $currency->iso_code);
}
$product['image'] = $this->imageManager->getThumbnailForListing($product['id_image']);
$product['image_link'] = Context::getContext()->link->getImageLink($product['link_rewrite'], $product['id_image']);
}
// post treatment by hooks
// exec legacy hook but with different parameters (retro-compat < 1.7 is broken here)
Hook::exec('actionAdminProductsListingResultsModifier', [
'_ps_version' => AppKernel::VERSION,
'products' => &$products,
'total' => $total,
]);
return $products;
}
/**
* {@inheritdoc}
*/
public function countAllProducts()
{
$idShop = Context::getContext()->shop->id;
$query = new DbQuery();
$query->select('COUNT(ps.id_product)');
$query->from('product_shop', 'ps');
$query->where('ps.id_shop = ' . (int) $idShop);
$total = Db::getInstance()->getValue($query);
return (int) $total;
}
/**
* Translates new Core route parameters into their Legacy equivalent.
*
* @param string[] $coreParameters The new Core route parameters
*
* @return array<string, int|string> The URL parameters for Legacy URL (GETs)
*/
public function mapLegacyParametersProductForm($coreParameters = [])
{
$params = [];
if ($coreParameters['id'] == '0') {
$params['addproduct'] = 1;
} else {
$params['updateproduct'] = 1;
$params['id_product'] = $coreParameters['id'];
}
return $params;
}
/**
* {@inheritdoc}
*/
public function getPaginationLimitChoices()
{
$paginationLimitChoices = [20, 50, 100];
$memory = Tools::getMemoryLimit();
if ($memory >= 512 * 1024 * 1024) {
$paginationLimitChoices[] = 300;
}
if ($memory >= 1536 * 1024 * 1024) {
$paginationLimitChoices[] = 1000;
}
return $paginationLimitChoices;
}
/**
* {@inheritdoc}
*/
public function isNewProductDefaultActivated()
{
return (bool) Configuration::get('PS_PRODUCT_ACTIVATION_DEFAULT');
}
}

View File

@@ -0,0 +1,299 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
namespace PrestaShop\PrestaShop\Adapter\Product;
use Category;
use Configuration;
use Db;
use GroupReduction;
use Image;
use Pack;
use PrestaShop\PrestaShop\Core\Hook\HookDispatcherInterface;
use PrestaShopBundle\Exception\UpdateProductException;
use PrestaShopBundle\Service\DataUpdater\Admin\ProductInterface;
use Product;
use Search;
use Shop;
use ShopGroup;
use Validate;
/**
* This class will update/insert/delete data from DB / ORM about Product, for both Front and Admin interfaces.
*/
class AdminProductDataUpdater implements ProductInterface
{
/**
* @var HookDispatcherInterface
*/
private $hookDispatcher;
/**
* Constructor. HookDispatcher is injected by Sf container.
*
* @param HookDispatcherInterface $hookDispatcher
*/
public function __construct(HookDispatcherInterface $hookDispatcher)
{
$this->hookDispatcher = $hookDispatcher;
}
/**
* {@inheritdoc}
*/
public function activateProductIdList(array $productListId, $activate = true)
{
if (count($productListId) < 1) {
throw new \Exception('AdminProductDataUpdater->activateProductIdList() should always receive at least one ID. Zero given.', 5003);
}
$failedIdList = [];
foreach ($productListId as $productId) {
$product = new Product($productId);
if (!Validate::isLoadedObject($product)
|| $product->validateFields(false, true) !== true
|| $product->validateFieldsLang(false, true) !== true) {
$failedIdList[] = $productId;
continue;
}
$product->active = (bool) $activate;
$product->update();
if (in_array($product->visibility, ['both', 'search']) && Configuration::get('PS_SEARCH_INDEXATION')) {
Search::indexation(false, $product->id);
}
$this->hookDispatcher->dispatchWithParameters('actionProductActivation', ['id_product' => (int) $product->id, 'product' => $product, 'activated' => $activate]);
}
if (count($failedIdList) > 0) {
throw new UpdateProductException('Cannot change activation state on many requested products', 5004);
}
return true;
}
/**
* {@inheritdoc}
*/
public function deleteProductIdList(array $productIdList)
{
if (count($productIdList) < 1) {
throw new \Exception('AdminProductDataUpdater->deleteProductIdList() should always receive at least one ID. Zero given.', 5005);
}
$failedIdList = $productIdList; // Since we have just one call to delete all, cannot have distinctive fails.
// Hooks: will trigger actionProductDelete multiple times
$result = (new Product())->deleteSelection($productIdList);
if ($result === 0) {
throw new UpdateProductException('Cannot delete many requested products.', 5006);
}
return true;
}
/**
* {@inheritdoc}
*/
public function duplicateProductIdList(array $productIdList)
{
if (count($productIdList) < 1) {
throw new \Exception('AdminProductDataUpdater->duplicateProductIdList() should always receive at least one ID. Zero given.', 5005);
}
$failedIdList = [];
foreach ($productIdList as $productId) {
try {
$this->duplicateProduct($productId);
} catch (\Exception $e) {
$failedIdList[] = $productId;
continue;
}
}
if (count($failedIdList) > 0) {
throw new UpdateProductException('Cannot duplicate many requested products', 5004);
}
return true;
}
/**
* {@inheritdoc}
*/
public function deleteProduct($productId)
{
$product = new Product($productId);
if (!Validate::isLoadedObject($product)) {
throw new \Exception('AdminProductDataUpdater->deleteProduct() received an unknown ID.', 5005);
}
// dumb? no: delete() makes a lot of things, and can reject deletion in specific cases.
// Hooks: will trigger actionProductDelete
$result = $product->delete();
if ($result === 0) {
throw new UpdateProductException('Cannot delete the requested product.', 5007);
}
return true;
}
/**
* {@inheritdoc}
*/
public function duplicateProduct($productId, $namePattern = 'copy of %s')
{
//TODO : use the $namePattern var to input translated version of 'copy of %s', if translation requested.
$product = new Product($productId);
if (!Validate::isLoadedObject($product)) {
throw new \Exception('AdminProductDataUpdater->duplicateProduct() received an unknown ID.', 5005);
}
if (($error = $product->validateFields(false, true)) !== true
|| ($error = $product->validateFieldsLang(false, true)) !== true) {
throw new UpdateProductException(sprintf('Cannot duplicate this product: %s', $error));
}
$id_product_old = $product->id;
if (empty($product->price) && Shop::getContext() == Shop::CONTEXT_GROUP) {
$shops = ShopGroup::getShopsFromGroup(Shop::getContextShopGroupID());
foreach ($shops as $shop) {
if ($product->isAssociatedToShop($shop['id_shop'])) {
$product_price = new Product($id_product_old, false, null, $shop['id_shop']);
$product->price = $product_price->price;
}
}
}
unset(
$product->id,
$product->id_product
);
$product->indexed = false;
$product->active = false;
// change product name to prefix it
foreach ($product->name as $langKey => $oldName) {
if (!preg_match('/^' . str_replace('%s', '.*', preg_quote($namePattern, '/') . '$/'), $oldName)) {
$newName = sprintf($namePattern, $oldName);
if (mb_strlen($newName, 'UTF-8') <= 127) {
$product->name[$langKey] = $newName;
}
}
}
if ($product->add()
&& Category::duplicateProductCategories($id_product_old, $product->id)
&& Product::duplicateSuppliers($id_product_old, $product->id)
&& ($combination_images = Product::duplicateAttributes($id_product_old, $product->id)) !== false
&& GroupReduction::duplicateReduction($id_product_old, $product->id)
&& Product::duplicateAccessories($id_product_old, $product->id)
&& Product::duplicateFeatures($id_product_old, $product->id)
&& Product::duplicateSpecificPrices($id_product_old, $product->id)
&& Pack::duplicate($id_product_old, $product->id)
&& Product::duplicateCustomizationFields($id_product_old, $product->id)
&& Product::duplicatePrices($id_product_old, $product->id)
&& Product::duplicateTags($id_product_old, $product->id)
&& Product::duplicateTaxes($id_product_old, $product->id)
&& Product::duplicateDownload($id_product_old, $product->id)) {
if ($product->hasAttributes()) {
Product::updateDefaultAttribute($product->id);
}
if (!Image::duplicateProductImages($id_product_old, $product->id, $combination_images)) {
throw new UpdateProductException('An error occurred while copying images.', 5008);
} else {
$this->hookDispatcher->dispatchWithParameters('actionProductAdd', ['id_product_old' => $id_product_old, 'id_product' => (int) $product->id, 'product' => $product]);
if (in_array($product->visibility, ['both', 'search']) && Configuration::get('PS_SEARCH_INDEXATION')) {
Search::indexation(false, $product->id);
}
return $product->id;
}
} else {
if ($product->id !== null) {
$product->delete();
}
throw new \Exception('An error occurred while creating an object.', 5009);
}
}
/**
* {@inheritdoc}
*/
public function sortProductIdList(array $productList, $filterParams)
{
if (count($productList) < 2) {
return false;
}
if (!isset($filterParams['filter_category'])) {
throw new \Exception('Cannot sort when filterParams does not contains \'filter_category\'.', 5010);
}
foreach ($filterParams as $k => $v) {
if ($v == '' || strpos($k, 'filter_') !== 0) {
continue;
}
if ($k == 'filter_category') {
continue;
}
throw new \Exception('Cannot sort when filterParams contains other filter than \'filter_category\'.', 5010);
}
$categoryId = $filterParams['filter_category'];
$minPosition = min(array_values($productList));
$productsIds = implode(',', array_map('intval', array_keys($productList)));
/*
* First request to update position on category_product
*/
Db::getInstance()->query('SET @i := ' . (((int) $minPosition) - 1));
$updatePositions = 'UPDATE `' . _DB_PREFIX_ . 'category_product` cp ' .
'SET cp.`position` = (SELECT @i := @i + 1) ' .
'WHERE cp.`id_category` = ' . (int) $categoryId . ' AND cp.`id_product` IN (' . $productsIds . ') ' .
'ORDER BY FIELD(cp.`id_product`, ' . $productsIds . ')';
Db::getInstance()->query($updatePositions);
/**
* Second request to update date_upd because
* ORDER BY is not working on multi-tables update
*/
$updateProducts = 'UPDATE `' . _DB_PREFIX_ . 'product` p ' .
'' . Shop::addSqlAssociation('product', 'p') . ' ' .
'SET ' .
' p.`date_upd` = "' . date('Y-m-d H:i:s') . '", ' .
' product_shop.`date_upd` = "' . date('Y-m-d H:i:s') . '" ' .
'WHERE p.`id_product` IN (' . $productsIds . ') ';
Db::getInstance()->query($updateProducts);
return true;
}
}

View File

@@ -0,0 +1,964 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
namespace PrestaShop\PrestaShop\Adapter\Product;
use AdminProductsController;
use Attachment;
use Category;
use Combination;
use Configuration;
use Context;
use Customer;
use Db;
use Hook;
use Image;
use Language;
use ObjectModel;
use PrestaShop\PrestaShop\Adapter\Entity\Customization;
use PrestaShop\PrestaShop\Core\Foundation\Database\EntityNotFoundException;
use PrestaShop\PrestaShop\Core\Localization\Locale;
use PrestaShopBundle\Form\Admin\Type\CustomMoneyType;
use PrestaShopBundle\Utils\FloatParser;
use Product;
use ProductDownload;
use Shop;
use ShopUrl;
use SpecificPrice;
use SpecificPriceRule;
use StockAvailable;
use Symfony\Component\Translation\TranslatorInterface;
use Tax;
use Tools;
use Validate;
/**
* Admin controller wrapper for new Architecture, about Product admin controller.
*/
class AdminProductWrapper
{
/**
* @var array
*/
private $errors = [];
/**
* @var Locale
*/
private $locale;
/**
* @var TranslatorInterface
*/
private $translator;
/**
* @var array
*/
private $employeeAssociatedShops;
/**
* @var FloatParser
*/
private $floatParser;
/**
* Constructor : Inject Symfony\Component\Translation Translator.
*
* @param object $translator
* @param array $employeeAssociatedShops
* @param Locale $locale
* @param FloatParser|null $floatParser
*/
public function __construct($translator, array $employeeAssociatedShops, Locale $locale, FloatParser $floatParser = null)
{
$this->translator = $translator;
$this->employeeAssociatedShops = $employeeAssociatedShops;
$this->locale = $locale;
$this->floatParser = $floatParser ?? new FloatParser();
}
/**
* getInstance
* Get the legacy AdminProductsControllerCore instance.
*
* @return AdminProductsController instance
*/
public function getInstance()
{
return new AdminProductsController();
}
/**
* processProductAttribute
* Update a combination.
*
* @param object $product
* @param array $combinationValues the posted values
*
* @return void
*/
public function processProductAttribute($product, $combinationValues)
{
$id_product_attribute = (int) $combinationValues['id_product_attribute'];
$images = [];
if (!Combination::isFeatureActive() || $id_product_attribute == 0) {
return;
}
if (!isset($combinationValues['attribute_wholesale_price'])) {
$combinationValues['attribute_wholesale_price'] = 0;
}
if (!isset($combinationValues['attribute_price_impact'])) {
$combinationValues['attribute_price_impact'] = 0;
}
if (!isset($combinationValues['attribute_weight_impact'])) {
$combinationValues['attribute_weight_impact'] = 0;
}
// This is VERY UGLY, but since ti ComputingPrecision can never return enough decimals for now we have no
// choice but to hard code this one to make sure enough precision is saved in the DB or it results in errors
// of 1 cent in the shop
$computingPrecision = CustomMoneyType::PRESTASHOP_DECIMALS;
if (!isset($combinationValues['attribute_ecotax']) || 0.0 === (float) $combinationValues['attribute_ecotax']) {
$combinationValues['attribute_ecotax'] = 0;
} else {
// Value is displayed tax included but must be saved tax excluded
$combinationValues['attribute_ecotax'] = Tools::ps_round(
$combinationValues['attribute_ecotax'] / (1 + Tax::getProductEcotaxRate() / 100),
$computingPrecision
);
}
if ((isset($combinationValues['attribute_default']) && $combinationValues['attribute_default'] == 1)) {
$product->deleteDefaultAttributes();
}
if (!empty($combinationValues['id_image_attr'])) {
$images = $combinationValues['id_image_attr'];
} else {
$combination = new Combination($id_product_attribute);
$combination->setImages([]);
}
if (!isset($combinationValues['attribute_low_stock_threshold'])) {
$combinationValues['attribute_low_stock_threshold'] = null;
}
if (!isset($combinationValues['attribute_low_stock_alert'])) {
$combinationValues['attribute_low_stock_alert'] = false;
}
$product->updateAttribute(
$id_product_attribute,
$combinationValues['attribute_wholesale_price'],
$combinationValues['attribute_price'] * $combinationValues['attribute_price_impact'],
$combinationValues['attribute_weight'] * $combinationValues['attribute_weight_impact'],
$combinationValues['attribute_unity'] * $combinationValues['attribute_unit_impact'],
$combinationValues['attribute_ecotax'],
$images,
$combinationValues['attribute_reference'],
$combinationValues['attribute_ean13'],
(isset($combinationValues['attribute_default']) && $combinationValues['attribute_default'] == 1),
isset($combinationValues['attribute_location']) ? $combinationValues['attribute_location'] : null,
$combinationValues['attribute_upc'],
$combinationValues['attribute_minimal_quantity'],
$combinationValues['available_date_attribute'],
false,
[],
$combinationValues['attribute_isbn'],
$combinationValues['attribute_low_stock_threshold'],
$combinationValues['attribute_low_stock_alert'],
$combinationValues['attribute_mpn']
);
StockAvailable::setProductDependsOnStock((int) $product->id, $product->depends_on_stock, null, $id_product_attribute);
StockAvailable::setProductOutOfStock((int) $product->id, $product->out_of_stock, null, $id_product_attribute);
StockAvailable::setLocation((int) $product->id, $combinationValues['attribute_location'], null, $id_product_attribute);
$product->checkDefaultAttributes();
if ((isset($combinationValues['attribute_default']) && $combinationValues['attribute_default'] == 1)) {
Product::updateDefaultAttribute((int) $product->id);
$product->cache_default_attribute = (int) $id_product_attribute;
// We need to reload the product because some other calls have modified the database
// It's done just for the setAvailableDate to avoid side effects
Product::disableCache();
$consistentProduct = new Product($product->id);
if ($available_date = $combinationValues['available_date_attribute']) {
$consistentProduct->setAvailableDate($available_date);
} else {
$consistentProduct->setAvailableDate();
}
Product::enableCache();
}
if (isset($combinationValues['attribute_quantity'])) {
$this->processQuantityUpdate($product, $combinationValues['attribute_quantity'], $id_product_attribute);
}
}
/**
* Update a quantity for a product or a combination.
*
* Does not work in Advanced stock management.
*
* @param Product $product
* @param int $quantity
* @param int $forAttributeId
*/
public function processQuantityUpdate(Product $product, $quantity, $forAttributeId = 0)
{
// Hook triggered by legacy code below: actionUpdateQuantity('id_product', 'id_product_attribute', 'quantity')
StockAvailable::setQuantity((int) $product->id, $forAttributeId, $quantity);
Hook::exec('actionProductUpdate', ['id_product' => (int) $product->id, 'product' => $product]);
}
/**
* Update the out of stock strategy.
*
* @param Product $product
* @param int $out_of_stock
*/
public function processProductOutOfStock(Product $product, $out_of_stock)
{
StockAvailable::setProductOutOfStock((int) $product->id, (int) $out_of_stock);
}
/**
* @param Product $product
* @param string $location
*/
public function processLocation(Product $product, $location)
{
StockAvailable::setLocation($product->id, $location);
}
/**
* Set if a product depends on stock (ASM). For a product or a combination.
*
* Does work only in Advanced stock management.
*
* @param Product $product
* @param bool $dependsOnStock
* @param int $forAttributeId
*/
public function processDependsOnStock(Product $product, $dependsOnStock, $forAttributeId = 0)
{
StockAvailable::setProductDependsOnStock((int) $product->id, $dependsOnStock, null, $forAttributeId);
}
/**
* Add/Update a SpecificPrice object.
*
* @param int $id_product
* @param array $specificPriceValues the posted values
* @param int|null $idSpecificPrice if this is an update of an existing specific price, null else
*
* @return AdminProductsController|array
*/
public function processProductSpecificPrice($id_product, $specificPriceValues, $idSpecificPrice = null)
{
// ---- data formatting ----
$id_product_attribute = $specificPriceValues['sp_id_product_attribute'] ?? 0;
$id_shop = $specificPriceValues['sp_id_shop'] ? $specificPriceValues['sp_id_shop'] : 0;
$id_currency = $specificPriceValues['sp_id_currency'] ? $specificPriceValues['sp_id_currency'] : 0;
$id_country = $specificPriceValues['sp_id_country'] ? $specificPriceValues['sp_id_country'] : 0;
$id_group = $specificPriceValues['sp_id_group'] ? $specificPriceValues['sp_id_group'] : 0;
$id_customer = !empty($specificPriceValues['sp_id_customer']['data']) ? $specificPriceValues['sp_id_customer']['data'][0] : 0;
$price = isset($specificPriceValues['leave_bprice']) ? '-1' : $this->floatParser->fromString($specificPriceValues['sp_price']);
$from_quantity = $specificPriceValues['sp_from_quantity'];
$reduction = $this->floatParser->fromString($specificPriceValues['sp_reduction']);
$reduction_tax = $specificPriceValues['sp_reduction_tax'];
$reduction_type = !$reduction ? 'amount' : $specificPriceValues['sp_reduction_type'];
$reduction_type = $reduction_type == '-' ? 'amount' : $reduction_type;
$from = $specificPriceValues['sp_from'];
if (!$from) {
$from = '0000-00-00 00:00:00';
}
$to = $specificPriceValues['sp_to'];
if (!$to) {
$to = '0000-00-00 00:00:00';
}
$isThisAnUpdate = (null !== $idSpecificPrice);
// ---- validation ----
if (($price == '-1') && ((float) $reduction == '0')) {
$this->errors[] = $this->translator->trans('No reduction value has been submitted', [], 'Admin.Catalog.Notification');
} elseif ($to != '0000-00-00 00:00:00' && strtotime($to) < strtotime($from)) {
$this->errors[] = $this->translator->trans('Invalid date range', [], 'Admin.Catalog.Notification');
} elseif ($reduction_type == 'percentage' && ((float) $reduction <= 0 || (float) $reduction > 100)) {
$this->errors[] = $this->translator->trans('Submitted reduction value (0-100) is out-of-range', [], 'Admin.Catalog.Notification');
}
$validationResult = $this->validateSpecificPrice(
$id_product,
$id_shop,
$id_currency,
$id_country,
$id_group,
$id_customer,
$price,
$from_quantity,
$reduction,
$reduction_type,
$from,
$to,
$id_product_attribute,
$isThisAnUpdate
);
if (false === $validationResult || count($this->errors)) {
return $this->errors;
}
// ---- data modification ----
if ($isThisAnUpdate) {
$specificPrice = new SpecificPrice($idSpecificPrice);
} else {
$specificPrice = new SpecificPrice();
}
$specificPrice->id_product = (int) $id_product;
$specificPrice->id_product_attribute = (int) $id_product_attribute;
$specificPrice->id_shop = (int) $id_shop;
$specificPrice->id_currency = (int) ($id_currency);
$specificPrice->id_country = (int) ($id_country);
$specificPrice->id_group = (int) ($id_group);
$specificPrice->id_customer = (int) $id_customer;
$specificPrice->price = (float) ($price);
$specificPrice->from_quantity = (int) ($from_quantity);
$specificPrice->reduction = (float) ($reduction_type == 'percentage' ? $reduction / 100 : $reduction);
$specificPrice->reduction_tax = $reduction_tax;
$specificPrice->reduction_type = $reduction_type;
$specificPrice->from = $from;
$specificPrice->to = $to;
if ($isThisAnUpdate) {
$dataSavingResult = $specificPrice->save();
} else {
$dataSavingResult = $specificPrice->add();
}
if (false === $dataSavingResult) {
$this->errors[] = $this->translator->trans('An error occurred while updating the specific price.', [], 'Admin.Catalog.Notification');
}
return $this->errors;
}
/**
* Validate a specific price.
*/
private function validateSpecificPrice(
$id_product,
$id_shop,
$id_currency,
$id_country,
$id_group,
$id_customer,
$price,
$from_quantity,
$reduction,
$reduction_type,
$from,
$to,
$id_combination = 0,
$isThisAnUpdate = false
) {
if (!Validate::isUnsignedId($id_shop) || !Validate::isUnsignedId($id_currency) || !Validate::isUnsignedId($id_country) || !Validate::isUnsignedId($id_group) || !Validate::isUnsignedId($id_customer)) {
$this->errors[] = 'Wrong IDs';
} elseif ((!isset($price) && !isset($reduction)) || (isset($price) && !Validate::isNegativePrice($price)) || (isset($reduction) && !Validate::isPrice($reduction))) {
$this->errors[] = 'Invalid price/discount amount';
} elseif (!Validate::isUnsignedInt($from_quantity)) {
$this->errors[] = 'Invalid quantity';
} elseif ($reduction && !Validate::isReductionType($reduction_type)) {
$this->errors[] = 'Please select a discount type (amount or percentage).';
} elseif ($from && $to && (!Validate::isDateFormat($from) || !Validate::isDateFormat($to))) {
$this->errors[] = 'The from/to date is invalid.';
} elseif (!$isThisAnUpdate && SpecificPrice::exists((int) $id_product, $id_combination, $id_shop, $id_group, $id_country, $id_currency, $id_customer, $from_quantity, $from, $to, false)) {
$this->errors[] = 'A specific price already exists for these parameters.';
} else {
return true;
}
return false;
}
/**
* Get specific prices list for a product.
*
* @param object $product
* @param object $defaultCurrency
* @param array $shops Available shops
* @param array $currencies Available currencies
* @param array $countries Available countries
* @param array $groups Available users groups
*
* @return array
*/
public function getSpecificPricesList($product, $defaultCurrency, $shops, $currencies, $countries, $groups)
{
$content = [];
$specific_prices = array_merge(
SpecificPrice::getByProductId((int) $product->id),
SpecificPrice::getByProductId(0)
);
$tmp = [];
foreach ($shops as $shop) {
$tmp[$shop['id_shop']] = $shop;
}
$shops = $tmp;
$tmp = [];
foreach ($currencies as $currency) {
$tmp[$currency['id_currency']] = $currency;
}
$currencies = $tmp;
$tmp = [];
foreach ($countries as $country) {
$tmp[$country['id_country']] = $country;
}
$countries = $tmp;
$tmp = [];
foreach ($groups as $group) {
$tmp[$group['id_group']] = $group;
}
$groups = $tmp;
if (is_array($specific_prices) && count($specific_prices)) {
foreach ($specific_prices as $specific_price) {
$id_currency = $specific_price['id_currency'] ? $specific_price['id_currency'] : $defaultCurrency->id;
if (!isset($currencies[$id_currency])) {
continue;
}
$current_specific_currency = $currencies[$id_currency];
if ($specific_price['reduction_type'] == 'percentage') {
$impact = '- ' . ($specific_price['reduction'] * 100) . ' %';
} elseif ($specific_price['reduction'] > 0) {
$impact = '- ' . $this->locale->formatPrice($specific_price['reduction'], $current_specific_currency['iso_code']) . ' ';
if ($specific_price['reduction_tax']) {
$impact .= '(' . $this->translator->trans('Tax incl.', [], 'Admin.Global') . ')';
} else {
$impact .= '(' . $this->translator->trans('Tax excl.', [], 'Admin.Global') . ')';
}
} else {
$impact = '--';
}
if ($specific_price['from'] == '0000-00-00 00:00:00' && $specific_price['to'] == '0000-00-00 00:00:00') {
$period = $this->translator->trans('Unlimited', [], 'Admin.Global');
} else {
$period = $this->translator->trans('From', [], 'Admin.Global') . ' ' . ($specific_price['from'] != '0000-00-00 00:00:00' ? $specific_price['from'] : '0000-00-00 00:00:00') . '<br />' . $this->translator->trans('to', [], 'Admin.Global') . ' ' . ($specific_price['to'] != '0000-00-00 00:00:00' ? $specific_price['to'] : '0000-00-00 00:00:00');
}
if ($specific_price['id_product_attribute']) {
$combination = new Combination((int) $specific_price['id_product_attribute']);
$attributes = $combination->getAttributesName(1);
$attributes_name = '';
foreach ($attributes as $attribute) {
$attributes_name .= $attribute['name'] . ' - ';
}
$attributes_name = rtrim($attributes_name, ' - ');
} else {
$attributes_name = $this->translator->trans('All combinations', [], 'Admin.Catalog.Feature');
}
$rule = new SpecificPriceRule((int) $specific_price['id_specific_price_rule']);
$rule_name = ($rule->id ? $rule->name : '--');
if ($specific_price['id_customer']) {
$customer = new Customer((int) $specific_price['id_customer']);
if (Validate::isLoadedObject($customer)) {
$customer_full_name = $customer->firstname . ' ' . $customer->lastname;
}
unset($customer);
}
if (!$specific_price['id_shop'] || in_array($specific_price['id_shop'], Shop::getContextListShopID())) {
$can_delete_specific_prices = true;
if (Shop::isFeatureActive()) {
$can_delete_specific_prices = (count($this->employeeAssociatedShops) > 1 && !$specific_price['id_shop']) || $specific_price['id_shop'];
}
$price = Tools::ps_round($specific_price['price'], 2);
$fixed_price = (($price == Tools::ps_round($product->price, 2) && $current_specific_currency['id_currency'] == $defaultCurrency->id) || $specific_price['price'] == -1) ? '--' : $this->locale->formatPrice($price, $current_specific_currency['iso_code']);
$content[] = [
'id_specific_price' => $specific_price['id_specific_price'],
'id_product' => $product->id,
'rule_name' => $rule_name,
'attributes_name' => $attributes_name,
'shop' => ($specific_price['id_shop'] ? $shops[$specific_price['id_shop']]['name'] : $this->translator->trans('All shops', [], 'Admin.Global')),
'currency' => ($specific_price['id_currency'] ? $currencies[$specific_price['id_currency']]['name'] : $this->translator->trans('All currencies', [], 'Admin.Global')),
'country' => ($specific_price['id_country'] ? $countries[$specific_price['id_country']]['name'] : $this->translator->trans('All countries', [], 'Admin.Global')),
'group' => ($specific_price['id_group'] ? $groups[$specific_price['id_group']]['name'] : $this->translator->trans('All groups', [], 'Admin.Global')),
'customer' => (isset($customer_full_name) ? $customer_full_name : $this->translator->trans('All customers', [], 'Admin.Global')),
'fixed_price' => $fixed_price,
'impact' => $impact,
'period' => $period,
'from_quantity' => $specific_price['from_quantity'],
'can_delete' => (!$rule->id && $can_delete_specific_prices) ? true : false,
'can_edit' => (!$rule->id && $can_delete_specific_prices) ? true : false,
];
unset($customer_full_name);
}
}
}
return $content;
}
/**
* @param int $id
*
* @return SpecificPrice
*
* @throws EntityNotFoundException
*/
public function getSpecificPriceDataById($id)
{
$price = new SpecificPrice($id);
if (null === $price->id) {
throw new EntityNotFoundException(sprintf('Cannot find specific price with id %d', $id));
}
return $price;
}
/**
* Delete a specific price.
*
* @param int $id_specific_price
*
* @return array error & status
*/
public function deleteSpecificPrice($id_specific_price)
{
if (!$id_specific_price || !Validate::isUnsignedId($id_specific_price)) {
$error = $this->translator->trans('The specific price ID is invalid.', [], 'Admin.Catalog.Notification');
} else {
$specificPrice = new SpecificPrice((int) $id_specific_price);
if (!$specificPrice->delete()) {
$error = $this->translator->trans('An error occurred while attempting to delete the specific price.', [], 'Admin.Catalog.Notification');
}
}
if (isset($error)) {
return [
'status' => 'error',
'message' => $error,
];
}
return [
'status' => 'ok',
'message' => $this->translator->trans('Successful deletion', [], 'Admin.Notifications.Success'),
];
}
/**
* Get price priority.
*
* @param int|null $idProduct
*
* @return array
*/
public function getPricePriority($idProduct = null)
{
if (!$idProduct) {
return [
0 => 'id_shop',
1 => 'id_currency',
2 => 'id_country',
3 => 'id_group',
];
}
$specific_price_priorities = SpecificPrice::getPriority((int) $idProduct);
// Not use id_customer
if ($specific_price_priorities[0] == 'id_customer') {
unset($specific_price_priorities[0]);
}
return array_values($specific_price_priorities);
}
/**
* Process customization collection.
*
* @param object $product
* @param array $data
*
* @return array<int, int>
*/
public function processProductCustomization($product, $data)
{
$customization_ids = [];
if ($data) {
foreach ($data as $customization) {
$customization_ids[] = (int) $customization['id_customization_field'];
}
}
$shopList = Shop::getContextListShopID();
/* Update the customization fields to be deleted in the next step if not used */
$product->softDeleteCustomizationFields($customization_ids);
$usedCustomizationIds = $product->getUsedCustomizationFieldsIds();
$usedCustomizationIds = array_column($usedCustomizationIds, 'index');
$usedCustomizationIds = array_map('intval', $usedCustomizationIds);
$usedCustomizationIds = array_unique(array_merge($usedCustomizationIds, $customization_ids), SORT_REGULAR);
//remove customization field langs for current context shops
$productCustomization = $product->getCustomizationFieldIds();
$toDeleteCustomizationIds = [];
foreach ($productCustomization as $customizationFiled) {
if (!in_array((int) $customizationFiled['id_customization_field'], $usedCustomizationIds)) {
$toDeleteCustomizationIds[] = (int) $customizationFiled['id_customization_field'];
}
//if the customization_field is still in use, only delete the current context shops langs,
if (in_array((int) $customizationFiled['id_customization_field'], $customization_ids)) {
Customization::deleteCustomizationFieldLangByShop($customizationFiled['id_customization_field'], $shopList);
}
}
//remove unused customization for the product
$product->deleteUnusedCustomizationFields($toDeleteCustomizationIds);
//create new customizations
$countFieldText = 0;
$countFieldFile = 0;
$productCustomizableValue = 0;
$hasRequiredField = false;
$new_customization_fields_ids = [];
if ($data) {
foreach ($data as $key => $customization) {
if ($customization['require']) {
$hasRequiredField = true;
}
//create label
if (isset($customization['id_customization_field'])) {
$id_customization_field = (int) $customization['id_customization_field'];
Db::getInstance()->execute('UPDATE `' . _DB_PREFIX_ . 'customization_field`
SET `required` = ' . ($customization['require'] ? 1 : 0) . ', `type` = ' . (int) $customization['type'] . '
WHERE `id_customization_field` = ' . $id_customization_field);
} else {
Db::getInstance()->execute(
'INSERT INTO `' . _DB_PREFIX_ . 'customization_field` (`id_product`, `type`, `required`)
VALUES ('
. (int) $product->id . ', '
. (int) $customization['type'] . ', '
. ($customization['require'] ? 1 : 0)
. ')'
);
$id_customization_field = (int) Db::getInstance()->Insert_ID();
}
$new_customization_fields_ids[$key] = $id_customization_field;
// Create multilingual label name
$langValues = '';
foreach (Language::getLanguages() as $language) {
$name = $customization['label'][$language['id_lang']];
foreach ($shopList as $id_shop) {
$langValues .= '('
. (int) $id_customization_field . ', '
. (int) $language['id_lang'] . ', '
. (int) $id_shop . ',\''
. pSQL($name)
. '\'), ';
}
}
Db::getInstance()->execute(
'INSERT INTO `' . _DB_PREFIX_ . 'customization_field_lang` (`id_customization_field`, `id_lang`, `id_shop`, `name`) VALUES '
. rtrim(
$langValues,
', '
)
);
if ($customization['type'] == Product::CUSTOMIZE_FILE) {
++$countFieldFile;
} else {
++$countFieldText;
}
}
$productCustomizableValue = $hasRequiredField ? 2 : 1;
}
//update product count fields labels
Db::getInstance()->execute('UPDATE `' . _DB_PREFIX_ . 'product` SET `customizable` = ' . $productCustomizableValue . ', `uploadable_files` = ' . (int) $countFieldFile . ', `text_fields` = ' . (int) $countFieldText . ' WHERE `id_product` = ' . (int) $product->id);
//update product_shop count fields labels
ObjectModel::updateMultishopTable('product', [
'customizable' => $productCustomizableValue,
'uploadable_files' => (int) $countFieldFile,
'text_fields' => (int) $countFieldText,
], 'a.id_product = ' . (int) $product->id);
Configuration::updateGlobalValue('PS_CUSTOMIZATION_FEATURE_ACTIVE', '1');
return $new_customization_fields_ids;
}
/**
* Update product download.
*
* @param object $product
* @param array $data
*
* @return ProductDownload
*/
public function updateDownloadProduct($product, $data)
{
$id_product_download = ProductDownload::getIdFromIdProduct((int) $product->id, false);
$download = new ProductDownload($id_product_download ? $id_product_download : null);
if ((int) $data['is_virtual_file'] == 1) {
$fileName = null;
$file = $data['file'];
if (!empty($file)) {
$fileName = ProductDownload::getNewFilename();
$file->move(_PS_DOWNLOAD_DIR_, $fileName);
}
$product->setDefaultAttribute(0); //reset cache_default_attribute
$download->id_product = (int) $product->id;
$download->display_filename = $data['name'];
$download->filename = $fileName ? $fileName : $download->filename;
$download->date_add = date('Y-m-d H:i:s');
$download->date_expiration = $data['expiration_date'] ? $data['expiration_date'] . ' 23:59:59' : '';
$download->nb_days_accessible = (int) $data['nb_days'];
$download->nb_downloadable = (int) $data['nb_downloadable'];
$download->active = true;
$download->is_shareable = false;
if (!$id_product_download) {
$download->save();
} else {
$download->update();
}
} else {
if (!empty($id_product_download)) {
$download->date_expiration = date('Y-m-d H:i:s', time() - 1);
$download->active = false;
$download->update();
}
}
return $download;
}
/**
* Delete file from a virtual product.
*
* @param object $product
*/
public function processDeleteVirtualProductFile($product)
{
$id_product_download = ProductDownload::getIdFromIdProduct((int) $product->id, false);
$download = new ProductDownload($id_product_download ? $id_product_download : null);
if (!empty($download->filename)) {
unlink(_PS_DOWNLOAD_DIR_ . $download->filename);
Db::getInstance()->execute('UPDATE `' . _DB_PREFIX_ . 'product_download` SET filename = "" WHERE `id_product_download` = ' . (int) $download->id);
}
}
/**
* Delete a virtual product.
*
* @param object $product
*/
public function processDeleteVirtualProduct($product)
{
$id_product_download = ProductDownload::getIdFromIdProduct((int) $product->id, false);
$download = new ProductDownload($id_product_download ? $id_product_download : null);
if (Validate::isLoadedObject($download)) {
$download->delete(true);
}
}
/**
* Add attachement file.
*
* @param object $product
* @param array $data
* @param array $locales
*
* @return object|null Attachement
*/
public function processAddAttachment($product, $data, $locales)
{
$attachment = null;
$file = $data['file'];
if (!empty($file)) {
$fileName = sha1(microtime());
$attachment = new Attachment();
foreach ($locales as $locale) {
$attachment->name[(int) $locale['id_lang']] = $data['name'];
$attachment->description[(int) $locale['id_lang']] = $data['description'];
}
$attachment->file = $fileName;
$attachment->mime = $file->getMimeType();
$attachment->file_name = $file->getClientOriginalName();
$file->move(_PS_DOWNLOAD_DIR_, $fileName);
if ($attachment->add()) {
$attachment->attachProduct($product->id);
}
}
return $attachment;
}
/**
* Process product attachments.
*
* @param object $product
* @param array $data
*/
public function processAttachments($product, $data)
{
Attachment::attachToProduct($product->id, $data);
}
/**
* Update images positions.
*
* @param array $data Indexed array with id product/position
*/
public function ajaxProcessUpdateImagePosition($data)
{
foreach ($data as $id => $position) {
$img = new Image((int) $id);
$img->position = (int) $position;
$img->update();
}
}
/**
* Update image legend and cover.
*
* @param int $idImage
* @param array $data
*
* @return object image
*/
public function ajaxProcessUpdateImage($idImage, $data)
{
$img = new Image((int) $idImage);
if ($data['cover']) {
Image::deleteCover((int) $img->id_product);
$img->cover = true;
}
$img->legend = $data['legend'];
$img->update();
return $img;
}
/**
* Generate preview URL.
*
* @param object $product
* @param bool $preview
*
* @return string|bool Preview url
*/
public function getPreviewUrl($product, $preview = true)
{
$context = Context::getContext();
$id_lang = Configuration::get('PS_LANG_DEFAULT', null, null, $context->shop->id);
if (!ShopUrl::getMainShopDomain()) {
return false;
}
$is_rewrite_active = (bool) Configuration::get('PS_REWRITING_SETTINGS');
$preview_url = $context->link->getProductLink(
$product,
$product->link_rewrite[$context->language->id],
Category::getLinkRewrite($product->id_category_default, $context->language->id),
null,
$id_lang,
(int) $context->shop->id,
0,
$is_rewrite_active
);
if (!$product->active && $preview) {
$preview_url = $this->getPreviewUrlDeactivate($preview_url);
}
return $preview_url;
}
/**
* Generate preview URL deactivate.
*
* @param string $preview_url
*
* @return string preview url deactivate
*/
public function getPreviewUrlDeactivate($preview_url)
{
$context = Context::getContext();
$token = Tools::getAdminTokenLite('AdminProducts');
$admin_dir = dirname($_SERVER['PHP_SELF']);
$admin_dir = substr($admin_dir, strrpos($admin_dir, '/') + 1);
$preview_url_deactivate = $preview_url . ((strpos($preview_url, '?') === false) ? '?' : '&') . 'adtoken=' . $token . '&ad=' . $admin_dir . '&id_employee=' . (int) $context->employee->id . '&preview=1';
return $preview_url_deactivate;
}
/**
* Generate preview URL.
*
* @param int $productId
*
* @return string preview url
*/
public function getPreviewUrlFromId($productId)
{
$product = new Product($productId, false);
return $this->getPreviewUrl($product);
}
}

View File

@@ -0,0 +1,52 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
namespace PrestaShop\PrestaShop\Adapter\Product;
use Db;
/**
* This class will provide data from DB / ORM about attachment.
*/
class AttachmentDataProvider
{
/**
* Get all attachments.
*
* @param int $id_lang
*
* @return array Attachment
*/
public function getAllAttachments($id_lang)
{
return Db::getInstance()->executeS('
SELECT *
FROM ' . _DB_PREFIX_ . 'attachment a
LEFT JOIN ' . _DB_PREFIX_ . 'attachment_lang al
ON (a.id_attachment = al.id_attachment AND al.id_lang = ' . (int) $id_lang . ')
');
}
}

View File

@@ -0,0 +1,80 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\AttributeGroup;
use AttributeGroup;
use PrestaShop\PrestaShop\Core\Domain\Product\AttributeGroup\Exception\AttributeGroupException;
use PrestaShop\PrestaShop\Core\Domain\Product\AttributeGroup\Exception\AttributeGroupNotFoundException;
use PrestaShop\PrestaShop\Core\Domain\Product\AttributeGroup\ValueObject\AttributeGroupId;
use PrestaShopException;
/**
* Provides reusable methods for attribute group handlers
*/
abstract class AbstractAttributeGroupHandler
{
/**
* @param AttributeGroupId $attributeGroupId
*
* @return AttributeGroup
*
* @throws AttributeGroupException
*/
protected function getAttributeGroupById($attributeGroupId)
{
$idValue = $attributeGroupId->getValue();
try {
$attributeGroup = new AttributeGroup($idValue);
if ($attributeGroup->id !== $idValue) {
throw new AttributeGroupNotFoundException(sprintf('Attribute group with id "%s" was not found.', $idValue));
}
} catch (PrestaShopException $e) {
throw new AttributeGroupException(sprintf('An error occurred when trying to get attribute group with id %s', $idValue));
}
return $attributeGroup;
}
/**
* @param AttributeGroup $attributeGroup
*
* @return bool
*
* @throws AttributeGroupException
*/
protected function deleteAttributeGroup(AttributeGroup $attributeGroup)
{
try {
return $attributeGroup->delete();
} catch (PrestaShopException $e) {
throw new AttributeGroupException(sprintf('An error occurred when trying to delete attribute with id %s', $attributeGroup->id));
}
}
}

View File

@@ -0,0 +1,110 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\AttributeGroup;
use AttributeGroup;
use PrestaShop\PrestaShop\Core\AttributeGroup\AttributeGroupViewDataProviderInterface;
use PrestaShop\PrestaShop\Core\ConfigurationInterface;
use PrestaShop\PrestaShop\Core\Domain\Product\AttributeGroup\Exception\AttributeGroupException;
use PrestaShop\PrestaShop\Core\Domain\Product\AttributeGroup\Exception\AttributeGroupNotFoundException;
use PrestaShopException;
/**
* Provides data required for attribute group view action using legacy object models
*/
final class AttributeGroupViewDataProvider implements AttributeGroupViewDataProviderInterface
{
/**
* @var int
*/
private $contextLangId;
/**
* @var ConfigurationInterface
*/
private $configuration;
/**
* @param int $contextLangId
* @param ConfigurationInterface $configuration
*/
public function __construct($contextLangId, ConfigurationInterface $configuration)
{
$this->contextLangId = $contextLangId;
$this->configuration = $configuration;
}
/**
* {@inheritdoc}
*/
public function isColorGroup($attributeGroupId)
{
$attributeGroup = $this->getAttributeGroupById($attributeGroupId);
return (bool) $attributeGroup->is_color_group;
}
/**
* {@inheritdoc}
*/
public function getAttributeGroupNameById($attributeGroupId)
{
$attributeGroup = $this->getAttributeGroupById($attributeGroupId);
if (!isset($attributeGroup->name[$this->contextLangId])) {
return $attributeGroup->name[$this->configuration->get('PS_LANG_DEFAULT')];
}
return $attributeGroup->name[$this->contextLangId];
}
/**
* Gets legacy AttributeGroup object by provided id
*
* @param int $attributeGroupId
*
* @return AttributeGroup
*
* @throws AttributeGroupException
* @throws AttributeGroupNotFoundException
*/
private function getAttributeGroupById($attributeGroupId)
{
try {
$attributeGroup = new AttributeGroup($attributeGroupId);
if ($attributeGroup->id !== $attributeGroupId) {
throw new AttributeGroupNotFoundException(sprintf('Attribute group with id "%s" was not found.', $attributeGroupId));
}
} catch (PrestaShopException $e) {
throw new AttributeGroupException(sprintf('An error occurred when trying to get attribute group with id %s', $attributeGroupId));
}
return $attributeGroup;
}
}

View File

@@ -0,0 +1,53 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\AttributeGroup\CommandHandler;
use PrestaShop\PrestaShop\Adapter\Product\AttributeGroup\AbstractAttributeGroupHandler;
use PrestaShop\PrestaShop\Core\Domain\Product\AttributeGroup\Command\BulkDeleteAttributeGroupCommand;
use PrestaShop\PrestaShop\Core\Domain\Product\AttributeGroup\CommandHandler\BulkDeleteAttributeGroupHandlerInterface;
use PrestaShop\PrestaShop\Core\Domain\Product\AttributeGroup\Exception\DeleteAttributeGroupException;
/**
* Handles command which deletes multiple attribute groups using legacy object model
*/
final class BulkDeleteAttributeGroupHandler extends AbstractAttributeGroupHandler implements BulkDeleteAttributeGroupHandlerInterface
{
/**
* {@inheritdoc}
*/
public function handle(BulkDeleteAttributeGroupCommand $command)
{
foreach ($command->getAttributeGroupIds() as $attributeGroupId) {
$attributeGroup = $this->getAttributeGroupById($attributeGroupId);
if (false === $this->deleteAttributeGroup($attributeGroup)) {
throw new DeleteAttributeGroupException(sprintf('Failed to delete attribute group with id "%s"', $attributeGroupId->getValue()), DeleteAttributeGroupException::FAILED_BULK_DELETE);
}
}
}
}

View File

@@ -0,0 +1,55 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\AttributeGroup\CommandHandler;
use PrestaShop\PrestaShop\Adapter\Product\AttributeGroup\AbstractAttributeGroupHandler;
use PrestaShop\PrestaShop\Core\Domain\Product\AttributeGroup\Command\DeleteAttributeGroupCommand;
use PrestaShop\PrestaShop\Core\Domain\Product\AttributeGroup\CommandHandler\DeleteAttributeGroupHandlerInterface;
use PrestaShop\PrestaShop\Core\Domain\Product\AttributeGroup\Exception\AttributeGroupException;
use PrestaShop\PrestaShop\Core\Domain\Product\AttributeGroup\Exception\DeleteAttributeGroupException;
/**
* Handles command which deletes attribute group using legacy object model
*/
final class DeleteAttributeGroupHandler extends AbstractAttributeGroupHandler implements DeleteAttributeGroupHandlerInterface
{
/**
* {@inheritdoc}
*
* @throws AttributeGroupException
*/
public function handle(DeleteAttributeGroupCommand $command)
{
$attributeGroupId = $command->getAttributeGroupId();
$attributeGroup = $this->getAttributeGroupById($attributeGroupId);
if (false === $this->deleteAttributeGroup($attributeGroup)) {
throw new DeleteAttributeGroupException(sprintf('Failed deleting attribute group with id "%s"', $attributeGroupId->getValue()), DeleteAttributeGroupException::FAILED_DELETE);
}
}
}

View File

@@ -0,0 +1,106 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\AttributeGroup\QueryHandler;
use PrestaShop\PrestaShop\Core\Domain\Product\AttributeGroup\Attribute\QueryResult\Attribute;
use PrestaShop\PrestaShop\Core\Domain\Product\AttributeGroup\QueryResult\AttributeGroup;
use PrestaShopBundle\Entity\Attribute as AttributeEntity;
use PrestaShopBundle\Entity\AttributeGroup as AttributeGroupEntity;
use PrestaShopBundle\Entity\AttributeGroupLang;
use PrestaShopBundle\Entity\AttributeLang;
use PrestaShopBundle\Entity\Repository\AttributeGroupRepository;
abstract class AbstractAttributeGroupQueryHandler
{
/**
* @var AttributeGroupRepository
*/
protected $attributeGroupRepository;
/**
* @param AttributeGroupRepository $attributeGroupRepository
*/
public function __construct(
AttributeGroupRepository $attributeGroupRepository
) {
$this->attributeGroupRepository = $attributeGroupRepository;
}
/**
* @param array $attributeGroupEntities
* @param bool $withAttributes
*
* @return AttributeGroup[]
*/
protected function formatAttributeGroups(array $attributeGroupEntities, bool $withAttributes): array
{
$attributeGroups = [];
/** @var AttributeGroupEntity $attributeGroupEntity */
foreach ($attributeGroupEntities as $attributeGroupEntity) {
$localizedNames = $localizedPublicNames = [];
/** @var AttributeGroupLang $attributeGroupLang */
foreach ($attributeGroupEntity->getAttributeGroupLangs() as $attributeGroupLang) {
$localizedNames[$attributeGroupLang->getLang()->getId()] = $attributeGroupLang->getName();
$localizedPublicNames[$attributeGroupLang->getLang()->getId()] = $attributeGroupLang->getPublicName();
}
$attributes = null;
if ($withAttributes) {
$attributes = [];
/** @var AttributeEntity $attributeEntity */
foreach ($attributeGroupEntity->getAttributes() as $attributeEntity) {
$localizedAttributeNames = [];
/** @var AttributeLang $attributeLang */
foreach ($attributeEntity->getAttributeLangs() as $attributeLang) {
$localizedAttributeNames[$attributeLang->getLang()->getId()] = $attributeLang->getName();
}
$attributes[] = new Attribute(
$attributeEntity->getId(),
$attributeEntity->getPosition(),
$attributeEntity->getColor(),
$localizedAttributeNames
);
}
}
$attributeGroups[] = new AttributeGroup(
$attributeGroupEntity->getId(),
$localizedNames,
$localizedPublicNames,
$attributeGroupEntity->getGroupType(),
$attributeGroupEntity->getIsColorGroup(),
$attributeGroupEntity->getPosition(),
$attributes
);
}
return $attributeGroups;
}
}

View File

@@ -0,0 +1,48 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\AttributeGroup\QueryHandler;
use PrestaShop\PrestaShop\Core\Domain\Product\AttributeGroup\Query\GetAttributeGroupList;
use PrestaShop\PrestaShop\Core\Domain\Product\AttributeGroup\QueryHandler\GetAttributeGroupListHandlerInterface;
/**
* Handles the query GetAttributeGroupList using Doctrine repository
*/
class GetAttributeGroupListHandler extends AbstractAttributeGroupQueryHandler implements GetAttributeGroupListHandlerInterface
{
/**
* {@inheritDoc}
*/
public function handle(GetAttributeGroupList $query): array
{
$attributeGroupEntities = $this->attributeGroupRepository->listOrderedAttributeGroups($query->withAttributes());
return $this->formatAttributeGroups($attributeGroupEntities, $query->withAttributes());
}
}

View File

@@ -0,0 +1,72 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\AttributeGroup\QueryHandler;
use PrestaShop\PrestaShop\Adapter\Attribute\Repository\AttributeRepository;
use PrestaShop\PrestaShop\Core\Domain\Product\AttributeGroup\Query\GetProductAttributeGroups;
use PrestaShop\PrestaShop\Core\Domain\Product\AttributeGroup\QueryHandler\GetProductAttributeGroupsHandlerInterface;
use PrestaShopBundle\Entity\Repository\AttributeGroupRepository;
/**
* Handles the query GetProductAttributeGroups using adapter repository
*/
class GetProductAttributeGroupsHandler extends AbstractAttributeGroupQueryHandler implements GetProductAttributeGroupsHandlerInterface
{
/**
* @var AttributeRepository
*/
protected $attributeRepository;
/**
* @param AttributeGroupRepository $attributeGroupRepository
* @param AttributeRepository $attributeRepository
*/
public function __construct(
AttributeGroupRepository $attributeGroupRepository,
AttributeRepository $attributeRepository
) {
parent::__construct($attributeGroupRepository);
$this->attributeRepository = $attributeRepository;
}
/**
* {@inheritDoc}
*/
public function handle(GetProductAttributeGroups $query): array
{
$attributeIds = $this->attributeRepository->getProductAttributesIds($query->getProductId());
if (empty($attributeIds)) {
return [];
}
$attributeGroupEntities = $this->attributeGroupRepository->listOrderedAttributeGroups($query->withAttributes(), $attributeIds);
return $this->formatAttributeGroups($attributeGroupEntities, $query->withAttributes());
}
}

View File

@@ -0,0 +1,61 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\Combination\CommandHandler;
use PrestaShop\PrestaShop\Adapter\Product\Combination\Create\CombinationCreator;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\Command\GenerateProductCombinationsCommand;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\CommandHandler\GenerateProductCombinationsHandlerInterface;
/**
* Handles @see GenerateProductCombinationsCommand using legacy object model
*/
final class GenerateProductCombinationsHandler implements GenerateProductCombinationsHandlerInterface
{
/**
* @var CombinationCreator
*/
private $combinationCreator;
/**
* @param CombinationCreator $combinationCreator
*/
public function __construct(
CombinationCreator $combinationCreator
) {
$this->combinationCreator = $combinationCreator;
}
/**
* {@inheritdoc}
*/
public function handle(GenerateProductCombinationsCommand $command): array
{
return $this->combinationCreator->createCombinations($command->getProductId(), $command->getGroupedAttributeIdsList());
}
}

View File

@@ -0,0 +1,60 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\Combination\CommandHandler;
use PrestaShop\PrestaShop\Adapter\Product\Update\ProductSupplierUpdater;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\Command\RemoveAllAssociatedCombinationSuppliersCommand;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\CommandHandler\RemoveAllAssociatedCombinationSuppliersHandlerInterface;
/**
* Removes product suppliers associated to a certain combination using legacy object model
*/
final class RemoveAllAssociatedCombinationSuppliersHandler implements RemoveAllAssociatedCombinationSuppliersHandlerInterface
{
/**
* @var ProductSupplierUpdater
*/
private $productSupplierUpdater;
/**
* @param ProductSupplierUpdater $productSupplierUpdater
*/
public function __construct(
ProductSupplierUpdater $productSupplierUpdater
) {
$this->productSupplierUpdater = $productSupplierUpdater;
}
/**
* {@inheritdoc}
*/
public function handle(RemoveAllAssociatedCombinationSuppliersCommand $command): void
{
$this->productSupplierUpdater->removeAllForCombination($command->getCombinationId());
}
}

View File

@@ -0,0 +1,60 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\Combination\CommandHandler;
use PrestaShop\PrestaShop\Adapter\Product\Combination\Update\CombinationImagesUpdater;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\Command\RemoveAllCombinationImagesCommand;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\CommandHandler\RemoveAllCombinationImagesHandlerInterface;
/**
* Handles @see RemoveAllCombinationImagesCommand using adapter udpater service
*/
final class RemoveAllCombinationImagesHandler implements RemoveAllCombinationImagesHandlerInterface
{
/**
* @var CombinationImagesUpdater
*/
private $combinationImagesUpdater;
/**
* @param CombinationImagesUpdater $combinationImagesUpdater
*/
public function __construct(CombinationImagesUpdater $combinationImagesUpdater)
{
$this->combinationImagesUpdater = $combinationImagesUpdater;
}
/**
* {@inheritDoc}
*/
public function handle(RemoveAllCombinationImagesCommand $command): void
{
$this->combinationImagesUpdater->deleteAllImageAssociations($command->getCombinationId());
}
}

View File

@@ -0,0 +1,60 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\Combination\CommandHandler;
use PrestaShop\PrestaShop\Adapter\Product\Combination\Update\CombinationRemover;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\Command\RemoveCombinationCommand;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\CommandHandler\RemoveCombinationCommandHandlerInterface;
/**
* Handles @see RemoveCombinationCommand using adapter udpater service
*/
final class RemoveCombinationCommandHandler implements RemoveCombinationCommandHandlerInterface
{
/**
* @var CombinationRemover
*/
private $combinationRemover;
/**
* @param CombinationRemover $combinationRemover
*/
public function __construct(CombinationRemover $combinationRemover)
{
$this->combinationRemover = $combinationRemover;
}
/**
* {@inheritDoc}
*/
public function handle(RemoveCombinationCommand $command): void
{
$this->combinationRemover->removeCombination($command->getCombinationId());
}
}

View File

@@ -0,0 +1,73 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\Combination\CommandHandler;
use PrestaShop\PrestaShop\Adapter\Product\Combination\Repository\CombinationRepository;
use PrestaShop\PrestaShop\Adapter\Product\Update\ProductSupplierUpdater;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\Command\SetCombinationDefaultSupplierCommand;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\CommandHandler\SetCombinationDefaultSupplierHandlerInterface;
use PrestaShop\PrestaShop\Core\Domain\Product\ValueObject\ProductId;
class SetCombinationDefaultSupplierHandler implements SetCombinationDefaultSupplierHandlerInterface
{
/**
* @var CombinationRepository
*/
private $combinationRepository;
/**
* @var ProductSupplierUpdater
*/
private $productSupplierUpdater;
/**
* @param ProductSupplierUpdater $productSupplierUpdater
*/
public function __construct(
CombinationRepository $combinationRepository,
ProductSupplierUpdater $productSupplierUpdater
) {
$this->combinationRepository = $combinationRepository;
$this->productSupplierUpdater = $productSupplierUpdater;
}
/**
* {@inheritDoc}
*/
public function handle(SetCombinationDefaultSupplierCommand $command): void
{
$combination = $this->combinationRepository->get($command->getCombinationId());
$this->productSupplierUpdater->updateCombinationDefaultSupplier(
new ProductId((int) $combination->id_product),
$command->getDefaultSupplierId(),
$command->getCombinationId()
);
}
}

View File

@@ -0,0 +1,60 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\Combination\CommandHandler;
use PrestaShop\PrestaShop\Adapter\Product\Combination\Update\CombinationImagesUpdater;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\Command\SetCombinationImagesCommand;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\CommandHandler\SetCombinationImagesHandlerInterface;
/**
* Handles @see SetCombinationImagesCommand using adapter udpater service
*/
final class SetCombinationImagesHandler implements SetCombinationImagesHandlerInterface
{
/**
* @var CombinationImagesUpdater
*/
private $combinationImagesUpdater;
/**
* @param CombinationImagesUpdater $combinationImagesUpdater
*/
public function __construct(CombinationImagesUpdater $combinationImagesUpdater)
{
$this->combinationImagesUpdater = $combinationImagesUpdater;
}
/**
* {@inheritDoc}
*/
public function handle(SetCombinationImagesCommand $command): void
{
$this->combinationImagesUpdater->associateImages($command->getCombinationId(), $command->getImageIds());
}
}

View File

@@ -0,0 +1,85 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\Combination\CommandHandler;
use PrestaShop\PrestaShop\Adapter\Product\AbstractProductSupplierHandler;
use PrestaShop\PrestaShop\Adapter\Product\Combination\Repository\CombinationRepository;
use PrestaShop\PrestaShop\Adapter\Product\Repository\ProductSupplierRepository;
use PrestaShop\PrestaShop\Adapter\Product\Update\ProductSupplierUpdater;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\Command\SetCombinationSuppliersCommand;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\CommandHandler\SetCombinationSuppliersHandlerInterface;
use PrestaShop\PrestaShop\Core\Domain\Product\ValueObject\ProductId;
final class SetCombinationSuppliersHandler extends AbstractProductSupplierHandler implements SetCombinationSuppliersHandlerInterface
{
/**
* @var CombinationRepository
*/
private $combinationRepository;
/**
* @var ProductSupplierUpdater
*/
private $productSupplierUpdater;
/**
* @param CombinationRepository $combinationRepository
* @param ProductSupplierRepository $productSupplierRepository
* @param ProductSupplierUpdater $productSupplierUpdater
*/
public function __construct(
CombinationRepository $combinationRepository,
ProductSupplierRepository $productSupplierRepository,
ProductSupplierUpdater $productSupplierUpdater
) {
parent::__construct($productSupplierRepository);
$this->combinationRepository = $combinationRepository;
$this->productSupplierUpdater = $productSupplierUpdater;
}
/**
* {@inheritdoc}
*/
public function handle(SetCombinationSuppliersCommand $command): array
{
$combinationId = $command->getCombinationId();
$combination = $this->combinationRepository->get($combinationId);
$productId = new ProductId((int) $combination->id_product);
$productSuppliers = [];
foreach ($command->getCombinationSuppliers() as $productSupplierDTO) {
$productSuppliers[] = $this->loadEntityFromDTO($productId, $productSupplierDTO, $combinationId);
}
return $this->productSupplierUpdater->setCombinationSuppliers(
$productId,
$combinationId,
$productSuppliers
);
}
}

View File

@@ -0,0 +1,114 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\Combination\CommandHandler;
use Combination;
use PrestaShop\PrestaShop\Adapter\Product\Combination\Repository\CombinationRepository;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\Command\UpdateCombinationDetailsCommand;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\CommandHandler\UpdateCombinationDetailsHandlerInterface;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\Exception\CannotUpdateCombinationException;
/**
* Handles @see UpdateCombinationDetailsCommand using legacy object model
*/
final class UpdateCombinationDetailsHandler implements UpdateCombinationDetailsHandlerInterface
{
/**
* @var CombinationRepository
*/
private $combinationRepository;
/**
* @param CombinationRepository $combinationRepository
*/
public function __construct(
CombinationRepository $combinationRepository
) {
$this->combinationRepository = $combinationRepository;
}
/**
* {@inheritdoc}
*/
public function handle(UpdateCombinationDetailsCommand $command): void
{
$combination = $this->combinationRepository->get($command->getCombinationId());
$updatableProperties = $this->fillUpdatableProperties($combination, $command);
$this->combinationRepository->partialUpdate(
$combination,
$updatableProperties,
CannotUpdateCombinationException::FAILED_UPDATE_DETAILS
);
}
/**
* @param Combination $combination
* @param UpdateCombinationDetailsCommand $command
*
* @return string[]|array<string, int[]>
*/
private function fillUpdatableProperties(Combination $combination, UpdateCombinationDetailsCommand $command): array
{
//@todo: ps_stock table contains properties(reference, ean13 etc.) that should be updated too depending if we still support ADVANCED_STOCK_MANAGEMENT
// check Product::updateAttribute L 2165
$updatableProperties = [];
if (null !== $command->getEan13()) {
$combination->ean13 = $command->getEan13()->getValue();
$updatableProperties[] = 'ean13';
}
if (null !== $command->getIsbn()) {
$combination->isbn = $command->getIsbn()->getValue();
$updatableProperties[] = 'isbn';
}
if (null !== $command->getMpn()) {
$combination->mpn = $command->getMpn();
$updatableProperties[] = 'mpn';
}
if (null !== $command->getReference()) {
$combination->reference = $command->getReference()->getValue();
$updatableProperties[] = 'reference';
}
if (null !== $command->getUpc()) {
$combination->upc = $command->getUpc()->getValue();
$updatableProperties[] = 'upc';
}
if (null !== $command->getWeight()) {
$combination->weight = (float) (string) $command->getWeight();
}
return $updatableProperties;
}
}

View File

@@ -0,0 +1,124 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\Combination\CommandHandler;
use Combination;
use PrestaShop\PrestaShop\Adapter\Product\Combination\Repository\CombinationRepository;
use PrestaShop\PrestaShop\Adapter\Product\Combination\Update\CombinationStockProperties;
use PrestaShop\PrestaShop\Adapter\Product\Combination\Update\CombinationStockUpdater;
use PrestaShop\PrestaShop\Adapter\Product\Combination\Update\DefaultCombinationUpdater;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\Command\UpdateCombinationFromListingCommand;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\CommandHandler\UpdateCombinationFromListingHandlerInterface;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\Exception\CannotUpdateCombinationException;
/**
* Handles @see UpdateCombinationFromListingCommand using legacy object model
*/
final class UpdateCombinationFromListingHandler implements UpdateCombinationFromListingHandlerInterface
{
/**
* @var CombinationRepository
*/
private $combinationRepository;
/**
* @var DefaultCombinationUpdater
*/
private $defaultCombinationUpdater;
/**
* @var CombinationStockUpdater
*/
private $combinationStockUpdater;
/**
* @param CombinationRepository $combinationRepository
* @param DefaultCombinationUpdater $defaultCombinationUpdater
* @param CombinationStockUpdater $combinationStockUpdater
*/
public function __construct(
CombinationRepository $combinationRepository,
DefaultCombinationUpdater $defaultCombinationUpdater,
CombinationStockUpdater $combinationStockUpdater
) {
$this->combinationRepository = $combinationRepository;
$this->defaultCombinationUpdater = $defaultCombinationUpdater;
$this->combinationStockUpdater = $combinationStockUpdater;
}
/**
* {@inheritdoc}
*/
public function handle(UpdateCombinationFromListingCommand $command): void
{
$combination = $this->combinationRepository->get($command->getCombinationId());
$this->combinationRepository->partialUpdate(
$combination,
$this->fillUpdatableProperties($combination, $command),
CannotUpdateCombinationException::FAILED_UPDATE_LISTED_COMBINATION
);
if (true === $command->isDefault()) {
$this->defaultCombinationUpdater->setDefaultCombination($command->getCombinationId());
}
$this->combinationStockUpdater->update(
$command->getCombinationId(),
new CombinationStockProperties($command->getQuantity())
);
}
/**
* @param Combination $combination
* @param UpdateCombinationFromListingCommand $command
*
* @return array<int, string>
*/
private function fillUpdatableProperties(Combination $combination, UpdateCombinationFromListingCommand $command): array
{
$updatableProperties = [];
if (null !== $command->getImpactOnPrice()) {
$combination->price = (float) (string) $command->getImpactOnPrice();
$updatableProperties[] = 'price';
}
if (null !== $command->getQuantity()) {
$combination->quantity = $command->getQuantity();
$updatableProperties[] = 'quantity';
}
if (null !== $command->getReference()) {
$combination->reference = $command->getReference();
$updatableProperties[] = 'reference';
}
return $updatableProperties;
}
}

View File

@@ -0,0 +1,97 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\Combination\CommandHandler;
use Combination;
use PrestaShop\PrestaShop\Adapter\Product\Combination\Repository\CombinationRepository;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\Command\UpdateCombinationPricesCommand;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\CommandHandler\UpdateCombinationPricesHandlerInterface;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\Exception\CannotUpdateCombinationException;
/**
* Handles @see UpdateCombinationPricesCommand using legacy object model
*/
final class UpdateCombinationPricesHandler implements UpdateCombinationPricesHandlerInterface
{
/**
* @var CombinationRepository
*/
private $combinationRepository;
/**
* @param CombinationRepository $combinationRepository
*/
public function __construct(CombinationRepository $combinationRepository)
{
$this->combinationRepository = $combinationRepository;
}
/**
* {@inheritdoc}
*/
public function handle(UpdateCombinationPricesCommand $command): void
{
$combination = $this->combinationRepository->get($command->getCombinationId());
$updatableProperties = $this->fillUpdatableProperties($combination, $command);
$this->combinationRepository->partialUpdate($combination, $updatableProperties, CannotUpdateCombinationException::FAILED_UPDATE_PRICES);
}
/**
* @param Combination $combination
* @param UpdateCombinationPricesCommand $command
*
* @return array<int, string>
*/
private function fillUpdatableProperties(Combination $combination, UpdateCombinationPricesCommand $command): array
{
$updatableProperties = [];
if (null !== $command->getImpactOnPrice()) {
$combination->price = (float) (string) $command->getImpactOnPrice();
$updatableProperties[] = 'price';
}
if (null !== $command->getEcoTax()) {
$combination->ecotax = (float) (string) $command->getEcoTax();
$updatableProperties[] = 'ecotax';
}
if (null !== $command->getImpactOnUnitPrice()) {
$combination->unit_price_impact = (float) (string) $command->getImpactOnUnitPrice();
$updatableProperties[] = 'unit_price_impact';
}
if (null !== $command->getWholesalePrice()) {
$combination->wholesale_price = (float) (string) $command->getWholesalePrice();
$updatableProperties[] = 'wholesale_price';
}
return $updatableProperties;
}
}

View File

@@ -0,0 +1,71 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\Combination\CommandHandler;
use PrestaShop\PrestaShop\Adapter\Product\Combination\Update\CombinationStockProperties;
use PrestaShop\PrestaShop\Adapter\Product\Combination\Update\CombinationStockUpdater;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\Command\UpdateCombinationStockCommand;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\CommandHandler\UpdateCombinationStockHandlerInterface;
/**
* Handles @see UpdateCombinationStockCommand using legacy object model
*/
final class UpdateCombinationStockHandler implements UpdateCombinationStockHandlerInterface
{
/**
* @var CombinationStockUpdater
*/
private $combinationStockUpdater;
/**
* @param CombinationStockUpdater $combinationStockUpdater
*/
public function __construct(
CombinationStockUpdater $combinationStockUpdater
) {
$this->combinationStockUpdater = $combinationStockUpdater;
}
/**
* {@inheritdoc}
*/
public function handle(UpdateCombinationStockCommand $command): void
{
$properties = new CombinationStockProperties(
$command->getQuantity(),
$command->getMinimalQuantity(),
$command->getLocation(),
$command->getLowStockThreshold(),
$command->getLowStockAlertEnabled(),
$command->getAvailableDate()
);
$this->combinationStockUpdater->update($command->getCombinationId(), $properties);
}
}

View File

@@ -0,0 +1,208 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\Combination\Create;
use PrestaShop\PrestaShop\Adapter\Product\Combination\Repository\CombinationRepository;
use PrestaShop\PrestaShop\Adapter\Product\Repository\ProductRepository;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\ValueObject\CombinationId;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\ValueObject\GroupedAttributeIds;
use PrestaShop\PrestaShop\Core\Domain\Product\Exception\InvalidProductTypeException;
use PrestaShop\PrestaShop\Core\Domain\Product\ValueObject\ProductId;
use PrestaShop\PrestaShop\Core\Domain\Product\ValueObject\ProductType;
use PrestaShop\PrestaShop\Core\Exception\CoreException;
use PrestaShop\PrestaShop\Core\Product\Combination\Generator\CombinationGeneratorInterface;
use PrestaShopException;
use Product;
use SpecificPriceRule;
use Traversable;
/**
* Creates combinations from attributes
*/
class CombinationCreator
{
/**
* @var CombinationGeneratorInterface
*/
private $combinationGenerator;
/**
* @var CombinationRepository
*/
private $combinationRepository;
/**
* @var ProductRepository
*/
private $productRepository;
/**
* @param CombinationGeneratorInterface $combinationGenerator
* @param CombinationRepository $combinationRepository
* @param ProductRepository $productRepository
*/
public function __construct(
CombinationGeneratorInterface $combinationGenerator,
CombinationRepository $combinationRepository,
ProductRepository $productRepository
) {
$this->combinationGenerator = $combinationGenerator;
$this->combinationRepository = $combinationRepository;
$this->productRepository = $productRepository;
}
/**
* @param ProductId $productId
* @param GroupedAttributeIds[] $groupedAttributeIdsList
*
* @return CombinationId[]
*
* @todo: multistore
*/
public function createCombinations(ProductId $productId, array $groupedAttributeIdsList): array
{
$product = $this->productRepository->get($productId);
if ($product->product_type !== ProductType::TYPE_COMBINATIONS) {
throw new InvalidProductTypeException(InvalidProductTypeException::EXPECTED_COMBINATIONS_TYPE);
}
$generatedCombinations = $this->combinationGenerator->generate($this->formatScalarValues($groupedAttributeIdsList));
// avoid applying specificPrice on each combination.
$this->disableSpecificPriceRulesApplication();
$combinationIds = $this->addCombinations($product, $generatedCombinations);
// apply all specific price rules at once after all the combinations are generated
$this->applySpecificPriceRules($productId);
return $combinationIds;
}
/**
* @param GroupedAttributeIds[] $groupedAttributeIdsList
*
* @return array<int, array<int, int>>
*/
private function formatScalarValues(array $groupedAttributeIdsList): array
{
$groupedIdsList = [];
foreach ($groupedAttributeIdsList as $groupedAttributeIds) {
foreach ($groupedAttributeIds->getAttributeIds() as $attributeId) {
$groupedIdsList[$groupedAttributeIds->getAttributeGroupId()->getValue()][] = $attributeId->getValue();
}
}
return $groupedIdsList;
}
/**
* @param Product $product
* @param Traversable $generatedCombinations
*
* @return CombinationId[]
*
* @throws CoreException
*/
private function addCombinations(Product $product, Traversable $generatedCombinations): array
{
$product->setAvailableDate();
$productId = new ProductId((int) $product->id);
$alreadyHasCombinations = $hasDefault = (bool) $this->combinationRepository->findDefaultCombination($productId);
$addedCombinationIds = [];
foreach ($generatedCombinations as $generatedCombination) {
// Product already has combinations so we need to filter existing ones
if ($alreadyHasCombinations) {
$attributeIds = array_values($generatedCombination);
$matchingCombinations = $this->combinationRepository->getCombinationIdsByAttributes($productId, $attributeIds);
if (!empty($matchingCombinations)) {
continue;
}
}
$addedCombinationIds[] = $this->persistCombination($productId, $generatedCombination, !$hasDefault);
$hasDefault = true;
}
return $addedCombinationIds;
}
/**
* @param ProductId $productId
* @param int[] $generatedCombination
* @param bool $isDefault
*
* @return CombinationId
*
* @throws CoreException
*/
private function persistCombination(ProductId $productId, array $generatedCombination, bool $isDefault): CombinationId
{
$combination = $this->combinationRepository->create($productId, $isDefault);
$combinationId = new CombinationId((int) $combination->id);
//@todo: Use DB transaction instead if they are accepted (PR #21740)
try {
$this->combinationRepository->saveProductAttributeAssociation($combinationId, $generatedCombination);
} catch (CoreException $e) {
$this->combinationRepository->delete($combinationId);
throw $e;
}
return $combinationId;
}
/**
* @throws CoreException
*/
private function disableSpecificPriceRulesApplication(): void
{
try {
SpecificPriceRule::disableAnyApplication();
} catch (PrestaShopException $e) {
throw new CoreException('Error occurred when trying to disable specific price rules application', 0, $e);
}
}
/**
* @param ProductId $productId
*
* @throws CoreException
*/
private function applySpecificPriceRules(ProductId $productId): void
{
try {
SpecificPriceRule::enableAnyApplication();
SpecificPriceRule::applyAllRules([$productId->getValue()]);
} catch (PrestaShopException $e) {
throw new CoreException('Error occurred when trying to apply specific prices rules', 0, $e);
}
}
}

View File

@@ -0,0 +1,257 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\Combination\QueryHandler;
use Combination;
use DateTime;
use PrestaShop\PrestaShop\Adapter\Attribute\Repository\AttributeRepository;
use PrestaShop\PrestaShop\Adapter\Product\Combination\Repository\CombinationRepository;
use PrestaShop\PrestaShop\Adapter\Product\Image\Repository\ProductImageRepository;
use PrestaShop\PrestaShop\Adapter\Product\Repository\ProductRepository;
use PrestaShop\PrestaShop\Adapter\Product\Stock\Repository\StockAvailableRepository;
use PrestaShop\PrestaShop\Adapter\Tax\TaxComputer;
use PrestaShop\PrestaShop\Core\Domain\Country\ValueObject\CountryId;
use PrestaShop\PrestaShop\Core\Domain\Language\ValueObject\LanguageId;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\Query\GetCombinationForEditing;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\QueryHandler\GetCombinationForEditingHandlerInterface;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\QueryResult\CombinationDetails;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\QueryResult\CombinationForEditing;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\QueryResult\CombinationPrices;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\QueryResult\CombinationStock;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\ValueObject\CombinationId;
use PrestaShop\PrestaShop\Core\Domain\Product\Image\ValueObject\ImageId;
use PrestaShop\PrestaShop\Core\Domain\Product\ValueObject\ProductId;
use PrestaShop\PrestaShop\Core\Domain\TaxRulesGroup\ValueObject\TaxRulesGroupId;
use PrestaShop\PrestaShop\Core\Util\DateTime\DateTime as DateTimeUtil;
use PrestaShop\PrestaShop\Core\Util\Number\NumberExtractor;
use Product;
/**
* Handles @see GetCombinationForEditing query using legacy object model
*/
final class GetCombinationForEditingHandler implements GetCombinationForEditingHandlerInterface
{
/**
* @var CombinationRepository
*/
private $combinationRepository;
/**
* @var StockAvailableRepository
*/
private $stockAvailableRepository;
/**
* @var AttributeRepository
*/
private $attributeRepository;
/**
* @var ProductRepository
*/
private $productRepository;
/**
* @var ProductImageRepository
*/
private $productImageRepository;
/**
* @var int
*/
private $contextLanguageId;
/**
* @var NumberExtractor
*/
private $numberExtractor;
/**
* @var TaxComputer
*/
private $taxComputer;
/**
* @var int
*/
private $countryId;
/**
* @param CombinationRepository $combinationRepository
* @param StockAvailableRepository $stockAvailableRepository
* @param AttributeRepository $attributeRepository
* @param ProductRepository $productRepository
* @param ProductImageRepository $productImageRepository
* @param NumberExtractor $numberExtractor
* @param TaxComputer $taxComputer
* @param int $contextLanguageId
* @param int $countryId
*/
public function __construct(
CombinationRepository $combinationRepository,
StockAvailableRepository $stockAvailableRepository,
AttributeRepository $attributeRepository,
ProductRepository $productRepository,
ProductImageRepository $productImageRepository,
NumberExtractor $numberExtractor,
TaxComputer $taxComputer,
int $contextLanguageId,
int $countryId
) {
$this->combinationRepository = $combinationRepository;
$this->stockAvailableRepository = $stockAvailableRepository;
$this->attributeRepository = $attributeRepository;
$this->productRepository = $productRepository;
$this->productImageRepository = $productImageRepository;
$this->numberExtractor = $numberExtractor;
$this->taxComputer = $taxComputer;
$this->contextLanguageId = $contextLanguageId;
$this->countryId = $countryId;
}
/**
* {@inheritdoc}
*/
public function handle(GetCombinationForEditing $query): CombinationForEditing
{
$combination = $this->combinationRepository->get($query->getCombinationId());
$productId = new ProductId((int) $combination->id_product);
$product = $this->productRepository->get($productId);
return new CombinationForEditing(
$query->getCombinationId()->getValue(),
$productId->getValue(),
$this->getCombinationName($query->getCombinationId()),
$this->getDetails($combination),
$this->getPrices($combination, $product),
$this->getStock($combination),
$this->getImages($combination)
);
}
/**
* @param CombinationId $combinationId
*
* @return string
*/
private function getCombinationName(CombinationId $combinationId): string
{
$attributesInformation = $this->attributeRepository->getAttributesInfoByCombinationIds(
[$combinationId->getValue()],
new LanguageId($this->contextLanguageId)
);
$attributes = $attributesInformation[$combinationId->getValue()];
return implode(', ', array_map(function ($attribute) {
return sprintf(
'%s - %s',
$attribute['attribute_group_name'],
$attribute['attribute_name']
);
}, $attributes));
}
/**
* @param Combination $combination
*
* @return CombinationDetails
*/
private function getDetails(Combination $combination): CombinationDetails
{
return new CombinationDetails(
$combination->ean13,
$combination->isbn,
$combination->mpn,
$combination->reference,
$combination->upc,
$this->numberExtractor->extract($combination, 'weight')
);
}
/**
* @param Combination $combination
* @param Product $product
*
* @return CombinationPrices
*/
private function getPrices(Combination $combination, Product $product): CombinationPrices
{
$priceTaxExcluded = $this->numberExtractor->extract($combination, 'price');
$priceTaxIncluded = $this->taxComputer->computePriceWithTaxes(
$priceTaxExcluded,
new TaxRulesGroupId((int) $product->id_tax_rules_group),
new CountryId($this->countryId)
);
return new CombinationPrices(
$this->numberExtractor->extract($combination, 'ecotax'),
$priceTaxExcluded,
$priceTaxIncluded,
$this->numberExtractor->extract($combination, 'unit_price_impact'),
$this->numberExtractor->extract($combination, 'wholesale_price')
);
}
/**
* @param Combination $combination
*
* @return CombinationStock
*/
private function getStock(Combination $combination): CombinationStock
{
$stockAvailable = $this->stockAvailableRepository->getForCombination(new Combinationid($combination->id));
return new CombinationStock(
(int) $stockAvailable->quantity,
(int) $combination->minimal_quantity,
(int) $combination->low_stock_threshold,
(bool) $combination->low_stock_alert,
$stockAvailable->location,
DateTimeUtil::NULL_DATE === $combination->available_date ? null : new DateTime($combination->available_date)
);
}
/**
* @param Combination $combination
*
* @return int[]
*/
private function getImages(Combination $combination): array
{
$combinationId = (int) $combination->id;
$combinationImageIds = $this->productImageRepository->getImagesIdsForCombinations([$combinationId]);
if (empty($combinationImageIds[$combinationId])) {
return [];
}
return array_map(function (ImageId $imageId) {
return $imageId->getValue();
}, $combinationImageIds[$combinationId]);
}
}

View File

@@ -0,0 +1,77 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\Combination\QueryHandler;
use PrestaShop\PrestaShop\Adapter\Product\AbstractProductSupplierHandler;
use PrestaShop\PrestaShop\Adapter\Product\Combination\Repository\CombinationRepository;
use PrestaShop\PrestaShop\Adapter\Product\Repository\ProductRepository;
use PrestaShop\PrestaShop\Adapter\Product\Repository\ProductSupplierRepository;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\Query\GetCombinationSuppliers;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\QueryHandler\GetCombinationSuppliersHandlerInterface;
use PrestaShop\PrestaShop\Core\Domain\Product\ValueObject\ProductId;
final class GetCombinationSuppliersHandler extends AbstractProductSupplierHandler implements GetCombinationSuppliersHandlerInterface
{
/**
* @var CombinationRepository
*/
private $combinationRepository;
/**
* @var ProductRepository
*/
private $productRepository;
/**
* @param ProductSupplierRepository $productSupplierRepository
* @param CombinationRepository $combinationRepository
* @param ProductRepository $productRepository
*/
public function __construct(
ProductSupplierRepository $productSupplierRepository,
CombinationRepository $combinationRepository,
ProductRepository $productRepository
) {
parent::__construct($productSupplierRepository);
$this->combinationRepository = $combinationRepository;
$this->productRepository = $productRepository;
}
/**
* {@inheritdoc}
*/
public function handle(GetCombinationSuppliers $query): array
{
$combination = $this->combinationRepository->get($query->getCombinationId());
return $this->getProductSuppliersInfo(
new ProductId((int) $combination->id_product),
$query->getCombinationId()
);
}
}

View File

@@ -0,0 +1,208 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\Combination\QueryHandler;
use PDO;
use PrestaShop\Decimal\DecimalNumber;
use PrestaShop\PrestaShop\Adapter\Attribute\Repository\AttributeRepository;
use PrestaShop\PrestaShop\Adapter\Product\Image\ProductImagePathFactory;
use PrestaShop\PrestaShop\Adapter\Product\Image\Repository\ProductImageRepository;
use PrestaShop\PrestaShop\Adapter\Product\Stock\Repository\StockAvailableRepository;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\Query\GetEditableCombinationsList;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\QueryHandler\GetEditableCombinationsListHandlerInterface;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\QueryResult\CombinationAttributeInformation;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\QueryResult\CombinationListForEditing;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\QueryResult\EditableCombinationForListing;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\ValueObject\CombinationId;
use PrestaShop\PrestaShop\Core\Grid\Query\DoctrineQueryBuilderInterface;
use PrestaShop\PrestaShop\Core\Search\Filters\ProductCombinationFilters;
/**
* Handles @see GetEditableCombinationsList using legacy object model
*/
final class GetEditableCombinationsListHandler implements GetEditableCombinationsListHandlerInterface
{
/**
* @var StockAvailableRepository
*/
private $stockAvailableRepository;
/**
* @var DoctrineQueryBuilderInterface
*/
private $combinationQueryBuilder;
/**
* @var AttributeRepository
*/
private $attributeRepository;
/**
* @var ProductImageRepository
*/
private $productImageRepository;
/**
* @var ProductImagePathFactory
*/
private $productImagePathFactory;
/**
* @param StockAvailableRepository $stockAvailableRepository
* @param DoctrineQueryBuilderInterface $combinationQueryBuilder
* @param AttributeRepository $attributeRepository
* @param ProductImageRepository $productImageRepository
* @param ProductImagePathFactory $productImagePathFactory
*/
public function __construct(
StockAvailableRepository $stockAvailableRepository,
DoctrineQueryBuilderInterface $combinationQueryBuilder,
AttributeRepository $attributeRepository,
ProductImageRepository $productImageRepository,
ProductImagePathFactory $productImagePathFactory
) {
$this->stockAvailableRepository = $stockAvailableRepository;
$this->combinationQueryBuilder = $combinationQueryBuilder;
$this->attributeRepository = $attributeRepository;
$this->productImageRepository = $productImageRepository;
$this->productImagePathFactory = $productImagePathFactory;
}
/**
* {@inheritdoc}
*/
public function handle(GetEditableCombinationsList $query): CombinationListForEditing
{
$filters = $query->getFilters();
$filters['product_id'] = $query->getProductId()->getValue();
$searchCriteria = new ProductCombinationFilters([
'limit' => $query->getLimit(),
'offset' => $query->getOffset(),
'orderBy' => $query->getOrderBy(),
'sortOrder' => $query->getOrderWay(),
'filters' => $filters,
]);
$combinations = $this->combinationQueryBuilder->getSearchQueryBuilder($searchCriteria)->execute()->fetchAll();
$total = (int) $this->combinationQueryBuilder->getCountQueryBuilder($searchCriteria)->execute()->fetch(PDO::FETCH_COLUMN);
$combinationIds = array_map(function ($combination): int {
return (int) $combination['id_product_attribute'];
}, $combinations);
$attributesInformation = $this->attributeRepository->getAttributesInfoByCombinationIds(
$combinationIds,
$query->getLanguageId()
);
$productImageIds = $this->productImageRepository->getImagesIds($query->getProductId());
$imageIdsByCombinationIds = $this->productImageRepository->getImagesIdsForCombinations($combinationIds);
return $this->formatEditableCombinationsForListing(
$combinations,
$attributesInformation,
$total,
$imageIdsByCombinationIds,
$productImageIds
);
}
/**
* @param array $combinations
* @param array<int, array<int, mixed>> $attributesInformationByCombinationId
* @param int $totalCombinationsCount
* @param array $imageIdsByCombinationIds
* @param array $defaultImageIds
*
* @return CombinationListForEditing
*/
private function formatEditableCombinationsForListing(
array $combinations,
array $attributesInformationByCombinationId,
int $totalCombinationsCount,
array $imageIdsByCombinationIds,
array $defaultImageIds
): CombinationListForEditing {
$combinationsForEditing = [];
foreach ($combinations as $combination) {
$combinationId = (int) $combination['id_product_attribute'];
$combinationAttributesInformation = [];
foreach ($attributesInformationByCombinationId[$combinationId] as $attributeInfo) {
$combinationAttributesInformation[] = new CombinationAttributeInformation(
(int) $attributeInfo['id_attribute_group'],
$attributeInfo['attribute_group_name'],
(int) $attributeInfo['id_attribute'],
$attributeInfo['attribute_name']
);
}
$imageId = null;
if (!empty($imageIdsByCombinationIds[$combinationId])) {
$imageId = reset($imageIdsByCombinationIds[$combinationId]);
} elseif (!empty($defaultImageIds)) {
$imageId = reset($defaultImageIds);
}
$impactOnPrice = new DecimalNumber($combination['price']);
$combinationsForEditing[] = new EditableCombinationForListing(
$combinationId,
$this->buildCombinationName($combinationAttributesInformation),
$combination['reference'],
$combinationAttributesInformation,
(bool) $combination['default_on'],
$impactOnPrice,
(int) $this->stockAvailableRepository->getForCombination(new CombinationId($combinationId))->quantity,
$imageId ? $this->productImagePathFactory->getPathByType($imageId, ProductImagePathFactory::IMAGE_TYPE_SMALL_DEFAULT) : null
);
}
return new CombinationListForEditing($totalCombinationsCount, $combinationsForEditing);
}
/**
* @param CombinationAttributeInformation[] $attributesInformation
*
* @return string
*/
private function buildCombinationName(array $attributesInformation): string
{
$combinedNameParts = [];
foreach ($attributesInformation as $combinationAttributeInformation) {
$combinedNameParts[] = sprintf(
'%s - %s',
$combinationAttributeInformation->getAttributeGroupName(),
$combinationAttributeInformation->getAttributeName()
);
}
return implode(', ', $combinedNameParts);
}
}

View File

@@ -0,0 +1,306 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\Combination\Repository;
use Combination;
use Db;
use Doctrine\DBAL\Connection;
use PrestaShop\PrestaShop\Adapter\AbstractObjectModelRepository;
use PrestaShop\PrestaShop\Adapter\Attribute\Repository\AttributeRepository;
use PrestaShop\PrestaShop\Adapter\Product\Combination\Validate\CombinationValidator;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\Exception\CannotAddCombinationException;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\Exception\CannotBulkDeleteCombinationException;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\Exception\CannotDeleteCombinationException;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\Exception\CombinationNotFoundException;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\ValueObject\CombinationId;
use PrestaShop\PrestaShop\Core\Domain\Product\ValueObject\ProductId;
use PrestaShop\PrestaShop\Core\Exception\CoreException;
use PrestaShopException;
use Product;
/**
* Provides access to Combination data source
*/
class CombinationRepository extends AbstractObjectModelRepository
{
/**
* @var Connection
*/
private $connection;
/**
* @var string
*/
private $dbPrefix;
/**
* @var AttributeRepository
*/
private $attributeRepository;
/**
* @var CombinationValidator
*/
private $combinationValidator;
/**
* @param Connection $connection
* @param string $dbPrefix
* @param AttributeRepository $attributeRepository
* @param CombinationValidator $combinationValidator
*/
public function __construct(
Connection $connection,
string $dbPrefix,
AttributeRepository $attributeRepository,
CombinationValidator $combinationValidator
) {
$this->connection = $connection;
$this->dbPrefix = $dbPrefix;
$this->attributeRepository = $attributeRepository;
$this->combinationValidator = $combinationValidator;
}
/**
* @param CombinationId $combinationId
*
* @return Combination
*
* @throws CombinationNotFoundException
*/
public function get(CombinationId $combinationId): Combination
{
/** @var Combination $combination */
$combination = $this->getObjectModel(
$combinationId->getValue(),
Combination::class,
CombinationNotFoundException::class
);
return $combination;
}
/**
* @param ProductId $productId
* @param bool $isDefault
*
* @return Combination
*
* @throws CoreException
*/
public function create(ProductId $productId, bool $isDefault): Combination
{
$combination = new Combination();
$combination->id_product = $productId->getValue();
$combination->default_on = $isDefault;
$this->addObjectModel($combination, CannotAddCombinationException::class);
return $combination;
}
/**
* @param Combination $combination
* @param array $updatableProperties
* @param int $errorCode
*/
public function partialUpdate(Combination $combination, array $updatableProperties, int $errorCode): void
{
$this->combinationValidator->validate($combination);
$this->partiallyUpdateObjectModel(
$combination,
$updatableProperties,
CannotAddCombinationException::class,
$errorCode
);
}
/**
* @param CombinationId $combinationId
* @param int $errorCode
*
* @throws CoreException
*/
public function delete(CombinationId $combinationId, int $errorCode = 0): void
{
$this->deleteObjectModel($this->get($combinationId), CannotDeleteCombinationException::class, $errorCode);
}
/**
* @param ProductId $productId
*
* @throws CannotDeleteCombinationException
*/
public function deleteByProductId(ProductId $productId): void
{
$combinationIds = $this->getCombinationIdsByProductId($productId);
$this->bulkDelete($combinationIds);
}
/**
* @param array $combinationIds
*/
public function bulkDelete(array $combinationIds): void
{
$failedIds = [];
foreach ($combinationIds as $combinationId) {
try {
$this->delete($combinationId);
} catch (CannotDeleteCombinationException $e) {
$failedIds[] = $combinationId->getValue();
}
}
if (empty($failedIds)) {
return;
}
throw new CannotBulkDeleteCombinationException($failedIds, sprintf(
'Failed to delete following combinations: %s',
implode(', ', $failedIds)
));
}
/**
* @param ProductId $productId
*
* @return CombinationId[]
*/
public function getCombinationIdsByProductId(ProductId $productId): array
{
$qb = $this->connection->createQueryBuilder();
$qb
->select('pa.id_product_attribute')
->from($this->dbPrefix . 'product_attribute', 'pa')
->andWhere('pa.id_product = :productId')
->setParameter('productId', $productId->getValue())
->addOrderBy('pa.id_product_attribute', 'ASC')
;
$combinationIds = $qb->execute()->fetchAll();
return array_map(
function (array $combination) { return new CombinationId((int) $combination['id_product_attribute']); },
$combinationIds
);
}
/**
* @param CombinationId $combinationId
*
* @throws CoreException
*/
public function assertCombinationExists(CombinationId $combinationId): void
{
$this->assertObjectModelExists(
$combinationId->getValue(),
'product_attribute',
CombinationNotFoundException::class
);
}
/**
* @param CombinationId $combinationId
* @param int[] $attributeIds
*/
public function saveProductAttributeAssociation(CombinationId $combinationId, array $attributeIds): void
{
$this->assertCombinationExists($combinationId);
$this->attributeRepository->assertAllAttributesExist($attributeIds);
$attributesList = [];
foreach ($attributeIds as $attributeId) {
$attributesList[] = [
'id_product_attribute' => $combinationId->getValue(),
'id_attribute' => $attributeId,
];
}
try {
if (!Db::getInstance()->insert('product_attribute_combination', $attributesList)) {
throw new CannotAddCombinationException('Failed saving product-combination associations');
}
} catch (PrestaShopException $e) {
throw new CoreException('Error occurred when saving product-combination associations', 0, $e);
}
}
/**
* @param ProductId $productId
*
* @return Combination|null
*
* @throws CoreException
*/
public function findDefaultCombination(ProductId $productId): ?Combination
{
try {
$id = (int) Product::getDefaultAttribute($productId->getValue(), 0, true);
} catch (PrestaShopException $e) {
throw new CoreException('Error occurred while trying to get product default combination', 0, $e);
}
return $id ? $this->get(new CombinationId($id)) : null;
}
/**
* @param int[] $attributeIds
*
* @return CombinationId[]
*/
public function getCombinationIdsByAttributes(ProductId $productId, array $attributeIds): array
{
sort($attributeIds);
$qb = $this->connection->createQueryBuilder();
$qb
->addSelect('pa.id_product_attribute')
->addSelect('GROUP_CONCAT(pac.id_attribute ORDER BY pac.id_attribute ASC SEPARATOR "-") AS attribute_ids')
->from($this->dbPrefix . 'product_attribute', 'pa')
->innerJoin(
'pa',
$this->dbPrefix . 'product_attribute_combination',
'pac',
'pac.id_product_attribute = pa.id_product_attribute'
)
->andWhere('pa.id_product = :productId')
->andHaving('attribute_ids = :attributeIds')
->setParameter('productId', $productId->getValue())
->setParameter('attributeIds', implode('-', $attributeIds))
->addGroupBy('pa.id_product_attribute')
;
$result = $qb->execute()->fetchAll();
if (empty($result)) {
return [];
}
return array_map(function (array $combination) {
return new CombinationId((int) $combination['id_product_attribute']);
}, $result);
}
}

View File

@@ -0,0 +1,95 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\Combination\Update;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Exception\InvalidArgumentException;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\ValueObject\CombinationId;
use PrestaShop\PrestaShop\Core\Domain\Product\Image\ValueObject\ImageId;
/**
* Updates images associated to combination
*/
class CombinationImagesUpdater
{
/**
* @var Connection
*/
private $connection;
/**
* @var string
*/
private $dbPrefix;
public function __construct(
Connection $connection,
string $dbPrefix
) {
$this->connection = $connection;
$this->dbPrefix = $dbPrefix;
}
/**
* @param CombinationId $combinationId
*
* @throws DBALException
* @throws InvalidArgumentException
*/
public function deleteAllImageAssociations(CombinationId $combinationId): void
{
$this->connection->delete(
$this->dbPrefix . 'product_attribute_image',
['id_product_attribute' => $combinationId->getValue()]
);
}
/**
* @param CombinationId $combinationId
* @param ImageId[] $imageIds
*
* @throws DBALException
* @throws InvalidArgumentException
*/
public function associateImages(CombinationId $combinationId, array $imageIds): void
{
// First delete all images
$this->deleteAllImageAssociations($combinationId);
// Then create all new ones
foreach ($imageIds as $imageId) {
$insertedValues = [
'id_product_attribute' => $combinationId->getValue(),
'id_image' => $imageId->getValue(),
];
$this->connection->insert($this->dbPrefix . 'product_attribute_image', $insertedValues);
}
}
}

View File

@@ -0,0 +1,112 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\Combination\Update;
use PrestaShop\PrestaShop\Adapter\Product\Combination\Repository\CombinationRepository;
use PrestaShop\PrestaShop\Adapter\Product\Repository\ProductRepository;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\Exception\CannotAddCombinationException;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\Exception\CannotDeleteCombinationException;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\Exception\CombinationNotFoundException;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\ValueObject\CombinationId;
use PrestaShop\PrestaShop\Core\Domain\Product\Exception\InvalidProductTypeException;
use PrestaShop\PrestaShop\Core\Domain\Product\Exception\ProductConstraintException;
use PrestaShop\PrestaShop\Core\Domain\Product\ValueObject\ProductId;
use PrestaShop\PrestaShop\Core\Domain\Product\ValueObject\ProductType;
use PrestaShop\PrestaShop\Core\Exception\CoreException;
class CombinationRemover
{
/**
* @var ProductRepository
*/
private $productRepository;
/**
* @var CombinationRepository
*/
private $combinationRepository;
/**
* @var DefaultCombinationUpdater
*/
private $defaultCombinationUpdater;
/**
* @param ProductRepository $productRepository
* @param CombinationRepository $combinationRepository
* @param DefaultCombinationUpdater $defaultCombinationUpdater
*/
public function __construct(
ProductRepository $productRepository,
CombinationRepository $combinationRepository,
DefaultCombinationUpdater $defaultCombinationUpdater
) {
$this->productRepository = $productRepository;
$this->combinationRepository = $combinationRepository;
$this->defaultCombinationUpdater = $defaultCombinationUpdater;
}
/**
* @param CombinationId $combinationId
*
* @throws CoreException
* @throws CannotAddCombinationException
* @throws CombinationNotFoundException
* @throws ProductConstraintException
*/
public function removeCombination(CombinationId $combinationId): void
{
$combination = $this->combinationRepository->get($combinationId);
$this->combinationRepository->delete($combinationId);
if ($combination->default_on) {
$productId = new ProductId((int) $combination->id_product);
$defaultCombination = $this->combinationRepository->findDefaultCombination($productId);
if (null !== $defaultCombination) {
$this->defaultCombinationUpdater->setDefaultCombination(new CombinationId((int) $defaultCombination->id));
}
}
}
/**
* @param ProductId $productId
*
* @throws InvalidProductTypeException
* @throws CannotDeleteCombinationException
* @throws CoreException
*/
public function removeAllProductCombinations(ProductId $productId): void
{
$product = $this->productRepository->get($productId);
if ($product->product_type !== ProductType::TYPE_COMBINATIONS) {
throw new InvalidProductTypeException(InvalidProductTypeException::EXPECTED_COMBINATIONS_TYPE);
}
$this->combinationRepository->deleteByProductId($productId);
}
}

View File

@@ -0,0 +1,135 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\Combination\Update;
use DateTimeInterface;
class CombinationStockProperties
{
/**
* @var int|null
*/
private $quantity;
/**
* @var int|null
*/
private $minimalQuantity;
/**
* @var string|null
*/
private $location;
/**
* @var int|null
*/
private $lowStockThreshold;
/**
* @var bool|null
*/
private $lowStockAlertEnabled;
/**
* @var DateTimeInterface|null
*/
private $availableDate;
/**
* @param int|null $quantity
* @param int|null $minimalQuantity
* @param string|null $location
* @param int|null $lowStockThreshold
* @param bool|null $lowStockAlertEnabled
* @param DateTimeInterface|null $availableDate
*/
public function __construct(
?int $quantity = null,
?int $minimalQuantity = null,
?string $location = null,
?int $lowStockThreshold = null,
?bool $lowStockAlertEnabled = null,
?DateTimeInterface $availableDate = null
) {
$this->quantity = $quantity;
$this->minimalQuantity = $minimalQuantity;
$this->location = $location;
$this->lowStockThreshold = $lowStockThreshold;
$this->lowStockAlertEnabled = $lowStockAlertEnabled;
$this->availableDate = $availableDate;
}
/**
* @return int|null
*/
public function getQuantity(): ?int
{
return $this->quantity;
}
/**
* @return int|null
*/
public function getMinimalQuantity(): ?int
{
return $this->minimalQuantity;
}
/**
* @return string|null
*/
public function getLocation(): ?string
{
return $this->location;
}
/**
* @return int|null
*/
public function getLowStockThreshold(): ?int
{
return $this->lowStockThreshold;
}
/**
* @return bool|null
*/
public function isLowStockAlertEnabled(): ?bool
{
return $this->lowStockAlertEnabled;
}
/**
* @return DateTimeInterface|null
*/
public function getAvailableDate(): ?DateTimeInterface
{
return $this->availableDate;
}
}

View File

@@ -0,0 +1,191 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\Combination\Update;
use Combination;
use PrestaShop\PrestaShop\Adapter\Product\Combination\Repository\CombinationRepository;
use PrestaShop\PrestaShop\Adapter\Product\Stock\Repository\StockAvailableRepository;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\Exception\CannotUpdateCombinationException;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\ValueObject\CombinationId;
use PrestaShop\PrestaShop\Core\Exception\CoreException;
use PrestaShop\PrestaShop\Core\Stock\StockManager;
use PrestaShop\PrestaShop\Core\Util\DateTime\DateTime;
use PrestaShopException;
/**
* Updates stock for product combination
*/
class CombinationStockUpdater
{
/**
* @var StockAvailableRepository
*/
private $stockAvailableRepository;
/**
* @var CombinationRepository
*/
private $combinationRepository;
/**
* @var StockManager
*/
private $stockManager;
/**
* @param StockAvailableRepository $stockAvailableRepository
* @param CombinationRepository $combinationRepository
* @param StockManager $stockManager
*/
public function __construct(
StockAvailableRepository $stockAvailableRepository,
CombinationRepository $combinationRepository,
StockManager $stockManager
) {
$this->stockAvailableRepository = $stockAvailableRepository;
$this->combinationRepository = $combinationRepository;
$this->stockManager = $stockManager;
}
/**
* @param CombinationId $combinationId
* @param CombinationStockProperties $properties
*/
public function update(CombinationId $combinationId, CombinationStockProperties $properties): void
{
$combination = $this->combinationRepository->get($combinationId);
$this->combinationRepository->partialUpdate(
$combination,
$this->fillUpdatableProperties($combination, $properties),
CannotUpdateCombinationException::FAILED_UPDATE_STOCK
);
$this->updateStockAvailable($combination, $properties);
}
/**
* @param Combination $combination
* @param CombinationStockProperties $properties
*
* @return string[]
*/
private function fillUpdatableProperties(Combination $combination, CombinationStockProperties $properties): array
{
$updatableProperties = [];
if (null !== $properties->getQuantity()) {
$combination->quantity = $properties->getQuantity();
$updatableProperties[] = 'quantity';
}
if (null !== $properties->getAvailableDate()) {
$combination->available_date = $properties->getAvailableDate()->format(DateTime::DEFAULT_DATE_FORMAT);
$updatableProperties[] = 'available_date';
}
if (null !== $properties->getLocation()) {
$combination->location = $properties->getLocation();
$updatableProperties[] = 'location';
}
if (null !== $properties->getLowStockThreshold()) {
$combination->low_stock_threshold = $properties->getLowStockThreshold();
$updatableProperties[] = 'low_stock_threshold';
}
if (null !== $properties->getMinimalQuantity()) {
$combination->minimal_quantity = $properties->getMinimalQuantity();
$updatableProperties[] = 'minimal_quantity';
}
if (null !== $properties->isLowStockAlertEnabled()) {
$combination->low_stock_alert = $properties->isLowStockAlertEnabled();
$updatableProperties[] = 'low_stock_alert';
}
return $updatableProperties;
}
/**
* @param Combination $combination
* @param CombinationStockProperties $properties
*/
private function updateStockAvailable(Combination $combination, CombinationStockProperties $properties): void
{
$updateQuantity = null !== $properties->getQuantity();
$updateLocation = null !== $properties->getLocation();
if (!$updateQuantity && !$updateLocation) {
return;
}
$newQuantity = $properties->getQuantity();
$newLocation = $properties->getLocation();
$stockAvailable = $this->stockAvailableRepository->getForCombination(new CombinationId((int) $combination->id));
if ($updateQuantity) {
$this->saveMovement($combination, (int) $stockAvailable->quantity, $newQuantity);
$stockAvailable->quantity = $newQuantity;
}
if ($updateLocation) {
$stockAvailable->location = $newLocation;
}
$this->stockAvailableRepository->update($stockAvailable);
}
/**
* @param Combination $combination
* @param int $oldQuantity
* @param int $newQuantity
*
* @throws CoreException
*/
private function saveMovement(Combination $combination, int $oldQuantity, int $newQuantity): void
{
$combinationId = $combination->id;
$deltaQuantity = $newQuantity - $oldQuantity;
if (0 === $deltaQuantity) {
return;
}
try {
$this->stockManager->saveMovement($combination->id_product, $combinationId, $deltaQuantity);
} catch (PrestaShopException $e) {
throw new CoreException(
sprintf('Error occurred when trying to save stock movement for combination %d', $combinationId),
0,
$e
);
}
}
}

View File

@@ -0,0 +1,96 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\Combination\Update;
use Combination;
use PrestaShop\PrestaShop\Adapter\Product\Combination\Repository\CombinationRepository;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\Exception\CannotAddCombinationException;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\Exception\CannotUpdateCombinationException;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\Exception\CombinationNotFoundException;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\ValueObject\CombinationId;
use PrestaShop\PrestaShop\Core\Domain\Product\Exception\ProductConstraintException;
use PrestaShop\PrestaShop\Core\Domain\Product\ValueObject\ProductId;
use PrestaShop\PrestaShop\Core\Exception\CoreException;
/**
* Updates default combination for product
*/
class DefaultCombinationUpdater
{
/**
* @var CombinationRepository
*/
private $combinationRepository;
/**
* @param CombinationRepository $combinationRepository
*/
public function __construct(
CombinationRepository $combinationRepository
) {
$this->combinationRepository = $combinationRepository;
}
/**
* @param CombinationId $defaultCombinationId
*
* @throws CoreException
* @throws CannotAddCombinationException
* @throws CombinationNotFoundException
* @throws ProductConstraintException
*/
public function setDefaultCombination(CombinationId $defaultCombinationId): void
{
$newDefaultCombination = $this->combinationRepository->get($defaultCombinationId);
$productId = new ProductId((int) $newDefaultCombination->id_product);
$currentDefaultCombination = $this->combinationRepository->findDefaultCombination($productId);
if ($currentDefaultCombination) {
$this->updateCombinationDefaultProperty($currentDefaultCombination, false);
}
$this->updateCombinationDefaultProperty($newDefaultCombination, true);
}
/**
* @param Combination $combination
* @param bool $isDefault
*
* @throws CannotAddCombinationException
*/
private function updateCombinationDefaultProperty(Combination $combination, bool $isDefault): void
{
$combination->default_on = $isDefault;
$this->combinationRepository->partialUpdate(
$combination,
['default_on'],
CannotUpdateCombinationException::FAILED_UPDATE_DEFAULT_COMBINATION
);
}
}

View File

@@ -0,0 +1,114 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\Combination\Validate;
use Combination;
use PrestaShop\PrestaShop\Adapter\AbstractObjectModelValidator;
use PrestaShop\PrestaShop\Core\Domain\Product\Exception\ProductConstraintException;
use PrestaShop\PrestaShop\Core\Domain\Product\Stock\Exception\ProductStockConstraintException;
use PrestaShop\PrestaShop\Core\Exception\CoreException;
/**
* Validates Combination properties using legacy object model
*/
class CombinationValidator extends AbstractObjectModelValidator
{
/**
* @param Combination $combination
*/
public function validate(Combination $combination): void
{
$this->validateDetails($combination);
$this->validatePrices($combination);
$this->validateStock($combination);
}
/**
* @param Combination $combination
*
* @throws CoreException
* @throws ProductConstraintException
*/
private function validateDetails(Combination $combination): void
{
$this->validateCombinationProperty($combination, 'ean13', ProductConstraintException::INVALID_EAN_13);
$this->validateCombinationProperty($combination, 'isbn', ProductConstraintException::INVALID_ISBN);
$this->validateCombinationProperty($combination, 'mpn', ProductConstraintException::INVALID_MPN);
$this->validateCombinationProperty($combination, 'reference', ProductConstraintException::INVALID_REFERENCE);
$this->validateCombinationProperty($combination, 'upc', ProductConstraintException::INVALID_UPC);
$this->validateCombinationProperty($combination, 'weight', ProductConstraintException::INVALID_WEIGHT);
}
/**
* @param Combination $combination
*
* @throws CoreException
* @throws ProductConstraintException
*/
private function validatePrices(Combination $combination): void
{
$this->validateCombinationProperty($combination, 'price', ProductConstraintException::INVALID_PRICE);
$this->validateCombinationProperty($combination, 'ecotax', ProductConstraintException::INVALID_ECOTAX);
$this->validateCombinationProperty($combination, 'unit_price_impact', ProductConstraintException::INVALID_UNIT_PRICE);
$this->validateCombinationProperty($combination, 'wholesale_price', ProductConstraintException::INVALID_WHOLESALE_PRICE);
}
/**
* @param Combination $combination
*
* @throws CoreException
* @throws ProductConstraintException
*/
private function validateStock(Combination $combination): void
{
$this->validateCombinationProperty($combination, 'minimal_quantity', ProductConstraintException::INVALID_MINIMAL_QUANTITY);
$this->validateCombinationProperty($combination, 'low_stock_threshold', ProductConstraintException::INVALID_LOW_STOCK_THRESHOLD);
$this->validateCombinationProperty($combination, 'low_stock_alert', ProductConstraintException::INVALID_LOW_STOCK_ALERT);
$this->validateCombinationProperty($combination, 'available_date', ProductConstraintException::INVALID_AVAILABLE_DATE);
$this->validateObjectModelProperty(
$combination,
'quantity',
ProductStockConstraintException::class,
ProductStockConstraintException::INVALID_QUANTITY
);
}
/**
* @param Combination $combination
* @param string $property
* @param int $errorCode
*
* @throws CoreException
* @throws ProductConstraintException
*/
private function validateCombinationProperty(Combination $combination, string $property, int $errorCode): void
{
$this->validateObjectModelProperty($combination, $property, ProductConstraintException::class, $errorCode);
}
}

View File

@@ -0,0 +1,64 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\CommandHandler;
use PrestaShop\PrestaShop\Adapter\Product\Repository\ProductRepository;
use PrestaShop\PrestaShop\Core\Domain\Product\Command\AddProductCommand;
use PrestaShop\PrestaShop\Core\Domain\Product\CommandHandler\AddProductHandlerInterface;
use PrestaShop\PrestaShop\Core\Domain\Product\ValueObject\ProductId;
/**
* Handles @see AddProductCommand using legacy object model
*/
final class AddProductHandler implements AddProductHandlerInterface
{
/**
* @var ProductRepository
*/
private $productRepository;
/**
* @param ProductRepository $productRepository
*/
public function __construct(
ProductRepository $productRepository
) {
$this->productRepository = $productRepository;
}
/**
* {@inheritdoc}
*/
public function handle(AddProductCommand $command): ProductId
{
$product = $this->productRepository->create($command->getLocalizedNames(), $command->getProductType()->getValue());
return new ProductId((int) $product->id);
}
}

View File

@@ -0,0 +1,64 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
namespace PrestaShop\PrestaShop\Adapter\Product\CommandHandler;
use PrestaShop\PrestaShop\Adapter\Domain\AbstractObjectModelHandler;
use PrestaShop\PrestaShop\Adapter\Product\ProductDataProvider;
use PrestaShop\PrestaShop\Core\Domain\Product\Command\AssignProductToCategoryCommand;
use PrestaShop\PrestaShop\Core\Domain\Product\CommandHandler\AssignProductToCategoryHandlerInterface;
use PrestaShop\PrestaShop\Core\Domain\Product\Exception\CannotAssignProductToCategoryException;
/**
* Adds a category to a product
*
* @internal
*/
final class AssignProductToCategoryHandler extends AbstractObjectModelHandler implements AssignProductToCategoryHandlerInterface
{
/**
* @param AssignProductToCategoryCommand $command
*/
public function handle(AssignProductToCategoryCommand $command)
{
$this->assignProductToCategory($command);
}
/**
* @param AssignProductToCategoryCommand $command
*
* @throws CannotAssignProductToCategoryException
*/
private function assignProductToCategory(AssignProductToCategoryCommand $command)
{
$productDataProvider = new ProductDataProvider();
$product = $productDataProvider->getProductInstance($command->getProductId()->getValue());
$product->addToCategories($command->getCategoryId()->getValue());
if (false === $product->save()) {
throw new CannotAssignProductToCategoryException(sprintf('Failed to add category to product %d', $command->getProductId()->getValue()));
}
}
}

View File

@@ -0,0 +1,61 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\CommandHandler;
use PrestaShop\PrestaShop\Adapter\Product\Update\ProductAttachmentUpdater;
use PrestaShop\PrestaShop\Core\Domain\Product\Command\AssociateProductAttachmentCommand;
use PrestaShop\PrestaShop\Core\Domain\Product\CommandHandler\AssociateProductAttachmentHandlerInterface;
/**
* Handles @see AssociateProductAttachmentCommand using legacy object model
*/
final class AssociateProductAttachmentHandler implements AssociateProductAttachmentHandlerInterface
{
/**
* @var ProductAttachmentUpdater
*/
private $productAttachmentUpdater;
/**
* @param ProductAttachmentUpdater $productAttachmentUpdater
*/
public function __construct(
ProductAttachmentUpdater $productAttachmentUpdater
) {
$this->productAttachmentUpdater = $productAttachmentUpdater;
}
/**
* {@inheritdoc}
*/
public function handle(AssociateProductAttachmentCommand $command): void
{
$this->productAttachmentUpdater->associateProductAttachment($command->getProductId(), $command->getAttachmentId());
}
}

View File

@@ -0,0 +1,60 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\CommandHandler;
use PrestaShop\PrestaShop\Adapter\Product\Repository\ProductRepository;
use PrestaShop\PrestaShop\Core\Domain\Product\Command\BulkDeleteProductCommand;
use PrestaShop\PrestaShop\Core\Domain\Product\CommandHandler\BulkDeleteProductHandlerInterface;
/**
* Handles command which deletes addresses in bulk action
*/
final class BulkDeleteProductHandler implements BulkDeleteProductHandlerInterface
{
/**
* @var ProductRepository
*/
private $productRepository;
/**
* @param ProductRepository $productRepository
*/
public function __construct(ProductRepository $productRepository)
{
$this->productRepository = $productRepository;
}
/**
* {@inheritdoc}
*/
public function handle(BulkDeleteProductCommand $command): void
{
$this->productRepository->bulkDelete($command->getProductIds());
}
}

View File

@@ -0,0 +1,60 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\CommandHandler;
use PrestaShop\PrestaShop\Adapter\Product\Repository\ProductRepository;
use PrestaShop\PrestaShop\Core\Domain\Product\Command\DeleteProductCommand;
use PrestaShop\PrestaShop\Core\Domain\Product\CommandHandler\DeleteProductHandlerInterface;
/**
* Handles @see DeleteProductCommand using legacy object model
*/
final class DeleteProductHandler implements DeleteProductHandlerInterface
{
/**
* @var ProductRepository
*/
private $productRepository;
/**
* @param ProductRepository $productRepository
*/
public function __construct(ProductRepository $productRepository)
{
$this->productRepository = $productRepository;
}
/**
* {@inheritdoc}
*/
public function handle(DeleteProductCommand $command): void
{
$this->productRepository->delete($command->getProductId());
}
}

View File

@@ -0,0 +1,62 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\CommandHandler;
use PrestaShop\PrestaShop\Adapter\Product\ProductDuplicator;
use PrestaShop\PrestaShop\Core\Domain\Product\Command\DuplicateProductCommand;
use PrestaShop\PrestaShop\Core\Domain\Product\CommandHandler\DuplicateProductHandlerInterface;
use PrestaShop\PrestaShop\Core\Domain\Product\ValueObject\ProductId;
/**
* Handles @see DuplicateProductCommand
*/
final class DuplicateProductHandler implements DuplicateProductHandlerInterface
{
/**
* @var ProductDuplicator
*/
private $productDuplicator;
/**
* @param ProductDuplicator $productDuplicator
*/
public function __construct(
ProductDuplicator $productDuplicator
) {
$this->productDuplicator = $productDuplicator;
}
/**
* {@inheritdoc}
*/
public function handle(DuplicateProductCommand $command): ProductId
{
return $this->productDuplicator->duplicate($command->getProductId());
}
}

View File

@@ -0,0 +1,61 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\CommandHandler;
use PrestaShop\PrestaShop\Adapter\Product\Update\ProductAttachmentUpdater;
use PrestaShop\PrestaShop\Core\Domain\Product\Command\RemoveAllAssociatedProductAttachmentsCommand;
use PrestaShop\PrestaShop\Core\Domain\Product\CommandHandler\RemoveAllAssociatedProductAttachmentsHandlerInterface;
/**
* Removes all product-attachment associations for given product
*/
final class RemoveAllAssociatedProductAttachmentsHandler implements RemoveAllAssociatedProductAttachmentsHandlerInterface
{
/**
* @var ProductAttachmentUpdater
*/
private $productAttachmentUpdater;
/**
* @param ProductAttachmentUpdater $productAttachmentUpdater
*/
public function __construct(
ProductAttachmentUpdater $productAttachmentUpdater
) {
$this->productAttachmentUpdater = $productAttachmentUpdater;
}
/**
* {@inheritdoc}
*/
public function handle(RemoveAllAssociatedProductAttachmentsCommand $command): void
{
$this->productAttachmentUpdater->setAttachments($command->getProductId(), []);
}
}

View File

@@ -0,0 +1,84 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\CommandHandler;
use PrestaShop\PrestaShop\Adapter\Product\Repository\ProductRepository;
use PrestaShop\PrestaShop\Adapter\Product\Update\ProductCategoryUpdater;
use PrestaShop\PrestaShop\Core\Domain\Category\ValueObject\CategoryId;
use PrestaShop\PrestaShop\Core\Domain\Product\Command\RemoveAllAssociatedProductCategoriesCommand;
use PrestaShop\PrestaShop\Core\Domain\Product\CommandHandler\RemoveAllAssociatedProductCategoriesHandlerInterface;
/**
* Handles @see RemoveAllAssociatedProductCategoriesCommand using legacy object model
*/
final class RemoveAllAssociatedProductCategoriesHandler implements RemoveAllAssociatedProductCategoriesHandlerInterface
{
/**
* @var int
*/
private $homeCategoryId;
/**
* @var ProductCategoryUpdater
*/
private $productCategoryUpdater;
/**
* @var ProductRepository
*/
private $productRepository;
/**
* @param int $homeCategoryId
* @param ProductCategoryUpdater $productCategoryUpdater
* @param ProductRepository $productRepository
*/
public function __construct(
int $homeCategoryId,
ProductCategoryUpdater $productCategoryUpdater,
ProductRepository $productRepository
) {
$this->homeCategoryId = $homeCategoryId;
$this->productCategoryUpdater = $productCategoryUpdater;
$this->productRepository = $productRepository;
}
/**
* {@inheritdoc}
*/
public function handle(RemoveAllAssociatedProductCategoriesCommand $command): void
{
$product = $this->productRepository->get($command->getProductId());
$categoryId = new CategoryId($this->homeCategoryId);
// remove all categories associated with this product, keep only home Category
// @todo: this is likely to break with multishop
$this->productCategoryUpdater->updateCategories($product, [$categoryId], $categoryId);
}
}

View File

@@ -0,0 +1,69 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\CommandHandler;
use PrestaShop\PrestaShop\Adapter\Product\Repository\ProductRepository;
use PrestaShop\PrestaShop\Adapter\Product\Update\ProductTagUpdater;
use PrestaShop\PrestaShop\Core\Domain\Product\Command\RemoveAllProductTagsCommand;
use PrestaShop\PrestaShop\Core\Domain\Product\CommandHandler\RemoveAllProductTagsHandlerInterface;
final class RemoveAllProductTagsHandler implements RemoveAllProductTagsHandlerInterface
{
/**
* @var ProductRepository
*/
private $productRepository;
/**
* @var ProductTagUpdater
*/
private $productTagUpdater;
/**
* @param ProductRepository $productRepository
* @param ProductTagUpdater $productTagUpdater
*/
public function __construct(
ProductRepository $productRepository,
ProductTagUpdater $productTagUpdater
) {
$this->productRepository = $productRepository;
$this->productTagUpdater = $productTagUpdater;
}
/**
* {@inheritdoc}
*/
public function handle(RemoveAllProductTagsCommand $command): void
{
$product = $this->productRepository->get($command->getProductId());
$this->productTagUpdater->setProductTags($product, []);
}
}

View File

@@ -0,0 +1,61 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\CommandHandler;
use PrestaShop\PrestaShop\Adapter\Product\Update\RelatedProductsUpdater;
use PrestaShop\PrestaShop\Core\Domain\Product\Command\RemoveAllRelatedProductsCommand;
use PrestaShop\PrestaShop\Core\Domain\Product\CommandHandler\RemoveAllRelatedProductsHandlerInterface;
/**
* Handles @see RemoveAllRelatedProductsCommand using legacy object model
*/
final class RemoveAllRelatedProductsHandler implements RemoveAllRelatedProductsHandlerInterface
{
/**
* @var RelatedProductsUpdater
*/
private $relatedProductsUpdater;
/**
* @param RelatedProductsUpdater $relatedProductsUpdater
*/
public function __construct(
RelatedProductsUpdater $relatedProductsUpdater
) {
$this->relatedProductsUpdater = $relatedProductsUpdater;
}
/**
* {@inheritdoc}
*/
public function handle(RemoveAllRelatedProductsCommand $command): void
{
$this->relatedProductsUpdater->setRelatedProducts($command->getProductId(), []);
}
}

View File

@@ -0,0 +1,61 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\CommandHandler;
use PrestaShop\PrestaShop\Adapter\Product\Update\ProductAttachmentUpdater;
use PrestaShop\PrestaShop\Core\Domain\Product\Command\SetAssociatedProductAttachmentsCommand;
use PrestaShop\PrestaShop\Core\Domain\Product\CommandHandler\SetAssociatedProductAttachmentsHandlerInterface;
/**
* Handles @see SetAssociatedProductAttachmentsCommand using legacy object model
*/
final class SetAssociatedProductAttachmentsHandler implements SetAssociatedProductAttachmentsHandlerInterface
{
/**
* @var ProductAttachmentUpdater
*/
private $productAttachmentUpdater;
/**
* @param ProductAttachmentUpdater $productUpdater
*/
public function __construct(
ProductAttachmentUpdater $productUpdater
) {
$this->productAttachmentUpdater = $productUpdater;
}
/**
* {@inheritdoc}
*/
public function handle(SetAssociatedProductAttachmentsCommand $command): void
{
$this->productAttachmentUpdater->setAttachments($command->getProductId(), $command->getAttachmentIds());
}
}

View File

@@ -0,0 +1,71 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\CommandHandler;
use PrestaShop\PrestaShop\Adapter\Product\Repository\ProductRepository;
use PrestaShop\PrestaShop\Adapter\Product\Update\ProductCategoryUpdater;
use PrestaShop\PrestaShop\Core\Domain\Product\Command\SetAssociatedProductCategoriesCommand;
use PrestaShop\PrestaShop\Core\Domain\Product\CommandHandler\SetAssociatedProductCategoriesHandlerInterface;
/**
* Handles @var SetAssociatedProductCategoriesCommand using legacy object model
*/
final class SetAssociatedProductCategoriesHandler implements SetAssociatedProductCategoriesHandlerInterface
{
/**
* @var ProductRepository
*/
private $productRepository;
/**
* @var ProductCategoryUpdater
*/
private $productCategoryUpdater;
/**
* @param ProductRepository $productRepository
* @param ProductCategoryUpdater $productCategoryUpdater
*/
public function __construct(
ProductRepository $productRepository,
ProductCategoryUpdater $productCategoryUpdater
) {
$this->productRepository = $productRepository;
$this->productCategoryUpdater = $productCategoryUpdater;
}
/**
* {@inheritdoc}
*/
public function handle(SetAssociatedProductCategoriesCommand $command): void
{
$product = $this->productRepository->get($command->getProductId());
$this->productCategoryUpdater->updateCategories($product, $command->getCategoryIds(), $command->getDefaultCategoryId());
}
}

View File

@@ -0,0 +1,71 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\CommandHandler;
use PrestaShop\PrestaShop\Adapter\Product\Repository\ProductRepository;
use PrestaShop\PrestaShop\Adapter\Product\Update\ProductTagUpdater;
use PrestaShop\PrestaShop\Core\Domain\Product\Command\SetProductTagsCommand;
use PrestaShop\PrestaShop\Core\Domain\Product\CommandHandler\UpdateProductTagsHandlerInterface;
/**
* Handles UpdateProductTagsCommand using legacy object model
*/
final class SetProductTagsHandler implements UpdateProductTagsHandlerInterface
{
/**
* @var ProductRepository
*/
private $productRepository;
/**
* @var ProductTagUpdater
*/
private $productTagUpdater;
/**
* @param ProductRepository $productRepository
* @param ProductTagUpdater $productTagUpdater
*/
public function __construct(
ProductRepository $productRepository,
ProductTagUpdater $productTagUpdater
) {
$this->productRepository = $productRepository;
$this->productTagUpdater = $productTagUpdater;
}
/**
* {@inheritdoc}
*/
public function handle(SetProductTagsCommand $command): void
{
$product = $this->productRepository->get($command->getProductId());
$this->productTagUpdater->setProductTags($product, $command->getLocalizedTagsList());
}
}

View File

@@ -0,0 +1,61 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\CommandHandler;
use PrestaShop\PrestaShop\Adapter\Product\Update\RelatedProductsUpdater;
use PrestaShop\PrestaShop\Core\Domain\Product\Command\SetRelatedProductsCommand;
use PrestaShop\PrestaShop\Core\Domain\Product\CommandHandler\SetRelatedProductsHandlerInterface;
/**
* handles @see SetRelatedProductsCommand using legacy object models
*/
final class SetRelatedProductsHandler implements SetRelatedProductsHandlerInterface
{
/**
* @var RelatedProductsUpdater
*/
private $relatedProductsUpdater;
/**
* @param RelatedProductsUpdater $relatedProductsUpdater
*/
public function __construct(
RelatedProductsUpdater $relatedProductsUpdater
) {
$this->relatedProductsUpdater = $relatedProductsUpdater;
}
/**
* {@inheritdoc}
*/
public function handle(SetRelatedProductsCommand $command): void
{
$this->relatedProductsUpdater->setRelatedProducts($command->getProductId(), $command->getRelatedProductIds());
}
}

View File

@@ -0,0 +1,105 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\CommandHandler;
use PrestaShop\PrestaShop\Adapter\Product\Repository\ProductRepository;
use PrestaShop\PrestaShop\Core\Domain\Product\Command\UpdateProductBasicInformationCommand;
use PrestaShop\PrestaShop\Core\Domain\Product\CommandHandler\UpdateProductBasicInformationHandlerInterface;
use PrestaShop\PrestaShop\Core\Domain\Product\Exception\CannotUpdateProductException;
use Product;
/**
* Handles command for product basic information update using legacy object model
*/
final class UpdateProductBasicInformationHandler implements UpdateProductBasicInformationHandlerInterface
{
/**
* @var ProductRepository
*/
private $productRepository;
/**
* @param ProductRepository $productRepository
*/
public function __construct(
ProductRepository $productRepository
) {
$this->productRepository = $productRepository;
}
/**
* {@inheritdoc}
*
* Null values are not updated, because are considered unchanged
*/
public function handle(UpdateProductBasicInformationCommand $command): void
{
$product = $this->productRepository->get($command->getProductId());
$updatableProperties = $this->fillUpdatableProperties($product, $command);
if (empty($updatableProperties)) {
return;
}
$this->productRepository->partialUpdate($product, $updatableProperties, CannotUpdateProductException::FAILED_UPDATE_BASIC_INFO);
}
/**
* @param Product $product
* @param UpdateProductBasicInformationCommand $command
*
* @return array<string, mixed>
*/
private function fillUpdatableProperties(
Product $product,
UpdateProductBasicInformationCommand $command
): array {
$updatableProperties = [];
$localizedNames = $command->getLocalizedNames();
if (null !== $localizedNames) {
$product->name = $localizedNames;
$updatableProperties['name'] = array_keys($localizedNames);
}
$localizedDescriptions = $command->getLocalizedDescriptions();
if (null !== $localizedDescriptions) {
$product->description = $localizedDescriptions;
$updatableProperties['description'] = array_keys($localizedDescriptions);
}
$localizedShortDescriptions = $command->getLocalizedShortDescriptions();
if (null !== $localizedShortDescriptions) {
$product->description_short = $localizedShortDescriptions;
$updatableProperties['description_short'] = array_keys($localizedShortDescriptions);
}
return $updatableProperties;
}
}

View File

@@ -0,0 +1,104 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\CommandHandler;
use PrestaShop\PrestaShop\Adapter\Product\Repository\ProductRepository;
use PrestaShop\PrestaShop\Core\Domain\Product\Command\UpdateProductDetailsCommand;
use PrestaShop\PrestaShop\Core\Domain\Product\CommandHandler\UpdateProductDetailsHandlerInterface;
use PrestaShop\PrestaShop\Core\Domain\Product\Exception\CannotUpdateProductException;
use Product;
/**
* Handles @see UpdateProductDetailsCommand using leagacy object model
*/
final class UpdateProductDetailsHandler implements UpdateProductDetailsHandlerInterface
{
/**
* @var ProductRepository
*/
private $productRepository;
/**
* @param ProductRepository $productRepository
*/
public function __construct(
ProductRepository $productRepository
) {
$this->productRepository = $productRepository;
}
/**
* {@inheritdoc}
*/
public function handle(UpdateProductDetailsCommand $command): void
{
$product = $this->productRepository->get($command->getProductId());
$updatableProperties = $this->fillUpdatableProperties($product, $command);
$this->productRepository->partialUpdate($product, $updatableProperties, CannotUpdateProductException::FAILED_UPDATE_DETAILS);
}
/**
* @param Product $product
* @param UpdateProductDetailsCommand $command
*
* @return string[] updatable properties
*/
private function fillUpdatableProperties(Product $product, UpdateProductDetailsCommand $command): array
{
$updatableProperties = [];
if (null !== $command->getEan13()) {
$product->ean13 = $command->getEan13()->getValue();
$updatableProperties[] = 'ean13';
}
if (null !== $command->getIsbn()) {
$product->isbn = $command->getIsbn()->getValue();
$updatableProperties[] = 'isbn';
}
if (null !== $command->getMpn()) {
$product->mpn = $command->getMpn();
$updatableProperties[] = 'mpn';
}
if (null !== $command->getReference()) {
$product->reference = $command->getReference()->getValue();
$updatableProperties[] = 'reference';
}
if (null !== $command->getUpc()) {
$product->upc = $command->getUpc()->getValue();
$updatableProperties[] = 'upc';
}
return $updatableProperties;
}
}

View File

@@ -0,0 +1,150 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\CommandHandler;
use PrestaShop\PrestaShop\Adapter\Manufacturer\Repository\ManufacturerRepository;
use PrestaShop\PrestaShop\Adapter\Product\Repository\ProductRepository;
use PrestaShop\PrestaShop\Adapter\Product\Update\ProductIndexationUpdater;
use PrestaShop\PrestaShop\Core\ConfigurationInterface;
use PrestaShop\PrestaShop\Core\Domain\Product\Command\UpdateProductOptionsCommand;
use PrestaShop\PrestaShop\Core\Domain\Product\CommandHandler\UpdateProductOptionsHandlerInterface;
use PrestaShop\PrestaShop\Core\Domain\Product\Exception\CannotUpdateProductException;
use Product;
/**
* Handles @see UpdateProductOptionsCommand using legacy object models
*/
final class UpdateProductOptionsHandler implements UpdateProductOptionsHandlerInterface
{
/**
* @var ProductRepository
*/
private $productRepository;
/**
* @var ManufacturerRepository
*/
private $manufacturerRepository;
/**
* @var ProductIndexationUpdater
*/
private $productIndexationUpdater;
/**
* @var ConfigurationInterface
*/
private $configuration;
/**
* @param ProductRepository $productRepository
* @param ManufacturerRepository $manufacturerRepository
* @param ProductIndexationUpdater $productIndexationUpdater
* @param ConfigurationInterface $configuration
*/
public function __construct(
ProductRepository $productRepository,
ManufacturerRepository $manufacturerRepository,
ProductIndexationUpdater $productIndexationUpdater,
ConfigurationInterface $configuration
) {
$this->productRepository = $productRepository;
$this->manufacturerRepository = $manufacturerRepository;
$this->productIndexationUpdater = $productIndexationUpdater;
$this->configuration = $configuration;
}
/**
* {@inheritdoc}
*/
public function handle(UpdateProductOptionsCommand $command): void
{
$product = $this->productRepository->get($command->getProductId());
$updatableProperties = $this->fillUpdatableProperties($product, $command);
$this->productRepository->partialUpdate($product, $updatableProperties, CannotUpdateProductException::FAILED_UPDATE_OPTIONS);
if (true === $command->isActive() && $this->configuration->get('PS_SEARCH_INDEXATION')) {
$this->productIndexationUpdater->updateIndexation($product->id);
}
}
/**
* @param Product $product
* @param UpdateProductOptionsCommand $command
*
* @return string[]|array<string, int[]> updatable properties
*/
private function fillUpdatableProperties(Product $product, UpdateProductOptionsCommand $command): array
{
$updatableProperties = [];
if (null !== $command->isActive()) {
$product->active = $command->isActive();
$updatableProperties[] = 'active';
}
if (null !== $command->getVisibility()) {
$product->visibility = $command->getVisibility()->getValue();
$updatableProperties[] = 'visibility';
}
if (null !== $command->isAvailableForOrder()) {
$product->available_for_order = $command->isAvailableForOrder();
$updatableProperties[] = 'available_for_order';
}
if (null !== $command->isOnlineOnly()) {
$product->online_only = $command->isOnlineOnly();
$updatableProperties[] = 'online_only';
}
if (null !== $command->showPrice()) {
$product->show_price = $command->showPrice();
$updatableProperties[] = 'show_price';
}
if (null !== $command->getCondition()) {
$product->condition = $command->getCondition()->getValue();
$updatableProperties[] = 'condition';
}
if (null !== $command->showCondition()) {
$product->show_condition = $command->showCondition();
$updatableProperties[] = 'show_condition';
}
$manufacturerId = $command->getManufacturerId();
if (null !== $manufacturerId) {
$product->id_manufacturer = $manufacturerId->getValue();
$updatableProperties[] = 'id_manufacturer';
}
return $updatableProperties;
}
}

View File

@@ -0,0 +1,118 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\CommandHandler;
use PrestaShop\PrestaShop\Adapter\Product\Repository\ProductRepository;
use PrestaShop\PrestaShop\Adapter\Product\Update\ProductPricePropertiesFiller;
use PrestaShop\PrestaShop\Core\Domain\Product\Command\UpdateProductPricesCommand;
use PrestaShop\PrestaShop\Core\Domain\Product\CommandHandler\UpdateProductPricesHandlerInterface;
use PrestaShop\PrestaShop\Core\Domain\Product\Exception\CannotUpdateProductException;
use PrestaShop\PrestaShop\Core\Domain\Product\Exception\ProductConstraintException;
use Product;
/**
* Updates product price information using legacy object models
*/
final class UpdateProductPricesHandler implements UpdateProductPricesHandlerInterface
{
/**
* @var ProductRepository
*/
private $productRepository;
/**
* @var ProductPricePropertiesFiller
*/
private $productPricePropertiesFiller;
/**
* @param ProductRepository $productRepository
* @param ProductPricePropertiesFiller $productPricePropertiesFiller
*/
public function __construct(
ProductRepository $productRepository,
ProductPricePropertiesFiller $productPricePropertiesFiller
) {
$this->productRepository = $productRepository;
$this->productPricePropertiesFiller = $productPricePropertiesFiller;
}
/**
* {@inheritdoc}
*/
public function handle(UpdateProductPricesCommand $command): void
{
$product = $this->productRepository->get($command->getProductId());
$updatableProperties = $this->fillUpdatableProperties($product, $command);
$this->productRepository->partialUpdate($product, $updatableProperties, CannotUpdateProductException::FAILED_UPDATE_PRICES);
}
/**
* @param Product $product
* @param UpdateProductPricesCommand $command
*
* @return string[] updatable properties
*
* @throws ProductConstraintException
*/
private function fillUpdatableProperties(Product $product, UpdateProductPricesCommand $command): array
{
$updatableProperties = $this->productPricePropertiesFiller->fillWithPrices(
$product,
$command->getPrice(),
$command->getUnitPrice(),
$command->getWholesalePrice()
);
if (null !== $command->getUnity()) {
$product->unity = $command->getUnity();
$updatableProperties[] = 'unity';
}
if (null !== $command->getEcotax()) {
$product->ecotax = (float) (string) $command->getEcotax();
$updatableProperties[] = 'ecotax';
}
$taxRulesGroupId = $command->getTaxRulesGroupId();
if (null !== $taxRulesGroupId) {
$product->id_tax_rules_group = $taxRulesGroupId;
$updatableProperties[] = 'id_tax_rules_group';
}
if (null !== $command->isOnSale()) {
$product->on_sale = $command->isOnSale();
$updatableProperties[] = 'on_sale';
}
return $updatableProperties;
}
}

View File

@@ -0,0 +1,113 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\CommandHandler;
use PrestaShop\PrestaShop\Adapter\Product\Repository\ProductRepository;
use PrestaShop\PrestaShop\Adapter\Product\Update\ProductSeoPropertiesFiller;
use PrestaShop\PrestaShop\Core\Domain\Product\Command\UpdateProductSeoCommand;
use PrestaShop\PrestaShop\Core\Domain\Product\CommandHandler\UpdateProductSeoHandlerInterface;
use PrestaShop\PrestaShop\Core\Domain\Product\Exception\CannotUpdateProductException;
use Product;
/**
* Handles @var UpdateProductSeoCommand using legacy object model
*/
class UpdateProductSeoHandler implements UpdateProductSeoHandlerInterface
{
/**
* @var ProductRepository
*/
private $productRepository;
/**
* @var ProductSeoPropertiesFiller
*/
private $productSeoPropertiesFiller;
/**
* @param ProductRepository $productRepository
* @param ProductSeoPropertiesFiller $productSeoPropertiesFiller
*/
public function __construct(
ProductRepository $productRepository,
ProductSeoPropertiesFiller $productSeoPropertiesFiller
) {
$this->productRepository = $productRepository;
$this->productSeoPropertiesFiller = $productSeoPropertiesFiller;
}
/**
* {@inheritdoc}
*/
public function handle(UpdateProductSeoCommand $command): void
{
$product = $this->productRepository->get($command->getProductId());
$updatableProperties = $this->fillUpdatableProperties($product, $command);
$this->productRepository->partialUpdate($product, $updatableProperties, CannotUpdateProductException::FAILED_UPDATE_SEO);
}
/**
* @param Product $product
* @param UpdateProductSeoCommand $command
*
* @return array
*/
private function fillUpdatableProperties(Product $product, UpdateProductSeoCommand $command): array
{
$updatableProperties = [];
if (null !== $command->getRedirectOption()) {
$updatableProperties = array_merge(
$updatableProperties,
$this->productSeoPropertiesFiller->fillWithRedirectOption($product, $command->getRedirectOption())
);
}
$localizedMetaDescriptions = $command->getLocalizedMetaDescriptions();
if (null !== $localizedMetaDescriptions) {
$product->meta_description = $localizedMetaDescriptions;
$updatableProperties['meta_description'] = array_keys($localizedMetaDescriptions);
}
$localizedMetaTitles = $command->getLocalizedMetaTitles();
if (null !== $localizedMetaTitles) {
$product->meta_title = $localizedMetaTitles;
$updatableProperties['meta_title'] = array_keys($localizedMetaTitles);
}
$localizedLinkRewrites = $command->getLocalizedLinkRewrites();
if (null !== $localizedLinkRewrites) {
$product->link_rewrite = $localizedLinkRewrites;
$updatableProperties['link_rewrite'] = array_keys($localizedLinkRewrites);
}
return $updatableProperties;
}
}

View File

@@ -0,0 +1,127 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\CommandHandler;
use PrestaShop\PrestaShop\Adapter\Product\Repository\ProductRepository;
use PrestaShop\PrestaShop\Core\Domain\Product\Command\UpdateProductShippingCommand;
use PrestaShop\PrestaShop\Core\Domain\Product\CommandHandler\UpdateProductShippingHandlerInterface;
use PrestaShop\PrestaShop\Core\Domain\Product\Exception\CannotUpdateProductException;
use Product;
/**
* Handles @var UpdateProductShippingCommand using legacy object model
*/
final class UpdateProductShippingHandler implements UpdateProductShippingHandlerInterface
{
/**
* @var ProductRepository
*/
private $productRepository;
/**
* @param ProductRepository $productRepository
*/
public function __construct(
ProductRepository $productRepository
) {
$this->productRepository = $productRepository;
}
/**
* {@inheritdoc}
*/
public function handle(UpdateProductShippingCommand $command): void
{
$product = $this->productRepository->get($command->getProductId());
$updatableProperties = $this->fillUpdatableProperties($product, $command);
$this->productRepository->partialUpdate(
$product,
$updatableProperties,
CannotUpdateProductException::FAILED_UPDATE_SHIPPING_OPTIONS
);
}
/**
* @param Product $product
* @param UpdateProductShippingCommand $command
*
* @return string[] updatable properties
*/
private function fillUpdatableProperties(Product $product, UpdateProductShippingCommand $command): array
{
$updatableProperties = [];
if (null !== $command->getWidth()) {
$product->width = (string) $command->getWidth();
$updatableProperties[] = 'width';
}
if (null !== $command->getHeight()) {
$product->height = (string) $command->getHeight();
$updatableProperties[] = 'height';
}
if (null !== $command->getDepth()) {
$product->depth = (string) $command->getDepth();
$updatableProperties[] = 'depth';
}
if (null !== $command->getWeight()) {
$product->weight = (string) $command->getWeight();
$updatableProperties[] = 'weight';
}
if (null !== $command->getAdditionalShippingCost()) {
$product->additional_shipping_cost = (string) $command->getAdditionalShippingCost();
$updatableProperties[] = 'additional_shipping_cost';
}
if (null !== $command->getCarrierReferences()) {
$product->setCarriers($command->getCarrierReferences());
}
if (null !== $command->getDeliveryTimeNoteType()) {
$product->additional_delivery_times = $command->getDeliveryTimeNoteType()->getValue();
$updatableProperties[] = 'additional_delivery_times';
}
if (null !== $command->getLocalizedDeliveryTimeInStockNotes()) {
$product->delivery_in_stock = $command->getLocalizedDeliveryTimeInStockNotes();
$updatableProperties['delivery_in_stock'] = array_keys($command->getLocalizedDeliveryTimeInStockNotes());
}
if (null !== $command->getLocalizedDeliveryTimeOutOfStockNotes()) {
$product->delivery_out_stock = $command->getLocalizedDeliveryTimeOutOfStockNotes();
$updatableProperties['delivery_out_stock'] = array_keys($command->getLocalizedDeliveryTimeOutOfStockNotes());
}
return $updatableProperties;
}
}

View File

@@ -0,0 +1,57 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
namespace PrestaShop\PrestaShop\Adapter\Product\CommandHandler;
use PrestaShop\PrestaShop\Adapter\Entity\Product;
use PrestaShop\PrestaShop\Core\Domain\Product\Command\UpdateProductStatusCommand;
use PrestaShop\PrestaShop\Core\Domain\Product\CommandHandler\UpdateProductStatusCommandHandlerInterface;
use PrestaShop\PrestaShop\Core\Domain\Product\Exception\CannotUpdateProductException;
use PrestaShop\PrestaShop\Core\Domain\Product\Exception\ProductNotFoundException;
/**
* @internal
*/
class UpdateProductStatusCommandHandler implements UpdateProductStatusCommandHandlerInterface
{
/**
* @param UpdateProductStatusCommand $command
*/
public function handle(UpdateProductStatusCommand $command)
{
$productId = $command->getProductId()->getValue();
$product = new Product($productId);
if ($product->id !== $productId) {
throw new ProductNotFoundException(sprintf('Product with id "%d" was not found', $productId));
}
if ($product->active != $command->getEnable()) {
if (!$product->toggleStatus()) {
throw new CannotUpdateProductException(sprintf('Cannot update status for product with id "%d"', $productId));
}
}
}
}

View File

@@ -0,0 +1,61 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\CommandHandler;
use PrestaShop\PrestaShop\Adapter\Product\Update\ProductTypeUpdater;
use PrestaShop\PrestaShop\Core\Domain\Product\Command\UpdateProductTypeCommand;
use PrestaShop\PrestaShop\Core\Domain\Product\CommandHandler\UpdateProductTypeHandlerInterface;
/**
* Handle @see UpdateProductTypeCommand
*/
class UpdateProductTypeHandler implements UpdateProductTypeHandlerInterface
{
/**
* @var ProductTypeUpdater
*/
private $productTypeUpdater;
/**
* @param ProductTypeUpdater $productTypeUpdater
*/
public function __construct(
ProductTypeUpdater $productTypeUpdater
) {
$this->productTypeUpdater = $productTypeUpdater;
}
/**
* {@inheritDoc}
*/
public function handle(UpdateProductTypeCommand $command): void
{
$this->productTypeUpdater->updateType($command->getProductId(), $command->getProductType());
}
}

View File

@@ -0,0 +1,87 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\Customization\CommandHandler;
use PrestaShop\PrestaShop\Adapter\Product\Customization\Update\CustomizationFieldDeleter;
use PrestaShop\PrestaShop\Adapter\Product\Customization\Update\ProductCustomizationFieldUpdater;
use PrestaShop\PrestaShop\Adapter\Product\Repository\ProductRepository;
use PrestaShop\PrestaShop\Core\Domain\Product\Customization\Command\RemoveAllCustomizationFieldsFromProductCommand;
use PrestaShop\PrestaShop\Core\Domain\Product\Customization\CommandHandler\RemoveAllCustomizationFieldsFromProductHandlerInterface;
use PrestaShop\PrestaShop\Core\Domain\Product\Customization\ValueObject\CustomizationFieldId;
/**
* Handles @see RemoveAllCustomizationFieldsFromProductCommand using legacy object model
*/
final class RemoveAllCustomizationFieldsFromProductHandler implements RemoveAllCustomizationFieldsFromProductHandlerInterface
{
/**
* @var CustomizationFieldDeleter
*/
private $customizationFieldDeleter;
/**
* @var ProductRepository
*/
private $productRepository;
/**
* @var ProductCustomizationFieldUpdater
*/
private $productCustomizationFieldUpdater;
/**
* @param CustomizationFieldDeleter $customizationFieldDeleter
* @param ProductRepository $productRepository
* @param ProductCustomizationFieldUpdater $productCustomizationFieldUpdater
*/
public function __construct(
CustomizationFieldDeleter $customizationFieldDeleter,
ProductRepository $productRepository,
ProductCustomizationFieldUpdater $productCustomizationFieldUpdater
) {
$this->customizationFieldDeleter = $customizationFieldDeleter;
$this->productRepository = $productRepository;
$this->productCustomizationFieldUpdater = $productCustomizationFieldUpdater;
}
/**
* {@inheritdoc}
*/
public function handle(RemoveAllCustomizationFieldsFromProductCommand $command): void
{
$product = $this->productRepository->get($command->getProductId());
$customizationFieldIds = array_map(function (array $field): CustomizationFieldId {
return new CustomizationFieldId((int) $field['id_customization_field']);
}, $product->getCustomizationFieldIds());
$this->customizationFieldDeleter->bulkDelete($customizationFieldIds);
$this->productCustomizationFieldUpdater->refreshProductCustomizability($product);
}
}

View File

@@ -0,0 +1,107 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\Customization\CommandHandler;
use CustomizationField;
use PrestaShop\PrestaShop\Adapter\Product\Customization\Update\ProductCustomizationFieldUpdater;
use PrestaShop\PrestaShop\Adapter\Product\Repository\ProductRepository;
use PrestaShop\PrestaShop\Core\Domain\Product\Customization\Command\SetProductCustomizationFieldsCommand;
use PrestaShop\PrestaShop\Core\Domain\Product\Customization\CommandHandler\SetProductCustomizationFieldsHandlerInterface;
use PrestaShop\PrestaShop\Core\Domain\Product\Customization\CustomizationField as CustomizationFieldDTO;
use PrestaShop\PrestaShop\Core\Domain\Product\Customization\ValueObject\CustomizationFieldId;
use PrestaShop\PrestaShop\Core\Domain\Product\ValueObject\ProductId;
/**
* Handles @see SetProductCustomizationFieldsCommand using legacy object model
*/
class SetProductCustomizationFieldsHandler implements SetProductCustomizationFieldsHandlerInterface
{
/**
* @var ProductRepository
*/
private $productRepository;
/**
* @var ProductCustomizationFieldUpdater
*/
private $productCustomizationFieldUpdater;
/**
* @param ProductRepository $productRepository
* @param ProductCustomizationFieldUpdater $productCustomizationFieldUpdater
*/
public function __construct(
ProductRepository $productRepository,
ProductCustomizationFieldUpdater $productCustomizationFieldUpdater
) {
$this->productRepository = $productRepository;
$this->productCustomizationFieldUpdater = $productCustomizationFieldUpdater;
}
/**
* {@inheritdoc}
*
* Creates, updates or deletes customization fields depending on differences of existing and provided fields
*/
public function handle(SetProductCustomizationFieldsCommand $command): array
{
$productId = $command->getProductId();
$product = $this->productRepository->get($productId);
$customizationFields = [];
foreach ($command->getCustomizationFields() as $providedCustomizationField) {
$customizationFields[] = $this->buildEntityFromDTO($productId, $providedCustomizationField);
}
$this->productCustomizationFieldUpdater->setProductCustomizationFields($productId, $customizationFields);
return array_map(function (int $customizationFieldId): CustomizationFieldId {
return new CustomizationFieldId($customizationFieldId);
}, $product->getNonDeletedCustomizationFieldIds());
}
/**
* @param ProductId $productId
* @param CustomizationFieldDTO $customizationFieldDTO
*
* @return CustomizationField
*/
private function buildEntityFromDTO(ProductId $productId, CustomizationFieldDTO $customizationFieldDTO): CustomizationField
{
$customizationField = new CustomizationField();
$customizationField->id = $customizationFieldDTO->getCustomizationFieldId();
$customizationField->id_product = $productId->getValue();
$customizationField->type = $customizationFieldDTO->getType();
$customizationField->required = $customizationFieldDTO->isRequired();
$customizationField->name = $customizationFieldDTO->getLocalizedNames();
$customizationField->is_module = $customizationFieldDTO->isAddedByModule();
return $customizationField;
}
}

View File

@@ -0,0 +1,100 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\Customization\QueryHandler;
use PrestaShop\PrestaShop\Adapter\Product\Customization\Repository\CustomizationFieldRepository;
use PrestaShop\PrestaShop\Adapter\Product\Repository\ProductRepository;
use PrestaShop\PrestaShop\Core\Domain\Product\Customization\Query\GetProductCustomizationFields;
use PrestaShop\PrestaShop\Core\Domain\Product\Customization\QueryHandler\GetProductCustomizationFieldsHandlerInterface;
use PrestaShop\PrestaShop\Core\Domain\Product\Customization\QueryResult\CustomizationField;
use PrestaShop\PrestaShop\Core\Domain\Product\Customization\ValueObject\CustomizationFieldId;
/**
* Defines contract to handle @var GetProductCustomizationFields query
*/
final class GetProductCustomizationFieldsHandler implements GetProductCustomizationFieldsHandlerInterface
{
/**
* @var CustomizationFieldRepository
*/
private $customizationFieldRepository;
/**
* @var ProductRepository
*/
private $productRepository;
/**
* @param CustomizationFieldRepository $customizationFieldRepository
* @param ProductRepository $productRepository
*/
public function __construct(
CustomizationFieldRepository $customizationFieldRepository,
ProductRepository $productRepository
) {
$this->customizationFieldRepository = $customizationFieldRepository;
$this->productRepository = $productRepository;
}
/**
* {@inheritdoc}
*/
public function handle(GetProductCustomizationFields $query): array
{
$productId = $query->getProductId();
$product = $this->productRepository->get($productId);
$fieldIds = $product->getNonDeletedCustomizationFieldIds();
$customizationFields = [];
foreach ($fieldIds as $fieldId) {
$customizationFields[] = $this->buildCustomizationField((int) $fieldId);
}
return $customizationFields;
}
/**
* @param int $fieldId
*
* @return CustomizationField
*/
private function buildCustomizationField(int $fieldId): CustomizationField
{
$fieldEntity = $this->customizationFieldRepository->get(new CustomizationFieldId($fieldId));
return new CustomizationField(
$fieldId,
(int) $fieldEntity->type,
$fieldEntity->name,
(bool) $fieldEntity->required,
(bool) $fieldEntity->is_module
);
}
}

View File

@@ -0,0 +1,121 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\Customization\Repository;
use CustomizationField;
use PrestaShop\PrestaShop\Adapter\AbstractObjectModelRepository;
use PrestaShop\PrestaShop\Adapter\Product\Customization\Validate\CustomizationFieldValidator;
use PrestaShop\PrestaShop\Core\Domain\Product\Customization\Exception\CannotAddCustomizationFieldException;
use PrestaShop\PrestaShop\Core\Domain\Product\Customization\Exception\CannotDeleteCustomizationFieldException;
use PrestaShop\PrestaShop\Core\Domain\Product\Customization\Exception\CannotUpdateCustomizationFieldException;
use PrestaShop\PrestaShop\Core\Domain\Product\Customization\Exception\CustomizationFieldNotFoundException;
use PrestaShop\PrestaShop\Core\Domain\Product\Customization\ValueObject\CustomizationFieldId;
use PrestaShop\PrestaShop\Core\Exception\CoreException;
/**
* Methods to access data storage for CustomizationField
*/
class CustomizationFieldRepository extends AbstractObjectModelRepository
{
/**
* @var CustomizationFieldValidator
*/
private $customizationFieldValidator;
/**
* @param CustomizationFieldValidator $customizationFieldValidator
*/
public function __construct(
CustomizationFieldValidator $customizationFieldValidator
) {
$this->customizationFieldValidator = $customizationFieldValidator;
}
/**
* @param CustomizationFieldId $fieldId
*
* @return CustomizationField
*
* @throws CoreException
*/
public function get(CustomizationFieldId $fieldId): CustomizationField
{
/** @var CustomizationField $customizationField */
$customizationField = $this->getObjectModel(
$fieldId->getValue(),
CustomizationField::class,
CustomizationFieldNotFoundException::class
);
return $customizationField;
}
/**
* @param CustomizationField $customizationField
* @param int $errorCode
*
* @return CustomizationFieldId
*
* @throws CoreException
*/
public function add(CustomizationField $customizationField, int $errorCode = 0): CustomizationFieldId
{
$this->customizationFieldValidator->validate($customizationField);
$this->addObjectModel($customizationField, CannotAddCustomizationFieldException::class, $errorCode);
return new CustomizationFieldId((int) $customizationField->id);
}
/**
* @param CustomizationField $customizationField
*
* @throws CannotUpdateCustomizationFieldException
*/
public function update(CustomizationField $customizationField): void
{
$this->customizationFieldValidator->validate($customizationField);
$this->updateObjectModel($customizationField, CannotUpdateCustomizationFieldException::class);
}
/**
* @param CustomizationField $customizationField
*/
public function delete(CustomizationField $customizationField): void
{
$this->deleteObjectModel($customizationField, CannotDeleteCustomizationFieldException::class);
}
/**
* @param CustomizationField $customizationField
*/
public function softDelete(CustomizationField $customizationField): void
{
$this->softDeleteObjectModel($customizationField, CannotDeleteCustomizationFieldException::class);
}
}

View File

@@ -0,0 +1,143 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\Customization\Update;
use CustomizationField;
use PrestaShop\PrestaShop\Adapter\Product\Customization\Repository\CustomizationFieldRepository;
use PrestaShop\PrestaShop\Adapter\Product\Repository\ProductRepository;
use PrestaShop\PrestaShop\Core\Domain\Product\Customization\Exception\CannotBulkDeleteCustomizationFieldException;
use PrestaShop\PrestaShop\Core\Domain\Product\Customization\Exception\CannotDeleteCustomizationFieldException;
use PrestaShop\PrestaShop\Core\Domain\Product\Customization\ValueObject\CustomizationFieldId;
use PrestaShop\PrestaShop\Core\Domain\Product\Exception\ProductException;
use PrestaShop\PrestaShop\Core\Domain\Product\Exception\ProductNotFoundException;
use PrestaShop\PrestaShop\Core\Domain\Product\ValueObject\ProductId;
use Product;
/**
* Deletes customization field/fields using legacy object models
*/
class CustomizationFieldDeleter
{
/**
* @var CustomizationFieldRepository
*/
private $customizationFieldRepository;
/**
* @var ProductRepository
*/
private $productRepository;
/**
* @var array<int, Product>
*/
private $productsById = [];
/**
* @param CustomizationFieldRepository $customizationFieldRepository
* @param ProductRepository $productRepository
*/
public function __construct(
CustomizationFieldRepository $customizationFieldRepository,
ProductRepository $productRepository
) {
$this->customizationFieldRepository = $customizationFieldRepository;
$this->productRepository = $productRepository;
}
/**
* @param CustomizationFieldId $customizationFieldId
*/
public function delete(CustomizationFieldId $customizationFieldId): void
{
$customizationField = $this->customizationFieldRepository->get($customizationFieldId);
$this->performDeletion($customizationField);
}
/**
* @param array $customizationFieldIds
*
* @throws CannotBulkDeleteCustomizationFieldException
*/
public function bulkDelete(array $customizationFieldIds): void
{
$failedIds = [];
foreach ($customizationFieldIds as $customizationFieldId) {
$customizationField = $this->customizationFieldRepository->get($customizationFieldId);
try {
$this->performDeletion($customizationField);
} catch (CannotDeleteCustomizationFieldException $e) {
$failedIds[] = $customizationFieldId->getValue();
}
}
if (empty($failedIds)) {
return;
}
throw new CannotBulkDeleteCustomizationFieldException(
$failedIds,
sprintf('Failed deleting following customization fields: "%s"', implode(', ', $failedIds))
);
}
/**
* @param CustomizationField $customizationField
*/
private function performDeletion(CustomizationField $customizationField): void
{
$product = $this->getProduct((int) $customizationField->id_product);
$usedFieldIds = array_map('intval', $product->getUsedCustomizationFieldsIds());
$fieldId = (int) $customizationField->id;
if (in_array($fieldId, $usedFieldIds)) {
$this->customizationFieldRepository->softDelete($customizationField);
} else {
$this->customizationFieldRepository->delete($customizationField);
}
}
/**
* @param int $productId
*
* @return Product
*
* @throws ProductException
* @throws ProductNotFoundException
*/
private function getProduct(int $productId): Product
{
if (!isset($this->productsById[$productId])) {
$this->productsById[$productId] = $this->productRepository->get(new ProductId($productId));
}
return $this->productsById[$productId];
}
}

View File

@@ -0,0 +1,147 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\Customization\Update;
use CustomizationField;
use PrestaShop\PrestaShop\Adapter\Product\Customization\Repository\CustomizationFieldRepository;
use PrestaShop\PrestaShop\Adapter\Product\Repository\ProductRepository;
use PrestaShop\PrestaShop\Core\Domain\Product\Customization\ValueObject\CustomizationFieldId;
use PrestaShop\PrestaShop\Core\Domain\Product\Customization\ValueObject\CustomizationFieldType;
use PrestaShop\PrestaShop\Core\Domain\Product\Exception\CannotUpdateProductException;
use PrestaShop\PrestaShop\Core\Domain\Product\ProductCustomizabilitySettings;
use PrestaShop\PrestaShop\Core\Domain\Product\ValueObject\ProductId;
use Product;
/**
* Updates CustomizationField & Product relation
*/
class ProductCustomizationFieldUpdater
{
/**
* @var CustomizationFieldRepository
*/
private $customizationFieldRepository;
/**
* @var CustomizationFieldDeleter
*/
private $customizationFieldDeleter;
/**
* @var ProductRepository
*/
private $productRepository;
/**
* @param CustomizationFieldRepository $customizationFieldRepository
* @param CustomizationFieldDeleter $customizationFieldDeleter
* @param ProductRepository $productRepository
*/
public function __construct(
CustomizationFieldRepository $customizationFieldRepository,
CustomizationFieldDeleter $customizationFieldDeleter,
ProductRepository $productRepository
) {
$this->customizationFieldRepository = $customizationFieldRepository;
$this->customizationFieldDeleter = $customizationFieldDeleter;
$this->productRepository = $productRepository;
}
/**
* @param ProductId $productId
* @param CustomizationField[] $customizationFields
*/
public function setProductCustomizationFields(ProductId $productId, array $customizationFields): void
{
$product = $this->productRepository->get($productId);
$deletableFieldIds = $this->getDeletableFieldIds($customizationFields, $product);
foreach ($customizationFields as $customizationField) {
if ($customizationField->id) {
$this->customizationFieldRepository->update($customizationField);
} else {
$this->customizationFieldRepository->add($customizationField);
}
}
$this->customizationFieldDeleter->bulkDelete($deletableFieldIds);
$this->refreshProductCustomizability($product);
}
/**
* @param Product $product
*/
public function refreshProductCustomizability(Product $product): void
{
if ($product->hasActivatedRequiredCustomizableFields()) {
$product->customizable = ProductCustomizabilitySettings::REQUIRES_CUSTOMIZATION;
} elseif (!empty($product->getNonDeletedCustomizationFieldIds())) {
$product->customizable = ProductCustomizabilitySettings::ALLOWS_CUSTOMIZATION;
} else {
$product->customizable = ProductCustomizabilitySettings::NOT_CUSTOMIZABLE;
}
$product->text_fields = $product->countCustomizationFields(CustomizationFieldType::TYPE_TEXT);
$product->uploadable_files = $product->countCustomizationFields(CustomizationFieldType::TYPE_FILE);
$this->productRepository->partialUpdate(
$product,
['customizable', 'text_fields', 'uploadable_files'],
CannotUpdateProductException::FAILED_UPDATE_CUSTOMIZATION_FIELDS
);
}
/**
* Checks provided customization fields against existing ones to determine which ones to delete
*
* @param CustomizationField[] $providedCustomizationFields
* @param Product $product
*
* @return CustomizationFieldId[] ids of customization fields which should be deleted
*/
private function getDeletableFieldIds(array $providedCustomizationFields, Product $product): array
{
$existingFieldIds = $product->getNonDeletedCustomizationFieldIds();
$deletableIds = [];
foreach ($existingFieldIds as $existingFieldId) {
$deletableIds[$existingFieldId] = new CustomizationFieldId($existingFieldId);
}
foreach ($providedCustomizationFields as $providedCustomizationField) {
$providedId = (int) $providedCustomizationField->id;
if (isset($deletableIds[$providedId])) {
unset($deletableIds[$providedId]);
}
}
return $deletableIds;
}
}

View File

@@ -0,0 +1,55 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\Customization\Validate;
use CustomizationField;
use PrestaShop\PrestaShop\Adapter\AbstractObjectModelValidator;
use PrestaShop\PrestaShop\Core\Domain\Product\Customization\Exception\CustomizationFieldConstraintException;
use PrestaShop\PrestaShop\Core\Exception\CoreException;
/**
* Validates CustomizationField field using legacy object model
*/
class CustomizationFieldValidator extends AbstractObjectModelValidator
{
/**
* @param CustomizationField $customizationField
*
* @throws CoreException
*/
public function validate(CustomizationField $customizationField): void
{
$this::validateObjectModelProperty($customizationField, 'type', CustomizationFieldConstraintException::class, CustomizationFieldConstraintException::INVALID_TYPE);
$this::validateObjectModelLocalizedProperty($customizationField, 'name', CustomizationFieldConstraintException::class, CustomizationFieldConstraintException::INVALID_NAME);
$this::validateObjectModelProperty($customizationField, 'required', CustomizationFieldConstraintException::class);
$this::validateObjectModelProperty($customizationField, 'is_module', CustomizationFieldConstraintException::class);
$this::validateObjectModelProperty($customizationField, 'is_deleted', CustomizationFieldConstraintException::class);
$this::validateObjectModelProperty($customizationField, 'id_product', CustomizationFieldConstraintException::class);
}
}

View File

@@ -0,0 +1,57 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\FeatureValue\CommandHandler;
use PrestaShop\PrestaShop\Adapter\Product\FeatureValue\Update\ProductFeatureValueUpdater;
use PrestaShop\PrestaShop\Core\Domain\Product\FeatureValue\Command\RemoveAllFeatureValuesFromProductCommand;
use PrestaShop\PrestaShop\Core\Domain\Product\FeatureValue\CommandHandler\RemoveAllFeatureValuesFromProductHandlerInterface;
/**
* Handles @see RemoveAllFeatureValuesFromProductCommand using legacy object model
*/
class RemoveAllFeatureValuesFromProductHandler implements RemoveAllFeatureValuesFromProductHandlerInterface
{
/**
* @var ProductFeatureValueUpdater
*/
private $productFeatureValueUpdater;
public function __construct(ProductFeatureValueUpdater $productFeatureValueUpdater)
{
$this->productFeatureValueUpdater = $productFeatureValueUpdater;
}
/**
* {@inheritDoc}
*/
public function handle(RemoveAllFeatureValuesFromProductCommand $command): void
{
$this->productFeatureValueUpdater->setFeatureValues($command->getProductId(), []);
}
}

View File

@@ -0,0 +1,57 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\FeatureValue\CommandHandler;
use PrestaShop\PrestaShop\Adapter\Product\FeatureValue\Update\ProductFeatureValueUpdater;
use PrestaShop\PrestaShop\Core\Domain\Product\FeatureValue\Command\SetProductFeatureValuesCommand;
use PrestaShop\PrestaShop\Core\Domain\Product\FeatureValue\CommandHandler\SetProductFeatureValuesHandlerInterface;
/**
* Handles @see SetProductFeatureValuesCommand using legacy object model
*/
class SetProductFeatureValuesHandler implements SetProductFeatureValuesHandlerInterface
{
/**
* @var ProductFeatureValueUpdater
*/
private $productFeatureValueUpdater;
public function __construct(ProductFeatureValueUpdater $productFeatureValueUpdater)
{
$this->productFeatureValueUpdater = $productFeatureValueUpdater;
}
/**
* {@inheritDoc}
*/
public function handle(SetProductFeatureValuesCommand $command): array
{
return $this->productFeatureValueUpdater->setFeatureValues($command->getProductId(), $command->getFeatureValues());
}
}

View File

@@ -0,0 +1,69 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\FeatureValue\QueryHandler;
use PrestaShop\PrestaShop\Adapter\Feature\Repository\FeatureValueRepository;
use PrestaShop\PrestaShop\Core\Domain\Product\FeatureValue\Query\GetProductFeatureValues;
use PrestaShop\PrestaShop\Core\Domain\Product\FeatureValue\QueryHandler\GetProductFeatureValuesHandlerInterface;
use PrestaShop\PrestaShop\Core\Domain\Product\FeatureValue\QueryResult\ProductFeatureValue;
/**
* Defines contract to handle @var GetProductFeatureValues query
*/
class GetProductFeatureValuesHandler implements GetProductFeatureValuesHandlerInterface
{
/**
* @var FeatureValueRepository
*/
private $featureValueRepository;
public function __construct(FeatureValueRepository $featureValueRepository)
{
$this->featureValueRepository = $featureValueRepository;
}
/**
* {@inheritDoc}
*/
public function handle(GetProductFeatureValues $query): array
{
$featureValuesData = $this->featureValueRepository->getProductFeatureValues($query->getProductId());
$productFeatureValues = [];
foreach ($featureValuesData as $featureValuesDatum) {
$productFeatureValues[] = new ProductFeatureValue(
(int) $featureValuesDatum['id_feature'],
(int) $featureValuesDatum['id_feature_value'],
$featureValuesDatum['localized_values'],
1 === (int) $featureValuesDatum['custom']
);
}
return $productFeatureValues;
}
}

View File

@@ -0,0 +1,246 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\FeatureValue\Update;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Exception\InvalidArgumentException;
use FeatureValue;
use PrestaShop\PrestaShop\Adapter\Feature\Repository\FeatureRepository;
use PrestaShop\PrestaShop\Adapter\Feature\Repository\FeatureValueRepository;
use PrestaShop\PrestaShop\Adapter\Product\Repository\ProductRepository;
use PrestaShop\PrestaShop\Core\Domain\Feature\Exception\CannotAddFeatureValueException;
use PrestaShop\PrestaShop\Core\Domain\Feature\Exception\CannotUpdateFeatureValueException;
use PrestaShop\PrestaShop\Core\Domain\Feature\Exception\FeatureNotFoundException;
use PrestaShop\PrestaShop\Core\Domain\Feature\Exception\FeatureValueNotFoundException;
use PrestaShop\PrestaShop\Core\Domain\Feature\ValueObject\FeatureValueId;
use PrestaShop\PrestaShop\Core\Domain\Product\FeatureValue\Exception\DuplicateFeatureValueAssociationException;
use PrestaShop\PrestaShop\Core\Domain\Product\FeatureValue\Exception\InvalidAssociatedFeatureException;
use PrestaShop\PrestaShop\Core\Domain\Product\FeatureValue\ValueObject\ProductFeatureValue;
use PrestaShop\PrestaShop\Core\Domain\Product\ValueObject\ProductId;
use PrestaShop\PrestaShop\Core\Exception\CoreException;
/**
* Updates FeatureValue & Product relation
*/
class ProductFeatureValueUpdater
{
/**
* @var Connection
*/
private $connection;
/**
* @var string
*/
private $dbPrefix;
/**
* @var ProductRepository
*/
private $productRepository;
/**
* @var FeatureRepository
*/
private $featureRepository;
/**
* @var FeatureValueRepository
*/
private $featureValueRepository;
/**
* @param Connection $connection
* @param string $dbPrefix
* @param ProductRepository $productRepository
* @param FeatureRepository $featureRepository
* @param FeatureValueRepository $featureValueRepository
*/
public function __construct(
Connection $connection,
string $dbPrefix,
ProductRepository $productRepository,
FeatureRepository $featureRepository,
FeatureValueRepository $featureValueRepository
) {
$this->connection = $connection;
$this->dbPrefix = $dbPrefix;
$this->productRepository = $productRepository;
$this->featureRepository = $featureRepository;
$this->featureValueRepository = $featureValueRepository;
}
/**
* @param ProductId $productId
* @param ProductFeatureValue[] $productFeatureValues
*
* @return FeatureValueId[]
*
* @throws CannotAddFeatureValueException
* @throws CannotUpdateFeatureValueException
* @throws CoreException
* @throws DBALException
* @throws FeatureValueNotFoundException
* @throws InvalidArgumentException
* @throws FeatureNotFoundException
*/
public function setFeatureValues(ProductId $productId, array $productFeatureValues): array
{
// First assert that all entities exist
$this->productRepository->assertProductExists($productId);
$previousFeatureIds = [];
foreach ($productFeatureValues as $productFeatureValue) {
$this->featureRepository->assertExists($productFeatureValue->getFeatureId());
if (null !== $productFeatureValue->getFeatureValueId()) {
$featureValue = $this->featureValueRepository->get($productFeatureValue->getFeatureValueId());
if ((int) $featureValue->id_feature !== $productFeatureValue->getFeatureId()->getValue()) {
throw new InvalidAssociatedFeatureException('You cannot associate a value to another feature.');
}
if (in_array($productFeatureValue->getFeatureValueId()->getValue(), $previousFeatureIds)) {
throw new DuplicateFeatureValueAssociationException('You cannot associate the same feature value more than once.');
}
$previousFeatureIds[] = $productFeatureValue->getFeatureValueId()->getValue();
}
}
foreach ($productFeatureValues as $productFeatureValue) {
if (null !== $productFeatureValue->getFeatureValueId()) {
$this->updateFeatureValue($productFeatureValue);
} else {
$this->addFeatureValue($productFeatureValue);
}
}
return $this->updateAssociations($productId, $productFeatureValues);
}
/**
* @param ProductId $productId
* @param array $productFeatureValues
*
* @return FeatureValueId[]
*
* @throws DBALException
* @throws InvalidArgumentException
*/
private function updateAssociations(ProductId $productId, array $productFeatureValues): array
{
// First delete all associations from the product
$this->connection->delete(
$this->dbPrefix . 'feature_product',
['id_product' => $productId->getValue()]
);
// Then create all new ones
$productFeatureValueIds = [];
foreach ($productFeatureValues as $productFeatureValue) {
$insertedValues = [
'id_product' => $productId->getValue(),
'id_feature' => $productFeatureValue->getFeatureId()->getValue(),
'id_feature_value' => $productFeatureValue->getFeatureValueId()->getValue(),
];
$this->connection->insert($this->dbPrefix . 'feature_product', $insertedValues);
$productFeatureValueIds[] = $productFeatureValue->getFeatureValueId();
}
$this->cleanOrphanCustomFeatureValues();
return $productFeatureValueIds;
}
/**
* Remove custom feature values that are no longer associated to a product
*/
private function cleanOrphanCustomFeatureValues(): void
{
$qb = $this->connection->createQueryBuilder();
$qb->from($this->dbPrefix . 'feature_value', 'fv')
->select('fv.*, fp.id_product')
->leftJoin('fv', $this->dbPrefix . 'feature_product', 'fp', 'fp.id_feature_value = fv.id_feature_value')
->where($qb->expr()->andX(
$qb->expr()->isNull('fp.id_product')),
$qb->expr()->neq('fv.custom', 0)
)
;
$orphanCustomFeatureValues = $qb->execute()->fetchAll();
if (empty($orphanCustomFeatureValues)) {
return;
}
$orphanIds = [];
foreach ($orphanCustomFeatureValues as $orphanCustomFeatureValue) {
$orphanIds[] = $orphanCustomFeatureValue['id_feature_value'];
}
$qb = $this->connection->createQueryBuilder();
$qb->delete($this->dbPrefix . 'feature_value')
->where($qb->expr()->in('id_feature_value', $orphanIds))
;
$qb->execute();
}
/**
* @param ProductFeatureValue $productFeatureValue
*
* @throws CannotUpdateFeatureValueException
* @throws CoreException
* @throws FeatureValueNotFoundException
*/
private function updateFeatureValue(ProductFeatureValue $productFeatureValue): void
{
// Only custom values need to be updated
if (null === $productFeatureValue->getLocalizedCustomValues()) {
return;
}
$featureValue = $this->featureValueRepository->get($productFeatureValue->getFeatureValueId());
$featureValue->value = $productFeatureValue->getLocalizedCustomValues();
$this->featureValueRepository->update($featureValue);
}
/**
* @param ProductFeatureValue $productFeatureValue
*
* @throws CannotAddFeatureValueException
* @throws CoreException
*/
private function addFeatureValue(ProductFeatureValue $productFeatureValue): void
{
$featureValue = new FeatureValue();
$featureValue->id_feature = (int) $productFeatureValue->getFeatureId()->getValue();
$featureValue->custom = null !== $productFeatureValue->getLocalizedCustomValues();
if (null !== $productFeatureValue->getLocalizedCustomValues()) {
$featureValue->value = $productFeatureValue->getLocalizedCustomValues();
}
$featureValueId = $this->featureValueRepository->add($featureValue);
$productFeatureValue->setFeatureValueId($featureValueId);
}
}

View File

@@ -0,0 +1,57 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
namespace PrestaShop\PrestaShop\Adapter\Product;
use Symfony\Component\HttpFoundation\Request;
/**
* Extracted from Product Controller, used to cleanup the request.
* For internal use only.
*/
final class FilterCategoriesRequestPurifier
{
public const CATEGORY = 'filter_category';
/**
* Changes the filter category values in case it is not numeric or signed.
*
* @param Request $request
*
* @return Request
*/
public function purify(Request $request)
{
if ($request->isMethod('POST')) {
$value = $request->request->get(self::CATEGORY);
if (null !== $value && (!is_numeric($value) || $value < 0)) {
$request->request->set(self::CATEGORY, '');
}
}
return $request;
}
}

View File

@@ -0,0 +1,105 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
namespace PrestaShop\PrestaShop\Adapter\Product;
use PrestaShop\PrestaShop\Adapter\Configuration;
use PrestaShop\PrestaShop\Core\Configuration\DataConfigurationInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
/**
* This class loads and saves general configuration for product.
*/
class GeneralConfiguration implements DataConfigurationInterface
{
/**
* @var Configuration
*/
private $configuration;
public function __construct(Configuration $configuration)
{
$this->configuration = $configuration;
}
/**
* {@inheritdoc}
*/
public function getConfiguration()
{
return [
'catalog_mode' => $this->configuration->getBoolean('PS_CATALOG_MODE'),
'catalog_mode_with_prices' => $this->configuration->getBoolean('PS_CATALOG_MODE_WITH_PRICES'),
'new_days_number' => $this->configuration->get('PS_NB_DAYS_NEW_PRODUCT'),
'short_description_limit' => $this->configuration->get('PS_PRODUCT_SHORT_DESC_LIMIT'),
'quantity_discount' => $this->configuration->get('PS_QTY_DISCOUNT_ON_COMBINATION'),
'force_friendly_url' => $this->configuration->getBoolean('PS_FORCE_FRIENDLY_PRODUCT'),
'default_status' => $this->configuration->getBoolean('PS_PRODUCT_ACTIVATION_DEFAULT'),
];
}
/**
* {@inheritdoc}
*/
public function updateConfiguration(array $config)
{
$errors = [];
if ($this->validateConfiguration($config)) {
$catalogMode = (int) $config['catalog_mode'];
$this->configuration->set('PS_CATALOG_MODE', $catalogMode);
$this->configuration->set('PS_CATALOG_MODE_WITH_PRICES', $catalogMode ? (int) $config['catalog_mode_with_prices'] : 0);
$this->configuration->set('PS_NB_DAYS_NEW_PRODUCT', (int) $config['new_days_number']);
$this->configuration->set('PS_PRODUCT_SHORT_DESC_LIMIT', (int) $config['short_description_limit']);
$this->configuration->set('PS_QTY_DISCOUNT_ON_COMBINATION', (int) $config['quantity_discount']);
$this->configuration->set('PS_FORCE_FRIENDLY_PRODUCT', (int) $config['force_friendly_url']);
$this->configuration->set('PS_PRODUCT_ACTIVATION_DEFAULT', (int) $config['default_status']);
}
return $errors;
}
/**
* {@inheritdoc}
*/
public function validateConfiguration(array $configuration)
{
$resolver = new OptionsResolver();
$resolver->setRequired([
'catalog_mode',
'catalog_mode_with_prices',
'new_days_number',
'short_description_limit',
'quantity_discount',
'force_friendly_url',
'default_status',
]);
$resolver->resolve($configuration);
return true;
}
}

View File

@@ -0,0 +1,94 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\Image\CommandHandler;
use PrestaShop\PrestaShop\Adapter\Image\ImageValidator;
use PrestaShop\PrestaShop\Adapter\Product\Image\Repository\ProductImageRepository;
use PrestaShop\PrestaShop\Adapter\Product\Image\Uploader\ProductImageUploader;
use PrestaShop\PrestaShop\Core\Domain\Product\Image\Command\AddProductImageCommand;
use PrestaShop\PrestaShop\Core\Domain\Product\Image\CommandHandler\AddProductImageHandlerInterface;
use PrestaShop\PrestaShop\Core\Domain\Product\Image\ValueObject\ImageId;
/**
* Handles @see AddProductImageCommand
*/
final class AddProductImageHandler implements AddProductImageHandlerInterface
{
/**
* @var ProductImageUploader
*/
private $productImageUploader;
/**
* @var ProductImageRepository
*/
private $productImageRepository;
/**
* @var array
*/
private $contextShopIds;
/**
* @var ImageValidator
*/
private $imageValidator;
/**
* @param ProductImageUploader $productImageUploader
* @param ProductImageRepository $productImageRepository
* @param ImageValidator $imageValidator
* @param array $contextShopIds
*/
public function __construct(
ProductImageUploader $productImageUploader,
ProductImageRepository $productImageRepository,
ImageValidator $imageValidator,
array $contextShopIds
) {
$this->productImageUploader = $productImageUploader;
$this->productImageRepository = $productImageRepository;
$this->contextShopIds = $contextShopIds;
$this->imageValidator = $imageValidator;
}
/**
* {@inheritdoc}
*/
public function handle(AddProductImageCommand $command): ImageId
{
$this->imageValidator->assertFileUploadLimits($command->getFilePath());
$this->imageValidator->assertIsValidImageType($command->getFilePath());
$image = $this->productImageRepository->create($command->getProductId(), $this->contextShopIds);
$this->productImageUploader->upload($image, $command->getFilePath());
return new ImageId((int) $image->id);
}
}

View File

@@ -0,0 +1,58 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\Image\CommandHandler;
use PrestaShop\PrestaShop\Adapter\Product\Image\Update\ProductImageUpdater;
use PrestaShop\PrestaShop\Core\Domain\Product\Image\Command\DeleteProductImageCommand;
use PrestaShop\PrestaShop\Core\Domain\Product\Image\CommandHandler\DeleteProductImageHandlerInterface;
/**
* Handles @see DeleteProductImageCommand
*/
class DeleteProductImageHandler implements DeleteProductImageHandlerInterface
{
/**
* @var ProductImageUpdater
*/
private $productImageUpdater;
public function __construct(
ProductImageUpdater $productImageUpdater
) {
$this->productImageUpdater = $productImageUpdater;
}
/**
* {@inheritDoc}
*/
public function handle(DeleteProductImageCommand $command): void
{
$this->productImageUpdater->deleteImage($command->getImageId());
}
}

View File

@@ -0,0 +1,112 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\Image\CommandHandler;
use PrestaShop\PrestaShop\Adapter\Image\ImageValidator;
use PrestaShop\PrestaShop\Adapter\Product\Image\Repository\ProductImageRepository;
use PrestaShop\PrestaShop\Adapter\Product\Image\Update\ProductImageUpdater;
use PrestaShop\PrestaShop\Adapter\Product\Image\Uploader\ProductImageUploader;
use PrestaShop\PrestaShop\Core\Domain\Product\Image\Command\UpdateProductImageCommand;
use PrestaShop\PrestaShop\Core\Domain\Product\Image\CommandHandler\UpdateProductImageHandlerInterface;
use PrestaShop\PrestaShop\Core\Domain\Product\Image\Exception\CannotUpdateProductImageException;
class UpdateProductImageHandler implements UpdateProductImageHandlerInterface
{
/**
* @var ProductImageRepository
*/
private $productImageRepository;
/**
* @var ProductImageUpdater
*/
private $productImageUpdater;
/**
* @var ProductImageUploader
*/
private $productImageUploader;
/**
* @var ImageValidator
*/
private $imageValidator;
/**
* @param ProductImageRepository $productImageRepository
* @param ProductImageUpdater $productImageUpdater
* @param ProductImageUploader $productImageUploader
* @param ImageValidator $imageValidator
*/
public function __construct(
ProductImageRepository $productImageRepository,
ProductImageUpdater $productImageUpdater,
ProductImageUploader $productImageUploader,
ImageValidator $imageValidator
) {
$this->productImageRepository = $productImageRepository;
$this->productImageUpdater = $productImageUpdater;
$this->productImageUploader = $productImageUploader;
$this->imageValidator = $imageValidator;
}
/**
* {@inheritDoc}
*/
public function handle(UpdateProductImageCommand $command): void
{
if (null !== $command->getFilePath()) {
$this->imageValidator->assertFileUploadLimits($command->getFilePath());
$this->imageValidator->assertIsValidImageType($command->getFilePath());
}
$image = $this->productImageRepository->get($command->getImageId());
if (null !== $command->getLocalizedLegends()) {
$image->legend = $command->getLocalizedLegends();
$this->productImageRepository->partialUpdate(
$image,
['legend' => array_keys($command->getLocalizedLegends())],
CannotUpdateProductImageException::FAILED_UPDATE_COVER
);
}
if ($command->isCover()) {
$this->productImageUpdater->updateProductCover($image);
}
if (null !== $command->getFilePath()) {
$this->productImageUploader->upload($image, $command->getFilePath());
}
if (null !== $command->getPosition()) {
$this->productImageUpdater->updatePosition($image, $command->getPosition());
}
}
}

View File

@@ -0,0 +1,158 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\Image;
use PrestaShop\PrestaShop\Core\Domain\Product\Image\ValueObject\ImageId;
class ProductImagePathFactory
{
public const IMAGE_TYPE_SMALL_DEFAULT = 'small_default';
public const IMAGE_TYPE_MEDIUM_DEFAULT = 'medium_default';
public const IMAGE_TYPE_LARGE_DEFAULT = 'large_default';
public const IMAGE_TYPE_HOME_DEFAULT = 'home_default';
public const IMAGE_TYPE_CART_DEFAULT = 'cart_default';
public const DEFAULT_IMAGE_FORMAT = 'jpg';
/**
* @var string
*/
private $temporaryImgDir;
/**
* @var string
*/
private $pathToBaseDir;
/**
* @var string
*/
private $contextLangIsoCode;
/**
* @param string $pathToBaseDir
* @param string $temporaryImgDir
* @param string $contextLangIsoCode
*/
public function __construct(
string $pathToBaseDir,
string $temporaryImgDir,
string $contextLangIsoCode
) {
// make sure one trailing slash is always there
$this->temporaryImgDir = rtrim($temporaryImgDir, '/') . '/';
$this->pathToBaseDir = rtrim($pathToBaseDir, '/') . '/';
$this->contextLangIsoCode = $contextLangIsoCode;
}
/**
* @param ImageId $imageId
* @param string $extension
*
* @return string
*/
public function getPath(ImageId $imageId, string $extension = self::DEFAULT_IMAGE_FORMAT): string
{
$path = $this->getBaseImagePathWithoutExtension($imageId);
return sprintf('%s.%s', $path, $extension);
}
/**
* @param ImageId $imageId
* @param string $type
* @param string $extension
*
* @return string
*/
public function getPathByType(ImageId $imageId, string $type, string $extension = self::DEFAULT_IMAGE_FORMAT): string
{
$path = $this->getBaseImagePathWithoutExtension($imageId);
return sprintf('%s-%s.%s', $path, $type, $extension);
}
/**
* @param string $type
* @param string|null $langIso if null, will use $contextLangIsoCode by default
*
* @return string
*/
public function getNoImagePath(string $type, ?string $langIso = null): string
{
if (!$langIso) {
$langIso = $this->contextLangIsoCode;
}
return sprintf('%s%s-%s-%s.jpg', $this->pathToBaseDir, $langIso, 'default', $type);
}
/**
* @param int $productId
*
* @return string
*/
public function getCachedCover(int $productId): string
{
return sprintf('%sproduct_%d.jpg', $this->temporaryImgDir, $productId);
}
/**
* @param int $productId
* @param int $shopId
*
* @return string
*/
public function getHelperThumbnail(int $productId, int $shopId): string
{
return sprintf('%sproduct_mini_%d_%d.jpg', $this->temporaryImgDir, $productId, $shopId);
}
/**
* @param ImageId $imageId
*
* @return string
*/
public function getImageFolder(ImageId $imageId): string
{
$path = implode('/', str_split((string) $imageId->getValue()));
return $this->pathToBaseDir . $path;
}
/**
* @param ImageId $imageId
*
* @return string
*/
private function getBaseImagePathWithoutExtension(ImageId $imageId): string
{
return $this->getImageFolder($imageId) . '/' . $imageId->getValue();
}
}

View File

@@ -0,0 +1,94 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\Image\QueryHandler;
use Image;
use PrestaShop\PrestaShop\Adapter\Product\Image\ProductImagePathFactory;
use PrestaShop\PrestaShop\Adapter\Product\Image\Repository\ProductImageRepository;
use PrestaShop\PrestaShop\Core\Domain\Product\Image\Query\GetProductImage;
use PrestaShop\PrestaShop\Core\Domain\Product\Image\QueryHandler\GetProductImageHandlerInterface;
use PrestaShop\PrestaShop\Core\Domain\Product\Image\QueryResult\ProductImage;
use PrestaShop\PrestaShop\Core\Domain\Product\Image\ValueObject\ImageId;
/**
* Handles @see GetProductImage query
*/
class GetProductImageHandler implements GetProductImageHandlerInterface
{
/**
* @var ProductImageRepository
*/
private $productImageRepository;
/**
* @var ProductImagePathFactory
*/
private $productImageUrlFactory;
/**
* @param ProductImageRepository $productImageRepository
* @param ProductImagePathFactory $productImageUrlFactory
*/
public function __construct(
ProductImageRepository $productImageRepository,
ProductImagePathFactory $productImageUrlFactory
) {
$this->productImageRepository = $productImageRepository;
$this->productImageUrlFactory = $productImageUrlFactory;
}
/**
* {@inheritDoc}
*/
public function handle(GetProductImage $query): ProductImage
{
$image = $this->productImageRepository->get($query->getImageId());
return $this->formatImage($image);
}
/**
* @param Image $image
*
* @return ProductImage
*/
private function formatImage(Image $image): ProductImage
{
$imageId = new ImageId((int) $image->id);
return new ProductImage(
(int) $image->id,
(bool) $image->cover,
(int) $image->position,
$image->legend,
$this->productImageUrlFactory->getPath($imageId),
$this->productImageUrlFactory->getPathByType($imageId, ProductImagePathFactory::IMAGE_TYPE_SMALL_DEFAULT)
);
}
}

View File

@@ -0,0 +1,99 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\Image\QueryHandler;
use Image;
use PrestaShop\PrestaShop\Adapter\Product\Image\ProductImagePathFactory;
use PrestaShop\PrestaShop\Adapter\Product\Image\Repository\ProductImageRepository;
use PrestaShop\PrestaShop\Core\Domain\Product\Image\Query\GetProductImages;
use PrestaShop\PrestaShop\Core\Domain\Product\Image\QueryHandler\GetProductImagesHandlerInterface;
use PrestaShop\PrestaShop\Core\Domain\Product\Image\QueryResult\ProductImage;
use PrestaShop\PrestaShop\Core\Domain\Product\Image\ValueObject\ImageId;
/**
* Handles @see GetProductImages query
*/
final class GetProductImagesHandler implements GetProductImagesHandlerInterface
{
/**
* @var ProductImageRepository
*/
private $productImageRepository;
/**
* @var ProductImagePathFactory
*/
private $productImageUrlFactory;
/**
* @param ProductImageRepository $productImageRepository
* @param ProductImagePathFactory $productImageUrlFactory
*/
public function __construct(
ProductImageRepository $productImageRepository,
ProductImagePathFactory $productImageUrlFactory
) {
$this->productImageRepository = $productImageRepository;
$this->productImageUrlFactory = $productImageUrlFactory;
}
/**
* {@inheritdoc}
*/
public function handle(GetProductImages $query): array
{
$images = $this->productImageRepository->getImages($query->getProductId());
return $this->formatImages($images);
}
/**
* @param Image[] $images
*
* @return ProductImage[]
*/
private function formatImages(array $images): array
{
$productImages = [];
foreach ($images as $image) {
$imageId = new ImageId((int) $image->id);
$productImages[] = new ProductImage(
(int) $image->id,
(bool) $image->cover,
(int) $image->position,
$image->legend,
$this->productImageUrlFactory->getPath($imageId),
$this->productImageUrlFactory->getPathByType($imageId, ProductImagePathFactory::IMAGE_TYPE_SMALL_DEFAULT)
);
}
return $productImages;
}
}

View File

@@ -0,0 +1,324 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\Image\Repository;
use Doctrine\DBAL\Connection;
use Image;
use ImageType;
use PrestaShop\PrestaShop\Adapter\AbstractObjectModelRepository;
use PrestaShop\PrestaShop\Adapter\Product\Image\Validate\ProductImageValidator;
use PrestaShop\PrestaShop\Core\Domain\Product\Image\Exception\CannotAddProductImageException;
use PrestaShop\PrestaShop\Core\Domain\Product\Image\Exception\CannotDeleteProductImageException;
use PrestaShop\PrestaShop\Core\Domain\Product\Image\Exception\CannotUpdateProductImageException;
use PrestaShop\PrestaShop\Core\Domain\Product\Image\Exception\ProductImageException;
use PrestaShop\PrestaShop\Core\Domain\Product\Image\Exception\ProductImageNotFoundException;
use PrestaShop\PrestaShop\Core\Domain\Product\Image\ValueObject\ImageId;
use PrestaShop\PrestaShop\Core\Domain\Product\ValueObject\ProductId;
use PrestaShop\PrestaShop\Core\Exception\CoreException;
use PrestaShopException;
/**
* Provides access to product Image data source
*/
class ProductImageRepository extends AbstractObjectModelRepository
{
/**
* @var Connection
*/
private $connection;
/**
* @var string
*/
private $dbPrefix;
/**
* @var ProductImageValidator
*/
private $productImageValidator;
/**
* @param Connection $connection
* @param string $dbPrefix
* @param ProductImageValidator $productImageValidator
*/
public function __construct(
Connection $connection,
string $dbPrefix,
ProductImageValidator $productImageValidator
) {
$this->connection = $connection;
$this->dbPrefix = $dbPrefix;
$this->productImageValidator = $productImageValidator;
}
/**
* @param ProductId $productId
* @param int[] $shopIds
*
* @return Image
*
* @throws CoreException
* @throws ProductImageException
* @throws CannotAddProductImageException
*/
public function create(ProductId $productId, array $shopIds): Image
{
$productIdValue = $productId->getValue();
$image = new Image();
$image->id_product = $productIdValue;
$image->cover = !Image::getCover($productIdValue);
$this->addObjectModel($image, CannotAddProductImageException::class);
try {
if (!$image->associateTo($shopIds)) {
throw new ProductImageException(sprintf(
'Failed to associate product image #%d with shops',
$image->id
));
}
} catch (PrestaShopException $e) {
throw new CoreException(
sprintf('Error occurred when trying to associate image #%d with shops', $image->id),
0,
$e
);
}
return $image;
}
/**
* @param ProductId $productId
*
* @return ImageId[]
*
* @throws CoreException
*/
public function getImagesIds(ProductId $productId): array
{
$qb = $this->connection->createQueryBuilder();
//@todo: multishop not handled
$results = $qb->select('id_image')
->from($this->dbPrefix . 'image', 'i')
->where('i.id_product = :productId')
->setParameter('productId', $productId->getValue())
->addOrderBy('i.position', 'ASC')
->addOrderBy('i.id_image', 'ASC')
->execute()
->fetchAll()
;
if (!$results) {
return [];
}
$imagesIds = [];
foreach ($results as $result) {
$imagesIds[] = new ImageId((int) $result['id_image']);
}
return $imagesIds;
}
/**
* @param ProductId $productId
*
* @return Image[]
*
* @throws CoreException
*/
public function getImages(ProductId $productId): array
{
$imagesIds = $this->getImagesIds($productId);
if (empty($imagesIds)) {
return [];
}
$images = [];
foreach ($imagesIds as $imageId) {
$images[] = $this->get($imageId);
}
return $images;
}
/**
* @return ImageType[]
*/
public function getProductImageTypes(): array
{
try {
$results = ImageType::getImagesTypes('products');
} catch (PrestaShopException $e) {
throw new CoreException('Error occurred when trying to get product image types');
}
if (!$results) {
return [];
}
$imageTypes = [];
foreach ($results as $result) {
$imageType = new ImageType();
$imageType->id = (int) $result['id_image_type'];
$imageType->name = $result['name'];
$imageType->width = (int) $result['width'];
$imageType->height = (int) $result['height'];
$imageType->products = (bool) $result['products'];
$imageType->categories = (bool) $result['categories'];
$imageType->manufacturers = (bool) $result['manufacturers'];
$imageType->suppliers = (bool) $result['suppliers'];
$imageType->stores = (bool) $result['stores'];
$imageTypes[] = $imageType;
}
return $imageTypes;
}
/**
* @param ImageId $imageId
*
* @return Image
*
* @throws CoreException
*/
public function get(ImageId $imageId): Image
{
/** @var Image $image */
$image = $this->getObjectModel(
$imageId->getValue(),
Image::class,
ProductImageNotFoundException::class
);
return $image;
}
/**
* @param ProductId $productId
*
* @return Image|null
*
* @throws CoreException
*/
public function findCover(ProductId $productId): ?Image
{
try {
$qb = $this->connection->createQueryBuilder();
$qb
->addSelect('i.id_image')
->from($this->dbPrefix . 'image', 'i')
->andWhere('i.id_product = :productId')
->andWhere('i.cover = 1')
->setParameter('productId', $productId->getValue())
;
$result = $qb->execute()->fetch();
$id = !empty($result['id_image']) ? (int) $result['id_image'] : null;
} catch (PrestaShopException $e) {
throw new CoreException('Error occurred while trying to get product default combination', 0, $e);
}
return $id ? $this->get(new ImageId($id)) : null;
}
/**
* Retrieves a list of image ids ordered by position for each provided combination id
*
* @param int[] $combinationIds
*
* @return array<int, ImageId[]> [(int) id_combination => [ImageId]]
*/
public function getImagesIdsForCombinations(array $combinationIds): array
{
//@todo: multishop not handled
$qb = $this->connection->createQueryBuilder();
$qb->select('pai.id_product_attribute, pai.id_image')
->from($this->dbPrefix . 'product_attribute_image', 'pai')
->leftJoin(
'pai',
$this->dbPrefix . 'image', 'i',
'i.id_image = pai.id_image'
)
->andWhere($qb->expr()->in('pai.id_product_attribute', ':combinationIds'))
->setParameter('combinationIds', $combinationIds, Connection::PARAM_INT_ARRAY)
->orderBy('i.position', 'asc')
;
$results = $qb->execute()->fetchAll();
if (empty($results)) {
return [];
}
// Temporary ImageId pool to avoid creating duplicates
$imageIds = [];
$imagesIdsByCombinationIds = [];
foreach ($results as $result) {
$id = (int) $result['id_image'];
if (!isset($imageIds[$id])) {
$imageIds[$id] = new ImageId($id);
}
$imagesIdsByCombinationIds[(int) $result['id_product_attribute']][] = $imageIds[$id];
}
return $imagesIdsByCombinationIds;
}
/**
* @param Image $image
* @param array $updatableProperties
* @param int $errorCode
*
* @throws CannotUpdateProductImageException
*/
public function partialUpdate(Image $image, array $updatableProperties, int $errorCode = 0): void
{
$this->productImageValidator->validate($image);
$this->partiallyUpdateObjectModel(
$image,
$updatableProperties,
CannotUpdateProductImageException::class,
$errorCode
);
}
/**
* @param Image $image
*
* @throws CannotDeleteProductImageException
*/
public function delete(Image $image): void
{
$this->deleteObjectModel($image, CannotDeleteProductImageException::class);
}
}

View File

@@ -0,0 +1,188 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\Image\Update;
use Image;
use PrestaShop\PrestaShop\Adapter\Product\Image\Repository\ProductImageRepository;
use PrestaShop\PrestaShop\Adapter\Product\Image\Uploader\ProductImageUploader;
use PrestaShop\PrestaShop\Core\Domain\Product\Image\Exception\CannotDeleteProductImageException;
use PrestaShop\PrestaShop\Core\Domain\Product\Image\Exception\CannotUpdateProductImageException;
use PrestaShop\PrestaShop\Core\Domain\Product\Image\ValueObject\ImageId;
use PrestaShop\PrestaShop\Core\Domain\Product\ValueObject\ProductId;
use PrestaShop\PrestaShop\Core\Grid\Position\Exception\PositionDataException;
use PrestaShop\PrestaShop\Core\Grid\Position\Exception\PositionUpdateException;
use PrestaShop\PrestaShop\Core\Grid\Position\GridPositionUpdaterInterface;
use PrestaShop\PrestaShop\Core\Grid\Position\PositionDefinition;
use PrestaShop\PrestaShop\Core\Grid\Position\PositionUpdateFactory;
use PrestaShop\PrestaShop\Core\Image\Exception\CannotUnlinkImageException;
class ProductImageUpdater
{
/**
* @var ProductImageUploader
*/
private $productImageUploader;
/**
* @var ProductImageRepository
*/
private $productImageRepository;
/**
* @var PositionUpdateFactory
*/
private $positionUpdateFactory;
/**
* @var PositionDefinition
*/
private $positionDefinition;
/**
* @var GridPositionUpdaterInterface
*/
private $positionUpdater;
/**
* @param ProductImageRepository $productImageRepository
* @param ProductImageUploader $productImageUploader
* @param PositionUpdateFactory $positionUpdateFactory
* @param PositionDefinition $positionDefinition
* @param GridPositionUpdaterInterface $positionUpdater
*/
public function __construct(
ProductImageRepository $productImageRepository,
ProductImageUploader $productImageUploader,
PositionUpdateFactory $positionUpdateFactory,
PositionDefinition $positionDefinition,
GridPositionUpdaterInterface $positionUpdater
) {
$this->productImageRepository = $productImageRepository;
$this->productImageUploader = $productImageUploader;
$this->positionUpdateFactory = $positionUpdateFactory;
$this->positionDefinition = $positionDefinition;
$this->positionUpdater = $positionUpdater;
}
/**
* @param ImageId $imageId
*
* @throws CannotDeleteProductImageException
* @throws CannotUnlinkImageException
*/
public function deleteImage(ImageId $imageId)
{
$image = $this->productImageRepository->get($imageId);
$this->productImageUploader->remove($image);
$this->productImageRepository->delete($image);
if ($image->cover) {
$images = $this->productImageRepository->getImages(new ProductId((int) $image->id_product));
if (count($images) > 0) {
$firstImage = $images[0];
$this->updateCover($firstImage, true);
}
}
}
/**
* @param Image $newCover
*
* @throws CannotUpdateProductImageException
*/
public function updateProductCover(Image $newCover): void
{
$productId = new ProductId((int) $newCover->id_product);
$currentCover = $this->productImageRepository->findCover($productId);
if ($currentCover) {
$this->updateCover($currentCover, false);
}
$this->updateCover($newCover, true);
}
/**
* @param Image $image
* @param int $newPosition
*
* @throws CannotUpdateProductImageException
*/
public function updatePosition(Image $image, int $newPosition): void
{
$oldPosition = (int) $image->position;
// The images are sorted by their position values, but since only one of them as un updated value there will be
// two images with the same position, so we need to add an offset to the new position depending on the way it
// is being modified
if ($oldPosition < $newPosition) {
++$newPosition;
} elseif ($oldPosition > $newPosition) {
--$newPosition;
}
$positionsData = [
'positions' => [
[
'rowId' => (int) $image->id_image,
'oldPosition' => $oldPosition,
'newPosition' => $newPosition,
],
],
'parentId' => (int) $image->id_product,
];
try {
$positionUpdate = $this->positionUpdateFactory->buildPositionUpdate($positionsData, $this->positionDefinition);
$this->positionUpdater->update($positionUpdate);
} catch (PositionDataException | PositionUpdateException $e) {
throw new CannotUpdateProductImageException(
'Cannot update image position',
CannotUpdateProductImageException::FAILED_UPDATE_POSITION,
$e
);
}
}
/**
* @param Image $image
* @param bool $isCover
*
* @throws CannotUpdateProductImageException
*/
private function updateCover(Image $image, bool $isCover): void
{
$image->cover = $isCover;
$this->productImageRepository->partialUpdate(
$image,
['cover'],
CannotUpdateProductImageException::FAILED_UPDATE_COVER
);
}
}

View File

@@ -0,0 +1,230 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\Image\Uploader;
use Image;
use PrestaShop\PrestaShop\Adapter\Image\ImageGenerator;
use PrestaShop\PrestaShop\Adapter\Image\Uploader\AbstractImageUploader;
use PrestaShop\PrestaShop\Adapter\Product\Image\ProductImagePathFactory;
use PrestaShop\PrestaShop\Adapter\Product\Image\Repository\ProductImageRepository;
use PrestaShop\PrestaShop\Core\Domain\Product\Image\ValueObject\ImageId;
use PrestaShop\PrestaShop\Core\Foundation\Filesystem\FileSystem as PsFileSystem;
use PrestaShop\PrestaShop\Core\Hook\HookDispatcherInterface;
use PrestaShop\PrestaShop\Core\Image\Exception\CannotUnlinkImageException;
use PrestaShop\PrestaShop\Core\Image\Exception\ImageOptimizationException;
use PrestaShop\PrestaShop\Core\Image\Uploader\Exception\ImageUploadException;
use PrestaShop\PrestaShop\Core\Image\Uploader\Exception\MemoryLimitException;
use Symfony\Component\Filesystem\Exception\IOException;
use Symfony\Component\Filesystem\Filesystem;
/**
* Uploads product image to filesystem
*/
class ProductImageUploader extends AbstractImageUploader
{
/**
* @var ProductImagePathFactory
*/
private $productImagePathFactory;
/**
* @var int
*/
private $contextShopId;
/**
* @var ImageGenerator
*/
private $imageGenerator;
/**
* @var HookDispatcherInterface
*/
private $hookDispatcher;
/**
* @var ProductImageRepository
*/
private $productImageRepository;
/**
* @var Filesystem
*/
private $fileSystem;
/**
* @param ProductImagePathFactory $productImagePathFactory
* @param int $contextShopId
* @param ImageGenerator $imageGenerator
* @param HookDispatcherInterface $hookDispatcher
* @param ProductImageRepository $productImageRepository
*/
public function __construct(
ProductImagePathFactory $productImagePathFactory,
int $contextShopId,
ImageGenerator $imageGenerator,
HookDispatcherInterface $hookDispatcher,
ProductImageRepository $productImageRepository
) {
$this->productImagePathFactory = $productImagePathFactory;
$this->contextShopId = $contextShopId;
$this->imageGenerator = $imageGenerator;
$this->hookDispatcher = $hookDispatcher;
$this->productImageRepository = $productImageRepository;
$this->fileSystem = new Filesystem();
}
/**
* @param Image $image
* @param string $filePath
*
* @return string destination path of main image
*
* @throws CannotUnlinkImageException
* @throws ImageUploadException
* @throws ImageOptimizationException
* @throws MemoryLimitException
*/
public function upload(Image $image, string $filePath): string
{
$imageId = new ImageId((int) $image->id);
$productId = (int) $image->id_product;
$this->createDestinationDirectory($imageId, $productId);
$destinationPath = $this->productImagePathFactory->getPath($imageId);
$this->uploadFromTemp($filePath, $destinationPath);
$this->imageGenerator->generateImagesByTypes($destinationPath, $this->productImageRepository->getProductImageTypes());
$this->hookDispatcher->dispatchWithParameters(
'actionWatermark',
['id_image' => $imageId->getValue(), 'id_product' => $productId]
);
$this->deleteCachedImages($productId);
return $destinationPath;
}
/**
* @param Image $image
*
* @throws CannotUnlinkImageException
*/
public function remove(Image $image): void
{
$destinationPath = $this->productImagePathFactory->getPath(new ImageId((int) $image->id));
$this->deleteCachedImages((int) $image->id_product);
$this->deleteGeneratedImages($destinationPath, $this->productImageRepository->getProductImageTypes());
}
/**
* @param ImageId $imageId
* @param int $productId
*
* @throws ImageUploadException
*/
private function createDestinationDirectory(ImageId $imageId, int $productId): void
{
$imageFolder = $this->productImagePathFactory->getImageFolder($imageId);
if (is_dir($imageFolder)) {
return;
}
try {
$this->fileSystem->mkdir($imageFolder, PsFileSystem::DEFAULT_MODE_FOLDER);
} catch (IOException $e) {
throw new ImageUploadException(sprintf(
'Error occurred when trying to create directory for product #%d image',
$productId
));
}
}
/**
* @param int $productId
*
* @throws CannotUnlinkImageException
*/
private function deleteCachedImages(int $productId): void
{
$cachedImages = [
$this->productImagePathFactory->getHelperThumbnail($productId, $this->contextShopId),
$this->productImagePathFactory->getCachedCover($productId),
];
foreach ($cachedImages as $cachedImage) {
if (!file_exists($cachedImage)) {
continue;
}
if (!@unlink($cachedImage)) {
throw new CannotUnlinkImageException(
sprintf(
'Failed to remove cached image "%s"',
$cachedImage
)
);
}
}
}
/**
* Note: we can't delete the whole folder here, or Image::delete will return an error
* because it expects the original image and the folder to be present in order to remove
* them correctly. So for now this service only handles removing generated image types.
* When Image ObjectModel is no longer used, it could also remove the remaining files.
*
* @param string $imagePath
* @param array $imageTypes
*
* @throws CannotUnlinkImageException
*/
private function deleteGeneratedImages(string $imagePath, array $imageTypes): void
{
$fileExtension = pathinfo($imagePath, PATHINFO_EXTENSION);
$destinationExtension = '.jpg';
$imageBaseName = rtrim($imagePath, '.' . $fileExtension);
foreach ($imageTypes as $imageType) {
$generatedImagePath = sprintf('%s-%s%s', $imageBaseName, stripslashes($imageType->name), $destinationExtension);
if (!file_exists($generatedImagePath)) {
continue;
}
if (!@unlink($generatedImagePath)) {
throw new CannotUnlinkImageException(
sprintf(
'Failed to remove generated image "%s"',
$generatedImagePath
)
);
}
}
}
}

View File

@@ -0,0 +1,62 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\Image\Validate;
use Image;
use PrestaShop\PrestaShop\Adapter\AbstractObjectModelValidator;
use PrestaShop\PrestaShop\Core\Domain\Product\Image\Exception\ProductImageConstraintException;
use PrestaShop\PrestaShop\Core\Exception\CoreException;
class ProductImageValidator extends AbstractObjectModelValidator
{
public function validate(Image $image): void
{
$this->validateProductImageProperty($image, 'cover', ProductImageConstraintException::INVALID_COVER);
$this->validateProductImageProperty($image, 'position', ProductImageConstraintException::INVALID_POSITION);
$this->validateObjectModelLocalizedProperty(
$image,
'legend',
ProductImageConstraintException::class,
ProductImageConstraintException::INVALID_LEGENDS
);
}
/**
* @param Image $image
* @param string $property
* @param int $errorCode
*
* @throws CoreException
* @throws ProductImageConstraintException
*/
private function validateProductImageProperty(Image $image, string $property, int $errorCode): void
{
$this->validateObjectModelProperty($image, $property, ProductImageConstraintException::class, $errorCode);
}
}

View File

@@ -0,0 +1,143 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
namespace PrestaShop\PrestaShop\Adapter\Product;
use PrestaShop\PrestaShop\Core\Exception\ProductException;
/**
* Can manage filter parameters from request in Product Catalogue Page.
* For internal use only.
*/
final class ListParametersUpdater
{
/**
* In case of position ordering all the filters should be reset.
*
* @param array $filterParameters
* @param string $orderBy
* @param bool $hasCategoryFilter
*
* @return array $filterParameters
*/
public function cleanFiltersForPositionOrdering($filterParameters, $orderBy, $hasCategoryFilter)
{
if ($orderBy == 'position_ordering' && $hasCategoryFilter) {
foreach (array_keys($filterParameters) as $key) {
if (strpos($key, 'filter_column_') === 0) {
$filterParameters[$key] = '';
}
}
}
return $filterParameters;
}
/**
* @param array $queryFilterParameters
* @param array $persistedFilterParameters
* @param array $defaultFilterParameters
*
* @return array
*
* @throws ProductException
*/
public function buildListParameters(
array $queryFilterParameters,
array $persistedFilterParameters,
array $defaultFilterParameters
) {
$filters = [
'offset' => (int) $this->getParameter(
'offset',
$queryFilterParameters,
$persistedFilterParameters,
$defaultFilterParameters
),
'limit' => (int) $this->getParameter(
'limit',
$queryFilterParameters,
$persistedFilterParameters,
$defaultFilterParameters
),
'orderBy' => (string) $this->getParameter(
'orderBy',
$queryFilterParameters,
$persistedFilterParameters,
$defaultFilterParameters
),
'sortOrder' => (string) $this->getParameter(
'sortOrder',
$queryFilterParameters,
$persistedFilterParameters,
$defaultFilterParameters
),
];
/*
* We need to force the sort order when the order by
* is set to position_ordering
*/
if ('position_ordering' === $filters['orderBy']) {
$filters['sortOrder'] = 'asc';
}
return $filters;
}
/**
* @param string $parameterName
* @param array $queryFilterParameters
* @param array $persistedFilterParameters
* @param array $defaultFilterParameters
*
* @return string|int
*
* @throws ProductException
*/
private function getParameter(
$parameterName,
array $queryFilterParameters,
array $persistedFilterParameters,
array $defaultFilterParameters
) {
if (isset($queryFilterParameters[$parameterName])) {
$value = $queryFilterParameters[$parameterName];
} elseif (isset($persistedFilterParameters[$parameterName])) {
$value = $persistedFilterParameters[$parameterName];
} elseif (isset($defaultFilterParameters[$parameterName])) {
$value = $defaultFilterParameters[$parameterName];
} else {
throw new ProductException('Could not find the parameter %s', 'Admin.Notifications.Error', [$parameterName]);
}
if ($value === 'last' && isset($persistedFilterParameters['last_' . $parameterName])) {
$value = $persistedFilterParameters['last_' . $parameterName];
}
return $value;
}
}

View File

@@ -0,0 +1,61 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\Pack\CommandHandler;
use PrestaShop\PrestaShop\Adapter\Product\Pack\Update\ProductPackUpdater;
use PrestaShop\PrestaShop\Core\Domain\Product\Pack\Command\RemoveAllProductsFromPackCommand;
use PrestaShop\PrestaShop\Core\Domain\Product\Pack\CommandHandler\RemoveAllProductsFromPackHandlerInterface;
/**
* Handles @see RemoveAllProductsFromPackCommand using legacy object model
*/
final class RemoveAllProductsFromPackHandler implements RemoveAllProductsFromPackHandlerInterface
{
/**
* @var ProductPackUpdater
*/
private $productPackUpdater;
/**
* @param ProductPackUpdater $productPackUpdater
*/
public function __construct(
ProductPackUpdater $productPackUpdater
) {
$this->productPackUpdater = $productPackUpdater;
}
/**
* {@inheritdoc}
*/
public function handle(RemoveAllProductsFromPackCommand $command): void
{
$this->productPackUpdater->setPackProducts($command->getPackId(), []);
}
}

View File

@@ -0,0 +1,61 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\Pack\CommandHandler;
use PrestaShop\PrestaShop\Adapter\Product\Pack\Update\ProductPackUpdater;
use PrestaShop\PrestaShop\Core\Domain\Product\Pack\Command\SetPackProductsCommand;
use PrestaShop\PrestaShop\Core\Domain\Product\Pack\CommandHandler\SetPackProductsHandlerInterface;
/**
* Handles @see SetPackProductsCommand using legacy object model
*/
final class SetPackProductsHandler implements SetPackProductsHandlerInterface
{
/**
* @var ProductPackUpdater
*/
private $productPackUpdater;
/**
* @param ProductPackUpdater $productPackUpdater
*/
public function __construct(
ProductPackUpdater $productPackUpdater
) {
$this->productPackUpdater = $productPackUpdater;
}
/**
* {@inheritdoc}
*/
public function handle(SetPackProductsCommand $command): void
{
$this->productPackUpdater->setPackProducts($command->getPackId(), $command->getProducts());
}
}

View File

@@ -0,0 +1,74 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\Pack\QueryHandler;
use Pack;
use PrestaShop\PrestaShop\Core\Domain\Product\Pack\Query\GetPackedProducts;
use PrestaShop\PrestaShop\Core\Domain\Product\Pack\QueryHandler\GetPackedProductsHandlerInterface;
use PrestaShop\PrestaShop\Core\Domain\Product\Pack\QueryResult\PackedProduct;
/**
* Handles GetPackedProducts query using legacy object model
*/
final class GetPackedProductsHandler implements GetPackedProductsHandlerInterface
{
/**
* @var int
*/
private $defaultLangId;
/**
* @param int $defaultLangId
*/
public function __construct(int $defaultLangId)
{
$this->defaultLangId = $defaultLangId;
}
/**
* {@inheritdoc}
*/
public function handle(GetPackedProducts $query): array
{
$packId = $query->getPackId()->getValue();
$packedItems = Pack::getItems($packId, $this->defaultLangId);
$packedProducts = [];
foreach ($packedItems as $packedItem) {
$packedProducts[] = new PackedProduct(
(int) $packedItem->id,
(int) $packedItem->pack_quantity,
(int) $packedItem->id_pack_product_attribute
);
}
return $packedProducts;
}
}

View File

@@ -0,0 +1,124 @@
<?php
/**
* Copyright since 2007 PrestaShop SA and Contributors
* PrestaShop is an International Registered Trademark & Property of PrestaShop SA
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://opensource.org/licenses/OSL-3.0
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to https://devdocs.prestashop.com/ for more information.
*
* @author PrestaShop SA and Contributors <contact@prestashop.com>
* @copyright Since 2007 PrestaShop SA and Contributors
* @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
*/
declare(strict_types=1);
namespace PrestaShop\PrestaShop\Adapter\Product\Pack\Repository;
use Pack;
use PrestaShop\PrestaShop\Core\Domain\Product\Combination\ValueObject\CombinationId;
use PrestaShop\PrestaShop\Core\Domain\Product\Pack\Exception\ProductPackException;
use PrestaShop\PrestaShop\Core\Domain\Product\Pack\ValueObject\PackId;
use PrestaShop\PrestaShop\Core\Domain\Product\QuantifiedProduct;
use PrestaShop\PrestaShop\Core\Exception\CoreException;
use PrestaShopException;
class ProductPackRepository
{
/**
* @param PackId $packId
* @param QuantifiedProduct $productForPacking
*
* @throws CoreException
* @throws ProductPackException
*/
public function addProductToPack(PackId $packId, QuantifiedProduct $productForPacking): void
{
$packIdValue = $packId->getValue();
try {
$packed = Pack::addItem(
$packIdValue,
$productForPacking->getProductId()->getValue(),
$productForPacking->getQuantity(),
$productForPacking->getCombinationId() ?
$productForPacking->getCombinationId()->getValue() :
CombinationId::NO_COMBINATION
);
if (!$packed) {
throw new ProductPackException(
$this->appendIdsToMessage('Failed to add product to pack.', $productForPacking, $packIdValue),
ProductPackException::FAILED_ADDING_TO_PACK
);
}
} catch (PrestaShopException $e) {
throw new CoreException(
$this->appendIdsToMessage('Error occurred when trying to add product to pack.', $productForPacking, $packIdValue),
0,
$e
);
}
}
/**
* @param PackId $packId
*
* @throws CoreException
* @throws ProductPackException
*/
public function removeAllProductsFromPack(PackId $packId): void
{
$packIdValue = $packId->getValue();
try {
if (!Pack::deleteItems($packIdValue)) {
throw new ProductPackException(
sprintf('Failed to remove products from pack #%d', $packIdValue),
ProductPackException::FAILED_DELETING_PRODUCTS_FROM_PACK
);
}
} catch (PrestaShopException $e) {
throw new CoreException(
sprintf('Error occurred when trying to remove pack items from pack #%d', $packIdValue),
0,
$e
);
}
}
/**
* Builds string with ids, that will help to identify objects that was being updated in case of error
*
* @param string $messageBody
* @param QuantifiedProduct $product
* @param int $packId
*
* @return string
*/
private function appendIdsToMessage(string $messageBody, QuantifiedProduct $product, int $packId): string
{
if ($product->getCombinationId()) {
$combinationId = sprintf(' combinationId #%d', $product->getCombinationId()->getValue());
}
return sprintf(
"$messageBody. [packId #%d; productId #%d;%s]",
$packId,
$product->getProductId()->getValue(),
isset($combinationId) ? $combinationId : ''
);
}
}

Some files were not shown because too many files have changed in this diff Show More