<?php

namespace SystemConnector\TransferObject\Product\Variation;

use DateTimeImmutable;
use SystemConnector\TransferObject\AbstractTransferObject;
use SystemConnector\TransferObject\AttributableInterface;
use SystemConnector\TransferObject\Product\Barcode\Barcode;
use SystemConnector\TransferObject\Product\Image\Image;
use SystemConnector\TransferObject\Product\Price\Price;
use SystemConnector\TransferObject\Product\Property\Property;
use SystemConnector\ValueObject\Attribute\Attribute;

class Variation extends AbstractTransferObject implements AttributableInterface
{
    const TYPE = 'Variation';

    /**
     * Identifier of the object.
     *
     * @var string
     */
    private $identifier = '';

    /**
     * @var string
     */
    private $productIdentifier = '';

    /**
     * @var bool
     */
    private $active = false;

    /**
     * @var bool
     */
    private $isMain = false;

    /**
     * @var string
     */
    private $number = '';

    /**
     * @var string
     */
    private $name = '';

    /**
     * @var int
     */
    private $position = 0;

    /**
     * @var Barcode[]
     */
    private $barcodes = [];

    /**
     * @var string
     */
    private $model = '';

    /**
     * @var Image[]
     */
    private $images = [];

    /**
     * @var Price[]
     */
    private $prices = [];

    /**
     * @var float
     */
    private $purchasePrice = 0.0;

    /**
     * @var string
     */
    private $unitIdentifier = '';

    /**
     * @var float
     */
    private $content = 0.0;

    /**
     * @var float
     */
    private $referenceAmount = 0.0;

    /**
     * @var bool
     */
    private $stockLimitation = false;

    /**
     * @var float
     */
    private $maximumOrderQuantity;

    /**
     * @var float
     */
    private $minimumOrderQuantity = 1.0;

    /**
     * @var float
     */
    private $intervalOrderQuantity = 1.0;

    /**
     * @var int
     */
    private $shippingTime = 0;

    /**
     * @var null|DateTimeImmutable
     */
    private $releaseDate;

    /**
     * @var int
     */
    private $width = 0;

    /**
     * @var int
     */
    private $height = 0;

    /**
     * @var int
     */
    private $length = 0;

    /**
     * @var float
     */
    private $weight = 0.0;

    /**
     * @var Property[]
     */
    private $properties = [];

    /**
     * @var Attribute[]
     */
    private $attributes = [];

    /**
     * {@inheritdoc}
     */
    public function getType()
    {
        return self::TYPE;
    }

    /**
     * @return string
     */
    public function getIdentifier()
    {
        return $this->identifier;
    }

    /**
     * {@inheritdoc}
     */
    public function setIdentifier($identifier)
    {
        $this->identifier = $identifier;
    }

    /**
     * @return string
     */
    public function getProductIdentifier()
    {
        return $this->productIdentifier;
    }

    /**
     * @param string $productIdentifier
     */
    public function setProductIdentifier($productIdentifier)
    {
        $this->productIdentifier = $productIdentifier;
    }

    /**
     * @return bool
     */
    public function getActive()
    {
        return $this->active;
    }

    /**
     * @param bool $active
     */
    public function setActive($active)
    {
        $this->active = $active;
    }

    /**
     * @return bool
     */
    public function isMain()
    {
        return $this->isMain;
    }

    /**
     * @param bool $isMain
     */
    public function setIsMain($isMain)
    {
        $this->isMain = $isMain;
    }

    /**
     * @return string
     */
    public function getNumber()
    {
        return $this->number;
    }

    /**
     * @param string $number
     */
    public function setNumber($number)
    {
        $this->number = $number;
    }

    /**
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * @param string $name
     */
    public function setName($name)
    {
        $this->name = $name;
    }

    /**
     * @return int
     */
    public function getPosition()
    {
        return $this->position;
    }

    /**
     * @param int $position
     */
    public function setPosition($position)
    {
        $this->position = $position;
    }

    /**
     * @return Barcode[]
     */
    public function getBarcodes()
    {
        return $this->barcodes;
    }

    /**
     * @param Barcode[] $barcodes
     */
    public function setBarcodes(array $barcodes)
    {
        $this->barcodes = $barcodes;
    }

    /**
     * @return string
     */
    public function getModel()
    {
        return $this->model;
    }

    /**
     * @param string $model
     */
    public function setModel($model)
    {
        $this->model = $model;
    }

    /**
     * @return Image[]
     */
    public function getImages()
    {
        return $this->images;
    }

    /**
     * @param Image[] $images
     */
    public function setImages($images)
    {
        $this->images = $images;
    }

    /**
     * @return Price[]
     */
    public function getPrices()
    {
        return $this->prices;
    }

    /**
     * @param Price[] $prices
     */
    public function setPrices($prices)
    {
        $this->prices = $prices;
    }

    /**
     * @return float
     */
    public function getPurchasePrice()
    {
        return $this->purchasePrice;
    }

    /**
     * @param float $purchasePrice
     */
    public function setPurchasePrice($purchasePrice)
    {
        $this->purchasePrice = $purchasePrice;
    }

    /**
     * @return string
     */
    public function getUnitIdentifier()
    {
        return $this->unitIdentifier;
    }

    /**
     * @param string $unitIdentifier
     */
    public function setUnitIdentifier($unitIdentifier)
    {
        $this->unitIdentifier = $unitIdentifier;
    }

    /**
     * @return float
     */
    public function getContent()
    {
        return $this->content;
    }

    /**
     * @param float $content
     */
    public function setContent($content)
    {
        $this->content = $content;
    }

    /**
     * @return float
     */
    public function getReferenceAmount()
    {
        return $this->referenceAmount;
    }

    /**
     * @param float $referenceAmount
     */
    public function setReferenceAmount($referenceAmount)
    {
        $this->referenceAmount = $referenceAmount;
    }

    /**
     * @return bool
     */
    public function hasStockLimitation()
    {
        return $this->stockLimitation;
    }

    /**
     * @param bool $stockLimitation
     */
    public function setStockLimitation($stockLimitation)
    {
        $this->stockLimitation = $stockLimitation;
    }

    /**
     * @return float
     */
    public function getMaximumOrderQuantity()
    {
        return $this->maximumOrderQuantity;
    }

    /**
     * @param float $maximumOrderQuantity
     */
    public function setMaximumOrderQuantity($maximumOrderQuantity)
    {
        $this->maximumOrderQuantity = $maximumOrderQuantity;
    }

    /**
     * @return float
     */
    public function getMinimumOrderQuantity()
    {
        return $this->minimumOrderQuantity;
    }

    /**
     * @param float $minimumOrderQuantity
     */
    public function setMinimumOrderQuantity($minimumOrderQuantity)
    {
        $this->minimumOrderQuantity = $minimumOrderQuantity;
    }

    /**
     * @return float
     */
    public function getIntervalOrderQuantity()
    {
        return $this->intervalOrderQuantity;
    }

    /**
     * @param float $intervalOrderQuantity
     */
    public function setIntervalOrderQuantity($intervalOrderQuantity)
    {
        $this->intervalOrderQuantity = $intervalOrderQuantity;
    }

    /**
     * @return int
     */
    public function getShippingTime()
    {
        return $this->shippingTime;
    }

    /**
     * @param int $shippingTime
     */
    public function setShippingTime($shippingTime)
    {
        $this->shippingTime = $shippingTime;
    }

    /**
     * @return null|DateTimeImmutable
     */
    public function getReleaseDate()
    {
        return $this->releaseDate;
    }

    /**
     * @param null|DateTimeImmutable $releaseDate
     */
    public function setReleaseDate(DateTimeImmutable $releaseDate = null)
    {
        $this->releaseDate = $releaseDate;
    }

    /**
     * @return int
     */
    public function getWidth()
    {
        return $this->width;
    }

    /**
     * @param int $width
     */
    public function setWidth($width)
    {
        $this->width = $width;
    }

    /**
     * @return int
     */
    public function getHeight()
    {
        return $this->height;
    }

    /**
     * @param int $height
     */
    public function setHeight($height)
    {
        $this->height = $height;
    }

    /**
     * @return int
     */
    public function getLength()
    {
        return $this->length;
    }

    /**
     * @param int $length
     */
    public function setLength($length)
    {
        $this->length = $length;
    }

    /**
     * @return float
     */
    public function getWeight()
    {
        return $this->weight;
    }

    /**
     * @param float $weight
     */
    public function setWeight($weight)
    {
        $this->weight = $weight;
    }

    /**
     * @return Property[]
     */
    public function getProperties()
    {
        return $this->properties;
    }

    /**
     * @param Property[] $properties
     */
    public function setProperties(array $properties)
    {
        $this->properties = $properties;
    }

    /**
     * @return Attribute[]
     */
    public function getAttributes()
    {
        return $this->attributes;
    }

    /**
     * @param Attribute[] $attributes
     */
    public function setAttributes(array $attributes)
    {
        $this->attributes = $attributes;
    }

    /**
     * {@inheritdoc}
     */
    public function getClassProperties()
    {
        return [
            'identifier' => $this->getIdentifier(),
            'productIdentifier' => $this->getProductIdentifier(),
            'active' => $this->getActive(),
            'main' => $this->isMain(),
            'number' => $this->getNumber(),
            'name' => $this->getName(),
            'position' => $this->getPosition(),
            'barcodes' => $this->getBarcodes(),
            'model' => $this->getModel(),
            'images' => $this->getImages(),
            'prices' => $this->getPrices(),
            'purchasePrice' => $this->getPurchasePrice(),
            'unitIdentifier' => $this->getUnitIdentifier(),
            'content' => $this->getContent(),
            'referenceAmount' => $this->getReferenceAmount(),
            'stockLimitation' => $this->hasStockLimitation(),
            'maximumOrderQuantity' => $this->getMaximumOrderQuantity(),
            'minimumOrderQuantity' => $this->getMinimumOrderQuantity(),
            'intervalOrderQuantity' => $this->getIntervalOrderQuantity(),
            'shippingTime' => $this->getShippingTime(),
            'releaseDate' => $this->getReleaseDate(),
            'width' => $this->getWidth(),
            'height' => $this->getHeight(),
            'length' => $this->getLength(),
            'weight' => $this->getWeight(),
            'properties' => $this->getProperties(),
            'attributes' => $this->getAttributes(),
        ];
    }
}


<?php

namespace SystemConnector;

use Assert\Assertion;
use Psr\Log\LoggerInterface;
use SystemConnector\Console\OutputHandler\OutputHandlerInterface;
use SystemConnector\DefinitionProvider\DefinitionProviderInterface;
use SystemConnector\DefinitionProvider\Struct\Definition;
use SystemConnector\ServiceBus\CommandFactory\CommandFactoryInterface;
use SystemConnector\ServiceBus\CommandType;
use SystemConnector\ServiceBus\QueryFactory\QueryFactoryInterface;
use SystemConnector\ServiceBus\QueryType;
use SystemConnector\ServiceBus\ServiceBusInterface;
use SystemConnector\TransferObject\TransferObjectInterface;

class Connector implements ConnectorInterface
{
    /**
     * @var ServiceBusInterface
     */
    private $serviceBus;

    /**
     * @var QueryFactoryInterface
     */
    private $queryFactory;

    /**
     * @var CommandFactoryInterface
     */
    private $commandFactory;

    /**
     * @var OutputHandlerInterface
     */
    private $outputHandler;

