JEMBOT MAWOT Bypass Shell
<?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\Exception\ShopDefinitionNotFound;
use PrestaShop\PrestaShop\Core\Domain\Shop\ValueObject\ShopId;
use PrestaShop\PrestaShop\Core\Exception\CoreException;
use PrestaShop\PrestaShop\Core\Exception\InvalidArgumentException;
use PrestaShopDatabaseException;
use PrestaShopException;
use Shop;
/**
* 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
* @param ShopId $shopId
* @param string $shopAssociationClass
*
* @return ObjectModel
*
* @throws CoreException
* @throws ShopAssociationNotFound
*/
protected function getObjectModelForShop(int $id, string $objectModelClass, string $exceptionClass, ShopId $shopId, string $shopAssociationClass = ShopAssociationNotFound::class): 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, $shopAssociationClass);
// 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 ShopId[] $shopIds
* @param string $exceptionClass
* @param int $errorCode
*
* @return int
*/
protected function addObjectModelToShops(ObjectModel $objectModel, array $shopIds, 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 = array_map(function (ShopId $shopId): int {
return $shopId->getValue();
}, $shopIds);
return $this->addObjectModel($objectModel, $exceptionClass, $errorCode);
}
/**
* @param ObjectModel $objectModel
* @param ShopId[] $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 = array_map(function (ShopId $shopId): int {
return $shopId->getValue();
}, $shopIds);
$this->updateObjectModel($objectModel, $exceptionClass, $errorCode);
}
/**
* @param ObjectModel $objectModel
* @param array<int|string, string|int[]> $propertiesToUpdate
* @param ShopId[] $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();
if (Shop::isTableAssociated($objectTable)) {
$query
->select('e.`' . bqSQL($primaryColumn) . '` as id')
->from(bqSQL($objectTable) . '_shop', 'e')
->where('e.`' . bqSQL($primaryColumn) . '` = ' . $id)
->where('e.`id_shop` = ' . $shopId->getValue())
;
} elseif (!empty($modelDefinition['multilang_shop'])) {
$query
->select('e.`' . bqSQL($primaryColumn) . '` as id')
->from(bqSQL($objectTable) . '_lang', 'e')
->where('e.`' . bqSQL($primaryColumn) . '` = ' . $id)
->where('e.`id_shop` = ' . $shopId->getValue())
;
} else {
throw new ShopDefinitionNotFound(sprintf(
'Entity %s has no multishop feature',
$objectModelClassName
));
}
try {
$row = Db::getInstance()->getRow($query, false);
} catch (PrestaShopDatabaseException|PrestaShopException $e) {
$row = false;
}
return !empty($row['id']);
}
/**
* @param int $id
* @param string $objectModelClassName
* @param ShopId $shopId
* @param string $shopAssociationExceptionClass
*
* @throws ShopAssociationNotFound
*/
protected function checkShopAssociation(
int $id,
string $objectModelClassName,
ShopId $shopId,
string $shopAssociationExceptionClass = ShopAssociationNotFound::class
): void {
if (!$this->hasShopAssociation($id, $objectModelClassName, $shopId)) {
throw new $shopAssociationExceptionClass(sprintf(
'Could not find association between %s %d and Shop %d',
$objectModelClassName,
$id,
$shopId->getValue()
));
}
}
/**
* @param ObjectModel $objectModel
* @param ShopId[] $shopIds
* @param string $exceptionClass
* @param int $errorCode
*
* @throws CoreException
*/
protected function deleteObjectModelFromShops(ObjectModel $objectModel, array $shopIds, string $exceptionClass, int $errorCode = 0): void
{
if (empty($shopIds)) {
throw new InvalidArgumentException('The shopIds should not be empty');
}
try {
// 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 deleted
$objectModel->id_shop_list = array_map(static function (ShopId $shopId): int {
return $shopId->getValue();
}, $shopIds);
if (!$objectModel->delete()) {
throw new $exceptionClass(
sprintf('Failed to delete %s #%d', get_class($objectModel), $objectModel->id),
$errorCode
);
}
} catch (PrestaShopException $e) {
throw new CoreException(
sprintf(
'Error occurred when trying to delete %s #%d [%s]',
get_class($objectModel),
$objectModel->id,
$e->getMessage()
),
0,
$e
);
}
}
}
xxxxx1.0, XXX xxxx