Untitled

 avatar
unknown
plain_text
17 days ago
12 kB
3
Indexable
<?php

declare(strict_types=1);

namespace App\Import\Traits;

use App\Import\ArticleIterator;
use App\Import\ReducCe\ArticleDto;
use Doctrine\Common\Persistence\ManagerRegistry;
use JMS\Serializer\Naming\IdenticalPropertyNamingStrategy;
use JMS\Serializer\Naming\SerializedNameAnnotationStrategy;
use JMS\Serializer\SerializerBuilder;
use Puwnz\GoogleMapsLib\Geocode\DTO\GeocodeResult;

trait ArticleTrait
{
    use GeocodeTrait;

    private ?\Generator $articles = null;

    public function next(): void
    {
        $this->articles->next();
    }

    public function valid(): bool
    {
        return $this->articles->valid();
    }

    public function rewind(): void
    {
        if ($this->key() === 0) {
            $this->articles->rewind();
        }
    }

    public function key()
    {
        return $this->articles->key();
    }

    public function init(string $path): void
    {
        if ($this->articles !== null) {
            return;
        }

        $fileContents = str_replace('#cdata-section', 'cdata_section', $this->filesystem->read($path));

        $fileContents = json_decode($fileContents, true, 512, \JSON_THROW_ON_ERROR);

        $this->articles = $this->crawlArticles($fileContents);
    }

    private function crawlArticles(array $fileContents): \Generator
    {
        foreach ($fileContents['catalogues'] as $catalogue) {
            $currentCatalogue = $this->translateCode($catalogue['catalogues_id']);
            if (!$this->isCollection($catalogue['genres']['genre'])) {
                $catalogue['genres']['genre'] = [$catalogue['genres']['genre']];
            }
            foreach ($catalogue['genres']['genre'] as $genre) {
                if (isset($genre['sousgenres']['sousgenre'])) {
                    if (!$this->isCollection($genre['sousgenres']['sousgenre'])) {
                        $genre['sousgenres']['sousgenre'] = [$genre['sousgenres']['sousgenre']];
                    }
                    $currentGenre = $this->translateCode($genre['genres_id']);
                    foreach ($genre['sousgenres']['sousgenre'] as $sousgenre) {
                        if (isset($sousgenre['sousgenres_prix_dynamiques']) && $sousgenre['sousgenres_prix_dynamiques'] === true) {
                            continue;
                        }

                        $currentSousgenre = $this->translateCode($sousgenre['sousgenres_id']);
                        if (isset($sousgenre['articles'])) {
                            $articles = $sousgenre['articles'];
                            if (!$this->isCollection($articles)) {
                                $articles = [$articles];
                            }
                            foreach ($articles as $article) {
                                foreach ($article['article'] as $article1) {
                                    try {
                                        if (!is_array($article1['articles_tarifs'])) {
                                            $article1['articles_tarifs'] = [];
                                        }
                                        if (!is_array($article1['articles_lieux'])) {
                                            $article1['articles_lieux'] = [];
                                        }

                                        $article1['articles_puttc'] = number_format((float)strtr((string)$article1['articles_puttc'], ',', '.'), 2, '.', '');
                                        $article1['articles_puht'] = number_format((float)strtr((string)$article1['articles_puht'], ',', '.'), 2, '.', '');
                                        $article1['articles_prix_public'] = number_format((float)strtr((string)$article1['articles_prix_public'], ',', '.'), 2, '.', '');
                                        $article1['articles_tva'] = number_format((float)strtr((string)$article1['articles_tva'], ',', '.'), 2, '.', '');
                                        $article1['articles_descriptif'] = $article1['articles_descriptif']['cdata_section'];
                                        $article1['currentCatalogue'] = $currentCatalogue;
                                        $article1['currentGenre'] = $currentGenre;
                                        $article1['currentSousgenre'] = $currentSousgenre;
                                        $article1['articles_actif'] = $this->isActive($sousgenre, $article1);
                                        $article1['lieux_latitude'] = $sousgenre['lieux_latitude'];
                                        $article1['lieux_longitude'] = $sousgenre['lieux_longitude'];
                                        $article1['articles_date_fin'] = $article1['articles_date_fin'] ?: null;
                                        $article1['articles_date_debut'] = $article1['articles_date_debut'] ?: null;

                                        yield self::serialize($article1, ArticleDto::class);
                                    } catch (\Throwable $e) {
                                        $this->logger->emergency('Article error', [
                                            'article' => $article1,
                                            'error' => $e->getMessage(),
                                        ]);

                                        throw $e;
                                    }
                                }
                            }
                        }

                    }
                }
            }
        }
    }

    private function isActive(array $sousGenre, array $article): bool
    {
        if ($sousGenre['sousgenres_actif'] !== 'True') {
            return false;
        }

        if ($article['articles_actif'] !== 'True') {
            return false;
        }

        if ((int)($article['articles_multiple_cmd'] ?? 1) !== 1) {
            return false;
        }

        if ($article['articles_type'] === 'ETICKET' && $this->availableToSale($article) === false) {
            return false;
        }

        return true;
    }

    private function translateCode(string $code): string
    {
        return str_replace('-', '_', $code);
    }

    private function isCollection($array): bool
    {
        return is_array($array) && array_key_exists(0, $array);
    }