    /**
     * @var DefinitionProviderInterface
     */
    private $definitionProvider;

    /**
     * @var LoggerInterface
     */
    private $logger;

    public function __construct(
        ServiceBusInterface $serviceBus,
        QueryFactoryInterface $queryFactory,
        CommandFactoryInterface $commandFactory,
        OutputHandlerInterface $outputHandler,
        DefinitionProviderInterface $definitionProvider,
        LoggerInterface $logger
    ) {
        $this->serviceBus = $serviceBus;
        $this->queryFactory = $queryFactory;
        $this->commandFactory = $commandFactory;
        $this->outputHandler = $outputHandler;
        $this->definitionProvider = $definitionProvider;
        $this->logger = $logger;
    }

    /**
     * {@inheritdoc}
     */
    public function handle($queryType, $objectType = null, $identifier = null)
    {
        Assertion::inArray($queryType, QueryType::getAllTypes());
        Assertion::nullOrString($objectType);

        if ($queryType === QueryType::ONE) {
            Assertion::notNull($identifier);
            Assertion::uuid($identifier);
        }

        $definitions = $this->definitionProvider->getConnectorDefinitions($objectType);

        if (empty($definitions)) {
            $this->logger->notice('No connectordefinition found');
        }

        array_walk($definitions, function (Definition $definition) use ($queryType, $identifier) {
            $this->handleDefinition($definition, $queryType, $identifier);
        });
    }

    /**
     * @param Definition  $definition
     * @param int         $queryType
     * @param null|string $identifier
     */
    private function handleDefinition(Definition $definition, $queryType, $identifier = null)
    {
        $this->outputHandler->writeLine(sprintf(
            'handling definition: Type: %s, %s -> %s',
            $definition->getObjectType(),
            $definition->getOriginAdapterName(),
            $definition->getDestinationAdapterName()
        ));

        /**
         * @var TransferObjectInterface[] $objects
         */
        $objects = $this->serviceBus->handle($this->queryFactory->create(
            $definition->getOriginAdapterName(),
            $definition->getObjectType(),
            $queryType,
            $identifier
        ));

        if (empty($objects)) {
            $objects = [];
        }

        foreach ($objects as $object) {
            $this->serviceBus->handle($this->commandFactory->create(
                $definition->getDestinationAdapterName(),
                $object->getType(),
                CommandType::HANDLE,
                $definition->getPriority(),
                $object
            ));
        }
    }
}


<?php

namespace SystemConnector\TransferObject\Product;

use DateTimeImmutable;
use SystemConnector\TransferObject\AbstractTransferObject;
use SystemConnector\TransferObject\AttributableInterface;
use SystemConnector\TransferObject\Product\Badge\Badge;
use SystemConnector\TransferObject\Product\Image\Image;
use SystemConnector\TransferObject\Product\LinkedProduct\LinkedProduct;
use SystemConnector\TransferObject\Product\Property\Property;
use SystemConnector\TransferObject\TranslateableInterface;
use SystemConnector\ValueObject\Attribute\Attribute;
use SystemConnector\ValueObject\Translation\Translation;

class Product extends AbstractTransferObject implements TranslateableInterface, AttributableInterface
{
    const TYPE = 'Product';
    const MULTIPACK = 'multiPack';

    /**
     * Identifier of the object.
     *
     * @var string
     */
    private $identifier = '';

    /**
     * @var string
     */
    private $name = '';

    /**
     * @var string
     */
    private $number = '';

    /**
     * @var bool
     */
    private $active = false;

    /**
     * @var array
     */
    private $shopIdentifiers = [];

    /**
     * @var string
     */
    private $manufacturerIdentifier = '';

    /**
     * @var array
     */
    private $categoryIdentifiers = [];

    /**
     * @var array
     */
    private $defaultCategoryIdentifiers = [];

    /**
     * @var array
     */
    private $shippingProfileIdentifiers = [];

    /**
     * @var Image[]
     */
    private $images = [];

    /**
     * @var string
     */
    private $vatRateIdentifier = '';

    /**
     * @var string
     */
    private $description = '';

    /**
     * @var string
     */
    private $longDescription = '';

    /**
     * @var string
     */
    private $metaTitle = '';

    /**
     * @var string
     */
    private $metaDescription = '';

    /**
     * @var string
     */
    private $metaKeywords = '';

    /**
     * @var string
     */
    private $metaRobots = 'INDEX, FOLLOW';

    /**
     * @var LinkedProduct[]
     */
    private $linkedProducts = [];

    /**
     * @var array
     */
    private $documents = [];

    /**
     * @var Property[]
     */
    private $properties = [];

    /**
     * @var Translation[]
     */
    private $translations = [];

    /**
     * @var null|DateTimeImmutable
     */
    private $availableFrom;

    /**
     * @var null|DateTimeImmutable
     */
    private $availableTo;

    /**
     * @var null|DateTimeImmutable
     */
    private $createdAt;

    /**
     * @var Attribute[]
     */
    private $attributes = [];

    /**
     * @var Property[]
     */
    private $variantConfiguration;

    /**
     * @var Badge[]
     */
    private $badges = [];

    /**
     * {@inheritdoc}
     */
    public function getType()
    {
        return self::TYPE;
    }

    /**
     * @return string
     */
    public function getIdentifier()
    {
        return $this->identifier;
    }

    /**
     * {@inheritdoc}
     */
    public function setIdentifier($identifier)
    {
        $this->identifier = $identifier;
    }

    /**
     * @return string
     */
    public function getName()
    {
        return $this->name;
    }

    /**
     * @param string $name
     */
    public function setName($name)
    {
        $this->name = $name;
    }

    /**
     * @return string
     */
    public function getNumber()
    {
        return $this->number;
    }

    /**
     * @param string $number
     */
    public function setNumber($number)
    {
        $this->number = $number;
    }

    /**
     * @return bool
     */
    public function isActive()
    {
        return $this->active;
    }

    /**
     * @param bool $active
     */
    public function setActive($active)
    {
        $this->active = $active;
    }

    /**
     * @return array
     */
    public function getShopIdentifiers()
    {
        return $this->shopIdentifiers;
    }

    /**
     * @param array $shopIdentifiers
     */
    public function setShopIdentifiers(array $shopIdentifiers)
    {
        $this->shopIdentifiers = $shopIdentifiers;
    }

    /**
     * @return string
     */
    public function getManufacturerIdentifier()
    {
        return $this->manufacturerIdentifier;
    }

    /**
     * @param string $manufacturerIdentifier
     */
    public function setManufacturerIdentifier($manufacturerIdentifier)
    {
        $this->manufacturerIdentifier = $manufacturerIdentifier;
    }

    /**
     * @return array
     */
    public function getCategoryIdentifiers()
    {
        return $this->categoryIdentifiers;
    }

    /**
     * @param array $categoryIdentifiers
     */
    public function setCategoryIdentifiers(array $categoryIdentifiers)
    {
        $this->categoryIdentifiers = $categoryIdentifiers;
    }

    /**
     * @return array
     */
    public function getDefaultCategoryIdentifiers()
    {
        return $this->defaultCategoryIdentifiers;
    }

    /**
     * @param array $defaultCategoryIdentifiers
     */
    public function setDefaultCategoryIdentifiers(array $defaultCategoryIdentifiers)
    {
        $this->defaultCategoryIdentifiers = $defaultCategoryIdentifiers;
    }

    /**
     * @return array
     */
    public function getShippingProfileIdentifiers()
    {
        return $this->shippingProfileIdentifiers;
    }

    /**
     * @param array $shippingProfileIdentifiers
     */
    public function setShippingProfileIdentifiers(array $shippingProfileIdentifiers)
    {
        $this->shippingProfileIdentifiers = $shippingProfileIdentifiers;
    }

    /**
     * @return Image[]
     */
    public function getImages()
    {
        return $this->images;
    }

    /**
     * @param Image[] $images
     */
    public function setImages($images)
    {
        $this->images = $images;
    }

    /**
     * @return string
     */
    public function getVatRateIdentifier()
    {
        return $this->vatRateIdentifier;
    }

    /**
     * @param string $vatRateIdentifier
     */
    public function setVatRateIdentifier($vatRateIdentifier)
    {
        $this->vatRateIdentifier = $vatRateIdentifier;
    }

    /**
     * @return string
     */
    public function getDescription()
    {
        return $this->description;
    }

    /**
     * @param string $description
     */
    public function setDescription($description)
    {
        $this->description = $description;
    }

    /**
     * @return string
     */
    public function getLongDescription()
    {
        return $this->longDescription;
    }

    /**
     * @param string $longDescription
     */
    public function setLongDescription($longDescription)
    {
        $this->longDescription = $longDescription;
    }

    /**
     * @return string
     */
    public function getMetaTitle()
    {
        return $this->metaTitle;
    }

    /**
     * @param string $metaTitle
     */
    public function setMetaTitle($metaTitle)
    {
        $this->metaTitle = $metaTitle;
    }

    /**
     * @return string
     */
    public function getMetaDescription()
    {
        return $this->metaDescription;
    }

    /**
     * @param string $metaDescription
     */
    public function setMetaDescription($metaDescription)
    {
        $this->metaDescription = $metaDescription;
    }

    /**
     * @return string
     */
    public function getMetaKeywords()
    {
        return $this->metaKeywords;
    }

    /**
     * @param string $metaKeywords
     */
    public function setMetaKeywords($metaKeywords)
    {
        $this->metaKeywords = $metaKeywords;
    }

    /**
     * @return string
     */
    public function getMetaRobots()
    {
        return $this->metaRobots;
    }

    /**
     * @param string $metaRobots
     */
    public function setMetaRobots($metaRobots)
    {
        $this->metaRobots = $metaRobots;
    }

    /**
     * @return LinkedProduct[]
     */
    public function getLinkedProducts()
    {
        return $this->linkedProducts;
    }

    /**
     * @param LinkedProduct[] $linkedProducts
     */
    public function setLinkedProducts(array $linkedProducts)
    {
        $this->linkedProducts = $linkedProducts;
    }

    /**
     * @return array
     */
    public function getDocuments()
    {
        return $this->documents;
    }

    /**
     * @param array $documents
     */
    public function setDocuments(array $documents)
    {
        $this->documents = $documents;
    }

    /**
     * @return Property[]
     */
    public function getProperties()
    {
        return $this->properties;
    }

    /**
     * @param Property[] $properties
     */
    public function setProperties($properties)
    {
        $this->properties = $properties;
    }

    /**
     * @return Translation[]
     */
    public function getTranslations()
    {
        return $this->translations;
    }

    /**
     * @param Translation[] $translations
     */
    public function setTranslations(array $translations)
    {
        $this->translations = $translations;
    }

    /**
     * @return null|DateTimeImmutable
     */
    public function getAvailableFrom()
    {
        return $this->availableFrom;
    }

    /**
     * @param null|DateTimeImmutable $availableFrom
     */
    public function setAvailableFrom(DateTimeImmutable $availableFrom = null)
    {
        $this->availableFrom = $availableFrom;
    }

    /**
     * @return null|DateTimeImmutable
     */
    public function getAvailableTo()
    {
        return $this->availableTo;
    }

    /**
     * @param null|DateTimeImmutable $availableTo
     */
    public function setAvailableTo(DateTimeImmutable $availableTo = null)
    {
        $this->availableTo = $availableTo;
    }

