From 88c7293788abb665cab9d0f86f97de53387cc800 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9gory=20Laissus?= Date: Tue, 13 May 2025 14:46:06 +0200 Subject: [PATCH] feat: thelia 2.6 & refacto --- Api/Resource/CustomDeliverySlices.php | 133 +++++++++++++++++ Controller/BackController.php | 206 ++++++-------------------- CustomDelivery.php | 10 ++ Service/CustomDeliveryService.php | 150 +++++++++++++++++++ 4 files changed, 339 insertions(+), 160 deletions(-) create mode 100644 Api/Resource/CustomDeliverySlices.php create mode 100644 Service/CustomDeliveryService.php diff --git a/Api/Resource/CustomDeliverySlices.php b/Api/Resource/CustomDeliverySlices.php new file mode 100644 index 0000000..2ea7aec --- /dev/null +++ b/Api/Resource/CustomDeliverySlices.php @@ -0,0 +1,133 @@ + [self::GROUP_ADMIN_READ]], +)] +#[ApiResource( + operations: [ + new Get( + uriTemplate: '/front/custom-delivery/slices/{id}', + name: 'api_custom_delivery_slices_get_id_front', + provider: PropelItemProvider::class + ), + new GetCollection( + uriTemplate: '/front/custom-delivery/slices', + name: 'api_custom_delivery_slices_get_collection_front', + provider: PropelCollectionProvider::class + ), + ], + normalizationContext: ['groups' => [self::GROUP_FRONT_READ]], +)] +class CustomDeliverySlices implements PropelResourceInterface +{ + use PropelResourceTrait; + + public const GROUP_ADMIN_READ = 'admin:custom_delivery_slice:read'; + public const GROUP_FRONT_READ = 'front:custom_delivery_slice:read'; + + #[Groups([self::GROUP_ADMIN_READ, self::GROUP_FRONT_READ])] + public ?int $id = null; + + #[Groups([self::GROUP_ADMIN_READ, self::GROUP_FRONT_READ])] + public ?int $areaId = null; + + #[Groups([self::GROUP_ADMIN_READ, self::GROUP_FRONT_READ])] + public ?float $weightMax = null; + + #[Groups([self::GROUP_ADMIN_READ, self::GROUP_FRONT_READ])] + public ?float $priceMax = null; + + #[Groups([self::GROUP_ADMIN_READ, self::GROUP_FRONT_READ])] + public ?float $price = null; + + public function getId(): ?int + { + return $this->id; + } + + public function setId(?int $id): self + { + $this->id = $id; + return $this; + } + + public function getAreaId(): ?int + { + return $this->areaId; + } + + public function setAreaId(?int $areaId): self + { + $this->areaId = $areaId; + return $this; + } + + public function getWeightMax(): ?float + { + return $this->weightMax; + } + + public function setWeightMax(?float $weightMax): self + { + $this->weightMax = $weightMax; + return $this; + } + + public function getPriceMax(): ?float + { + return $this->priceMax; + } + + public function setPriceMax(?float $priceMax): self + { + $this->priceMax = $priceMax; + return $this; + } + + public function getPrice(): ?float + { + return $this->price; + } + + public function setPrice(?float $price): self + { + $this->price = $price; + return $this; + } + + /** + * @return TableMap|null + */ + #[Ignore] + public static function getPropelRelatedTableMap(): ?TableMap + { + return new CustomDeliverySliceTableMap(); + } + +} diff --git a/Controller/BackController.php b/Controller/BackController.php index fa790ae..b2ea257 100644 --- a/Controller/BackController.php +++ b/Controller/BackController.php @@ -14,219 +14,105 @@ namespace CustomDelivery\Controller; use CustomDelivery\CustomDelivery; -use CustomDelivery\Model\CustomDeliverySlice; -use CustomDelivery\Model\CustomDeliverySliceQuery; use Propel\Runtime\Map\TableMap; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Routing\Annotation\Route; use Thelia\Controller\Admin\BaseAdminController; use Thelia\Core\HttpFoundation\Request; use Thelia\Core\Security\AccessManager; use Thelia\Core\Security\Resource\AdminResources; -use Thelia\Core\Template\ParserContext; -use Thelia\Core\Translation\Translator; use Thelia\Model\ConfigQuery; use Thelia\Tools\URL; +use CustomDelivery\Service\CustomDeliveryService; + /** * Class BackController * @package CustomDelivery\Controller * @author Julien Chanséaume */ + class BackController extends BaseAdminController { - protected $currentRouter = 'router.customdelivery'; + protected CustomDeliveryService $customDeliveryService; - protected $useFallbackTemplate = true; - - /** - * Save slice - * - * @return \Symfony\Component\HttpFoundation\Response - */ - public function saveAction(Request $request) + public function __construct(CustomDeliveryService $customDeliveryService) { - $response = $this->checkAuth([], ['customdelivery'], AccessManager::UPDATE); - - if (null !== $response) { - return $response; - } + $this->customDeliveryService = $customDeliveryService; + } + #[Route('/admin/module/customdelivery/save', name: 'customdelivery.admin.update', methods: ['POST'])] + public function saveAction(Request $request): Response + { $this->checkXmlHttpRequest(); - $responseData = [ - "success" => false, - "message" => '', - "slice" => null + $data = [ + 'id' => (int) $request->get('id', 0), + 'area' => (int) $request->get('area', 0), + 'priceMax' => $request->get('priceMax', 0), + 'weightMax' => $request->get('weightMax', 0), + 'price' => $request->get('price', 0), ]; - $messages = []; - $response = null; - $config = CustomDelivery::getConfig(); - - try { - if (0 !== $id = (int)$request->get('id', 0)) { - $slice = CustomDeliverySliceQuery::create()->findPk($id); - } else { - $slice = new CustomDeliverySlice(); - } - - if (0 !== $areaId = (int)$request->get('area', 0)) { - $slice->setAreaId($areaId); - } else { - $messages[] = Translator::getInstance()->trans( - 'The area is not valid', - [], - CustomDelivery::MESSAGE_DOMAIN - ); - } - - if ($config['method'] !== CustomDelivery::METHOD_WEIGHT) { - $priceMax = $this->getFloatVal($request->get('priceMax', 0)); - if (0 < $priceMax) { - $slice->setPriceMax($priceMax); - } else { - $messages[] = Translator::getInstance()->trans( - 'The price max value is not valid', - [], - CustomDelivery::MESSAGE_DOMAIN - ); - } - } - - if ($config['method'] !== CustomDelivery::METHOD_PRICE) { - $weightMax = $this->getFloatVal($request->get('weightMax', 0)); - if (0 < $weightMax) { - $slice->setWeightMax($weightMax); - } else { - $messages[] = Translator::getInstance()->trans( - 'The weight max value is not valid', - [], - CustomDelivery::MESSAGE_DOMAIN - ); - } - } - - $price = $this->getFloatVal($request->get('price', 0)); - if (0 <= $price) { - $slice->setPrice($price); - } else { - $messages[] = Translator::getInstance()->trans( - 'The price value is not valid', - [], - CustomDelivery::MESSAGE_DOMAIN - ); - } - - if (0 === count($messages)) { - $slice->save(); - $messages[] = Translator::getInstance()->trans( - 'Your slice has been saved', - [], - CustomDelivery::MESSAGE_DOMAIN - ); - - $responseData['success'] = true; - $responseData['slice'] = $slice->toArray(TableMap::TYPE_STUDLYPHPNAME); - } - } catch (\Exception $e) { - $message[] = $e->getMessage(); - } + $result = $this->customDeliveryService->saveSlice( + $data + ); - $responseData['message'] = $messages; + $responseData = [ + 'success' => $result['success'], + 'message' => $result['messages'], + 'slice' => $result['slice'] ? $result['slice']->toArray(TableMap::TYPE_STUDLYPHPNAME) : null, + ]; return $this->jsonResponse(json_encode($responseData)); } - protected function getFloatVal($val, $default=-1) + #[Route('/admin/module/customdelivery/delete', name: 'customdelivery.admin.delete', methods: ['POST'])] + public function deleteAction(Request $request): Response { - if (preg_match("#^([\d.,]+)$#", $val, $match)) { - return (float) str_replace(array('.', ','), array('', '.'), $match[0]); + $authResponse = $this->checkAuth([], ['customdelivery'], AccessManager::DELETE); + if ($authResponse !== null) { + return $authResponse; } - return $default; - } - - /** - * Save slice - * - * @return Response - */ - public function deleteAction(Request $request) - { - $response = $this->checkAuth([], ['customdelivery'], AccessManager::DELETE); + $this->checkXmlHttpRequest(); - if (null !== $response) { - return $response; - } + $id = (int) $request->get('id', 0); - $this->checkXmlHttpRequest(); + $result = $this->customDeliveryService->deleteSlice($id); $responseData = [ - "success" => false, - "message" => '', - "slice" => null + 'success' => $result['success'], + 'message' => $result['messages'], + 'slice' => null, ]; - $response = null; - - try { - if (0 !== $id = (int)$request->get('id', 0)) { - $slice = CustomDeliverySliceQuery::create()->findPk($id); - $slice->delete(); - $responseData['success'] = true; - } else { - $responseData['message'] = Translator::getInstance()->trans( - 'The slice has not been deleted', - [], - CustomDelivery::MESSAGE_DOMAIN - ); - } - } catch (\Exception $e) { - $responseData['message'] = $e->getMessage(); - } - return $this->jsonResponse(json_encode($responseData)); } - /** - * Save module configuration - * - * @param ParserContext $parserContext - * @return \Symfony\Component\HttpFoundation\Response - */ - public function saveConfigurationAction() + #[Route('/admin/module/customdelivery/configuration', name: 'customdelivery.admin.configuration', methods: ['POST'])] + public function saveConfigurationAction(): Response { - $response = $this->checkAuth([AdminResources::MODULE], ['customdelivery'], AccessManager::UPDATE); - - if (null !== $response) { - return $response; + $authResponse = $this->checkAuth([AdminResources::MODULE], ['customdelivery'], AccessManager::UPDATE); + if ($authResponse !== null) { + return $authResponse; } $form = $this->createForm('customdelivery.configuration.form'); $message = ""; - $response = null; - try { $vform = $this->validateForm($form); $data = $vform->getData(); - ConfigQuery::write( - CustomDelivery::CONFIG_TRACKING_URL, - $data['url'] - ); - ConfigQuery::write( - CustomDelivery::CONFIG_PICKING_METHOD, - $data['method'] - ); - ConfigQuery::write( - CustomDelivery::CONFIG_TAX_RULE_ID, - $data['tax'] - ); + ConfigQuery::write(CustomDelivery::CONFIG_TRACKING_URL, $data['url']); + ConfigQuery::write(CustomDelivery::CONFIG_PICKING_METHOD, $data['method']); + ConfigQuery::write(CustomDelivery::CONFIG_TAX_RULE_ID, $data['tax']); } catch (\Exception $e) { $message = $e->getMessage(); } - if ($message) { + + if ($message !== "") { $form->setErrorMessage($message); $this->getParserContext() ->addForm($form) diff --git a/CustomDelivery.php b/CustomDelivery.php index 5f6ca1e..35a8b66 100755 --- a/CustomDelivery.php +++ b/CustomDelivery.php @@ -36,6 +36,8 @@ use Thelia\Module\Exception\DeliveryException; use Thelia\TaxEngine\Calculator; use Thelia\Tools\I18n; +use Symfony\Component\DependencyInjection\Loader\Configurator\ServicesConfigurator; + class CustomDelivery extends AbstractDeliveryModuleWithState { @@ -285,4 +287,12 @@ protected function getAreaPostage(CustomDeliverySlice $slice, Currency $currency return $this->buildOrderPostage($untaxedPostage, $country, $locale, $config['tax']); } + + public static function configureServices(ServicesConfigurator $servicesConfigurator): void + { + $servicesConfigurator->load(self::getModuleCode().'\\', __DIR__) + ->exclude(["/I18n/*"]) + ->autowire(true) + ->autoconfigure(true); + } } diff --git a/Service/CustomDeliveryService.php b/Service/CustomDeliveryService.php new file mode 100644 index 0000000..9cec31b --- /dev/null +++ b/Service/CustomDeliveryService.php @@ -0,0 +1,150 @@ + bool, 'messages' => array, 'slice' => ?CustomDeliverySlice ] + */ + public function saveSlice(array $data): array + { + $messages = []; + $config = CustomDelivery::getConfig(); + + $id = (int) ($data['id'] ?? 0); + $slice = CustomDeliverySliceQuery::create()->findPk($id) ?? new CustomDeliverySlice(); + + // Validation areaId + $areaId = (int) ($data['area'] ?? 0); + if ($areaId <= 0) { + $messages[] = Translator::getInstance()->trans( + 'The area is not valid', + [], + CustomDelivery::MESSAGE_DOMAIN + ); + } else { + $slice->setAreaId($areaId); + } + + // Validation priceMax si méthode différente de poids + if ($config['method'] !== CustomDelivery::METHOD_WEIGHT) { + $priceMax = $this->toFloat($data['priceMax'] ?? 0); + if ($priceMax <= 0) { + $messages[] = Translator::getInstance()->trans( + 'The price max value is not valid', + [], + CustomDelivery::MESSAGE_DOMAIN + ); + } else { + $slice->setPriceMax($priceMax); + } + } + + // Validation weightMax si méthode différente de prix + if ($config['method'] !== CustomDelivery::METHOD_PRICE) { + $weightMax = $this->toFloat($data['weightMax'] ?? 0); + if ($weightMax <= 0) { + $messages[] = Translator::getInstance()->trans( + 'The weight max value is not valid', + [], + CustomDelivery::MESSAGE_DOMAIN + ); + } else { + $slice->setWeightMax($weightMax); + } + } + + // Validation price (>= 0) + $price = $this->toFloat($data['price'] ?? 0); + if ($price < 0) { + $messages[] = Translator::getInstance()->trans( + 'The price value is not valid', + [], + CustomDelivery::MESSAGE_DOMAIN + ); + } else { + $slice->setPrice($price); + } + + $success = empty($messages); + + if ($success) { + $slice->save(); + $messages[] = Translator::getInstance()->trans( + 'Your slice has been saved', + [], + CustomDelivery::MESSAGE_DOMAIN + ); + } + + return [ + 'success' => $success, + 'messages' => $messages, + 'slice' => $success ? $slice : null, + ]; + } + + /** + * Supprime un slice par son ID. + * + * @param int $id + * @return array ['success' => bool, 'messages' => array] + */ + public function deleteSlice(int $id): array + { + $messages = []; + + if ($id <= 0) { + $messages[] = Translator::getInstance()->trans( + 'The slice has not been deleted', + [], + CustomDelivery::MESSAGE_DOMAIN + ); + + return ['success' => false, 'messages' => $messages]; + } + + $slice = CustomDeliverySliceQuery::create()->findPk($id); + + if (null === $slice) { + $messages[] = Translator::getInstance()->trans( + 'The slice was not found', + [], + CustomDelivery::MESSAGE_DOMAIN + ); + + return ['success' => false, 'messages' => $messages]; + } + + $slice->delete(); + + return ['success' => true, 'messages' => $messages]; + } + + /** + * Transforme une valeur en float en gérant le format européen. + */ + protected function toFloat($val, float $default = -1): float + { + if (is_string($val) && preg_match('#^([\d.,]+)$#', $val, $matches)) { + // Ex : "1.234,56" ou "1234,56" -> "1234.56" + $number = str_replace(['.', ','], ['', '.'], $matches[1]); + return (float) $number; + } + + if (is_numeric($val)) { + return (float) $val; + } + + return $default; + } +}