Covivo/mobicoop

View on GitHub
api/src/DataProvider/Entity/CarpoolProofGouvProvider.php

Summary

Maintainability
B
6 hrs
Test Coverage
<?php

/**
 * Copyright (c) 2020, MOBICOOP. All rights reserved.
 * This project is dual licensed under AGPL and proprietary licence.
 ***************************
 *    This program is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU Affero General Public License as
 *    published by the Free Software Foundation, either version 3 of the
 *    License, or (at your option) any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU Affero General Public License for more details.
 *
 *    You should have received a copy of the GNU Affero General Public License
 *    along with this program.  If not, see <gnu.org/licenses>.
 ***************************
 *    Licence MOBICOOP described in the file
 *    LICENSE
 */

namespace App\DataProvider\Entity;

use App\Carpool\Entity\CarpoolProof;
use App\Carpool\Entity\Criteria;
use App\DataProvider\Interfaces\ProviderInterface;
use App\DataProvider\Service\DataProvider;
use App\DataProvider\Service\RPCv3\Tools;
use Psr\Log\LoggerInterface;

/**
 * Beta gouv carpool proof management service.
 *
 * @author Sylvain Briat <sylvain.briat@mobicoop.org>
 */
class CarpoolProofGouvProvider implements ProviderInterface
{
    public const RESSOURCE_POST = 'v2/journeys';
    public const ISO8601 = 'Y-m-d\TH:i:s\Z';
    public const RESSOURCE_GET_ITEM = 'v2/journeys/';

    /**
     * @var Tools
     */
    protected $_tools;

    protected $uri;
    protected $token;
    protected $prefix;
    protected $logger;
    protected $testMode;

    public function __construct(Tools $tools, string $uri, string $token, ?string $prefix = null, LoggerInterface $logger, bool $testMode = false)
    {
        $this->_tools = $tools;

        $this->uri = $uri;
        $this->token = $token;
        $this->prefix = $prefix;
        $this->logger = $logger;
        $this->testMode = $testMode;
    }

    /**
     * Send a carpool proof.
     *
     * @param CarpoolProof $carpoolProof The carpool proof to send
     *
     * @return Response The result of the send
     */
    public function postCollection(CarpoolProof $carpoolProof, string $resource = self::RESSOURCE_POST)
    {
        if (is_null($carpoolProof->getAsk())) {
            return new Response(418);
        }

        // creation of the dataProvider
        $dataProvider = new DataProvider($this->uri, $resource);

        // creation of the headers
        $headers = [
            'Authorization' => 'Bearer '.$this->token,
            'Content-Type' => 'application/json',
        ];

        $journey = $this->serializeProof($carpoolProof);

        if (!is_null($journey)) {
            $this->logger->info('Send Proof #'.$carpoolProof->getId());
            $this->logger->info(json_encode($journey));

            if ($this->testMode) {
                return new Response(200, '');
            }

            return $dataProvider->postCollection($journey, $headers);
        }

        $this->logger->info('Proof #'.$carpoolProof->getId().' ignored');

        return new Response(200, '');
    }