    /**
     * @return null|DateTimeImmutable
     */
    public function getCreatedAt()
    {
        return $this->createdAt;
    }

    /**
     * @param null|DateTimeImmutable $createdAt
     */
    public function setCreatedAt(DateTimeImmutable $createdAt = null)
    {
        $this->createdAt = $createdAt;
    }

    /**
     * @return Attribute[]
     */
    public function getAttributes()
    {
        return $this->attributes;
    }

    /**
     * @param Attribute[] $attributes
     */
    public function setAttributes(array $attributes)
    {
        $this->attributes = $attributes;
    }

    /**
     * @return Property[]
     */
    public function getVariantConfiguration()
    {
        return $this->variantConfiguration;
    }

    /**
     * @param Property[] $variantConfiguration
     */
    public function setVariantConfiguration(array $variantConfiguration = [])
    {
        $this->variantConfiguration = $variantConfiguration;
    }

    /**
     * @return Badge[]
     */
    public function getBadges()
    {
        return $this->badges;
    }

    /**
     * @param Badge[] $badges
     */
    public function setBadges(array $badges = [])
    {
        $this->badges = $badges;
    }

    /**
     * {@inheritdoc}
     */
    public function getClassProperties()
    {
        return [
            'identifier' => $this->getIdentifier(),
            'name' => $this->getName(),
            'active' => $this->isActive(),
            'shopIdentifiers' => $this->getShopIdentifiers(),
            'manufacturerIdentifier' => $this->getManufacturerIdentifier(),
            'categoryIdentifiers' => $this->getCategoryIdentifiers(),
            'defaultCategoryIdentifiers' => $this->getDefaultCategoryIdentifiers(),
            'shippingProfileIdentifiers' => $this->getShippingProfileIdentifiers(),
            'vatRateIdentifier' => $this->getVatRateIdentifier(),
            'description' => $this->getDescription(),
            'longDescription' => $this->getLongDescription(),
            'metaTitle' => $this->getMetaTitle(),
            'metaDescription' => $this->getMetaDescription(),
            'metaKeywords' => $this->getMetaKeywords(),
            'metaRobots' => $this->getMetaRobots(),
            'linkedProducts' => $this->getLinkedProducts(),
            'documents' => $this->getDocuments(),
            'properties' => $this->getProperties(),
            'availableFrom' => $this->getAvailableFrom(),
            'availableTo' => $this->getAvailableTo(),
            'variantConfiguration' => $this->getVariantConfiguration(),
            'badges' => $this->getBadges(),
            'translations' => $this->getTranslations(),
            'attributes' => $this->getAttributes(),
        ];
    }
}


<?php

namespace ShopwareAdapter\ServiceBus\QueryHandler\OrderStatus;

use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\Query;
use Shopware\Models\Order\Status;
use ShopwareAdapter\ResponseParser\OrderStatus\OrderStatusResponseParserInterface;
use ShopwareAdapter\ShopwareAdapter;
use SystemConnector\ServiceBus\Query\FetchTransferObjectQuery;
use SystemConnector\ServiceBus\Query\QueryInterface;
use SystemConnector\ServiceBus\QueryHandler\QueryHandlerInterface;
use SystemConnector\ServiceBus\QueryType;
use SystemConnector\TransferObject\OrderStatus\OrderStatus;

class FetchAllOrderStatusesQueryHandler implements QueryHandlerInterface
{
    /**
     * @var EntityRepository
     */
    private $repository;

    /**
     * @var OrderStatusResponseParserInterface
     */
    private $responseParser;

    public function __construct(
        EntityManagerInterface $entityManager,
        OrderStatusResponseParserInterface $responseParser
    ) {
        $this->repository = $entityManager->getRepository(Status::class);
        $this->responseParser = $responseParser;
    }

    /**
     * {@inheritdoc}
     */
    public function supports(QueryInterface $query)
    {
        return $query instanceof FetchTransferObjectQuery &&
            $query->getAdapterName() === ShopwareAdapter::NAME &&
            $query->getObjectType() === OrderStatus::TYPE &&
            $query->getQueryType() === QueryType::ALL;
    }

    /**
     * {@inheritdoc}
     */
    public function handle(QueryInterface $query)
    {
        $elements = $this->createOrderStatusQuery()->getArrayResult();

        foreach ($elements as $element) {
            $result = $this->responseParser->parse($element);

            if (null === $result) {
                continue;
            }

            yield $result;
        }
    }

    /**
     * @return Query
     */
    private function createOrderStatusQuery()
    {
        $queryBuilder = $this->repository->createQueryBuilder('status');
        $queryBuilder->select([
            'status.id as id',
            'status.name as name',
        ]);
        $queryBuilder->where('status.group = :group');
        $queryBuilder->setParameter('group', Status::GROUP_STATE);

        $objectQuery = $queryBuilder->getQuery();
        $objectQuery->execute();

        return $objectQuery;
    }
}


<?php

namespace ShopwareAdapter\ResponseParser\PaymentStatus;

use ShopwareAdapter\ShopwareAdapter;
use SystemConnector\IdentityService\IdentityServiceInterface;
use SystemConnector\TransferObject\PaymentStatus\PaymentStatus;

class PaymentStatusResponseParser implements PaymentStatusResponseParserInterface
{
    /**
     * @var IdentityServiceInterface
     */
    private $identityService;

    public function __construct(IdentityServiceInterface $identityService)
    {
        $this->identityService = $identityService;
    }

    /**
     * {@inheritdoc}
     */
    public function parse(array $entry)
    {
        $identity = $this->identityService->findOneOrCreate(
            (string) $entry['id'],
            ShopwareAdapter::NAME,
            PaymentStatus::TYPE
        );

        if (!empty($entry['name'])) {
            $name = $entry['name'];
        } else {
            $name = $entry['id'];
        }

        return PaymentStatus::fromArray([
            'identifier' => $identity->getObjectIdentifier(),
            'name' => (string) $name,
        ]);
    }
}


<?php

namespace ShopwareAdapter\DataProvider\Currency;

use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
use InvalidArgumentException;
use Shopware\Models\Shop\Currency;

class CurrencyDataProvider implements CurrencyDataProviderInterface
{
    /**
     * @var EntityManagerInterface
     */
    private $entityManager;

    public function __construct(EntityManagerInterface $entityManager)
    {
        $this->entityManager = $entityManager;
    }

    /**
     * {@inheritdoc}
     */
    public function getCurrencyIdentifierByCode($code)
    {
        /**
         * @var EntityRepository $currencyRepository
         */
        $currencyRepository = $this->entityManager->getRepository(Currency::class);

        /**
         * @var null|Currency $currencyModel
         */
        $currencyModel = $currencyRepository->findOneBy(['currency' => $code]);

        if (null === $currencyModel) {
            throw new InvalidArgumentException('invalid currency code');
        }

        return $currencyModel->getId();
    }
}


<?php

namespace PlentyConnector\Components\PayPal\Plentymarkets;

use PlentyConnector\Components\PayPal\PaymentData\PayPalUnifiedPaymentData;
use PlentymarketsAdapter\RequestGenerator\Payment\PaymentRequestGeneratorInterface;
use SystemConnector\TransferObject\Payment\Payment;

class PayPalUnifiedRequestGenerator implements PaymentRequestGeneratorInterface
{
    /**
     * @var PaymentRequestGeneratorInterface
     */
    private $parentRequestGenerator;

    public function __construct(PaymentRequestGeneratorInterface $parentRequestGenerator)
    {
        $this->parentRequestGenerator = $parentRequestGenerator;
    }

    /**
     * {@inheritdoc}
     */
    public function generate(Payment $payment)
    {
        $paymentParams = $this->parentRequestGenerator->generate($payment);
        $data = $payment->getPaymentData();

        if (!($data instanceof PayPalUnifiedPaymentData)) {
            return $paymentParams;
        }

        $paymentParams['properties'][] = [
            'typeId' => 22,
            'value' => json_encode([
                'accountHolder' => $data->getAccountHolder(),
                'bankName' => $data->getBankName(),
                'bic' => $data->getBic(),
                'iban' => $data->getIban(),
                'paymentDue' => $data->getDueDate()->format(DATE_W3C),
                'referenceNumber' => $data->getReference(),
            ]),
        ];

        return $paymentParams;
    }
}


<?php

namespace SystemConnector\CleanupService;

use Psr\Log\LoggerInterface;
use SystemConnector\CleanupService\CallbackLogHandler\CallbackLogHandler;
use SystemConnector\Console\OutputHandler\OutputHandlerInterface;
use SystemConnector\DefinitionProvider\DefinitionProviderInterface;
use SystemConnector\DefinitionProvider\Struct\Definition;
use SystemConnector\IdentityService\IdentityServiceInterface;
use SystemConnector\IdentityService\Struct\Identity;
use SystemConnector\ServiceBus\CommandFactory\CommandFactoryInterface;
use SystemConnector\ServiceBus\CommandType;
use SystemConnector\ServiceBus\QueryFactory\QueryFactoryInterface;
use SystemConnector\ServiceBus\QueryType;
use SystemConnector\ServiceBus\ServiceBusInterface;
use SystemConnector\TransferObject\TransferObjectInterface;

class CleanupService implements CleanupServiceInterface
{
    /**
     * @var ServiceBusInterface
     */
    private $serviceBus;

    /**
     * @var QueryFactoryInterface
     */
    private $queryFactory;

    /**
     * @var CommandFactoryInterface
     */
    private $commandFactory;

    /**
     * @var IdentityServiceInterface
     */
    private $identityService;

    /**
     * @var OutputHandlerInterface
     */
    private $outputHandler;

    /**
     * @var DefinitionProviderInterface
     */
    private $definitionProvider;

    /**
     * @var LoggerInterface
     */
    private $logger;

    /**
     * Array of all the found elements
     *
     * @var array
     */
    private $elements = [];

    /**
     * Will be set to true if the logger encounters an error, this will stop the cleanup process
     *
     * @var bool
     */
    private $error = false;

    public function __construct(
        ServiceBusInterface $serviceBus,
        QueryFactoryInterface $queryFactory,
        CommandFactoryInterface $commandFactory,
        IdentityServiceInterface $identityService,
        OutputHandlerInterface $outputHandler,
        DefinitionProviderInterface $definitionProvider,
        LoggerInterface $logger
    ) {
        $this->serviceBus = $serviceBus;
        $this->queryFactory = $queryFactory;
        $this->commandFactory = $commandFactory;
        $this->identityService = $identityService;
        $this->outputHandler = $outputHandler;
        $this->definitionProvider = $definitionProvider;
        $this->logger = $logger;
    }

    public function cleanup()
    {
        if (method_exists($this->logger, 'pushHandler')) {
            $this->logger->pushHandler(new CallbackLogHandler(function () {
                $this->error = true;
            }));
        }

        $definitions = $this->definitionProvider->getCleanupDefinitions();

        if (empty($definitions)) {
            $this->logger->notice('No cleanup definition found');
        }

        foreach ($definitions as $definition) {
            if ($this->hasErrors()) {
                continue;
            }

            $foundElements = $this->collectObjectIdentifiers($definition);

            if (!$foundElements) {
                $this->removeAllElements($definition);
            }
        }

        $this->removeOrphanedElements();
    }

