Current File : //var/www/prestashop/src/Core/Repository/AbstractMultiShopObjectModelRepository.php |
<?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\Core\Repository;
use function bqSQL;
use Db;
use DbQuery;
use ObjectModel;
use PrestaShop\PrestaShop\Core\Domain\Shop\Exception\ShopAssociationNotFound;
use PrestaShop\PrestaShop\Core\Domain\Shop\ValueObject\ShopId;
use PrestaShop\PrestaShop\Core\Exception\CoreException;
use PrestaShopDatabaseException;
/**
* This abstract class is an extension of the AbstractObjectModelRepository that provides additional helper functions
* to deal with multi shop entities. It provides additional function which rely on mandatory shop IDs. When you use
* this class you shouldn't rely on single shop functions anymore, your repository should be oriented as a multi shop
* one and always require some shop parameters (single shop becomes only an edge case of you generic multi shop
* behaviour).
*/
class AbstractMultiShopObjectModelRepository extends AbstractObjectModelRepository
{
/**
* @param int $id
* @param string $objectModelClass
* @param string $exceptionClass
*
* @return ObjectModel
*
* @throws CoreException
*/
protected function getObjectModelForShop(int $id, string $objectModelClass, string $exceptionClass, ShopId $shopId): ObjectModel
{
$objectModel = $this->fetchObjectModel($id, $objectModelClass, $exceptionClass, $shopId->getValue());
// The object is fetched before checking the association, so that the NotFoundException has the priority over the NoAssociationException
$this->checkShopAssociation($id, $objectModelClass, $shopId);
// Force id_shop_list right away so that DB modification use the appropriate shop and not the one from context
$objectModel->id_shop_list = [$shopId->getValue()];
return $objectModel;
}
/**
* @param ObjectModel $objectModel
* @param string $exceptionClass
* @param int $errorCode
*
* @return int
*/
protected function addObjectModelToShop(ObjectModel $objectModel, int $shopId, string $exceptionClass, int $errorCode = 0): int
{
// Force internal shop list which is used as an override of the one from Context when generating the SQL queries
// this way we can control exactly which shop is updated
$objectModel->id_shop_list = [$shopId];
return $this->addObjectModel($objectModel, $exceptionClass, $errorCode);
}
/**
* @param ObjectModel $objectModel
* @param array $shopIds
* @param string $exceptionClass
* @param int $errorCode
*
* @throws CoreException
*/
protected function updateObjectModelForShops(
ObjectModel $objectModel,
array $shopIds,
string $exceptionClass,
int $errorCode = 0
): void {
// Force internal shop list which is used as an override of the one from Context when generating the SQL queries
// this way we can control exactly which shop is updated
$objectModel->id_shop_list = $shopIds;
$this->updateObjectModel($objectModel, $exceptionClass, $errorCode);
}
/**
* @param ObjectModel $objectModel
* @param array $propertiesToUpdate
* @param array $shopIds
* @param string $exceptionClass
* @param int $errorCode
*
* @throws CoreException
*/
protected function partiallyUpdateObjectModelForShops(
ObjectModel $objectModel,
array $propertiesToUpdate,
array $shopIds,
string $exceptionClass,
int $errorCode = 0
): void {
$objectModel->setFieldsToUpdate($this->formatPropertiesToUpdate($propertiesToUpdate));
$this->updateObjectModelForShops($objectModel, $shopIds, $exceptionClass, $errorCode);
}
/**
* @param int $id
* @param string $objectModelClassName
* @param ShopId $shopId
*
* @return bool
*/
protected function hasShopAssociation(int $id, string $objectModelClassName, ShopId $shopId): bool
{
$modelDefinition = $objectModelClassName::$definition;
$objectTable = $modelDefinition['table'];
$primaryColumn = $modelDefinition['primary'];
$query = new DbQuery();
$query
->select('e.`' . bqSQL($primaryColumn) . '` as id')
->from(bqSQL($objectTable) . '_shop', 'e')
->where('e.`' . bqSQL($primaryColumn) . '` = ' . $id)
->where('e.`id_shop` = ' . $shopId->getValue())
;
try {
$row = Db::getInstance()->getRow($query, false);
} catch (PrestaShopDatabaseException $e) {
$row = false;
}
return !empty($row['id']);
}
/**
* @param int $id
* @param string $objectModelClassName
* @param ShopId $shopId
*
* @throws ShopAssociationNotFound
*/
protected function checkShopAssociation(int $id, string $objectModelClassName, ShopId $shopId): void
{
if (!$this->hasShopAssociation($id, $objectModelClassName, $shopId)) {
throw new ShopAssociationNotFound(sprintf(
'Could not find association between %s %d and Shop %d',
$objectModelClassName,
$id,
$shopId->getValue()
));
}
}
}