inklabs/kommerce-core

View on GitHub
src/Lib/Mapper.php

Summary

Maintainability
D
2 days
Test Coverage
<?php
namespace inklabs\kommerce\Lib;

use inklabs\kommerce\EntityDTO\Builder\DTOBuilderFactoryInterface;
use inklabs\kommerce\EntityRepository\AttachmentRepositoryInterface;
use inklabs\kommerce\EntityRepository\AttributeRepositoryInterface;
use inklabs\kommerce\EntityRepository\AttributeValueRepositoryInterface;
use inklabs\kommerce\EntityRepository\CartPriceRuleDiscountRepositoryInterface;
use inklabs\kommerce\EntityRepository\CartPriceRuleItemRepositoryInterface;
use inklabs\kommerce\EntityRepository\CartPriceRuleRepositoryInterface;
use inklabs\kommerce\EntityRepository\CartRepositoryInterface;
use inklabs\kommerce\EntityRepository\CatalogPromotionRepositoryInterface;
use inklabs\kommerce\EntityRepository\ConfigurationRepositoryInterface;
use inklabs\kommerce\EntityRepository\CouponRepositoryInterface;
use inklabs\kommerce\EntityRepository\ImageRepositoryInterface;
use inklabs\kommerce\EntityRepository\InventoryLocationRepositoryInterface;
use inklabs\kommerce\EntityRepository\InventoryTransactionRepositoryInterface;
use inklabs\kommerce\EntityRepository\OptionProductRepositoryInterface;
use inklabs\kommerce\EntityRepository\OptionRepositoryInterface;
use inklabs\kommerce\EntityRepository\OptionValueRepositoryInterface;
use inklabs\kommerce\EntityRepository\OrderItemRepositoryInterface;
use inklabs\kommerce\EntityRepository\OrderRepositoryInterface;
use inklabs\kommerce\EntityRepository\ProductAttributeRepositoryInterface;
use inklabs\kommerce\EntityRepository\ProductQuantityDiscountRepositoryInterface;
use inklabs\kommerce\EntityRepository\ProductRepositoryInterface;
use inklabs\kommerce\EntityRepository\RepositoryFactory;
use inklabs\kommerce\EntityRepository\ShipmentTrackerRepositoryInterface;
use inklabs\kommerce\EntityRepository\TagRepositoryInterface;
use inklabs\kommerce\EntityRepository\TaxRateRepositoryInterface;
use inklabs\kommerce\EntityRepository\TextOptionRepositoryInterface;
use inklabs\kommerce\EntityRepository\UserRepositoryInterface;
use inklabs\kommerce\EntityRepository\UserTokenRepositoryInterface;
use inklabs\kommerce\EntityRepository\WarehouseRepositoryInterface;
use inklabs\kommerce\Lib\Command\CommandHandlerInterface;
use inklabs\kommerce\Lib\Command\CommandInterface;
use inklabs\kommerce\Lib\Query\QueryHandlerInterface;
use inklabs\kommerce\Lib\Query\QueryInterface;
use inklabs\kommerce\Lib\ShipmentGateway\ShipmentGatewayInterface;
use inklabs\kommerce\Service\AttachmentServiceInterface;
use inklabs\kommerce\Service\CartServiceInterface;
use inklabs\kommerce\Service\ImageServiceInterface;
use inklabs\kommerce\Service\Import\ImportOrderItemServiceInterface;
use inklabs\kommerce\Service\Import\ImportOrderServiceInterface;
use inklabs\kommerce\Service\Import\ImportPaymentServiceInterface;
use inklabs\kommerce\Service\Import\ImportUserServiceInterface;
use inklabs\kommerce\Service\InventoryServiceInterface;
use inklabs\kommerce\Service\OrderServiceInterface;
use inklabs\kommerce\Service\ServiceFactory;
use inklabs\kommerce\Service\UserServiceInterface;
use ReflectionClass;

class Mapper implements MapperInterface
{
    /** @var RepositoryFactory */
    private $repositoryFactory;

    /** @var ServiceFactory */
    private $serviceFactory;

    /** @var Pricing */
    private $pricing;

    /** @var DTOBuilderFactoryInterface */
    private $dtoBuilderFactory;

    public function __construct(
        RepositoryFactory $repositoryFactory,
        ServiceFactory $serviceFactory,
        Pricing $pricing,
        DTOBuilderFactoryInterface $dtoBuilderFactory
    ) {
        $this->repositoryFactory = $repositoryFactory;
        $this->serviceFactory = $serviceFactory;
        $this->pricing = $pricing;
        $this->dtoBuilderFactory = $dtoBuilderFactory;
    }