    /**
     * @param Definition $definition
     *
     * @return bool
     */
    private function collectObjectIdentifiers(Definition $definition)
    {
        $this->outputHandler->writeLine(sprintf(
            'checking transfer objects for existence: Type: %s, %s -> %s',
            $definition->getObjectType(),
            $definition->getOriginAdapterName(),
            $definition->getDestinationAdapterName()
        ));

        /**
         * @var TransferObjectInterface[] $objects
         */
        $objects = $this->serviceBus->handle($this->queryFactory->create(
            $definition->getOriginAdapterName(),
            $definition->getObjectType(),
            QueryType::ALL
        ));

        $found = false;

        if (empty($objects)) {
            return false;
        }

        foreach ($objects as $transferObject) {
            if (false === $found) {
                $found = true;
            }

            $this->elements[] = [
                'objectIdentifier' => $transferObject->getIdentifier(),
                'adapterName' => $definition->getDestinationAdapterName(),
                'type' => $transferObject->getType(),
            ];
        }

        return !(false === $found);
    }

    /**
     * @param Definition $definition
     */
    private function removeAllElements(Definition $definition)
    {
        if ($this->hasErrors()) {
            return;
        }

        $this->outputHandler->writeLine(sprintf(
            'remove all data for definition: Type: %s, %s -> %s',
            $definition->getObjectType(),
            $definition->getOriginAdapterName(),
            $definition->getDestinationAdapterName()
        ));

        $allIdentities = $this->identityService->findBy([
            'adapterName' => $definition->getDestinationAdapterName(),
            'objectType' => $definition->getObjectType(),
        ]);

        $this->outputHandler->startProgressBar(count($allIdentities));

        array_walk($allIdentities, function (Identity $identity) use ($definition) {
            $this->serviceBus->handle($this->commandFactory->create(
                $definition->getDestinationAdapterName(),
                $definition->getObjectType(),
                CommandType::REMOVE,
                -100,
                $identity->getObjectIdentifier()
            ));

            $this->outputHandler->advanceProgressBar();
        });

        $this->outputHandler->finishProgressBar();
    }

    /**
     * @return array
     */
    private function groupElementsByAdapterAndType()
    {
        $groups = [];

        foreach ($this->elements as $element) {
            $groups[$element['adapterName'] . '_' . $element['type']][] = $element;
        }

        return $groups;
    }

    /**
     * @param array $group
     *
     * @return Identity[]
     */
    private function findOrphanedIdentitiesByGroup(array $group)
    {
        $identifiers = array_column($group, 'objectIdentifier');

        $allIdentities = $this->identityService->findBy([
            'adapterName' => $group[0]['adapterName'],
            'objectType' => $group[0]['type'],
        ]);

        return array_filter($allIdentities, function (Identity $identity) use ($identifiers) {
            return !in_array($identity->getObjectIdentifier(), $identifiers, true);
        });
    }

    private function removeOrphanedElements()
    {
        if ($this->hasErrors()) {
            return;
        }

        $groups = $this->groupElementsByAdapterAndType();

        if (empty($groups)) {
            return;
        }

        foreach ($groups as $group) {
            $orphanedIdentities = $this->findOrphanedIdentitiesByGroup($group);

            $this->outputHandler->writeLine(sprintf(
                'remove orphaned data for adapter: %s type: %s',
                $group[0]['adapterName'],
                $group[0]['type']
            ));

            $this->outputHandler->startProgressBar(count($orphanedIdentities));

            foreach ($orphanedIdentities as $identity) {
                $this->serviceBus->handle($this->commandFactory->create(
                    $group[0]['adapterName'],
                    $group[0]['type'],
                    CommandType::REMOVE,
                    -100,
                    $identity->getObjectIdentifier()
                ));

                $this->outputHandler->advanceProgressBar();
            }

            $this->outputHandler->finishProgressBar();
        }
    }

    private function hasErrors()
    {
        if (!$this->error) {
            return false;
        }

        $this->logger->error('cleanup process stopped due to an error while collecting data');

        return true;
    }
}


<?php

namespace ShopwareAdapter\RequestGenerator\Media;

use Shopware\Models\Media\Album;
use ShopwareAdapter\DataProvider\Media\MediaDataProviderInterface;
use SystemConnector\TransferObject\Media\Media;

class MediaRequestGenerator implements MediaRequestGeneratorInterface
{
    /**
     * @var MediaDataProviderInterface
     */
    private $dataProvider;

    public function __construct(MediaDataProviderInterface $dataProvider)
    {
        $this->dataProvider = $dataProvider;
    }

    /**
     * {@inheritdoc}
     */
    public function generate(Media $media)
    {
        $params = [
            'album' => Album::ALBUM_ARTICLE,
            'file' => $media->getLink(),
            'description' => $media->getAlternateName() ?: $media->getName() ?: $media->getFilename(),
        ];

        if (null !== $media->getMediaCategoryIdentifier()) {
            $params['album'] = $this->dataProvider->getAlbumIdentifierFromMediaObject($media);
        }

        return $params;
    }
}


<?php

namespace ShopwareAdapter\DataProvider\Translation;

use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
use Shopware\Models\Article\Configurator\Group;
use Shopware\Models\Article\Configurator\Option;
use Shopware\Models\Article\Image;
use Shopware\Models\Property\Option as PropertyGroupModel;
use Shopware\Models\Property\Value as PropertyValueModel;
use Shopware\Models\Shop\Shop as ShopModel;
use SystemConnector\IdentityService\Struct\Identity;
use SystemConnector\TransferObject\Product\Property\Property;
use SystemConnector\TransferObject\Product\Property\Value\Value;

class TranslationDataProvider implements TranslationDataProviderInterface
{
    /**
     * @var EntityRepository
     */
    private $shopRepository;

    /**
     * @var EntityRepository
     */
    private $propertyGroupRepository;

    /**
     * @var EntityRepository
     */
    private $propertyValueRepository;

    /**
     * @var EntityRepository
     */
    private $configurationGroupRepository;

    /**
     * @var EntityRepository
     */
    private $configurationValueRepository;

    /**
     * @var EntityRepository
     */
    private $articleImageRepository;

    public function __construct(EntityManagerInterface $entityManager)
    {
        $this->shopRepository = $entityManager->getRepository(ShopModel::class);
        $this->propertyGroupRepository = $entityManager->getRepository(PropertyGroupModel::class);
        $this->propertyValueRepository = $entityManager->getRepository(PropertyValueModel::class);
        $this->configurationValueRepository = $entityManager->getRepository(Option::class);
        $this->configurationGroupRepository = $entityManager->getRepository(Group::class);
        $this->articleImageRepository = $entityManager->getRepository(Image::class);
    }

    /**
     * {@inheritdoc}
     */
    public function getShopsByLocaleIdentitiy(Identity $identity)
    {
        return $this->shopRepository->findBy([
            'locale' => $identity->getAdapterIdentifier(),
        ]);
    }

    /**
     * {@inheritdoc}
     */
    public function getPropertyOptionByName(Property $property)
    {
        return $this->propertyGroupRepository->findOneBy([
            'name' => $property->getName(),
        ]);
    }

    /**
     * {@inheritdoc}
     */
    public function getPropertyValueByValue(Value $value)
    {
        return $this->propertyValueRepository->findOneBy([
            'value' => $value->getValue(),
        ]);
    }

    /**
     * {@inheritdoc}
     */
    public function getConfigurationGroupByName(Property $property)
    {
        return $this->configurationGroupRepository->findOneBy([
            'name' => $property->getName(),
        ]);
    }

    /**
     * {@inheritdoc}
     */
    public function getConfigurationOptionByName(Value $value)
    {
        return $this->configurationValueRepository->findOneBy([
            'name' => $value->getValue(),
        ]);
    }

    /**
     * {@inheritdoc}
     */
    public function getArticleImage(Identity $mediaIdentity, $articleId)
    {
        return $this->articleImageRepository->findOneBy([
            'articleId' => $articleId,
            'media' => $mediaIdentity->getAdapterIdentifier(),
        ]);
    }
}


<?php

namespace PlentymarketsAdapter\RequestGenerator\Order\OrderItem;

use PlentymarketsAdapter\Client\ClientInterface;
use PlentymarketsAdapter\PlentymarketsAdapter;
use RuntimeException;
use SystemConnector\ConfigService\ConfigServiceInterface;
use SystemConnector\IdentityService\Exception\NotFoundException;
use SystemConnector\IdentityService\IdentityServiceInterface;
use SystemConnector\TransferObject\Currency\Currency;
use SystemConnector\TransferObject\Order\Order;
use SystemConnector\TransferObject\Order\OrderItem\OrderItem;
use SystemConnector\TransferObject\ShippingProfile\ShippingProfile;
use SystemConnector\TransferObject\VatRate\VatRate;

class OrderItemRequestGenerator implements OrderItemRequestGeneratorInterface
{
    /**
     * @var IdentityServiceInterface
     */
    private $identityService;

    /**
     * @var ClientInterface
     */
    private $client;

    /**
     * @var ConfigServiceInterface
     */
    private $configService;

    public function __construct(
        IdentityServiceInterface $identityService,
        ClientInterface $client,
        ConfigServiceInterface $configService
    ) {
        $this->identityService = $identityService;
        $this->client = $client;
        $this->configService = $configService;
    }

    /**
     * {@inheritdoc}
     */
    public function generate(OrderItem $orderItem, Order $order)
    {
        $shippingProfileIdentity = $this->identityService->findOneBy([
            'objectIdentifier' => $order->getShippingProfileIdentifier(),
            'objectType' => ShippingProfile::TYPE,
            'adapterName' => PlentymarketsAdapter::NAME,
        ]);

        if (null === $shippingProfileIdentity) {
            throw new NotFoundException('shipping profile not mapped');
        }

        $currencyIdentity = $this->identityService->findOneBy([
            'objectIdentifier' => $order->getCurrencyIdentifier(),
            'objectType' => Currency::TYPE,
            'adapterName' => PlentymarketsAdapter::NAME,
        ]);

        if (null === $currencyIdentity) {
            throw new NotFoundException('currency profile not mapped');
        }

        $itemParams = [];

        if ($orderItem->getType() === OrderItem::TYPE_PRODUCT) {
            $typeId = 1;
        } elseif ($orderItem->getType() === OrderItem::TYPE_DISCOUNT) {
            $typeId = 4;
        } elseif ($orderItem->getType() === OrderItem::TYPE_VOUCHER) {
            $typeId = 4;
        } elseif ($orderItem->getType() === OrderItem::TYPE_COUPON) {
            $typeId = 5;
        } elseif ($orderItem->getType() === OrderItem::TYPE_PAYMENT_SURCHARGE) {
            $typeId = 7;
        } elseif ($orderItem->getType() === OrderItem::TYPE_SHIPPING_COSTS) {
            $typeId = 6;
        } else {
            throw new RuntimeException('unsupported type');
        }

        // orderItemName should contain specific coupon number, to allow futher analysis
        if ($this->isCouponItem($orderItem)) {
            $itemParams['orderItemName'] = $orderItem->getNumber();
        } else {
            $itemParams['orderItemName'] = $orderItem->getName();
        }

        $itemParams['typeId'] = $typeId;
        $itemParams['quantity'] = $orderItem->getQuantity();

        if (!empty($orderItem->getNumber())) {
            $itemParams['itemVariationId'] = $this->getVariationIdentifier($orderItem);
        }

        if ($typeId === 1 && empty($itemParams['itemVariationId'])) {
            $itemParams['typeId'] = 9; // TYPE_UNASSIGEND_VARIATION;
        }

        if (null !== $orderItem->getVatRateIdentifier()) {
            $vatRateIdentity = $this->identityService->findOneBy([
                'objectIdentifier' => $orderItem->getVatRateIdentifier(),
                'objectType' => VatRate::TYPE,
                'adapterName' => PlentymarketsAdapter::NAME,
            ]);

            if (null === $vatRateIdentity) {
                throw new NotFoundException('vatRate not mapped');
            }

            $itemParams['countryVatId'] = 1;
            $itemParams['vatField'] = $vatRateIdentity->getAdapterIdentifier();
        } else {
            $itemParams['countryVatId'] = 1;
            $itemParams['vatRate'] = 0;
        }

        $itemParams['amounts'] = [
            [
                'currency' => $currencyIdentity->getAdapterIdentifier(),
                'priceOriginalGross' => $orderItem->getPrice(),
            ],
        ];

        if (null !== $shippingProfileIdentity) {
            $itemParams['properties'] = [
                [
                    'typeId' => 2,
                    'value' => (string) $shippingProfileIdentity->getAdapterIdentifier(),
                ],
            ];
        }

        $itemParams['referrerId'] = $this->configService->get('order_origin', '0.00');

        $itemParams['orderProperties'] = [];

        return $itemParams;
    }