    private function availableToSale(array $article): bool
    {
        if ($article['articles_type'] === 'RETRAIT_MAGASIN') {
            return false;
        }

        if ($article['articles_invisibleweb'] === 'True') {
            return false;
        }

        if (in_array($article['articles_statut_manif'], [ArticleIterator::STATUS_ON_SALE, ArticleIterator::STATUS_REPORTED], true) === false) {
            return false;
        }

        if (in_array($article['articles_sousgenre'], ArticleIterator::CATEGORIES_VALABLES, true) === false) {
            return false;
        }

        return true;
    }

    private function formatGeo($number)
    {
        if (is_numeric($number)) {
            return $number * 10000000;
        }
    }

    public static function serialize(array $body, string $class)
    {
        $serializer = SerializerBuilder::create()
            ->setPropertyNamingStrategy(
                new SerializedNameAnnotationStrategy(
                    new IdenticalPropertyNamingStrategy()
                )
            )
            ->setCacheDir('./var/cache/jms')
            ->setDebug(true)
            ->build();
        //todo mettre le cache sur redis
        return $serializer->deserialize(json_encode($body), $class, 'json');
    }

    protected function getAddress(array $product, ArticleDto $article, ?ManagerRegistry $managerRegistry = null): array
    {
        $article = $this->mapAddress($article);
        $geo = null;

        if (null !== $article->getArticlesLieux()) {
            $address = [
                'address_name' => $article->getArticlesLieuNom(),
                'address_1' => $article->getArticlesLieuAdresse1(),
                'address_2' => $article->getArticlesLieuAdresse2(),
                'address_zip_code' => $article->getArticlesLieuCodePostal(),
                'address_city' => $article->getArticlesLieuVille(),
                'address_district' => $article->getArticlesLieuRegion(),
                'address_country' => $article->getArticlesLieuPays(),
            ];

            $geo = $this->getGeocodeResult($address);
        }

        if ($geo === null && $article->getLieuxLatitude() && $article->getLieuxLongitude()) {
            $geo = $this->reverseGeocode($article->getLieuxLatitude(), $article->getLieuxLongitude());

            if ($geo) {
                $product['latitude'] = $geo->getGeometry()->getLocation()->getLatitude();
                $product['longitude'] = $geo->getGeometry()->getLocation()->getLongitude();
                $product['address_name'] = $geo->getFormattedAddress();
                $product['address_1'] = sprintf('%s %s', $this->getAddressComponent('street_number', $geo), $this->getAddressComponent('route', $geo));
                $product['address_zip_code'] = $this->getAddressComponent('postal_code', $geo);
                $product['address_city'] = $this->getAddressComponent('locality', $geo);
                $product['address_country'] = trim($this->getAddressComponent('country', $geo) ?? 'France');
                $product['address_district'] = trim($this->getAddressComponent('administrative_area_level_1', $geo) ?? 'France');
                $geo = null;
            }
        }

        if ($geo !== null) {
            $product['latitude'] = $geo->getGeometry()->getLocation()->getLatitude();
            $product['longitude'] = $geo->getGeometry()->getLocation()->getLongitude();
            $product['address_name'] = $address['address_name'];
            if ($managerRegistry !== null) {
                $product['address'] = $this->getOrCreateAddress($geo, $managerRegistry);
            }
        }

        return $product;
    }

    private function mapAddress(ArticleDto $article): ArticleDto
    {
        if (null !== $article->getArticlesLieux()) {
            $localisations = $article->getArticlesLieux()['articles_lieu'];
            if (null !== $localisations['articles_lieu_adresse1']) {
                $article->setArticlesLieuNom($localisations['articles_lieu_nom']);
                $article->setArticlesLieuAdresse1($localisations['articles_lieu_adresse1']);
                $article->setArticlesLieuAdresse2($localisations['articles_lieu_adresse2']);
                $article->setArticlesLieuCodePostal($localisations['articles_lieu_code_postal']);
                $article->setArticlesLieuVille($localisations['articles_lieu_ville']);
                $article->setArticlesLieuRegion($localisations['articles_lieu_region']);
                $article->setArticlesLieuPays($localisations['articles_lieu_pays']);
                $article->setLieuxLatitude((float)$localisations['articles_lieu_latitude'] ?: null);
                $article->setLieuxLongitude((float)$localisations['articles_lieu_longitude'] ?: null);
            }
        }

        return $article;
    }

    private function getGeocodeResult(array $addressArticle): ?GeocodeResult
    {
        if (null === $addressArticle['address_1']) {
            return null;
        }
        $address = sprintf('%s %s %s %s %s', $addressArticle['address_1'], $addressArticle['address_2'], $addressArticle['address_zip_code'], $addressArticle['address_city'], $addressArticle['address_country']);

        /** @var GeocodeResult[] $geocode */
        $geocode = $this->googleService->geocode($address);

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

        $geo = current($geocode);

        return $geo ?? null;
    }

    private function reverseGeocode(float $lat, float $lng): ?GeocodeResult
    {
        $geocode = $this->googleService->reverseGeocode($lat, $lng);

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

        $geo = current($geocode);

        return $geo ?? null;
    }

    private function getPriceCent($price): float
    {
        return (float)$price;
    }

    private function getRemisePart($public, $ttc): float
    {
        if (0 == $public || 0 == $ttc || 0 == ($public - $ttc)) {
            return 0;
        }

        return (($public - $ttc) / $public) * 100;
    }

    private function getPrice($price): float
    {
        return (float)str_replace(',', '.', (string)$price);
    }
}
Editor is loading...
Leave a Comment