    public function getCommandHandler(CommandInterface $command): CommandHandlerInterface
    {
        $handlerClassName = $this->getCommandHandlerClassName($command);
        return $this->getHandler($handlerClassName, $command);
    }

    public function getQueryHandler(QueryInterface $query): QueryHandlerInterface
    {
        $handlerClassName = $this->getQueryHandlerClassName($query);
        return $this->getHandler($handlerClassName, $query);
    }

    /**
     * @param string $handlerClassName
     * @param ActionInterface
     * @return null|object|CommandHandlerInterface|QueryHandlerInterface
     */
    public function getHandler(string $handlerClassName, ActionInterface $action)
    {
        $reflection = new ReflectionClass($handlerClassName);

        $constructorParameters = [];
        $constructor = $reflection->getConstructor();
        if ($constructor !== null) {
            foreach ($constructor->getParameters() as $key => $parameter) {
                if ($key === 0 && $action instanceof ActionInterface) {
                    $constructorParameters[] = $action;
                    continue;
                }

                $parameterClassName = $parameter->getClass()->getName();
                if ($parameterClassName === AttachmentRepositoryInterface::class) {
                    $constructorParameters[] = $this->repositoryFactory->getAttachmentRepository();
                } elseif ($parameterClassName === AttributeRepositoryInterface::class) {
                    $constructorParameters[] = $this->repositoryFactory->getAttributeRepository();
                } elseif ($parameterClassName === AttributeValueRepositoryInterface::class) {
                    $constructorParameters[] = $this->repositoryFactory->getAttributeValueRepository();
                } elseif ($parameterClassName === CartRepositoryInterface::class) {
                    $constructorParameters[] = $this->repositoryFactory->getCartRepository();
                } elseif ($parameterClassName === CartPriceRuleRepositoryInterface::class) {
                    $constructorParameters[] = $this->repositoryFactory->getCartPriceRuleRepository();
                } elseif ($parameterClassName === CartPriceRuleItemRepositoryInterface::class) {
                    $constructorParameters[] = $this->repositoryFactory->getCartPriceRuleItemRepository();
                } elseif ($parameterClassName === CartPriceRuleDiscountRepositoryInterface::class) {
                    $constructorParameters[] = $this->repositoryFactory->getCartPriceRuleDiscountRepository();
                } elseif ($parameterClassName === CatalogPromotionRepositoryInterface::class) {
                    $constructorParameters[] = $this->repositoryFactory->getCatalogPromotionRepository();
                } elseif ($parameterClassName === ConfigurationRepositoryInterface::class) {
                    $constructorParameters[] = $this->repositoryFactory->getConfigurationRepository();
                } elseif ($parameterClassName === CouponRepositoryInterface::class) {
                    $constructorParameters[] = $this->repositoryFactory->getCouponRepository();
                } elseif ($parameterClassName === ImageRepositoryInterface::class) {
                    $constructorParameters[] = $this->repositoryFactory->getImageRepository();
                } elseif ($parameterClassName === InventoryLocationRepositoryInterface::class) {
                    $constructorParameters[] = $this->repositoryFactory->getInventoryLocationRepository();
                } elseif ($parameterClassName === InventoryTransactionRepositoryInterface::class) {
                    $constructorParameters[] = $this->repositoryFactory->getInventoryTransactionRepository();
                } elseif ($parameterClassName === OptionRepositoryInterface::class) {
                    $constructorParameters[] = $this->repositoryFactory->getOptionRepository();
                } elseif ($parameterClassName === OptionProductRepositoryInterface::class) {
                    $constructorParameters[] = $this->repositoryFactory->getOptionProductRepository();
                } elseif ($parameterClassName === OptionValueRepositoryInterface::class) {
                    $constructorParameters[] = $this->repositoryFactory->getOptionValueRepository();
                } elseif ($parameterClassName === OrderRepositoryInterface::class) {
                    $constructorParameters[] = $this->repositoryFactory->getOrderRepository();
                } elseif ($parameterClassName === OrderItemRepositoryInterface::class) {
                    $constructorParameters[] = $this->repositoryFactory->getOrderItemRepository();
                } elseif ($parameterClassName === ProductRepositoryInterface::class) {
                    $constructorParameters[] = $this->repositoryFactory->getProductRepository();
                } elseif ($parameterClassName === ProductQuantityDiscountRepositoryInterface::class) {
                    $constructorParameters[] = $this->repositoryFactory->getProductQuantityDiscountRepository();
                } elseif ($parameterClassName === ProductAttributeRepositoryInterface::class) {
                    $constructorParameters[] = $this->repositoryFactory->getProductAttributeRepository();
                } elseif ($parameterClassName === ShipmentTrackerRepositoryInterface::class) {
                    $constructorParameters[] = $this->repositoryFactory->getShipmentTrackerRepository();
                } elseif ($parameterClassName === TagRepositoryInterface::class) {
                    $constructorParameters[] = $this->repositoryFactory->getTagRepository();
                } elseif ($parameterClassName === TextOptionRepositoryInterface::class) {
                    $constructorParameters[] = $this->repositoryFactory->getTextOptionRepository();
                } elseif ($parameterClassName === TaxRateRepositoryInterface::class) {
                    $constructorParameters[] = $this->repositoryFactory->getTaxRateRepository();
                } elseif ($parameterClassName === UserRepositoryInterface::class) {
                    $constructorParameters[] = $this->repositoryFactory->getUserRepository();
                } elseif ($parameterClassName === UserTokenRepositoryInterface::class) {
                    $constructorParameters[] = $this->repositoryFactory->getUserTokenRepository();
                } elseif ($parameterClassName === WarehouseRepositoryInterface::class) {
                    $constructorParameters[] = $this->repositoryFactory->getWarehouseRepository();
                } elseif ($parameterClassName === AttachmentServiceInterface::class) {
                    $constructorParameters[] = $this->serviceFactory->getAttachmentService();
                } elseif ($parameterClassName === CartCalculatorInterface::class
                    || $parameterClassName === CartCalculator::class) {
                    $constructorParameters[] = $this->serviceFactory->getCartCalculator();
                } elseif ($parameterClassName === CartServiceInterface::class) {
                    $constructorParameters[] = $this->serviceFactory->getCart();
                } elseif ($parameterClassName === DTOBuilderFactoryInterface::class) {
                    $constructorParameters[] = $this->dtoBuilderFactory;
                } elseif ($parameterClassName === ImportUserServiceInterface::class) {
                    $constructorParameters[] = $this->serviceFactory->getImportUser();
                } elseif ($parameterClassName === ImportOrderServiceInterface::class) {
                    $constructorParameters[] = $this->serviceFactory->getImportOrder();
                } elseif ($parameterClassName === ImportOrderItemServiceInterface::class) {
                    $constructorParameters[] = $this->serviceFactory->getImportOrderItem();
                } elseif ($parameterClassName === ImportPaymentServiceInterface::class) {
                    $constructorParameters[] = $this->serviceFactory->getImportPayment();
                } elseif ($parameterClassName === InventoryServiceInterface::class) {
                    $constructorParameters[] = $this->serviceFactory->getInventoryService();
                } elseif ($parameterClassName === ImageServiceInterface::class) {
                    $constructorParameters[] = $this->serviceFactory->getImageService();
                } elseif ($parameterClassName === OrderServiceInterface::class) {
                    $constructorParameters[] = $this->serviceFactory->getOrder();
                } elseif ($parameterClassName === ShipmentGatewayInterface::class) {
                    $constructorParameters[] = $this->serviceFactory->getShipmentGateway();
                } elseif ($parameterClassName === UserServiceInterface::class) {
                    $constructorParameters[] = $this->serviceFactory->getUser();
                } elseif ($parameterClassName === PricingInterface::class || $parameterClassName === Pricing::class) {
                    $constructorParameters[] = $this->pricing;
                }
            }
        }

        $handler = null;

        if (! empty($constructorParameters)) {
            $handler = $reflection->newInstanceArgs($constructorParameters);
        } else {
            $handler = $reflection->newInstance();
        }

        return $handler;
    }

    private function getCommandHandlerClassName(CommandInterface $command): string
    {
        $className = get_class($command);
        $className = str_replace('\\Action\\', '\\ActionHandler\\', $className);
        $pieces = explode('\\', $className);

        $baseName = array_pop($pieces);
        $handlerBaseName = substr($baseName, 0, -7) . 'Handler';

        $pieces[] = $handlerBaseName;

        return implode('\\', $pieces);
    }

    private function getQueryHandlerClassName(QueryInterface $query): string
    {
        $className = get_class($query);
        $className = str_replace('\\Action\\', '\\ActionHandler\\', $className);
        $pieces = explode('\\', $className);

        $baseName = array_pop($pieces);
        $handlerBaseName = substr($baseName, 0, -5) . 'Handler';

        $pieces[] = $handlerBaseName;

        return implode('\\', $pieces);
    }
}