    /**
     * @param OrderItem $orderItem
     *
     * @return int
     */
    private function getVariationIdentifier(OrderItem $orderItem)
    {
        if ($this->configService->get('variation_number_field', 'number') === 'number') {
            return $this->getVariationIdentifierFromNumber($orderItem->getNumber());
        }

        return $this->getVariationIdentifierByIdentifier($orderItem->getNumber());
    }

    /**
     * @param string $identifier
     *
     * @return int
     */
    private function getVariationIdentifierByIdentifier($identifier)
    {
        $variations = $this->client->request('GET', 'items/variations', ['id' => $identifier]);

        if (!empty($variations)) {
            $variation = array_shift($variations);

            return $variation['id'];
        }

        return 0;
    }

    /**
     * @param string $number
     *
     * @return int
     */
    private function getVariationIdentifierFromNumber($number)
    {
        $variations = $this->client->request('GET', 'items/variations', ['numberExact' => $number]);

        if (!empty($variations)) {
            $variation = array_shift($variations);

            return $variation['id'];
        }

        return 0;
    }

    /**
     * @param OrderItem $orderItem
     *
     * @return bool
     */
    private function isCouponItem(OrderItem $orderItem)
    {
        return $orderItem->getType() === OrderItem::TYPE_VOUCHER || $orderItem->getType() === OrderItem::TYPE_COUPON;
    }
}


<?php

namespace ShopwareAdapter\ServiceBus\CommandHandler\Order;

use DateTime;
use Psr\Log\LoggerInterface;
use Shopware\Components\Api\Manager;
use Shopware\Components\Api\Resource\Order as OrderResource;
use Shopware\Models\Order\Status;
use ShopwareAdapter\DataPersister\Attribute\AttributeDataPersisterInterface;
use ShopwareAdapter\ShopwareAdapter;
use SystemConnector\IdentityService\IdentityServiceInterface;
use SystemConnector\ServiceBus\Command\CommandInterface;
use SystemConnector\ServiceBus\Command\TransferObjectCommand;
use SystemConnector\ServiceBus\CommandHandler\CommandHandlerInterface;
use SystemConnector\ServiceBus\CommandType;
use SystemConnector\TransferObject\Order\Order;
use SystemConnector\TransferObject\Order\Package\Package;
use SystemConnector\TransferObject\OrderStatus\OrderStatus;
use SystemConnector\TransferObject\PaymentStatus\PaymentStatus;
use SystemConnector\ValueObject\Attribute\Attribute;

class HandleOrderCommandHandler implements CommandHandlerInterface
{
    /**
     * @var IdentityServiceInterface
     */
    private $identityService;

    /**
     * @var LoggerInterface
     */
    private $logger;

    /**
     * @var AttributeDataPersisterInterface
     */
    private $attributePersister;

    public function __construct(
        IdentityServiceInterface $identityService,
        LoggerInterface $logger,
        AttributeDataPersisterInterface $attributePersister
    ) {
        $this->identityService = $identityService;
        $this->logger = $logger;
        $this->attributePersister = $attributePersister;
    }

    /**
     * {@inheritdoc}
     */
    public function supports(CommandInterface $command)
    {
        return $command instanceof TransferObjectCommand &&
            $command->getAdapterName() === ShopwareAdapter::NAME &&
            $command->getObjectType() === Order::TYPE &&
            $command->getCommandType() === CommandType::HANDLE;
    }

    /**
     * {@inheritdoc}
     *
     * @param TransferObjectCommand $command
     */
    public function handle(CommandInterface $command)
    {
        /**
         * @var Order $order
         */
        $order = $command->getPayload();

        $orderIdentity = $this->identityService->findOneBy([
            'objectIdentifier' => $order->getIdentifier(),
            'objectType' => Order::TYPE,
            'adapterName' => ShopwareAdapter::NAME,
        ]);

        if (null === $orderIdentity) {
            return false;
        }

        $params = [
            'details' => [],
        ];

        $package = $this->getPackage($order);

        if (null !== $package) {
            $this->addShippingProviderAttribute($order, $package);

            $params['trackingCode'] = $package->getShippingCode();
        }

        $orderStatusIdentity = $this->identityService->findOneBy([
            'objectIdentifier' => $order->getOrderStatusIdentifier(),
            'objectType' => OrderStatus::TYPE,
            'adapterName' => ShopwareAdapter::NAME,
        ]);

        if (null !== $orderStatusIdentity) {
            $params['orderStatusId'] = $orderStatusIdentity->getAdapterIdentifier();
        } else {
            $this->logger->notice('order status not mapped', ['order' => $order]);
        }

        $paymentStatusIdentity = $this->identityService->findOneBy([
            'objectIdentifier' => $order->getPaymentStatusIdentifier(),
            'objectType' => PaymentStatus::TYPE,
            'adapterName' => ShopwareAdapter::NAME,
        ]);

        if (null !== $paymentStatusIdentity) {
            $params['paymentStatusId'] = $paymentStatusIdentity->getAdapterIdentifier();

            if ((int) $paymentStatusIdentity->getAdapterIdentifier() === Status::PAYMENT_STATE_COMPLETELY_PAID) {
                $params['cleareddate'] = new DateTime('now');
            }
        } else {
            $this->logger->notice('payment status not mapped', ['order' => $order]);
        }

        $resource = $this->getOrderResource();
        $orderModel = $resource->update($orderIdentity->getAdapterIdentifier(), $params);

        $this->attributePersister->saveOrderAttributes(
            $orderModel,
            $order->getAttributes()
        );

        return true;
    }

    /**
     * @param Order $order
     *
     * @return null|Package
     */
    private function getPackage(Order $order)
    {
        $packages = $order->getPackages();

        if (empty($packages)) {
            return null;
        }

        return array_shift($packages);
    }

    /**
     * @param Order   $order
     * @param Package $package
     */
    private function addShippingProviderAttribute(Order $order, Package $package)
    {
        if (null === $package->getShippingProvider()) {
            return;
        }

        $attributes = $order->getAttributes();

        $shippingProvider = new Attribute();
        $shippingProvider->setKey('shippingProvider');
        $shippingProvider->setValue($package->getShippingProvider());

        $attributes[] = $shippingProvider;

        $order->setAttributes($attributes);
    }

    /**
     * @return OrderResource
     */
    private function getOrderResource()
    {
        // without this reset the entitymanager sometimes the status is not found correctly.
        Shopware()->Container()->reset('models');

        return Manager::getResource('Order');
    }
}


<?php

namespace PlentyConnector\Subscriber;

use Enlight\Event\SubscriberInterface;
use Enlight_Components_Cron_EventArgs as Args;
use Exception;
use PlentyConnector\PlentyConnector;
use Psr\Log\LoggerInterface;
use SystemConnector\BacklogService\BacklogServiceInterface;
use SystemConnector\CleanupService\CleanupServiceInterface;
use SystemConnector\ConnectorInterface;
use SystemConnector\ServiceBus\QueryType;
use SystemConnector\ServiceBus\ServiceBusInterface;
use Throwable;

class CronjobSubscriber implements SubscriberInterface
{
    /**
     * @var ConnectorInterface
     */
    private $connector;

    /**
     * @var CleanupServiceInterface
     */
    private $cleanupService;

    /**
     * @var BacklogServiceInterface
     */
    private $backlogService;

    /**
     * @var ServiceBusInterface
     */
    private $serviceBus;

    /**
     * @var LoggerInterface
     */
    private $logger;

    public function __construct(
        ConnectorInterface $connector,
        CleanupServiceInterface $cleanupService,
        BacklogServiceInterface $backlogService,
        ServiceBusInterface $serviceBus,
        LoggerInterface $logger
    ) {
        $this->connector = $connector;
        $this->cleanupService = $cleanupService;
        $this->backlogService = $backlogService;
        $this->serviceBus = $serviceBus;
        $this->logger = $logger;
    }

    /**
     * {@inheritdoc}
     */
    public static function getSubscribedEvents()
    {
        return [
            'Shopware_CronJob_PlentyConnector' . PlentyConnector::CRONJOB_SYNCHRONIZE => 'onRunCronjobSynchronize',
            'Shopware_CronJob_PlentyConnector' . PlentyConnector::CRONJOB_CLEANUP => 'onRunCronjobCleanup',
            'Shopware_CronJob_PlentyConnector' . PlentyConnector::CRONJOB_BACKLOG => 'onRunCronjobProcessBacklog',
        ];
    }

    /**
     * @param Args $args
     *
     * @return bool
     */
    public function onRunCronjobSynchronize(Args $args)
    {
        try {
            $this->connector->handle(QueryType::CHANGED);
        } catch (Exception $exception) {
            $this->logger->error($exception->getMessage());
        } catch (Throwable $exception) {
            $this->logger->error($exception->getMessage());
        }

        $args->setReturn(true);

        return true;
    }

    /**
     * @param Args $args
     *
     * @return bool
     */
    public function onRunCronjobProcessBacklog(Args $args)
    {
        try {
            $counter = 0;
            while ($counter < 200 && $command = $this->backlogService->dequeue()) {
                ++$counter;

                $this->serviceBus->handle($command);
            }
        } catch (Exception $exception) {
            $this->logger->error($exception->getMessage());
        } catch (Throwable $exception) {
            $this->logger->error($exception->getMessage());
        }

        $args->setReturn(true);

        return true;
    }

    /**
     * @param Args $args
     *
     * @return bool
     */
    public function onRunCronjobCleanup(Args $args)
    {
        try {
            $this->cleanupService->cleanup();
        } catch (Exception $exception) {
            $this->logger->error($exception->getMessage());
        } catch (Throwable $exception) {
            $this->logger->error($exception->getMessage());
        }

        $args->setReturn(true);

        return true;
    }
}


<?php

namespace SystemConnector\TransferObject;

use JsonSerializable;

abstract class AbstractTransferObject implements TransferObjectInterface, JsonSerializable
{
    /**
     * @param array $params
     *
     * @return $this
     */
    public static function fromArray(array $params = [])
    {
        $object = new static();

        foreach ($params as $key => $value) {
            $method = 'set' . ucfirst($key);

            if (method_exists($object, $method)) {
                $object->$method($value);
            }
        }

        return $object;
    }