    public function serializeProof(CarpoolProof $carpoolProof): ?array
    {
        // creation of the journey
        $over18 = null;
        if (!is_null($carpoolProof->getPassenger()->getBirthDate())) {
            $over18 = $carpoolProof->getPassenger()->getBirthDate()->diff(new \DateTime('now'))->y >= 18;
        }

        // note : the casts are mandatory as the register checks for types
        $journey = [
            'journey_id' => (string) ((!is_null($this->prefix) ? $this->prefix : '').(string) $carpoolProof->getId()),
            'operator_class' => $carpoolProof->getType(),
            'passenger' => [
                'identity' => [
                    'email' => $carpoolProof->getPassenger()->getEmail(),
                    'phone' => $carpoolProof->getPassenger()->getTelephone(),
                    'over_18' => $over18,
                ],
                'start' => [
                    'lon' => (!is_null($carpoolProof->getPickUpPassengerAddress())) ? (float) $carpoolProof->getPickUpPassengerAddress()->getLongitude() : null,
                    'lat' => (!is_null($carpoolProof->getPickUpPassengerAddress())) ? (float) $carpoolProof->getPickUpPassengerAddress()->getLatitude() : null,
                    'datetime' => (!is_null($carpoolProof->getPickUpPassengerDate())) ? $carpoolProof->getPickUpPassengerDate()->format(self::ISO8601) : null,
                ],
                'end' => [
                    'lon' => (!is_null($carpoolProof->getDropOffPassengerAddress())) ? (float) $carpoolProof->getDropOffPassengerAddress()->getLongitude() : null,
                    'lat' => (!is_null($carpoolProof->getDropOffPassengerAddress())) ? (float) $carpoolProof->getDropOffPassengerAddress()->getLatitude() : null,
                    'datetime' => (!is_null($carpoolProof->getDropOffPassengerDate())) ? $carpoolProof->getDropOffPassengerDate()->format(self::ISO8601) : null,
                ],
                'seats' => $carpoolProof->getAsk()->getCriteria()->getSeatsPassenger(),
                'contribution' => (int) round($carpoolProof->getAsk()->getCriteria()->getPassengerComputedRoundedPrice() * 100, 0),
                'incentives' => [],
            ],
            'driver' => [
                'identity' => [
                    'email' => $carpoolProof->getDriver()->getEmail(),
                    'phone' => $carpoolProof->getDriver()->getTelephone(),
                ],
                'start' => [
                    'lon' => (!is_null($carpoolProof->getPickUpDriverAddress())) ? (float) $carpoolProof->getPickUpDriverAddress()->getLongitude() : null,
                    'lat' => (!is_null($carpoolProof->getPickUpDriverAddress())) ? (float) $carpoolProof->getPickUpDriverAddress()->getLatitude() : null,
                    'datetime' => (!is_null($carpoolProof->getPickUpDriverDate())) ? $carpoolProof->getPickUpDriverDate()->format(self::ISO8601) : null,
                ],
                'end' => [
                    'lon' => (!is_null($carpoolProof->getDropOffDriverAddress())) ? (float) $carpoolProof->getDropOffDriverAddress()->getLongitude() : null,
                    'lat' => (!is_null($carpoolProof->getDropOffDriverAddress())) ? (float) $carpoolProof->getDropOffDriverAddress()->getLatitude() : null,
                    'datetime' => (!is_null($carpoolProof->getDropOffDriverDate())) ? $carpoolProof->getDropOffDriverDate()->format(self::ISO8601) : null,
                ],
                'revenue' => (int) round($carpoolProof->getAsk()->getCriteria()->getPassengerComputedRoundedPrice() * 100, 0),
                'incentives' => [],
            ],
        ];
        // additional properties

        // Passenger or driver start and end need to be filled with lat/lon to be valid
        // In organized journey, we don't have pickup or dropoff for passengers. We use it's origin/destination
        if (CarpoolProof::TYPE_LOW == $carpoolProof->getType() || CarpoolProof::TYPE_MID == $carpoolProof->getType()) {
            if (is_null($journey['passenger']['start']['lon']) && is_null($journey['passenger']['start']['lat'])) {
                $matchingWaypoints = $carpoolProof->getAsk()->getMatching()->getWaypoints();
                $passengerWaypoints = [];
                foreach ($matchingWaypoints as $waypoint) {
                    if (2 == $waypoint->getRole()) {
                        $passengerWaypoints[] = $waypoint;
                    }
                }
                $journey['passenger']['start']['lon'] = (float) $passengerWaypoints[0]->getAddress()->getLongitude();
                $journey['passenger']['start']['lat'] = (float) $passengerWaypoints[0]->getAddress()->getLatitude();
                $journey['passenger']['end']['lon'] = (float) $passengerWaypoints[count($passengerWaypoints) - 1]->getAddress()->getLongitude();
                $journey['passenger']['end']['lat'] = (float) $passengerWaypoints[count($passengerWaypoints) - 1]->getAddress()->getLatitude();
            }

            $journey['driver']['start']['lon'] = $journey['passenger']['start']['lon'];
            $journey['driver']['start']['lat'] = $journey['passenger']['start']['lat'];
            $journey['driver']['end']['lon'] = $journey['passenger']['end']['lon'];
            $journey['driver']['end']['lat'] = $journey['passenger']['end']['lat'];

            // In organized, we need to use the driver's date and we search for the ask's criteria time for the passenger
            if (is_null($journey['passenger']['start']['datetime'])) {
                $fromDate = $carpoolProof->getStartDriverDate();

                if (Criteria::FREQUENCY_PUNCTUAL === $carpoolProof->getAsk()->getCriteria()->getFrequency()) {
                    $fromTime = $carpoolProof->getAsk()->getCriteria()->getFromTime();
                }

                switch ($fromDate->format('w')) {
                    case 0:
                        if (!$carpoolProof->getAsk()->getCriteria()->isSunCheck()) {
                            return null;
                        }

                        $fromTime = $carpoolProof->getAsk()->getCriteria()->getSunTime();

                        break;

                    case 1:
                        if (!$carpoolProof->getAsk()->getCriteria()->isMonCheck()) {
                            return null;
                        }

                        $fromTime = $carpoolProof->getAsk()->getCriteria()->getMonTime();

                        break;

                    case 2:
                        if (!$carpoolProof->getAsk()->getCriteria()->isTueCheck()) {
                            return null;
                        }

                        $fromTime = $carpoolProof->getAsk()->getCriteria()->getTueTime();

                        break;

                    case 3:
                        if (!$carpoolProof->getAsk()->getCriteria()->isWedCheck()) {
                            return null;
                        }

                        $fromTime = $carpoolProof->getAsk()->getCriteria()->getWedTime();

                        break;

                    case 4:
                        if (!$carpoolProof->getAsk()->getCriteria()->isThuCheck()) {
                            return null;
                        }

                        $fromTime = $carpoolProof->getAsk()->getCriteria()->getThuTime();

                        break;

                    case 5:
                        if (!$carpoolProof->getAsk()->getCriteria()->isFriCheck()) {
                            return null;
                        }

                        $fromTime = $carpoolProof->getAsk()->getCriteria()->getFriTime();

                        break;

                    case 6:
                        if (!$carpoolProof->getAsk()->getCriteria()->isSatCheck()) {
                            return null;
                        }

                        $fromTime = $carpoolProof->getAsk()->getCriteria()->getSatTime();

                        break;
                }

                // We compute the pickup time
                $pickUpTime = $fromTime->modify('+ '.$carpoolProof->getAsk()->getMatching()->getPickUpDuration().' second');
                $passengerStartDate = clone $fromDate;
                $journey['passenger']['start']['datetime'] = $passengerStartDate->setTime($pickUpTime->format('H'), $pickUpTime->format('i'), $pickUpTime->format('s'))->format(self::ISO8601);

                // We compute the drop off time
                $dropOffTime = $fromTime->modify('+ '.$carpoolProof->getAsk()->getMatching()->getDropOffDuration().' second');
                $passengerEndDate = clone $fromDate;
                $journey['passenger']['end']['datetime'] = $passengerEndDate->setTime($dropOffTime->format('H'), $dropOffTime->format('i'), $dropOffTime->format('s'))->format(self::ISO8601);
            }

            if (is_null($journey['driver']['start']['datetime']) && is_null($journey['driver']['end']['datetime'])) {
                $journey['driver']['start']['datetime'] = $journey['passenger']['start']['datetime'];
                $journey['driver']['end']['datetime'] = $journey['passenger']['end']['datetime'];
            }
        }

        return $journey;
    }

    public function getCarpoolProof(CarpoolProof $carpoolProof, string $resource = self::RESSOURCE_GET_ITEM)
    {
        $journeyId = (!is_null($this->prefix) ? $this->prefix : '').(string) $carpoolProof->getId();
        $dataProvider = new DataProvider($this->uri, $resource.$journeyId);

        // creation of the headers
        $headers = [
            'Authorization' => 'Bearer '.$this->token,
            'Content-Type' => 'application/json',
        ];

        return $dataProvider->getItem([], $headers);
    }

    public function getCollection(string $class, string $apikey, array $params) {}

    public function getItem(string $class, string $apikey, array $params) {}

    public function deserialize(string $class, array $data)
    {
        $this->logger->info('BetaGouv API return');
    }
}