<?php
namespace ShopWithMe\UI\Service;
use Econsor\Shopware\SearchBar\Storefront\Controller\EconsorTagSaverController;
use PhpParser\Node\Expr\AssignOp\Mul;
use Shopware\Core\Checkout\Customer\CustomerEntity;
use Shopware\Core\Checkout\Order\Aggregate\OrderTransaction\OrderTransactionStates;
use Shopware\Core\Checkout\Order\OrderEntity;
use Shopware\Core\Content\Media\Aggregate\MediaFolder\MediaFolderEntity;
use Shopware\Core\Content\Media\File\FileSaver;
use Shopware\Core\Content\Media\File\MediaFile;
use Shopware\Core\Content\Media\MediaEntity;
use Shopware\Core\Content\Media\MediaService;
use Shopware\Core\Content\Product\Aggregate\ProductVisibility\ProductVisibilityDefinition;
use Shopware\Core\Content\Product\SalesChannel\ProductAvailableFilter;
use Shopware\Core\Content\Product\SalesChannel\SalesChannelProductCollection;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
use Doctrine\DBAL\Connection;
use Shopware\Core\Content\Product\ProductEntity;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsAnyFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\MultiFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\NotFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\OrFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\RangeFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Sorting\FieldSorting;
use Shopware\Core\Framework\DataAbstractionLayer\Util\AfterSort;
use Shopware\Core\Framework\Uuid\Uuid;
use Shopware\Core\System\SalesChannel\Entity\SalesChannelRepositoryInterface;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use ShopWithMe\Reward\Controller\Storefront\CreditShopController;
use ShopWithMe\Reward\Service\RewardPointService;
use Symfony\Component\Cache\Adapter\RedisAdapter;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use ShopWithMe\MobileApi\Service\ProductService;
use Symfony\Component\HttpFoundation\JsonResponse;
class HomePageService
{
protected EntityRepository $productRepository;
protected Connection $connection;
protected EntityRepository $orderLineItemRepository;
protected CreditShopController $creditShopController;
protected RewardPointService $rewardPointService;
protected EntityRepository $orderRepository;
protected EntityRepository $orderCustomer;
protected EntityRepository $categoryRepository;
protected EntityRepository $rewardPointRepository;
protected EntityRepository $customerTagRepository;
protected SalesChannelRepositoryInterface $salesChannelProductRepository;
protected MediaService $mediaService;
protected FileSaver $fileSaver;
protected EntityRepository $mediaRepository;
protected EntityRepository $mediaFolderRepository;
protected EntityRepository $mediaDefaultFolderRepository;
protected EntityRepository $subscriptionRepository;
protected ProductService $productService;
protected $redisUrl;
public function __construct(
EntityRepository $repository,
Connection $connection,
EntityRepository $orderLineItemRepository,
CreditShopController $creditShopController,
RewardPointService $rewardPointService,
EntityRepository $orderRepository,
EntityRepository $orderCustomer,
EntityRepository $categoryRepository,
EntityRepository $rewardPointRepository,
EntityRepository $customerTagRepository,
SalesChannelRepositoryInterface $salesChannelProductRepository,
MediaService $mediaService,
FileSaver $fileSaver,
EntityRepository $mediaRepository,
EntityRepository $mediaFolderRepository,
EntityRepository $mediaDefaultFolderRepository,
protected EntityRepository $customerRepository,
EntityRepository $subscriptionRepository,
ProductService $productService,
)
{
$this->productRepository = $repository;
$this->connection = $connection;
$this->orderLineItemRepository = $orderLineItemRepository;
$this->creditShopController = $creditShopController;
$this->rewardPointService = $rewardPointService;
$this->orderRepository = $orderRepository;
$this->orderCustomer = $orderCustomer;
$this->categoryRepository = $categoryRepository;
$this->rewardPointRepository = $rewardPointRepository;
$this->customerTagRepository = $customerTagRepository;
$this->salesChannelProductRepository = $salesChannelProductRepository;
$this->mediaService = $mediaService;
$this->fileSaver = $fileSaver;
$this->mediaRepository = $mediaRepository;
$this->mediaFolderRepository = $mediaFolderRepository;
$this->mediaDefaultFolderRepository = $mediaDefaultFolderRepository;
$this->subscriptionRepository = $subscriptionRepository;
$this->productService = $productService;
$this->redisUrl = getenv('REDIS_URL');
}
public function searchProduct(?string $keyword, SalesChannelContext $context)
{
$criteria = new Criteria();
if (!empty($keyword)) {
$criteria->setTerm($keyword);
}
$criteria->addSorting(new FieldSorting('createdAt', FieldSorting::DESCENDING));
$criteria->addFilter(new NotFilter(
MultiFilter::CONNECTION_OR,
[
new EqualsFilter('customFields.productIsBuyWithCredit', true),
new EqualsFilter('customFields.isHideOnSearch', 'true')
]
));
$criteria->addAssociations(['deals', 'cover.media', 'customFields']);
return $this->salesChannelProductRepository->search($criteria, $context)->getEntities();
}
public function productDealDetail($productId, SalesChannelContext $salesChannelContext)
{
if (!$productId) {
return ['error' => 'Product ID is required'];
}
$context = $salesChannelContext->getContext();
$languageId = $context->getLanguageId();
$criteria = new Criteria([$productId]);
$criteria->addAssociation('media');
/** @var ProductEntity|null $product */
$product = $this->productRepository->search($criteria, $context)->first();
if (!$product) {
return ['error' => 'Product not found'];
}
$images = [];
$jpgImages = array_filter($product->getMedia()->getElements(), function ($media) {
return str_ends_with($media->getMedia()->getUrl(), '.jpg');
});
foreach ($jpgImages as $media) {
$images[] = [
'id' => $media->getMedia()->getId(),
'url' => $media->getMedia()->getUrl(),
];
}
$orderCriteria = new Criteria();
$orderCriteria->addFilter(new EqualsFilter('productId', $product->getId()));
$orderCriteria->addAssociation('order');
$orderLineItems = $this->orderLineItemRepository->search($orderCriteria, $context);
$orderDetails = [];
foreach ($orderLineItems as $lineItem) {
$order = $lineItem->getOrder();
$orderDetails[] = [
'purchaseDate' => $order->getOrderDateTime()->format('Y-m-d H:i:s'),
'transactionDate' => $order->getTransactions()?->first()->getCreatedAt()->format('Y-m-d H:i:s'),
'trackingCode' => $order->getDeliveries()?->first()->getTrackingCodes()
];
}
return [
'id' => $product->getId(),
'name' => $product->getTranslation('name', $languageId),
// 'price' => $product->getPrice()->first()->getGross(),
// 'description' => $product->getTranslation('description', $languageId),
'images' => $images,
'orderDetails' => $orderDetails,
];
}
public function loadNextCreditProductOfCustomer(int $customerCredit, SalesChannelContext $context)
{
// Define criteria to filter products
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('customFields.productIsBuyWithCredit', true));
$criteria->addFilter(new RangeFilter('customFields.productCreditPrice', [
RangeFilter::GTE => $customerCredit,
]));
// Optionally, add pagination, sorting, or other filters
$availableFilter = new ProductAvailableFilter($context->getSalesChannelId(),
ProductVisibilityDefinition::VISIBILITY_ALL);
$criteria->addFilter($availableFilter);
$criteria->addSorting(new FieldSorting('customFields.productCreditPrice', FieldSorting::ASCENDING));
// Load products using the productPageLoader and the defined criteria
// Note: The method to load products might differ based on your setup and Shopware version
// This is a generic example assuming you have a method similar to 'search' in your productPageLoader
$nextCreditProduct = $this->salesChannelProductRepository->search($criteria, $context)->first();
if (empty($nextCreditProduct)) {
$nextCreditProduct = $this->salesChannelProductRepository->search((new Criteria())
->addFilter(new EqualsFilter('customFields.productIsBuyWithCredit', true))
->addFilter($availableFilter)
->addSorting(new FieldSorting('customFields.productCreditPrice', FieldSorting::DESCENDING))
->setLimit(1), $context)->first();
}
return $nextCreditProduct;
}
public function loadProductsWithCreditOption(SalesChannelContext $context, $limit = 0)
{
// Define criteria to filter products
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('customFields.productIsBuyWithCredit', true));
// Optionally, add pagination, sorting, or other filters
// $criteria->setLimit(15); // Example: Limit to 15 products
$availableFilter = new ProductAvailableFilter($context->getSalesChannelId(),
ProductVisibilityDefinition::VISIBILITY_ALL);
$criteria->addFilter($availableFilter);
$criteria->addSorting(new FieldSorting('customFields.productCreditPrice', FieldSorting::DESCENDING));
if ($limit == 5) {
$criteria->setLimit($limit);
}
// Load products using the productPageLoader and the defined criteria
// Note: The method to load products might differ based on your setup and Shopware version
// This is a generic example assuming you have a method similar to 'search' in your productPageLoader
return $this->salesChannelProductRepository->search($criteria, $context);
}
public function getCustomerCredit(SalesChannelContext $channelContext, Context $context)
{
$customer = $channelContext->getCustomer();
if ($customer) {
$customerId = $customer->getId();
$balance = $this->rewardPointService->getCustomerTotalRewardPoint($customerId, $context);
return $balance;
}
return 0;
}
public function getCustomerAddress(SalesChannelContext $context)
{
$customerId = $context->getCustomer();
if (!$customerId) {
return false;
}
$data = [
'defaultBillingAddress' => $customerId->getDefaultBillingAddress(),
'defaultShippingAddress' => $customerId->getDefaultShippingAddress(),
'address' => $customerId->getAddresses()
];
return $data;
}
public function getCustomerOrderByStatus($status, SalesChannelContext $context)
{
$customerId = $context->getCustomer()?->getId();
if (!$customerId) {
return [];
}
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('orderCustomer.customerId', $customerId));
if ($status) {
if ($status == 'shipped') {
$criteria->addFilter(new EqualsFilter('deliveries.stateMachineState.technicalName', $status));
} else {
$criteria->addFilter(new EqualsFilter('stateMachineState.technicalName', $status));
}
}
$criteria->addAssociation('stateMachineState');
// $criteria->addAssociation('lineItems.product.media');
$criteria->addAssociation('lineItems.cover');
$criteria->addAssociation('lineItems.product');
$criteria->addAssociation('deliveries');
$criteria->addAssociation('transactions');
$criteria->addAssociation('currency');
$criteria->addAssociation('language.locale');
$criteria->addSorting(new FieldSorting('createdAt', FieldSorting::DESCENDING));
$orders = $this->orderRepository->search($criteria, $context->getContext());
if ($orders->count() === 0) {
return [];
}
$products = [];
foreach ($orders as $order) {
/** @var OrderEntity $order */
$isSubscription = false;
foreach ($order->getLineItems() as $lineItem) {
$product = $lineItem->getProduct();
if ($product) {
$customFields = $product->getCustomFields();
if (isset($customFields['isBuyProductSubscription']) && $customFields['isBuyProductSubscription']) {
$isSubscription = true;
break;
}
}
}
$products[] = [
'orderId' => $order->getId(),
'deliveryStatus' => $order->getDeliveries()->last(),
'orderNumber' => $order->getOrderNumber(),
'orderDate' => $order->getOrderDateTime() ? $order->getOrderDateTime()->format('Y-m-d H:i:s') : null,
'orderStatus' => $order->getStateMachineState()?->getTranslated()['name'] ?? 'Unknown',
'order' => $order,
'isSubscription' => $isSubscription,
];
}
return $products;
}
public function getCategories(SalesChannelContext $context, ?bool $isGetProduct = true)
{
$client = RedisAdapter::createConnection($this->redisUrl);
$cache = new RedisAdapter($client);
$entryPointId = $context->getSalesChannel()->getNavigationCategoryId();
$languageId = $context->getLanguageId();
$cacheKey = $entryPointId . '-categories-' . $languageId;
$item = $cache->getItem($cacheKey);
$categories = $item->get();
if(empty($categories)){
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('active', true));
$criteria->addFilter(new EqualsFilter('parentId', $entryPointId));
$criteria->addAssociation('translations');
$categoriesQuery = $this->categoryRepository->search($criteria, $context->getContext());
$cache->deleteItem($cacheKey);
$item->set($categoriesQuery);
$cache->save($item);
$item = $cache->getItem($cacheKey);
$categories = $item->get();
}
$categorySorted = AfterSort::sort($categories->getElements(), 'afterCategoryId');
$categoryList = [];
$products = new SalesChannelProductCollection([]);
if ($isGetProduct) {
$productCriteria = new Criteria();
$productCriteria->addFilter(new EqualsAnyFilter('categories.id', $categories->getIds()));
$productCriteria->addAssociations(['categories', 'media', 'deals']);
$productCriteria->addSorting(new FieldSorting('updatedAt', FieldSorting::DESCENDING));
$productCriteria->addFilter(new NotFilter(MultiFilter::CONNECTION_AND, [
new EqualsFilter('customFields.product_hide_from_list', 'true'),
]));
$products = $this->salesChannelProductRepository->search($productCriteria, $context);
$productList = [];
$categoryProducts = $products->filter(fn(ProductEntity $product) => empty($product->getCustomFields()['productIsBuyWithCredit']) || !$product->getCustomFields()['productIsBuyWithCredit']);
foreach ($categoryProducts as $key => $product) {
$this->productService->handleProductCustomFields($product, $context);
$productList[] = $product;
}
$categoryList[] = [
'id' => 'all',
'name' => 'All',
'visible' => true,
'active' => true,
'products' => $productList,
];
}
foreach ($categorySorted as $category) {
$productList = [];
if ($isGetProduct) {
$categoryProducts = $products->filter(fn(ProductEntity $product) => in_array($category->getId(), $product->getCategoryIds()));
if (!empty($categoryProducts)) {
foreach ($categoryProducts as $key => $product) {
$productList[] = $product;
}
}
}
$categoryList[] = [
'id' => $category->getId(),
'name' => $category->getTranslation('name'),
'visible' => $category->getVisible(),
'active' => $category->getActive(),
'products' => $productList
];
}
return $categoryList;
}
public function getProductNav(SalesChannelContext $context)
{
$productCriteria = new Criteria();
$productCriteria->addAssociations(['media', 'deals']);
$productCriteria->addFilter(new NotFilter(MultiFilter::CONNECTION_AND,
[new EqualsFilter('customFields.productIsBuyWithCredit', true)]));
$productCriteria->addFilter(
new OrFilter([
new EqualsFilter('productNumber', 'EUBT124241029'),
new EqualsFilter('productNumber', 'EUBT101241029'),
new EqualsFilter('productNumber', 'EUBT119241029'),
new EqualsFilter('productNumber', 'EUBT117241029'),
new EqualsFilter('productNumber', 'EUBT108241029'),
])
);
$productList = $this->salesChannelProductRepository->search($productCriteria, $context);
$products = $productList->getEntities();
if ($products->count() < 5) {
$randomCriteria = new Criteria();
$randomCriteria->addFilter(new NotFilter(MultiFilter::CONNECTION_AND,
[new EqualsFilter('customFields.productIsBuyWithCredit', true)]));
$randomCriteria->addSorting(new FieldSorting('id', FieldSorting::DESCENDING));
$randomCriteria->setLimit(5 - $products->count());
$randomProducts = $this->salesChannelProductRepository->search($randomCriteria, $context);
foreach ($randomProducts->getEntities() as $randomProduct) {
if (!$products->has($randomProduct->getId())) {
$products->add($randomProduct);
}
}
}
return $products;
}
public function getCredits(SalesChannelContext $context)
{
$result = new \stdClass();
$customer = $context->getCustomer();
$date = (new \DateTime())->format('Y-m-d H:i:s');
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('customerId', $customer->getId()));
$criteria->addFilter(new RangeFilter('amountTotal', ['gte' => 0]));
$criteria->addFilter(new OrFilter([
new EqualsFilter('releaseAt', null),
new RangeFilter('releaseAt', ['lte' => $date]),
]));
$criteria->addSorting(new FieldSorting('createdAt', FieldSorting::DESCENDING));
$criteria->addAssociation('order.lineItems');
$credits = $this->rewardPointRepository->search($criteria, $context->getContext())->getEntities();
$earns = array();
$spend = array();
foreach ($credits as $credit) {
if ($credit->getType()->{'value'} === 'awarded') {
array_push($earns, $credit->{'amountTotal'});
}
if ($credit->getType()->{'value'} === 'spent') {
array_push($spend, $credit->{'amountTotal'});
}
$productList = [];
if ($credit->order && $credit->order->lineItems) {
foreach ($credit->order->getLineItems() as $lineItem) {
$productList[] = $lineItem->productId;
}
$products = $this->queryProductById($productList, $context);
$credit->products = $products;
}
}
$result->credits = $credits;
$result->totalEarn = array_sum($earns);
$result->totalSpent = array_sum($spend);
return $result;
}
public function getTopProducts(SalesChannelContext $context)
{
$customer = $context->getCustomer();
$productCriteria = new Criteria();
$productCriteria->setLimit(5);
// $productCriteria->addFilter(new EqualsFilter('customFields.is_top_seller', true));
$productCriteria->addFilter(new NotFilter(
MultiFilter::CONNECTION_OR,
[
new EqualsFilter('customFields.productIsBuyWithCredit', true),
new EqualsFilter('customFields.isHideOnSearch', 'true')
]
));
$productCriteria->addSorting(new FieldSorting('customFields.is_top_seller', FieldSorting::DESCENDING));
$productCriteria->addSorting(new FieldSorting('updatedAt', FieldSorting::DESCENDING));
$productCriteria->addAssociations(['deals', 'cover.media', 'customFields']);
$products = $this->salesChannelProductRepository->search($productCriteria, $context)->getEntities();
foreach ($products as $product) {
if (!empty($product->getExtension('currentDeal')->dealPrice) && !empty($product->getExtension('currentDeal')->marketPrice)) {
$dealPriceKey = array_keys($product->getExtension('currentDeal')->dealPrice->getElements())[0];
$marketPriceKey = array_keys($product->getExtension('currentDeal')->marketPrice->getElements())[0];
$market = $product->getExtension('currentDeal')->marketPrice->getElements()[$marketPriceKey];
$dealPrice = $product->getExtension('currentDeal')->dealPrice->getElements()[$dealPriceKey];
$product->addArrayExtension('stat', [
'marketPrice' => $market->getGross(),
'dealPrice' => $dealPrice->getGross(),
'discountRate' => $product->getExtension('currentDeal')->getDiscountRate() == null ? 0 : $product->getExtension('currentDeal')->getDiscountRate(),
]);
} else {
$product->addArrayExtension('stat', [
'marketPrice' => 0,
'dealPrice' => 0,
'discountRate' => 0,
]);
}
}
return $products;
}
public function getRedeemedItems(SalesChannelContext $context)
{
$orderItemCriteria = new Criteria();
$customer = $context->getCustomer();
$orderItemCriteria->addFilter(new EqualsFilter('type', 'credit-product'));
$orderItemCriteria->addAssociation('order.transactions.paymentMethod');
$orderItemCriteria->addAssociation('order.transactions.stateMachineState');
$orderItemCriteria->addAssociation('order.stateMachineState');
$orderItemCriteria->addAssociation('order.deliveries');
$orderItemCriteria->addAssociation('product.media');
$orderItemCriteria->addAssociation('product.cover');
$orderItemCriteria->addFilter(new EqualsFilter('order.orderCustomer.customerId', $customer->getId()));
$orderItems = $this->orderLineItemRepository->search($orderItemCriteria, $context->getContext())->getEntities();
$productList = [];
foreach ($orderItems as $item) {
$trackingCode = $item->getOrder()->getDeliveries()->first()->getTrackingCodes();
if ($item->payload['productId']) {
$productList[] = $item->payload['productId'];
$products = $this->queryProductById($productList, $context);
$item->product = $products;
}
$item->trackingCode = $trackingCode;
}
return $orderItems;
}
public function getCustomerTag(SalesChannelContext $context)
{
$extensionId = null;
if ($context->getCustomer()->getExtension('customerInterests') && isset(
$context->getCustomer()->getExtension('customerInterests')->all()['id']
)) {
$extensionId = $context->getCustomer()->getExtension('customerInterests')->all()['id'];
}
if (!empty($extensionId)) {
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('customerId', $extensionId));
$criteria->addAssociation('tag.media');
return $this->customerTagRepository->search($criteria, $context->getContext())->getEntities();
}
return [];
}
public function queryProductById(array $productId, SalesChannelContext $context)
{
$criteria = new Criteria($productId);
$criteria->addAssociation('media');
return $this->productRepository->search($criteria, $context->getContext())->getEntities();
}
public function customerTransactionSlipUpload(
UploadedFile $file,
CustomerEntity $customer,
string $orderId,
SalesChannelContext $context
): ?MediaEntity
{
$folderName = 'Customer Media';
$fileName = explode('.',
$file->getClientOriginalName())[0] . 'customer-' . $customer->getId() . '-order-' . $orderId . '-transaction-slip';
return $this->customerUpload($file, $folderName, $fileName, $context);
}
public function customerAvatarUpload(
UploadedFile $file,
CustomerEntity $customer,
SalesChannelContext $context
): ?MediaEntity
{
$folderName = 'Customer Media';
$fileName = 'customer-avatar-' . $customer->getId();
return $this->customerUpload($file, $folderName, $fileName, $context);
}
public function customerUpload(
UploadedFile $file,
string $folderName,
string $fileName,
SalesChannelContext $context
): ?MediaEntity
{
$sourcePath = $file->getPathname();
$sourceMime = (string) $file->getMimeType();
$sourceExt = strtolower($file->getClientOriginalExtension() ?: '');
if ($this->isHeic($sourceExt, $sourceMime)) {
$converted = $this->convertHeicToJpeg($sourcePath);
if ($converted === null) {
return null;
}
[$sourcePath, $sourceMime, $sourceExt] = $converted;
}
$mediaFile = new MediaFile(
$sourcePath,
$sourceMime,
$sourceExt,
filesize($sourcePath) ?: $file->getSize()
);
$media = $this->getMediaByFileName($fileName, $context->getContext());
$mediaId = $media?->getId();
$mediaFolderId = $media?->getMediaFolderId();
if (empty($mediaId)) {
if (empty($mediaFolderId)) {
$mediaFolder = $this->getMediaFolder(
$folderName,
$context->getContext(),
);
$mediaFolderId = $mediaFolder?->getId();
}
$mediaId = $this->createMediaInFolder(
$mediaFolderId,
$context->getContext(),
);
}
$mediaId = $this->mediaService->saveMediaFile(
$mediaFile,
$fileName,
$context->getContext(),
$folderName,
$mediaId,
);
return $this->getMedia($mediaId, $context->getContext());
}
private function isHeic(string $ext, string $mime): bool
{
if (in_array($ext, ['heic', 'heif'], true)) {
return true;
}
return false;
}
private function convertHeicToJpeg(string $sourcePath): ?array
{
if (!class_exists(\Imagick::class)) {
return null;
}
$imagick = new \Imagick();
try {
$imagick->readImage($sourcePath);
if ($imagick->getNumberImages() > 1) {
$imagick->setIteratorIndex(0);
}
$imagick->setImageFormat('jpeg');
$imagick->setImageCompression(\Imagick::COMPRESSION_JPEG);
$imagick->setImageCompressionQuality(90);
$tmpBase = tempnam(sys_get_temp_dir(), 'heic_');
$jpgPath = $tmpBase . '.jpg';
@unlink($tmpBase);
$imagick->writeImage($jpgPath);
return [$jpgPath, 'image/jpeg', 'jpg'];
} catch (\Throwable $e) {
return null;
} finally {
$imagick->clear();
$imagick->destroy();
}
}
private function getMediaDefaultFolderId(string $folder, Context $context): string
{
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('entity', $folder));
$criteria->setLimit(1);
$mediaDefaultFolder = $this->mediaDefaultFolderRepository->search($criteria, $context)->first();
if (!$mediaDefaultFolder) {
$id = Uuid::randomHex();
$this->mediaDefaultFolderRepository->create([
[
'id' => $id,
'entity' => $folder,
'associationFields' => []
]
], $context);
} else {
$id = $mediaDefaultFolder->getId();
}
return $id;
}
private function getMediaFolder(string $folder, Context $context): ?MediaFolderEntity
{
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('name', $folder));
$criteria->addFilter(new EqualsFilter('defaultFolder.entity', 'customer'));
$criteria->addAssociation('defaultFolder');
$criteria->setLimit(1);
$mediaFolder = $this->mediaFolderRepository->search($criteria, $context)->first();
if (!$mediaFolder) {
$mediaDefaultFolderId = $this->getMediaDefaultFolderId('customer', $context);
$defaultMediaFolder = $this->mediaFolderRepository->search((new Criteria())
->addFilter(new EqualsFilter('defaultFolder.entity', 'user'))
->setLimit(1), $context)->first();
$newMediaFolder = new MediaFolderEntity();
$newMediaFolder->setId(Uuid::randomHex());
$newMediaFolder->setName($folder);
$newMediaFolder->setDefaultFolderId($mediaDefaultFolderId);
$newMediaFolder->setConfigurationId($defaultMediaFolder->getConfigurationId());
$this->createMediaFolder($newMediaFolder, $context);
$mediaFolder = $this->mediaFolderRepository->search(new Criteria([$newMediaFolder->getId()]),
$context)->first();
}
return $mediaFolder;
}
private function createMediaFolder(MediaFolderEntity $mediaFolder, Context $context): void
{
$payload = [
'id' => $mediaFolder->getId(),
'configurationId' => $mediaFolder->getConfigurationId(),
'name' => $mediaFolder->getName(),
];
if ($mediaFolder->getDefaultFolderId()) {
$payload['defaultFolderId'] = $mediaFolder->getDefaultFolderId();
} else {
if ($mediaFolder->getParentId()) {
$payload['parentId'] = $mediaFolder->getParentId();
$payload['useParentConfiguration'] = true;
}
}
$this->mediaFolderRepository->create([$payload], $context);
}
public function createMediaInFolder(string $mediaFolderId, Context $context): string
{
$mediaId = Uuid::randomHex();
$this->mediaRepository->create([
[
'id' => $mediaId,
'private' => false,
'mediaFolderId' => $mediaFolderId,
]
], $context);
return $mediaId;
}
private function getMediaByFileName(string $fileName, Context $context): ?MediaEntity
{
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('fileName', $fileName));
$criteria->setLimit(1);
return $this->mediaRepository->search($criteria, $context)->first();
}
private function getMedia(string $mediaId, Context $context): ?MediaEntity
{
$criteria = new Criteria([$mediaId]);
$criteria->setLimit(1);
return $this->mediaRepository->search($criteria, $context)->first();
}
public function getCustomerInvitedCount(SalesChannelContext $context): array
{
$customer = $context->getCustomer();
$emailInvitedCount = 0;
$emailJoinedCount = 0;
if (!empty($customer) && $customer->getAffiliateCode() === $customer->getCampaignCode()) {
$currentEmailListInvited = !empty($customer->getCustomFields()['emailListInvited']) ? (is_array($customer->getCustomFields()['emailListInvited']) ? $customer->getCustomFields()['emailListInvited'] : json_decode($customer->getCustomFields()['emailListInvited'])) : [];
$emailInvitedCount = count($currentEmailListInvited);
if (!empty($currentEmailListInvited)) {
$emailList = [];
foreach ($currentEmailListInvited as $email) {
$emailList[] = $email['email'];
}
$emailJoinedCount = $this->customerRepository->search((new Criteria())->addFilter(
new EqualsAnyFilter('email', $emailList),
new EqualsFilter('campaignCode', $customer->getAffiliateCode()),
new NotFilter(MultiFilter::CONNECTION_AND, [
new EqualsFilter('id', $customer->getId()),
]),
), $context->getContext())->count();
}
return [
'invitedCount' => $emailInvitedCount,
'joinedCount' => $emailJoinedCount,
];
}
return [
'invitedCount' => $emailInvitedCount,
'joinedCount' => $emailJoinedCount,
];
}
public function getCustomerInvitedList(SalesChannelContext $context): array
{
$customer = $context->getCustomer();
if (!empty($customer) && $customer->getAffiliateCode() === $customer->getCampaignCode()) {
$currentEmailListInvited = !empty($customer->getCustomFields()['emailListInvited']) ? (is_array($customer->getCustomFields()['emailListInvited']) ? $customer->getCustomFields()['emailListInvited'] : json_decode($customer->getCustomFields()['emailListInvited'])) : [];
if (!empty($currentEmailListInvited)) {
$emailList = [];
foreach ($currentEmailListInvited as $email) {
$emailList[] = $email['email'];
}
$customers = $this->customerRepository->search((new Criteria())->addFilter(
new EqualsAnyFilter('email', $emailList),
new EqualsFilter('campaignCode', $customer->getAffiliateCode()),
new NotFilter(MultiFilter::CONNECTION_AND, [
new EqualsFilter('id', $customer->getId()),
]),
), $context->getContext());
foreach ($currentEmailListInvited as &$item) {
$item['customer'] = $customers->filter(fn(CustomerEntity $customer) => $customer->getEmail() === $item['email'])->first();
}
}
return $currentEmailListInvited;
}
return [];
}
public function getOrderById($orderId, SalesChannelContext $context)
{
$criteria = new Criteria();
$criteria->addAssociation('stateMachineState');
$criteria->addAssociation('lineItems.cover');
$criteria->addAssociation('lineItems.product.cover');
$criteria->addAssociation('deliveries');
$criteria->addAssociation('language')
->addAssociation('transactions.paymentMethod');
$criteria->addFilter(new EqualsFilter('id', $orderId));
return $this->orderRepository->search($criteria, $context->getContext())->first();
}
public function getSubscriptions(SalesChannelContext $context)
{
$customerId = $context->getCustomerId();
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('customerId', $customerId));
$criteria->addAssociation('product.cover');
$criteria->addAssociation('customer');
$criteria->addAssociation('address');
$criteria->addSorting(new FieldSorting('createdAt', FieldSorting::DESCENDING));
return $this->subscriptionRepository->search($criteria, $context->getContext())->getElements();
}
public function sumPriceSubscriptions($subscriptions)
{
$price = 0;
foreach ($subscriptions as $subscription) {
$price += $subscription->getProduct()->getPrice()->last()->getGross();
}
return $price;
}
public function getOrderCreditType($orderId, SalesChannelContext $context)
{
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('orderId', $orderId));
return $this->rewardPointRepository->search($criteria, $context->getContext())->first()?->getType();
}
}