    abstract public function getClassProperties();

    /**
     * {@inheritdoc}
     */
    public function jsonSerialize()
    {
        return [
            'class' => static::class,
            'properties' => $this->getClassProperties(),
        ];
    }
}


<?php

namespace PlentymarketsAdapter\Client\Exception;

use Exception;

class InvalidResponseException extends Exception
{
    /**
     * @param string $method
     * @param string $path
     * @param array  $options
     *
     * @return InvalidResponseException
     */
    public static function fromParams($method, $path, $options)
    {
        $string = 'The response was null. Method: %s, Path: %s, options: %s';
        $message = sprintf($string, $method, $path, json_encode($options)) . "\n";

        return new static($message);
    }
}


<?php

namespace PlentymarketsAdapter\Helper;

use PlentymarketsAdapter\PlentymarketsAdapter;
use Psr\Log\LoggerInterface;
use SystemConnector\ConfigService\ConfigServiceInterface;
use SystemConnector\IdentityService\IdentityServiceInterface;
use SystemConnector\TransferObject\Shop\Shop;

class VariationHelper implements VariationHelperInterface
{
    /**
     * @var IdentityServiceInterface
     */
    private $identityService;

    /**
     * @var LoggerInterface
     */
    private $logger;

    /**
     * @var ConfigServiceInterface
     */
    private $configService;

    public function __construct(
        IdentityServiceInterface $identityService,
        LoggerInterface $logger,
        ConfigServiceInterface $configService
    ) {
        $this->identityService = $identityService;
        $this->logger = $logger;
        $this->configService = $configService;
    }

    /**
     * @param array $variation
     *
     * @return array
     */
    public function getShopIdentifiers(array $variation)
    {
        $identifiers = [];

        foreach ((array) $variation['variationClients'] as $client) {
            $identity = $this->identityService->findOneBy([
                'adapterIdentifier' => $client['plentyId'],
                'adapterName' => PlentymarketsAdapter::NAME,
                'objectType' => Shop::TYPE,
            ]);

            if (null === $identity) {
                $this->logger->notice('shop not found', $client);

                continue;
            }

            $isMappedIdentity = $this->identityService->isMappedIdentity(
                $identity->getObjectIdentifier(),
                $identity->getObjectType(),
                $identity->getAdapterName()
            );

            if (!$isMappedIdentity) {
                continue;
            }

            $identifiers[] = $identity->getObjectIdentifier();
        }

        return $identifiers;
    }

    /**
     * @return array
     */
    public function getMappedPlentyClientIds()
    {
        $identities = $this->identityService->findBy([
            'adapterName' => PlentymarketsAdapter::NAME,
            'objectType' => Shop::TYPE,
        ]);

        if (empty($identities)) {
            $this->logger->notice('no plentyIds found');

            return [];
        }

        $clientIds = [];

        foreach ($identities as $identity) {
            $isMappedIdentity = $this->identityService->isMappedIdentity(
                $identity->getObjectIdentifier(),
                $identity->getObjectType(),
                $identity->getAdapterName()
            );

            if (!$isMappedIdentity) {
                continue;
            }

            $clientIds[] = $identity->getAdapterIdentifier();
        }

        return $clientIds;
    }

    /**
     * @param array $variations
     *
     * @return array
     */
    public function getMainVariation(array $variations)
    {
        $mainVariation = array_filter($variations, function ($variation) {
            return $variation['isMain'] === true;
        });

        if (empty($mainVariation)) {
            return [];
        }

        return reset($mainVariation);
    }

    /**
     * @param array $mainVariation
     * @param array $variations
     *
     * @return string
     */
    public function getMainVariationNumber(array $mainVariation, array $variations = [])
    {
        $found = false;

        $mainVariationNumber = (string) $mainVariation['id'];

        if ($this->configService->get('variation_number_field', 'number') === 'number') {
            $mainVariationNumber = (string) $mainVariation['number'];
        }

        foreach ($variations as $variation) {
            if ($variation->getNumber() === $mainVariationNumber) {
                $found = true;
                break;
            }
        }

        if ($found) {
            $checkActiveMainVariation = json_decode($this->configService->get('check_active_main_variation'));

            if (!$checkActiveMainVariation && !$mainVariation['isActive']) {
                foreach ($variations as $variation) {
                    if ($variation->getActive()) {
                        return $variation->getNumber();
                    }
                }
            }

            return $mainVariationNumber;
        }

        foreach ($variations as $variation) {
            if ($variation->getActive()) {
                return $variation->getNumber();
            }
        }

        return $mainVariationNumber;
    }
}


<?php

namespace PlentymarketsAdapter\ResponseParser\Product\Stock;

use PlentymarketsAdapter\Client\ClientInterface;
use PlentymarketsAdapter\PlentymarketsAdapter;
use SystemConnector\ConfigService\ConfigServiceInterface;
use SystemConnector\IdentityService\IdentityServiceInterface;
use SystemConnector\TransferObject\Product\Stock\Stock;
use SystemConnector\TransferObject\Product\Variation\Variation;

class StockResponseParser implements StockResponseParserInterface
{
    const SALES_WAREHOUSE = 0;

    /**
     * @var IdentityServiceInterface
     */
    private $identityService;

    /**
     * @var ConfigServiceInterface
     */
    private $configService;

    /**
     * @var ClientInterface
     */
    private $client;

    public function __construct(
        IdentityServiceInterface $identityService,
        ConfigServiceInterface $configService,
        ClientInterface $client
    ) {
        $this->identityService = $identityService;
        $this->configService = $configService;
        $this->client = $client;
    }

    /**
     * {@inheritdoc}
     */
    public function parse(array $variation)
    {
        $variationIdentity = $this->identityService->findOneBy([
            'adapterIdentifier' => (string) $variation['id'],
            'adapterName' => PlentymarketsAdapter::NAME,
            'objectType' => Variation::TYPE,
        ]);

        if (null === $variationIdentity) {
            return null;
        }

        $stockIdentity = $this->identityService->findOneOrCreate(
            (string) $variationIdentity->getAdapterIdentifier(),
            PlentymarketsAdapter::NAME,
            Stock::TYPE
        );

        $stock = new Stock();
        $stock->setIdentifier($stockIdentity->getObjectIdentifier());
        $stock->setVariationIdentifier($variationIdentity->getObjectIdentifier());
        $stock->setStock($this->getStock($variation));

        return $stock;
    }

    /**
     * @param array $variation
     *
     * @return float
     */
    private function getStock($variation)
    {
        $arrayStocks = [];
        $itemWarehouse = (int) $this->configService->get('item_warehouse', 0);

        static $warehouses;

        if (null === $warehouses) {
            $warehouses = $this->client->request('GET', 'stockmanagement/warehouses');

            $warehouses = array_filter($warehouses, function (array $warehouse) {
                return $warehouse['typeId'] === self::SALES_WAREHOUSE;
            });

            $warehouses = array_column($warehouses, 'id');
        }

        foreach ($variation['stock'] as $stock) {
            if (!in_array($stock['warehouseId'], $warehouses, true)) {
                continue;
            }

            if ($itemWarehouse !== 0 && $stock['warehouseId'] !== $itemWarehouse) {
                continue;
            }

            if ($stock['variationId'] !== $variation['id']) {
                continue;
            }

            $arrayStocks[] = $stock['netStock'];
        }

        return (float) array_sum($arrayStocks);
    }
}


<?php

namespace ShopwareAdapter\ResponseParser\Customer;

use DateTimeImmutable;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\EntityRepository;
use InvalidArgumentException;
use Psr\Log\LoggerInterface;
use Shopware\Models\Customer\Customer as CustomerModel;
use Shopware\Models\Customer\Group as GroupModel;
use Shopware\Models\Newsletter\Address;
use Shopware\Models\Shop\Repository;
use Shopware\Models\Shop\Shop as ShopModel;
use ShopwareAdapter\ShopwareAdapter;
use SystemConnector\IdentityService\IdentityServiceInterface;
use SystemConnector\TransferObject\CustomerGroup\CustomerGroup;
use SystemConnector\TransferObject\Language\Language;
use SystemConnector\TransferObject\Order\Customer\Customer;
use SystemConnector\TransferObject\Shop\Shop;

class CustomerResponseParser implements CustomerResponseParserInterface
{
    /**
     * @var IdentityServiceInterface
     */
    private $identityService;

    /**
     * @var EntityManagerInterface
     */
    private $entityManager;

    /**
     * @var LoggerInterface
     */
    private $logger;

    public function __construct(
        IdentityServiceInterface $identityService,
        EntityManagerInterface $entityManager,
        LoggerInterface $logger
    ) {
        $this->identityService = $identityService;
        $this->entityManager = $entityManager;
        $this->logger = $logger;
    }

    /**
     * {@inheritdoc}
     */
    public function parse(array $entry)
    {
        $entry['salutation'] = strtolower($entry['salutation']);

        $shopIdentifier = $this->getIdentifier((string) $entry['shopId'], Shop::TYPE);

        $languageIdentifier = $this->getLanguageIdentifier($entry);
        if (null === $languageIdentifier) {
            $this->logger->warning('no customer language found');

            return null;
        }

        $customerGroup = $this->getCustomerGroup($entry);
        if (null === $customerGroup) {
            $this->logger->warning('no customer group found');

            return null;
        }

        $customerGroupIdentifier = $this->getIdentifier((string) $customerGroup->getId(), CustomerGroup::TYPE);

        if ($entry['salutation'] === 'mr' || $entry['salutation'] === 'herr') {
            $gender = Customer::GENDER_MALE;
        } elseif ($entry['salutation'] === 'ms' || $entry['salutation'] === 'frau') {
            $gender = Customer::GENDER_FEMALE;
        } else {
            $gender = null;
        }

        if (empty($entry['birthday'])) {
            $birthday = null;
        } else {
            $birthday = DateTimeImmutable::createFromMutable($entry['birthday']);

            if (!($birthday instanceof DateTimeImmutable)) {
                $birthday = null;
            }
        }

        if (empty($entry['title'])) {
            $entry['title'] = null;
        }

        $customer = new Customer();
        $customer->setBirthday($birthday);
        $customer->setType($this->getCustomerTypeId($entry['accountMode']));
        $customer->setEmail($entry['email']);
        $customer->setFirstname($entry['firstname']);
        $customer->setLastname($entry['lastname']);
        $customer->setNumber($entry['number']);
        $customer->setGender($gender);
        $customer->setTitle($entry['title']);
        $customer->setShopIdentifier($shopIdentifier);
        $customer->setLanguageIdentifier($languageIdentifier);
        $customer->setCustomerGroupIdentifier($customerGroupIdentifier);

        /**
         * @var EntityRepository $newsletterRepository
         */
        $newsletterRepository = $this->entityManager->getRepository(Address::class);

        /**
         * @var null|Address $newsletter
         */
        $newsletter = $newsletterRepository->findOneBy(['email' => $entry['email']]);

        if ($newsletter !== null) {
            $customer->setNewsletter(true);

            if (null !== $newsletter->getAdded()) {
                $customer->setNewsletterAgreementDate(DateTimeImmutable::createFromMutable($newsletter->getAdded()));
            }
        }

        return $customer;
    }

