<?php
namespace CioSponsoredOrderConfirmation\Subscriber;
use Exception;
use Shopware\Core\Checkout\Cart\Event\CheckoutOrderPlacedEvent;
use Shopware\Core\Checkout\Order\Aggregate\OrderTransaction\OrderTransactionEntity;
use Shopware\Core\Checkout\Payment\PaymentMethodEntity;
use Shopware\Core\Content\Media\Event\MediaFileExtensionWhitelistEvent;
use Shopware\Core\Content\Media\File\FileNameProvider;
use Shopware\Core\Content\Media\File\FileSaver;
use Shopware\Core\Content\Media\File\MediaFile;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\Framework\Util\Random;
use Shopware\Core\Framework\Uuid\Uuid;
use Shopware\Core\Framework\Validation\DataValidationDefinition;
use Shopware\Core\Framework\Validation\DataValidator;
use Shopware\Core\Framework\Validation\Exception\ConstraintViolationException;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Validator\Constraints\File;
use Throwable;
class CheckoutSubscriber implements EventSubscriberInterface
{
private ?Request $request;
private EntityRepositoryInterface $orderRepository;
private FileSaver $mediaUpdater;
private FileNameProvider $fileNameProvider;
private EntityRepositoryInterface $mediaRepository;
private EntityRepositoryInterface $mediaFolderRepository;
private DataValidator $dataValidator;
public function __construct(RequestStack $requestStack, EntityRepositoryInterface $orderRepository, FileSaver $mediaUpdater, FileNameProvider $fileNameProvider, EntityRepositoryInterface $mediaRepository, EntityRepositoryInterface $mediaFolderRepository, DataValidator $dataValidator)
{
$this->request = $requestStack->getCurrentRequest();
$this->orderRepository = $orderRepository;
$this->mediaUpdater = $mediaUpdater;
$this->fileNameProvider = $fileNameProvider;
$this->mediaRepository = $mediaRepository;
$this->mediaFolderRepository = $mediaFolderRepository;
$this->dataValidator = $dataValidator;
}
public static function getSubscribedEvents(): array
{
// Return the events to listen to as array like this: <event to listen to> => <method to execute>
return [
CheckoutOrderPlacedEvent::class => 'onCheckoutOrderPlacedEvent',
'framework.validation.order.create' => 'onValidateOrder',
MediaFileExtensionWhitelistEvent::class => 'onMediaFileExtensionWhitelistEvent'
];
}
public function onValidateOrder()
{
$data = $this->request->files;
foreach ($data as $file) {
/** @var UploadedFile $file */
if ($file) {
$definition = new DataValidationDefinition('sponsoringInformationsClubLogo');
$definition->add('sponsoringInformationsClubLogo', new File(null, '2m', null, [
'image/x-eps', // eps
'application/postscript', // eps, ai
'application/pdf', //ai
'image/svg+xml'
]));
$violations = $this->dataValidator->getViolations($data->all(), $definition);
if (!$violations->count()) {
return;
}
throw new ConstraintViolationException($violations, $data->all());
}
}
}
public function onMediaFileExtensionWhitelistEvent(MediaFileExtensionWhitelistEvent $event)
{
$event->setWhitelist(array_merge($event->getWhitelist(), ['ai']));
}
public function onCheckoutOrderPlacedEvent(CheckoutOrderPlacedEvent $event)
{
$customFields = [];
if ($currentCustomFields = $event->getOrder()->getCustomFields()) {
if (is_array($currentCustomFields)) {
$customFields = $currentCustomFields;
}
}
if ( $this->request &&
$event->getOrder()->getTransactions()->first() instanceof OrderTransactionEntity &&
$event->getOrder()->getTransactions()->first()->getPaymentMethod() instanceof PaymentMethodEntity &&
$event->getOrder()->getTransactions()->first()->getPaymentMethod()->getName() == 'Kostenstelle Sponsoring'
) {
$mediaIds = $this->uploadMedia($this->request);
$customFields = array_merge($customFields, [
'sponsoringBasicInformations' => [
'sponsoringInformationsPeriodFrom' => $this->request->request->get('sponsoringInformationsPeriodFrom'),
'sponsoringInformationsPeriodTo' => $this->request->request->get('sponsoringInformationsPeriodTo'),
'sponsoringInformationsStoreNumber' => $this->request->request->get('sponsoringInformationsStoreNumber'),
'sponsoringInformationsClubName' => $this->request->request->get('sponsoringInformationsClubName'),
'sponsoringInformationsClubLogo' => $mediaIds,
'sponsoringInformationsClubContactPerson' => $this->request->request->get('sponsoringInformationsClubContactPerson'),
'sponsoringInformationsClubAddress' => $this->request->request->get('sponsoringInformationsClubAddress'),
'sponsoringInformationsActionShortDescription' => $this->request->request->get('sponsoringInformationsActionShortDescription'),
'sponsoringInformationsOtherArticleInformations' => $this->request->request->get('sponsoringInformationsOtherArticleInformations'),
]
]);
}
$event->getOrder()->setCustomFields($customFields);
try {
$this->orderRepository->update([
[
'id' => $event->getOrder()->getId(),
'customFields' => $customFields
]
], $event->getContext());
} catch (Throwable $e) {
}
}
protected function uploadMedia(Request $request): array
{
$mediaIds = [];
$data = $request->files;
$context = Context::createDefaultContext();
$mediaRepository = $this->mediaRepository;
foreach ($data as $file) {
/** @var UploadedFile $file */
if ($file) {
// *.ai werden durch den mime-type als application/pdf erkannt und dann als pdf gespeichert. daher müssen wir das an einigen Stellen manuell auf ai ändern
$fileName = $file->getClientOriginalName();
$fileExtension = pathinfo($fileName, PATHINFO_EXTENSION);
$fileNameWithoutExtension = pathinfo($fileName, PATHINFO_FILENAME);
$mediaFolder = $this->mediaFolderRepository->search((new Criteria())->addFilter(new EqualsFilter('name', 'Trikot Logos')), $context)->first();
$mediaId = Uuid::randomHex();
$media = [
[
'id' => $mediaId,
'mediaFolderId' => ($mediaFolder) ? $mediaFolder->getId() : null,
'fileExtension' => ($fileExtension == 'ai') ? 'ai' : $file->getExtension(),
'mimeType' => ($fileExtension == 'ai') ? 'application/postscript' : $file->getMimeType(),
]
];
$mediaRepository->upsert($media, $context);
try {
$this->upload($file, $fileNameWithoutExtension, $mediaId, $context, ($fileExtension == 'ai') ? 'ai' : null);
} catch (Exception $exception) {
$fileNameWithoutExtension = $fileNameWithoutExtension . '_' . Random::getInteger(100, 1000) . Random::getInteger(100, 1000);
$this->upload($file, $fileNameWithoutExtension, $mediaId, $context, ($fileExtension == 'ai') ? 'ai' : null);
}
if ($fileExtension == 'ai') {
//noch mal updaten, da beim upload was anderes gespeichert wird
$this->mediaRepository->update($media, $context);
}
$mediaIds[] = $mediaId;
}
}
return $mediaIds;
}
protected function upload($file, $fileName, $mediaId, $context, $fileExtension = null)
{
$this->mediaUpdater->persistFileToMedia(
new MediaFile(
$file->getRealPath(),
$file->getMimeType(),
$fileExtension ?: $file->guessExtension(),
$file->getSize()
),
$this->fileNameProvider->provide(
$fileName,
$file->getExtension(),
$mediaId,
$context
),
$mediaId,
$context
);
}
}