    /**
     * @param array $entry
     *
     * @return null|GroupModel
     */
    private function getCustomerGroup(array $entry)
    {
        /**
         * @var EntityRepository $customerGroupRepository
         */
        $customerGroupRepository = $this->entityManager->getRepository(GroupModel::class);

        /**
         * @var GroupModel $customerGroup
         */
        return $customerGroupRepository->findOneBy(['key' => $entry['groupKey']]);
    }

    /**
     * @param array $entry
     *
     * @return null|string
     */
    private function getLanguageIdentifier(array $entry)
    {
        /**
         * @var Repository $shopRepository
         */
        $shopRepository = $this->entityManager->getRepository(ShopModel::class);

        /**
         * @var null|ShopModel $customerShop
         */
        $customerShop = $shopRepository->find($entry['languageId']);

        if (null === $customerShop) {
            return null;
        }

        $languageIdentifier = $this->getIdentifier((string) $customerShop->getLocale()->getId(), Language::TYPE);

        if (null === $languageIdentifier) {
            return null;
        }

        return $languageIdentifier;
    }

    /**
     * @param int $shopwareId
     *
     * @return int
     */
    private function getCustomerTypeId($shopwareId)
    {
        switch ($shopwareId) {
            case CustomerModel::ACCOUNT_MODE_CUSTOMER:
                return Customer::TYPE_NORMAL;

            case CustomerModel::ACCOUNT_MODE_FAST_LOGIN:
                return Customer::TYPE_GUEST;
        }

        throw new InvalidArgumentException('Unknown customer type ' . $shopwareId);
    }

    /**
     * @param string $entry
     * @param string $type
     *
     * @return string
     */
    private function getIdentifier($entry, $type)
    {
        return $this->identityService->findOneOrThrow(
            (string) $entry,
            ShopwareAdapter::NAME,
            $type
        )->getObjectIdentifier();
    }
}


<?php

namespace ShopwareAdapter\RequestGenerator\Product\ConfiguratorSet;

use SystemConnector\ConfigService\ConfigServiceInterface;
use SystemConnector\TransferObject\Product\Product;

class ConfiguratorSetRequestGenerator implements ConfiguratorSetRequestGeneratorInterface
{
    /**
     * @var ConfigServiceInterface
     */
    private $configService;

    public function __construct(ConfigServiceInterface $configService)
    {
        $this->configService = $configService;
    }

    /**
     * {@inheritdoc}
     */
    public function generate(Product $product)
    {
        $groups = [];
        foreach ($product->getVariantConfiguration() as $property) {
            $propertyName = $property->getName();

            $groups[$propertyName]['name'] = $propertyName;
            $groups[$propertyName]['position'] = $property->getPosition();

            foreach ($property->getValues() as $value) {
                $propertyValue = $value->getValue();

                $groups[$propertyName]['options'][$propertyValue]['name'] = $propertyValue;
                $groups[$propertyName]['options'][$propertyValue]['position'] = $value->getPosition();
            }
        }

        if (empty($groups)) {
            return [];
        }

        return [
            'name' => $product->getName(),
            'type' => (int) $this->configService->get('product_configurator_type', 0),
            'groups' => $groups,
        ];
    }
}


<?php

namespace SystemConnector\Translation;

use DeepCopy\DeepCopy;
use SystemConnector\TransferObject\TranslateableInterface;
use SystemConnector\ValueObject\Translation\Translation;

class TranslationHelper implements TranslationHelperInterface
{
    /**
     * @param TranslateableInterface $object
     *
     * @return array
     */
    public function getLanguageIdentifiers(TranslateableInterface $object)
    {
        $languages = [];

        foreach ($object->getTranslations() as $translation) {
            $languageIdentifier = $translation->getLanguageIdentifier();

            if (isset($languages[$languageIdentifier])) {
                continue;
            }

            $languages[$languageIdentifier] = $languageIdentifier;
        }

        return $languages;
    }

    /**
     * {@inheritdoc}
     */
    public function translate($languageIdentifier, TranslateableInterface $object)
    {
        $deepCopy = new DeepCopy();
        $object = $deepCopy->copy($object);

        /**
         * @var Translation[] $translations
         */
        $translations = array_filter($object->getTranslations(), function (Translation $translation) use ($languageIdentifier) {
            return $translation->getLanguageIdentifier() === $languageIdentifier;
        });

        if (empty($translations)) {
            return $object;
        }

        foreach ($translations as $translation) {
            $method = 'set' . ucfirst($translation->getProperty());

            if (method_exists($object, $method)) {
                $object->$method($translation->getValue());
            }
        }

        return $object;
    }
}


<?php

namespace PlentymarketsAdapter\ServiceBus\QueryHandler\Product;

use PlentymarketsAdapter\PlentymarketsAdapter;
use PlentymarketsAdapter\ReadApi\Item;
use PlentymarketsAdapter\ResponseParser\Product\ProductResponseParserInterface;
use SystemConnector\IdentityService\IdentityServiceInterface;
use SystemConnector\ServiceBus\Query\FetchTransferObjectQuery;
use SystemConnector\ServiceBus\Query\QueryInterface;
use SystemConnector\ServiceBus\QueryHandler\QueryHandlerInterface;
use SystemConnector\ServiceBus\QueryType;
use SystemConnector\TransferObject\Product\Product;

class FetchProductQueryHandler implements QueryHandlerInterface
{
    /**
     * @var Item
     */
    private $itemApi;

    /**
     * @var IdentityServiceInterface
     */
    private $identityService;

    /**
     * @var ProductResponseParserInterface
     */
    private $responseParser;

    public function __construct(
        Item $itemApi,
        IdentityServiceInterface $identityService,
        ProductResponseParserInterface $responseParser
    ) {
        $this->itemApi = $itemApi;
        $this->identityService = $identityService;
        $this->responseParser = $responseParser;
    }

    /**
     * {@inheritdoc}
     */
    public function supports(QueryInterface $query)
    {
        return $query instanceof FetchTransferObjectQuery &&
            $query->getAdapterName() === PlentymarketsAdapter::NAME &&
            $query->getObjectType() === Product::TYPE &&
            $query->getQueryType() === QueryType::ONE;
    }

    /**
     * {@inheritdoc}
     *
     * @param FetchTransferObjectQuery $query
     */
    public function handle(QueryInterface $query)
    {
        $identity = $this->identityService->findOneBy([
            'objectIdentifier' => $query->getObjectIdentifier(),
            'objectType' => Product::TYPE,
            'adapterName' => PlentymarketsAdapter::NAME,
        ]);

        if (null === $identity) {
            return [];
        }

        $product = $this->itemApi->findOne($identity->getAdapterIdentifier());

        $result = $this->responseParser->parse($product);

        return array_filter($result);
    }
}


<?php

namespace PlentymarketsAdapter\RequestGenerator\Order\Address;

use Exception;
use PlentymarketsAdapter\PlentymarketsAdapter;
use RuntimeException;
use SystemConnector\IdentityService\IdentityServiceInterface;
use SystemConnector\TransferObject\Country\Country;
use SystemConnector\TransferObject\Order\Address\Address;
use SystemConnector\TransferObject\Order\Order;
use VIISON\AddressSplitter\AddressSplitter;

class AddressRequestGenerator implements AddressRequestGeneratorInterface
{
    /**
     * @var IdentityServiceInterface
     */
    private $identityService;

    public function __construct(IdentityServiceInterface $identityService)
    {
        $this->identityService = $identityService;
    }

    /**
     * {@inheritdoc}
     */
    public function generate(Address $address, Order $order, $addressType = 0)
    {
        $countryIdentity = $this->identityService->findOneBy([
            'objectIdentifier' => $address->getCountryIdentifier(),
            'objectType' => Country::TYPE,
            'adapterName' => PlentymarketsAdapter::NAME,
        ]);

        if (null === $countryIdentity) {
            throw new RuntimeException('country not mapped');
        }

        try {
            $splitResult = AddressSplitter::splitAddress($address->getStreet());

            $address1 = $splitResult['streetName'];
            $address2 = $splitResult['houseNumber'];
            $address3 = trim($splitResult['additionToAddress1'] . ' ' . $splitResult['additionToAddress2']);
        } catch (Exception $exception) {
            $address1 = $address->getStreet();
            $address2 = '';
            $address3 = '';
        }

        $params = [
            'name1' => trim($address->getCompany() . ' ' . $address->getDepartment()),
            'name2' => $address->getFirstname(),
            'name3' => $address->getLastname(),
            'gender' => $address->getGender(),
            'postalCode' => $address->getPostalCode(),
            'town' => $address->getCity(),
            'countryId' => $countryIdentity->getAdapterIdentifier(),
            'typeId' => $addressType,
        ];

        if (0 === strcasecmp($address1, 'Packstation')) {
            $params = array_merge($params, [
                'isPackstation' => true,
                'address1' => 'PACKSTATION',
                'address2' => $address2,
                'options' => [
                    [
                        'typeId' => 5,
                        'value' => $order->getCustomer()->getEmail(),
                    ],
                ],
            ]);

            if (null !== $address->getAdditional()) {
                $params['options'][] = [
                    'typeId' => 6,
                    'value' => $address->getAdditional(),
                ];
            }
        } elseif (0 === strcasecmp($address1, 'Postfiliale')) {
            $params = array_merge($params, [
                'isPostfiliale' => true,
                'address1' => 'POSTFILIALE',
                'address2' => $address2,
                'options' => [
                    [
                        'typeId' => 5,
                        'value' => $order->getCustomer()->getEmail(),
                    ],
                ],
            ]);

            if (null !== $address->getAdditional()) {
                $params['options'][] = [
                    'typeId' => 6,
                    'value' => $address->getAdditional(),
                ];
            }
        } else {
            $params = array_merge($params, [
                'address1' => $address1,
                'address2' => $address2,
                'address3' => $address->getAdditional(),
                'address4' => $address3,
                'options' => [
                    [
                        'typeId' => 5,
                        'value' => $order->getCustomer()->getEmail(),
                    ],
                ],
            ]);
        }

        if (null !== $order->getCustomer()->getPhoneNumber()) {
            $params['options'][] = [
                'typeId' => 4,
                'value' => $order->getCustomer()->getPhoneNumber(),
            ];
        }

        if (null !== $address->getVatId()) {
            $params['options'][] = [
                'typeId' => 1,
                'value' => $address->getVatId(),
            ];
        }

        return $params;
    }
}


<?php

namespace ShopwareAdapter\DataProvider\Media;

use Shopware\Bundle\AttributeBundle\Service\DataLoader;
use ShopwareAdapter\ShopwareAdapter;
use SystemConnector\IdentityService\Exception\NotFoundException;
use SystemConnector\IdentityService\IdentityServiceInterface;
use SystemConnector\TransferObject\Media\Media;
use SystemConnector\TransferObject\MediaCategory\MediaCategory;

class MediaDataProvider implements MediaDataProviderInterface
{
    /**
     * @var IdentityServiceInterface
     */
    private $identityService;

    /**
     * @var DataLoader
     */
    private $dataLoader;

    public function __construct(IdentityServiceInterface $identityService, DataLoader $dataLoader)
    {
        $this->identityService = $identityService;
        $this->dataLoader = $dataLoader;
    }

    /**
     * @param Media $media
     *
     * @return string
     */
    public function getAlbumIdentifierFromMediaObject(Media $media)
    {
        $mediaCategoryIdentity = $this->identityService->findOneBy([
            'objectIdentifier' => $media->getMediaCategoryIdentifier(),
            'objectType' => MediaCategory::TYPE,
            'adapterName' => ShopwareAdapter::NAME,
        ]);

        if (null === $mediaCategoryIdentity) {
            throw new NotFoundException('missing media category for adapter');
        }

        return $mediaCategoryIdentity->getAdapterIdentifier();
    }

    /**
     * @param Media $media
     *
     * @return string
     */
    public function getMediaHashForMediaObject(Media $media)
    {
        $identity = $this->identityService->findOneBy([
            'objectIdentifier' => (string) $media->getIdentifier(),
            'objectType' => Media::TYPE,
            'adapterName' => ShopwareAdapter::NAME,
        ]);

        if (null === $identity) {
            return '';
        }

        $attributes = $this->dataLoader->load('s_media_attributes', $identity->getAdapterIdentifier());

        if (empty($attributes)) {
            return '';
        }

        foreach ($attributes as $key => $value) {
            if ($key !== 'plenty_connector_hash') {
                continue;
            }

            return $value;
        }

        return '';
    }
}


<?php

namespace ShopwareAdapter\ResponseParser\Payment;

use Assert\Assertion;
use Psr\Log\LoggerInterface;
use Shopware\Models\Order\Status;
use ShopwareAdapter\DataProvider\Currency\CurrencyDataProviderInterface;
use ShopwareAdapter\ShopwareAdapter;
use SystemConnector\IdentityService\IdentityServiceInterface;
use SystemConnector\TransferObject\Currency\Currency;
use SystemConnector\TransferObject\Order\Order;
use SystemConnector\TransferObject\Payment\Payment;
use SystemConnector\TransferObject\PaymentMethod\PaymentMethod;
use SystemConnector\TransferObject\Shop\Shop;

class PaymentResponseParser implements PaymentResponseParserInterface
{
    /**
     * @var IdentityServiceInterface
     */
    private $identityService;

    /**
     * @var CurrencyDataProviderInterface
     */
    private $currencyDataProvider;

    /**
     * @var LoggerInterface
     */
    private $logger;

    public function __construct(
        IdentityServiceInterface $identityService,
        CurrencyDataProviderInterface $currencyDataProvider,
        LoggerInterface $logger
    ) {
        $this->identityService = $identityService;
        $this->currencyDataProvider = $currencyDataProvider;
        $this->logger = $logger;
    }

    /**
     * {@inheritdoc}
     */
    public function parse(array $element)
    {
        $paymentIdentifier = $this->identityService->findOneOrCreate(
            (string) $element['id'],
            ShopwareAdapter::NAME,
            Payment::TYPE
        );

        $isMappedPaymentIdentity = $this->identityService->isMappedIdentity(
            $paymentIdentifier->getObjectIdentifier(),
            $paymentIdentifier->getObjectType(),
            $paymentIdentifier->getAdapterName()
        );

        if ($isMappedPaymentIdentity) {
            $this->logger->notice('paymentidentity' . $paymentIdentifier->getObjectIdentifier() . ' ist not mapped');

            return [];
        }

        if (empty($element['paymentStatus'])) {
            return [];
        }

        if (Status::PAYMENT_STATE_COMPLETELY_PAID !== $element['paymentStatus']['id']) {
            return [];
        }

        if (empty($element['transactionId'])) {
            $element['transactionId'] = $paymentIdentifier->getObjectIdentifier();
        }

        $shopIdentity = $this->identityService->findOneOrThrow(
            (string) $element['shopId'],
            ShopwareAdapter::NAME,
            Shop::TYPE
        );

        $isMappedShopIdentity = $this->identityService->isMappedIdentity(
            $shopIdentity->getObjectIdentifier(),
            $shopIdentity->getObjectType(),
            $shopIdentity->getAdapterName()
        );

        if (!$isMappedShopIdentity) {
            $this->logger->warning('shopidentity' . $shopIdentity->getObjectIdentifier() . ' ist not mapped');

            return [];
        }

        $shopwareCurrencyIdentifier = $this->currencyDataProvider->getCurrencyIdentifierByCode($element['currency']);
        $currencyIdentifier = $this->getConnectorIdentifier($shopwareCurrencyIdentifier, Currency::TYPE);

        $payment = new Payment();
        $payment->setIdentifier($paymentIdentifier->getObjectIdentifier());
        $payment->setShopIdentifier($shopIdentity->getObjectIdentifier());
        $payment->setOrderIdentifer($this->getConnectorIdentifier($element['id'], Order::TYPE));
        $payment->setAmount($element['invoiceAmount']);
        $payment->setAccountHolder($this->getAccountHolder($element));
        $payment->setCurrencyIdentifier($currencyIdentifier);
        $payment->setPaymentMethodIdentifier($this->getConnectorIdentifier($element['paymentId'], PaymentMethod::TYPE));
        $payment->setTransactionReference($element['transactionId']);

        return [$payment];
    }

    /**
     * @param int    $entry
     * @param string $type
     *
     * @return string
     */
    private function getConnectorIdentifier($entry, $type)
    {
        Assertion::integerish($entry);

        return $this->identityService->findOneOrThrow(
            (string) $entry,
            ShopwareAdapter::NAME,
            $type
        )->getObjectIdentifier();
    }

    /**
     * @param array $element
     *
     * @return string
     */
    private function getAccountHolder(array $element)
    {
        $firstName = !empty($element['billing']['firstName']) ? $element['billing']['firstName'] : '';
        $lastName = !empty($element['billing']['lastName']) ? $element['billing']['lastName'] : '';

        return trim(sprintf('%s %s', $firstName, $lastName));
    }
}


<?php

namespace PlentymarketsAdapter\Helper;

use PlentymarketsAdapter\ReadApi\Item\Unit as UnitApi;

class ReferenceAmountCalculator implements ReferenceAmountCalculatorInterface
{
    /**
     * @var UnitApi
     */
    private $itemUnitApi;

    /**
     * @var array
     */
    private static $units = [];

    /**
     * @var array
     */
    private static $convertionMatrix = [
        'KGM' => ['conversion' => 1], // kilogram
        'GRM' => ['conversion' => 0.001], // gram
        'MGM' => ['conversion' => 0.000001], // milligram

        'LTR' => ['conversion' => 1], // liter
        'MLT' => ['conversion' => 0.001], // millilitre

        'MTQ' => ['conversion' => 1], // cubic metre
        'CMQ' => ['conversion' => 0.0001], // cubic centimetre

        'MTK' => ['conversion' => 1], // square metre
        'CMK' => ['conversion' => 0.0001], // square centimetre

        'MTR' => ['conversion' => 1], // metre
        'CMT' => ['conversion' => 0.01], // centimetre
        'MMT' => ['conversion' => 0.001], // millimetre
    ];

    public function __construct(UnitApi $itemUnitApi)
    {
        $this->itemUnitApi = $itemUnitApi;
    }

    /**
     * @param array $variation
     *
     * @return float
     */
    public function calculate(array $variation)
    {
        if (empty(self::$units)) {
            self::$units = array_filter($this->itemUnitApi->findAll(), function (array $unit) {
                return array_key_exists($unit['unitOfMeasurement'], self::$convertionMatrix);
            });
        }

        $variationUnit = $this->getUnitOfVariation($variation);

        if (null === $variationUnit) {
            return 1.0;
        }

        $modifier = self::$convertionMatrix[$variationUnit]['conversion'];

        $content = $variation['unit']['content'] * $modifier;

        if ($content <= 0.25 && 5 !== $variation['unit']['unitId'] && 2 !== $variation['unit']['unitId']) {
            return 0.1 / $modifier;
        }

        return 1.0 / $modifier;
    }

    /**
     * @param array $variation
     *
     * @return null|string
     */
    private function getUnitOfVariation(array $variation)
    {
        foreach (self::$units as $unit) {
            if ((int) $unit['id'] === (int) $variation['unit']['unitId']) {
                return $unit['unitOfMeasurement'];
            }
        }

        return null;
    }
}


<?php

namespace ShopwareAdapter\ServiceBus\CommandHandler\Product;

use Exception;
use Psr\Log\LoggerInterface;
use Shopware\Components\Api\Manager;
use Shopware\Components\Api\Resource\Article;
use ShopwareAdapter\ShopwareAdapter;
use SystemConnector\IdentityService\IdentityServiceInterface;
use SystemConnector\IdentityService\Struct\Identity;
use SystemConnector\ServiceBus\Command\CommandInterface;
use SystemConnector\ServiceBus\Command\TransferObjectCommand;
use SystemConnector\ServiceBus\CommandHandler\CommandHandlerInterface;
use SystemConnector\ServiceBus\CommandType;
use SystemConnector\TransferObject\Product\Product;

class RemoveProductCommandHandler implements CommandHandlerInterface
{
    /**
     * @var IdentityServiceInterface
     */
    private $identityService;

    /**
     * @var LoggerInterface
     */
    private $logger;

    public function __construct(
        IdentityServiceInterface $identityService,
        LoggerInterface $logger
    ) {
        $this->identityService = $identityService;
        $this->logger = $logger;
    }

    /**
     * {@inheritdoc}
     */
    public function supports(CommandInterface $command)
    {
        return $command instanceof TransferObjectCommand &&
            $command->getAdapterName() === ShopwareAdapter::NAME &&
            $command->getObjectType() === Product::TYPE &&
            $command->getCommandType() === CommandType::REMOVE;
    }

    /**
     * {@inheritdoc}
     *
     * @param TransferObjectCommand $command
     */
    public function handle(CommandInterface $command)
    {
        $identifier = $command->getPayload();

        $identity = $this->identityService->findOneBy([
            'objectIdentifier' => (string) $identifier,
            'objectType' => Product::TYPE,
            'adapterName' => ShopwareAdapter::NAME,
        ]);

        if (null === $identity) {
            $this->logger->notice('no matching identity found', ['command' => $command]);

            return false;
        }

        try {
            $resource = $this->getArticleResource();
            $resource->delete($identity->getAdapterIdentifier());
        } catch (Exception $exception) {
            $this->logger->notice('identity removed but the object was not found', ['command' => $command]);
        }

        $identities = $this->identityService->findBy([
            'objectIdentifier' => $identifier,
        ]);

        array_walk($identities, function (Identity $identity) {
            $this->identityService->remove($identity);
        });

        return true;
    }

    /**
     * @return Article
     */
    private function getArticleResource()
    {
        Shopware()->Container()->reset('models');

        return Manager::getResource('Article');
    }
}


<?php

namespace SystemConnector\CleanupService\CallbackLogHandler;

use Closure;
use Monolog\Handler\AbstractProcessingHandler;
use Monolog\Logger;

class CallbackLogHandler extends AbstractProcessingHandler
{
    /**
     * The clousure which will be called if an error message was logged
     *
     * @var Closure
     */
    private $handler;

    /**
     * enable logging inside the closure
     *
     * @var bool
     */
    private $isProcessing = false;

    public function __construct($handler, $level = Logger::ERROR)
    {
        $this->handler = $handler;

        parent::__construct($level);
    }

    /**
     * {@inheritdoc}
     */
    protected function write(array $record)
    {
        if ($this->isProcessing) {
            return;
        }

        $this->isProcessing = true;
        call_user_func($this->handler, $record);
        $this->isProcessing = false;
    }
}