<?php
/**
 * amadeus-ws-client
 *
 * Copyright 2015 Amadeus Benelux NV
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * @package Amadeus
 * @license https://opensource.org/licenses/Apache-2.0 Apache 2.0
 */

namespace Amadeus\Client\Struct\Ticket;

use Amadeus\Client\RequestOptions\TicketDisplayTstOptions;
use Amadeus\Client\Struct\BaseWsMessage;
use Amadeus\Client\Struct\Ticket\DisplayTST\DisplayMode;
use Amadeus\Client\Struct\Ticket\DisplayTST\PsaInformation;
use Amadeus\Client\Struct\Ticket\DisplayTST\ScrollingInformation;

/**
 * DisplayTST
 *
 * @package Amadeus\Client\Struct\Ticket
 * @author Dieter Devlieghere <dermikagh@gmail.com>
 */
class DisplayTST extends BaseWsMessage
{
    /**
     * @var DisplayMode
     */
    public $displayMode;

    /**
     * @var PnrLocatorData
     */
    public $pnrLocatorData;

    /**
     * @var ScrollingInformation
     */
    public $scrollingInformation;

    /**
     * @var TstReference[]
     */
    public $tstReference = [];

    /**
     * @var PsaInformation
     */
    public $psaInformation;

    /**
     * DisplayTST constructor.
     *
     * @param TicketDisplayTstOptions $params
     */
    public function __construct(TicketDisplayTstOptions $params)
    {
        $this->displayMode = new DisplayMode($params->displayMode);

        if ($params->displayMode === AttributeDetails::MODE_SELECTIVE) {
            $this->loadSelective($params);
        }
    }

    /**
     * @param TicketDisplayTstOptions $params
     */
    protected function loadSelective($params)
    {
        foreach ($params->tstNumbers as $tstNumber) {
            $this->tstReference[] = new TstReference($tstNumber);
        }

        $this->loadReferences($params);

        if ($this->checkAllNotEmpty($params->scrollingCount, $params->scrollingStart)) {
            $this->scrollingInformation = new ScrollingInformation(
                $params->scrollingCount,
                $params->scrollingStart
            );
        }
    }

    /**
     * Load passenger & segment references
     *
     * @param TicketDisplayTstOptions $params
     */
    protected function loadReferences($params)
    {
        if ($this->checkAnyNotEmpty($params->passengers, $params->segments)) {
            $this->psaInformation = new PsaInformation();

            foreach ($params->passengers as $passenger) {
                $this->psaInformation->refDetails[] = new RefDetails($passenger, RefDetails::QUAL_PASSENGER);
            }

            foreach ($params->segments as $segment) {
                $this->psaInformation->refDetails[] = new RefDetails($segment, RefDetails::QUAL_SEGMENT_REFERENCE);
            }
        }
    }
}


<?php
/**
 * amadeus-ws-client
 *
 * Copyright 2015 Amadeus Benelux NV
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * @package Amadeus
 * @license https://opensource.org/licenses/Apache-2.0 Apache 2.0
 */

namespace Amadeus\Client\Struct\Pnr;

use Amadeus\Client\RequestOptions\Pnr\Element;
use Amadeus\Client\RequestOptions\Pnr\Element\ReceivedFrom;
use Amadeus\Client\RequestOptions\Pnr\Itinerary;
use Amadeus\Client\RequestOptions\Pnr\Segment;
use Amadeus\Client\RequestOptions\Pnr\Traveller;
use Amadeus\Client\RequestOptions\Pnr\TravellerGroup;
use Amadeus\Client\RequestOptions\PnrAddMultiElementsBase;
use Amadeus\Client\RequestOptions\PnrAddMultiElementsOptions;
use Amadeus\Client\RequestOptions\PnrCreatePnrOptions;
use Amadeus\Client\Struct\BaseWsMessage;
use Amadeus\Client\Struct\InvalidArgumentException;
use Amadeus\Client\Struct\Pnr\AddMultiElements\AirAuxItinerary;
use Amadeus\Client\Struct\Pnr\AddMultiElements\DataElementsIndiv;
use Amadeus\Client\Struct\Pnr\AddMultiElements\DataElementsMaster;
use Amadeus\Client\Struct\Pnr\AddMultiElements\ElementManagementItinerary;
use Amadeus\Client\Struct\Pnr\AddMultiElements\ItineraryInfo;
use Amadeus\Client\Struct\Pnr\AddMultiElements\OriginDestination;
use Amadeus\Client\Struct\Pnr\AddMultiElements\OriginDestinationDetails;
use Amadeus\Client\Struct\Pnr\AddMultiElements\Reference;
use Amadeus\Client\Struct\Pnr\AddMultiElements\ReferenceForDataElement;
use Amadeus\Client\Struct\Pnr\AddMultiElements\ReferenceForSegment;
use Amadeus\Client\Struct\Pnr\AddMultiElements\TravellerInfo;

/**
 * Structure class for representing the PNR_AddMultiElements request message
 *
 * @package Amadeus\Client\Struct\Pnr
 * @author Dieter Devlieghere <dermikagh@gmail.com>
 */
class AddMultiElements extends BaseWsMessage
{
    /**
     * @var AddMultiElements\ReservationInfo
     */
    public $reservationInfo;
    /**
     * @var AddMultiElements\PnrActions
     */
    public $pnrActions;
    /**
     * @var AddMultiElements\TravellerInfo[]
     */
    public $travellerInfo = [];
    /**
     * @var AddMultiElements\OriginDestinationDetails[]
     */
    public $originDestinationDetails = [];
    /**
     * @var AddMultiElements\DataElementsMaster
     */
    public $dataElementsMaster;

    /**
     * Create PNR_AddMultiElements object
     *
     * @param PnrAddMultiElementsBase|null $params
     * @throws \ReflectionException
     */
    public function __construct(PnrAddMultiElementsBase $params = null)
    {
        if (!is_null($params)) {
            if ($params instanceof PnrCreatePnrOptions) {
                $this->loadCreatePnr($params);
            } elseif ($params instanceof PnrAddMultiElementsOptions) {
                $this->loadBare($params);
            }
        }
    }

    /**
     * PNR_AddMultiElements call which only adds requested data to the message
     *
     * For doing specific actions like ignoring or saving PNR.
     *
     * @param PnrAddMultiElementsOptions $params
     * @throws \ReflectionException
     */
    protected function loadBare(PnrAddMultiElementsOptions $params)
    {
        $tattooCounter = 0;

        if (!is_null($params->actionCode)) {
            $this->pnrActions = new AddMultiElements\PnrActions(
                $params->actionCode
            );
        }

        if (!is_null($params->recordLocator)) {
            $this->reservationInfo = new AddMultiElements\ReservationInfo($params->recordLocator);
        }

        if ($params->travellerGroup !== null) {
            $this->addTravellerGroup($params->travellerGroup);
        } else {
            $this->addTravellers($params->travellers);
        }

        $this->addItineraries($params->itineraries, $params->tripSegments, $tattooCounter);

        if (!empty($params->elements)) {
            $this->addElements(
                $params->elements,
                $tattooCounter,
                $params->autoAddReceivedFrom,
                $params->defaultReceivedFrom,
                $params->receivedFrom
            );
        } else {
            $this->addReceivedFrom(
                $params->receivedFrom,
                $params->autoAddReceivedFrom,
                $params->defaultReceivedFrom,
                $tattooCounter
            );
        }
    }

    /**
     * Make PNR_AddMultiElements structure from a PnrCreatePnrOptions input.
     *
     * @throws InvalidArgumentException When invalid input is provided
     * @param PnrCreatePnrOptions $params
     * @throws \ReflectionException
     */
    protected function loadCreatePnr(PnrCreatePnrOptions $params)
    {
        $this->pnrActions = new AddMultiElements\PnrActions(
            $params->actionCode
        );

        $tattooCounter = 0;

        if ($params->travellerGroup !== null) {
            $this->addTravellerGroup($params->travellerGroup);
        } else {
            $this->addTravellers($params->travellers);
        }

        $this->addItineraries($params->itineraries, $params->tripSegments, $tattooCounter);

        $this->addElements(
            $params->elements,
            $tattooCounter,
            $params->autoAddReceivedFrom,
            $params->defaultReceivedFrom,
            $params->receivedFrom
        );
    }

    /**
     * Load Segment itinerary
     *
     * @param Itinerary[] $itineraries
     * @param Segment[] $legacySegments
     * @param int $tattooCounter (BYREF)
     * @throws \ReflectionException
     */
    protected function addItineraries($itineraries, $legacySegments, &$tattooCounter)
    {
        if (!empty($legacySegments)) {
            $this->addSegments($legacySegments, $tattooCounter);
        }

        foreach ($itineraries as $itinerary) {
            $this->addSegments(
                $itinerary->segments,
                $tattooCounter,
                $itinerary->origin,
                $itinerary->destination
            );
        }
    }

    /**
     * @param Segment[] $segments
     * @param int $tattooCounter
     * @param string|null $origin
     * @param string|null $destination
     * @throws \ReflectionException
     */
    protected function addSegments($segments, &$tattooCounter, $origin = null, $destination = null)
    {
        $tmpOrigDest = new OriginDestinationDetails();

        foreach ($segments as $segment) {
            $tmpOrigDest->itineraryInfo[] = $this->createSegment($segment, $tattooCounter);
        }

        if (!is_null($origin) && !is_null($destination)) {
            $tmpOrigDest->originDestination = new OriginDestination($origin, $destination);
        }

        $this->originDestinationDetails[] = $tmpOrigDest;
    }

    /**
     * @param Segment $segment
     * @param int $tattooCounter (BYREF)
     * @return ItineraryInfo
     * @throws \ReflectionException
     */
    protected function createSegment($segment, &$tattooCounter)
    {
        $createdSegment = null;

        $tattooCounter++;

        $reflect = new \ReflectionClass($segment);
        $segmentType = $reflect->getShortName();

        switch ($segmentType) {
            case 'Miscellaneous':
                /** @var Segment\Miscellaneous $segment */
                $createdSegment = new ItineraryInfo($tattooCounter, ElementManagementItinerary::SEGMENT_MISCELLANEOUS);
                $createdSegment->airAuxItinerary = new AirAuxItinerary($segmentType, $segment);
                break;
            case 'Air':
                /** @var Segment\Air $segment */
                $createdSegment = new ItineraryInfo($tattooCounter, ElementManagementItinerary::SEGMENT_AIR);
                $createdSegment->airAuxItinerary = new AirAuxItinerary($segmentType, $segment);
                break;
            case 'ArrivalUnknown':
                /** @var Segment\ArrivalUnknown $segment */
                $createdSegment = new ItineraryInfo($tattooCounter, ElementManagementItinerary::SEGMENT_AIR);
                $createdSegment->airAuxItinerary = new AirAuxItinerary($segmentType, $segment);
                break;
            case 'Ghost':
                throw new \RuntimeException('NOT YET IMPLEMENTED');
                break;
            default:
                throw new InvalidArgumentException('Segment type '.$segmentType.' is not supported');
                break;
        }

        if (count($segment->references) > 0) {
            $createdSegment->referenceForSegment = new ReferenceForSegment();
            foreach ($segment->references as $singleRef) {
                $createdSegment->referenceForSegment->reference[] = new Reference($singleRef->type, $singleRef->id);
            }
        }

        return $createdSegment;
    }

    /**
     * @param Traveller[] $travellers
     */
    protected function addTravellers($travellers)
    {
        foreach ($travellers as $traveller) {
            $this->travellerInfo[] = $this->createTraveller($traveller);
        }
    }

    /**
     * @param Traveller $traveller
     * @return TravellerInfo
     */
    protected function createTraveller($traveller)
    {
        return new TravellerInfo($traveller);
    }

    /**
     * @param TravellerGroup $group
     */
    protected function addTravellerGroup($group)
    {
        $this->travellerInfo[] = new TravellerInfo(null, $group);

        $this->addTravellers($group->travellers);
    }

    /**
     * @param Element[] $elements
     * @param int $tattooCounter (BYREF)
     * @param bool $autoAddRf
     * @param string|null $defaultRf
     * @param string|null $explicitRf
     * @throws \ReflectionException
     */
    protected function addElements($elements, &$tattooCounter, $autoAddRf, $defaultRf, $explicitRf = null)
    {
        if ($this->dataElementsMaster === null) {
            $this->dataElementsMaster = new DataElementsMaster();
        }

        //Only add a default RF element if there is no explicitly provided RF element!
        $hasReceivedFromElement = false;

        foreach ($elements as $element) {
            if ($element instanceof Element) {
                $this->dataElementsMaster->dataElementsIndiv[] = $this->createElement(
                    $element,
                    $tattooCounter
                );
            }

            if ($element instanceof ReceivedFrom) {
                $hasReceivedFromElement = true;
            }
        }

        if (!$hasReceivedFromElement) {
            $this->addReceivedFrom(
                $explicitRf,
                $autoAddRf,
                $defaultRf,
                $tattooCounter
            );
        }
    }

    /**
     * @param Element $element
     * @param int $tattooCounter (BYREF)
     * @throws InvalidArgumentException
     * @return DataElementsIndiv
     * @throws \ReflectionException
     */
    protected function createElement($element, &$tattooCounter)
    {
        $createdElement = null;

        $tattooCounter++;

        $createdElement = new DataElementsIndiv($element, $tattooCounter);

        if (!empty($element->references)) {
            $createdElement->referenceForDataElement = new ReferenceForDataElement($element->references);
        }

        return $createdElement;
    }

    /**
     * Add Received From field - if needed.
     *
     * @param string|null $explicitRf Explicitly provided RF string on request.
     * @param bool $doAutoAdd Wether to automatically add an RF field.
     * @param string|null $defaultRf The default RF string set in the client.
     * @param int $tattooCounter (BYREF)
     * @throws \ReflectionException
     */
    protected function addReceivedFrom($explicitRf, $doAutoAdd, $defaultRf, &$tattooCounter)
    {
        if ($this->dataElementsMaster === null) {
            $this->dataElementsMaster = new DataElementsMaster();
        }

        if (!empty($explicitRf) || ($doAutoAdd && !empty($defaultRf))) {
            //Set a received from if explicitly provided or if auto received from is enabled

            $tattooCounter++;

            $rfToAdd = (!empty($explicitRf)) ? $explicitRf : $defaultRf;

            $this->dataElementsMaster->dataElementsIndiv[] = $this->createElement(
                new ReceivedFrom(['receivedFrom' => $rfToAdd]),
                $tattooCounter
            );
        }
    }
}


<?php
/**
 * amadeus-ws-client
 *
 * Copyright 2015 Amadeus Benelux NV
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * @package Amadeus
 * @license https://opensource.org/licenses/Apache-2.0 Apache 2.0
 */

namespace Amadeus\Client\Struct\Air;

/**
 * FlightDate
 *
 * @package Amadeus\Client\Struct\Air
 * @author dieter <dermikagh@gmail.com>
 */
class FlightDate
{
    /**
     * DDMMYY
     *
     * @var string
     */
    public $departureDate;
    /**
     * HHMM
     *
     * @var string
     */
    public $departureTime;
    /**
     * DDMMYY
     *
     * @var string
     */
    public $arrivalDate;
    /**
     * HHMM
     *
     * @var string
     */
    public $arrivalTime;
    /**
     * @var string|int
     */
    public $dateVariation;

    /**
     * FlightDate constructor.
     *
     * @param string|\DateTime|null $departureDate in format DDMMYY or \DateTime
     * @param \DateTime|null $arrivalDate
     * @param string|\DateTime|null $arrivalTime
     * @param int|null $dateVariation
     */
    public function __construct($departureDate, $arrivalDate = null, $arrivalTime = null, $dateVariation = null)
    {
        $this->loadDepartureDate($departureDate);

        $this->loadArrivalDate($arrivalDate, $arrivalTime);

        if (!is_null($dateVariation)) {
            $this->dateVariation = $dateVariation;
        }
    }

    /**
     * @param \DateTime|string|null $departureDate
     */
    protected function loadDepartureDate($departureDate)
    {
        if ($departureDate instanceof \DateTime) {
            $this->departureDate = ($departureDate->format('dmy') !== '000000') ? $departureDate->format('dmy') : null;
            $time = $departureDate->format('Hi');
            if ($time !== '0000') {
                $this->departureTime = $time;
            }
        } elseif (!empty($departureDate)) {
            $this->departureDate = $departureDate;
        }
    }

    /**
     * @param \DateTime|null $arrivalDate
     * @param string|\DateTime|null $arrivalTime
     */
    protected function loadArrivalDate($arrivalDate, $arrivalTime)
    {
        if ($arrivalDate instanceof \DateTime) {
            $this->setArrivalDate($arrivalDate);
        } elseif ($arrivalTime instanceof \DateTime) {
            $time = $arrivalTime->format('Hi');
            if ($time !== '0000') {
                $this->arrivalTime = $time;
            }
        } elseif (is_string($arrivalTime) && !empty($arrivalTime)) {
            $this->arrivalTime = $arrivalTime;
        }
    }

    /**
     * Load Arrival date info from \DateTime
     *
     * @param \DateTime $arrivalDate
     */
    public function setArrivalDate(\DateTime $arrivalDate)
    {
        $this->arrivalDate = ($arrivalDate->format('dmy') !== '000000') ? $arrivalDate->format('dmy') : null;
        $time = $arrivalDate->format('Hi');
        if ($time !== '0000') {
            $this->arrivalTime = $time;
        }
    }
}


<?php
/**
 * amadeus-ws-client
 *
 * Copyright 2015 Amadeus Benelux NV
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * @package Amadeus
 * @license https://opensource.org/licenses/Apache-2.0 Apache 2.0
 */

namespace Amadeus\Client\Struct\Fop;

use Amadeus\Client\RequestOptions\Fop\MopInfo;
use Amadeus\Client\Struct\Fop\CreateFormOfPayment\GroupUsage14;
use Amadeus\Client\Struct\Fop\CreateFormOfPayment\PaymentModule14;
use Amadeus\Client\Struct\WsMessageUtility;

/**
 * PaymentModule
 *
 * @package Amadeus\Client\Struct\Fop
 * @author Dieter Devlieghere <dermikagh@gmail.com>
 */
class PaymentModule extends WsMessageUtility
{
    /**
     * @var GroupUsage
     */
    public $groupUsage;

    /**
     * @var PaymentData
     */
    public $paymentData;

    /**
     * @var PaymentStatus
     */
    public $paymentStatus;

    /**
     * @var PaymentSupplementaryData[]
     */
    public $paymentSupplementaryData = [];

    /**
     * @var MopInformation
     */
    public $mopInformation;

    /**
     * @var string
     */
    public $dummy;

    /**
     * @var MopDetailedData
     */
    public $mopDetailedData;

    /**
     * PaymentModule constructor.
     *
     * @param string $fopType
     */
    public function __construct($fopType)
    {
        if ($this instanceof PaymentModule14) {
            $this->groupUsage = new GroupUsage14($fopType);
        } else {
            $this->groupUsage = new GroupUsage($fopType);
        }
    }

    /**
     * Load all paymentData
     *
     * @param MopInfo $options
     */
    public function loadPaymentData(MopInfo $options)
    {
        if ($this->checkAnyNotEmpty(
            $options->payMerchant,
            $options->transactionDate,
            $options->payments,
            $options->installmentsInfo,
            $options->fraudScreening,
            $options->payIds
        )) {
            $this->paymentData = new PaymentData(
                $options->payMerchant,
                $options->transactionDate,
                $options->payments,
                $options->installmentsInfo,
                $options->fraudScreening,
                $options->payIds
            );
        }
    }
}


<?php
/**
 * Amadeus
 *
 * Copyright 2015 Amadeus Benelux NV
 */

namespace Amadeus\Client\Struct\Air\MultiAvailability;

use Amadeus\Client\RequestOptions\Air\MultiAvailability\RequestOptions;

/**
 * RequestSection
 *
 * @package Amadeus\Client\Struct\Air\MultiAvailability
 * @author Dieter Devlieghere <dermikagh@gmail.com>
 */
class RequestSection
{
    /**
     * @var AvailabilityProductInfo
     */
    public $availabilityProductInfo;

    /**
     * @var BoardOffDetails[]
     */
    public $boardOffDetails = [];

    /**
     * @var TravelChoiceInfo
     */
    public $travelChoiceInfo;

    /**
     * @var OptionClass
     */
    public $optionClass;

    /**
     * @var ConnectionOption[]
     */
    public $connectionOption = [];

    /**
     * @var NumberOfSeatsInfo
     */
    public $numberOfSeatsInfo;

    /**
     * @var AirlineOrFlightOption[]
     */
    public $airlineOrFlightOption = [];

    /**
     * @var CabinOption
     */
    public $cabinOption;

    /**
     * @var NegoSpaceDetails
     */
    public $negoSpaceDetails;

    /**
     * @var AvailabilityOptions
     */
    public $availabilityOptions;

    /**
     * @var UmRequest
     */
    public $umRequest;

    /**
     * RequestSection constructor.
     *
     * @param RequestOptions $params
     */
    public function __construct(RequestOptions $params)
    {
        $this->availabilityProductInfo = new AvailabilityProductInfo(
            $params->from,
            $params->to,
            $params->departureDate,
            $params->arrivalDate
        );

        if ($this instanceof RequestSection16) {
            $this->availabilityOptions = new AvailabilityOptions16($params->requestType);
        } else {
            $this->availabilityOptions = new AvailabilityOptions($params->requestType);
        }

        $this->loadCabinAndClass($params->cabinCode, $params->bookingClasses);

        $this->loadAirlines(
            $params->includedAirlines,
            $params->excludedAirlines,
            $params->operationalAirline,
            $params->flightNumber
        );

        $this->loadConnections($params->includedConnections, $params->excludedConnections);

        $this->loadSeats($params->nrOfSeats);

        $this->loadAvailabilityOptions($params->availabilityOptions);
    }

    /**
     * @param string|null $cabinCode
     * @param string[] $bookingClasses
     */
    protected function loadCabinAndClass($cabinCode, $bookingClasses)
    {
        if (!empty($cabinCode)) {
            $this->cabinOption = new CabinOption($cabinCode);
        }

        if (!empty($bookingClasses)) {
            $this->optionClass = new OptionClass($bookingClasses);
        }
    }

    /**
     * @param string[] $included
     * @param string[] $excluded
     * @param string|null $operational
     * @param string|null $flightNumber
     */
    protected function loadAirlines($included, $excluded, $operational, $flightNumber)
    {
        if (!empty($included)) {
            $this->airlineOrFlightOption[] = new AirlineOrFlightOption($included, $flightNumber);
        }

        if (!empty($excluded)) {
            $this->airlineOrFlightOption[] = new AirlineOrFlightOption(
                $excluded,
                null,
                AirlineOrFlightOption::INDICATOR_EXCLUDE
            );
        }

        if (!empty($operational)) {
            $this->airlineOrFlightOption[] = new AirlineOrFlightOption(
                [$operational],
                $flightNumber,
                AirlineOrFlightOption::INDICATOR_OPERATIONAL_CARRIER
            );
        }
    }

    /**
     * @param string[] $included
     * @param string[] $excluded
     */
    protected function loadConnections($included, $excluded)
    {
        if (!empty($included)) {
            $this->connectionOption[] = new ConnectionOption($included);
        }

        if (!empty($excluded)) {
            $this->connectionOption[] = new ConnectionOption($excluded, Connection::INDICATOR_EXCLUDE);
        }
    }

    /**
     * @param int|null $nrOfSeats
     */
    protected function loadSeats($nrOfSeats)
    {
        if (!empty($nrOfSeats)) {
            $this->numberOfSeatsInfo = new NumberOfSeatsInfo($nrOfSeats);
        }
    }

    /**
     * Availability options:
     * Keys are option types (RequestOptions::OPTION_TYPE_*),
     * values are option arguments.
     *
     * @param $availabilityOptions
     */
    protected function loadAvailabilityOptions($availabilityOptions)
    {
        if (!empty($availabilityOptions)) {
            foreach ($availabilityOptions as $type => $argument) {
                $this->availabilityOptions->optionInfo[] = new OptionInfo($type, $argument);
            }
        }
    }
}


<?php
/**
 * amadeus-ws-client
 *
 * Copyright 2015 Amadeus Benelux NV
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * @package Amadeus
 * @license https://opensource.org/licenses/Apache-2.0 Apache 2.0
 */

namespace Amadeus\Client\RequestCreator;

use Amadeus\Client\Params\RequestCreatorParams;

/**
 * Request Creator Factory
 *
 * @package Amadeus\Client\RequestCreator
 * @author Dieter Devlieghere <dermikagh@gmail.com>
 */
class Factory
{
    /**
     * Create a Request Creator
     *
     * @param RequestCreatorParams $params
     * @param string $libIdentifier
     * @return RequestCreatorInterface
     * @throws \InvalidArgumentException when the parameters to create the handler do not make sense.
     */
    public static function createRequestCreator($params, $libIdentifier)
    {
        $params->receivedFrom = self::makeReceivedFrom(
            $params->receivedFrom,
            $libIdentifier
        );

        $theRequestCreator = new Base($params);

        return $theRequestCreator;
    }

    /**
     * @param string $original
     * @param string $libIdentifier
     * @return string
     */
    protected static function makeReceivedFrom($original, $libIdentifier)
    {
        return $original." ".$libIdentifier;
    }
}


<?php
/**
 * amadeus-ws-client
 *
 * Copyright 2015 Amadeus Benelux NV
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * @package Amadeus
 * @license https://opensource.org/licenses/Apache-2.0 Apache 2.0
 */

namespace Amadeus\Client\Struct\Fare;

use Amadeus\Client\RequestOptions\Fare\InformativeBestPricingWithoutPnr\CabinOptions;
use Amadeus\Client\RequestOptions\FareInformativeBestPricingWithoutPnrOptions;
use Amadeus\Client\Struct\Fare\PricePnr13\PricingOptionGroup;
use Amadeus\Client\Struct\Fare\PricePnr13\PricingOptionKey;

/**
 * InformativeBestPricingWithoutPNR13
 *
 * @package Amadeus\Client\Struct\Fare
 * @author Dieter Devlieghere <dermikagh@gmail.com>
 */
class InformativeBestPricingWithoutPNR13 extends InformativePricingWithoutPNR13
{
    /**
     * InformativeBestPricingWithoutPNR13 constructor.
     *
     * @param FareInformativeBestPricingWithoutPnrOptions|null $options
     */
    public function __construct(FareInformativeBestPricingWithoutPnrOptions $options = null)
    {
        parent::__construct($options);

        if (!empty($options->cabin)) {
            $this->loadCabin($options->cabin);
        }
    }

    /**
     * @param CabinOptions $cabinOptions
     *
     * @return InformativeBestPricingWithoutPNR13
     */
    protected function loadCabin($cabinOptions)
    {
        if ($cabinOptions instanceof CabinOptions) {
            $optionDetails = [];
            foreach ($cabinOptions->getOptions() as $cabinOption) {
                $optionDetails[] = [$cabinOption->getType() =>$cabinOption->getClass()];
            }

            $this->pricingOptionGroup = array_merge(
                $this->pricingOptionGroup,
                [
                    new PricingOptionGroup(
                        PricingOptionKey::OPTION_CABIN,
                        $optionDetails
                    )
                ]
            );
        }

        return $this;
    }
}


<?php
/**
 * amadeus-ws-client
 *
 * Copyright 2015 Amadeus Benelux NV
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * @package Amadeus
 * @license https://opensource.org/licenses/Apache-2.0 Apache 2.0
 */

namespace Amadeus\Client\Struct\Fare\MasterPricer;

use Amadeus\Client\RequestOptions\Fare\MPTicketingPriceScheme;
use Amadeus\Client\RequestOptions\Fare\MPFeeId;

/**
 * FareOptions
 *
 * @package Amadeus\Client\Struct\Fare\MasterPricer
 * @author Dieter Devlieghere <dermikagh@gmail.com>
 */
class FareOptions
{
    /**
     * @var PricingTickInfo
     */
    public $pricingTickInfo;
    /**
     * @var Corporate
     */
    public $corporate;
    /**
     * @var TicketingPriceScheme
     */
    public $ticketingPriceScheme;
    /**
     * @var FeeIdDescription
     */
    public $feeIdDescription;
    /**
     * @var ConversionRate
     */
    public $conversionRate;
    /**
     * @var FormOfPaymentDetails[]|array
     */
    public $formOfPayment;

    public $frequentTravellerInfo;

    public $monetaryCabinInfo;

    public $multiTicket;

    /**
     * FareOptions constructor.
     *
     * @param array $flightOptions List of flight / fare options
     * @param array $corpCodesUniFares list of Corporate codes for Corporate Unifares
     * @param bool $tickPreCheck Do Ticketability pre-check?
     * @param string|null $currency Override Currency conversion
     * @param MPFeeId[]|null $feeIds List of FeeIds
     * @param string|null Corporate qualifier for Corporate Unifares
     * @param $multiTicket
     * @param MPTicketingPriceScheme|null $ticketingPriceScheme
     * @param array|null $formOfPayment
     */
    public function __construct(
        array $flightOptions,
        array $corpCodesUniFares,
        $tickPreCheck,
        $currency,
        $feeIds,
        $corporateQualifier,
        $multiTicket,
        $ticketingPriceScheme,
        $formOfPayment
    ) {
        if ($tickPreCheck === true) {
            $this->addPriceType(PricingTicketing::PRICETYPE_TICKETABILITY_PRECHECK);
        }

        foreach ($flightOptions as $flightOption) {
            $this->addPriceType($flightOption);

            if ($flightOption === PricingTicketing::PRICETYPE_CORPORATE_UNIFARES) {
                $this->corporate = new Corporate();
                $this->corporate->corporateId[] = new CorporateId($corpCodesUniFares, $corporateQualifier);
            }
        }

        $this->loadCurrencyOverride($currency);
        $this->loadMultiTicket($multiTicket);
        if (!is_null($feeIds)) {
            $this->loadFeeIds($feeIds);
        }
        if (!is_null($ticketingPriceScheme)) {
            $this->loadTicketingPriceScheme($ticketingPriceScheme);
        }
        if (!is_null($formOfPayment) && count($formOfPayment)) {
            $this->loadFormOfPayment($formOfPayment);
        }
    }

    /**
     * Set fee ids if needed
     *
     * @param MPFeeId[] $feeIds
     */
    protected function loadFeeIds($feeIds)
    {
        if (is_null($this->feeIdDescription)) {
            $this->feeIdDescription = new FeeIdDescription();
        }
        foreach ($feeIds as $feeId) {
            $this->feeIdDescription->feeId[] = new FeeId($feeId->type, $feeId->number);
        }
    }

    /**
     * Set currency override code if needed
     *
     * @param string|null $currency
     */
    protected function loadCurrencyOverride($currency)
    {
        if (is_string($currency) && strlen($currency) === 3) {
            $this->addPriceType(PricingTicketing::PRICETYPE_OVERRIDE_CURRENCY_CONVERSION);

            $this->conversionRate = new ConversionRate($currency);
        }
    }

    /**
     * Set multi ticket on if needed
     *
     * @param string|null $multiTicket
     */
    protected function loadMultiTicket($multiTicket)
    {
        if ($multiTicket) {
            $this->addPriceType(PricingTicketing::PRICETYPE_MULTI_TICKET);
        }
    }

    /**
     * Add PriceType
     *
     * @param string $type
     */
    protected function addPriceType($type)
    {
        if (is_null($this->pricingTickInfo)) {
            $this->pricingTickInfo = new PricingTickInfo();
        }
        if (is_null($this->pricingTickInfo->pricingTicketing)) {
            $this->pricingTickInfo->pricingTicketing = new PricingTicketing();
        }

        $this->pricingTickInfo->pricingTicketing->priceType[] = $type;
    }

    protected function loadTicketingPriceScheme($ticketingPriceScheme)
    {
        $priceScheme = new TicketingPriceScheme();
        $priceScheme->referenceNumber = $ticketingPriceScheme->referenceNumber;
        $priceScheme->name = $ticketingPriceScheme->name;
        $priceScheme->status = $ticketingPriceScheme->status;
        $priceScheme->description = $ticketingPriceScheme->description;
        $this->ticketingPriceScheme = $priceScheme;
    }

    protected function loadFormOfPayment(array $formOfPayment)
    {
        /** @var \Amadeus\Client\RequestOptions\Fare\MasterPricer\FormOfPaymentDetails $fop */
        foreach ($formOfPayment as $fop) {
            $this->formOfPayment[] = new FormOfPaymentDetails(
                $fop->type,
                $fop->chargedAmount,
                $fop->creditCardNumber
            );
        }
    }
}


<?php
/**
 * amadeus-ws-client
 *
 * Copyright 2015 Amadeus Benelux NV
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * @package Amadeus
 * @license https://opensource.org/licenses/Apache-2.0 Apache 2.0
 */

namespace Amadeus\Client\ResponseHandler\Air;

use Amadeus\Client\ResponseHandler\StandardResponseHandler;
use Amadeus\Client\Result;
use Amadeus\Client\Session\Handler\SendResult;

/**
 * Utility class to get proper error messages from an Air_RetrieveSeatMapReply message
 *
 * @package Amadeus\Client\ResponseHandler\Air
 * @author Dieter Devlieghere <dermikagh@gmail.com>
 */
class HandlerRetrieveSeatMap extends StandardResponseHandler
{
    /**
     * @param SendResult $response
     * @return Result
     */
    public function analyze(SendResult $response)
    {
        $analyzeResponse = new Result($response);

        $domXpath = $this->makeDomXpath($response->responseXml);

        $errorCodeNode = $domXpath->query('//m:errorInformation/m:errorDetails/m:code');
        if ($errorCodeNode->length > 0) {
            $analyzeResponse->status = Result::STATUS_ERROR;

            $errCode = $errorCodeNode->item(0)->nodeValue;
            $level = null;

            $errorLevelNode = $domXpath->query('//m:errorInformation/m:errorDetails/m:processingLevel');
            if ($errorLevelNode->length > 0) {
                $level = self::decodeProcessingLevel($errorLevelNode->item(0)->nodeValue);
            }

            $errorDescNode = $domXpath->query('//m:errorInformation/m:errorDetails/m:description');
            if ($errorDescNode->length > 0) {
                $errDesc = $errorDescNode->item(0)->nodeValue;
            } else {
                $errDesc = self::findMessage($errCode);
            }

            $analyzeResponse->messages[] = new Result\NotOk(
                $errCode,
                $errDesc,
                $level
            );
        }

        $codeNode = $domXpath->query('//m:warningInformation/m:warningDetails/m:number');
        if ($codeNode->length > 0) {
            $analyzeResponse->status = Result::STATUS_WARN;

            $warnCode = $codeNode->item(0)->nodeValue;
            $level = null;

            $levelNode = $domXpath->query('//m:warningInformation/m:warningDetails/m:processingLevel');
            if ($levelNode->length > 0) {
                $level = self::decodeProcessingLevel($levelNode->item(0)->nodeValue);
            }

            $descNode = $domXpath->query('//m:warningInformation/m:warningDetails/m:description');
            if ($descNode->length > 0) {
                $warnDesc = $descNode->item(0)->nodeValue;
            } else {
                $warnDesc = self::findMessage($warnCode);
            }

            $analyzeResponse->messages[] = new Result\NotOk(
                $warnCode,
                $warnDesc,
                $level
            );
        }

        return $analyzeResponse;
    }

    /**
     * Find the error message for a given error code
     *
     * @param string $code
     * @return string|null
     */
    public static function findMessage($code)
    {
        $message = null;

        if (array_key_exists($code, self::$errorList)) {
            $message = self::$errorList[$code];
        }

        return $message;
    }

    /**
     * Decode error processing level code
     *
     * @param int|string $level
     * @return string|null
     */
    public static function decodeProcessingLevel($level)
    {
        $decoded = null;

        $map = [
            0 => 'system',
            1 => 'application'
        ];

        if (array_key_exists($level, $map)) {
            $decoded = $map[$level];
        }

        return $decoded;
    }

    /**
     * @var array
     */
    public static $errorList = [
        '1' => 'Passenger surname not found',
        '10' => 'Location of arrival is invalid',
        '100' => 'Seat map not available, request seat at check-in',
        '101' => 'Seat map contains conditional seats, it may be subject to reseating',
        '102' => 'Unable to process',
        '103' => 'Segment/Passenger does not qualify for advanced seating',
        '11' => 'Departure/Arrival city pair is invalid',
        '12' => 'Unique name not found',
        '13' => 'Invalid seat number',
        '14' => 'Airline code and/or flight number invalid',
        '15' => 'Flight cancelled',
        '16' => 'Flight check-in held or suspended temporarily',
        '17' => 'Passenger surname already checked in',
        '18' => 'Seating conflict - request contradicts the facility rules',
        '185' => 'Use airline name',
        '186' => 'Use passenger status',
        '187' => 'Flight changes from smoking to non smoking',
        '188' => 'Flight changes from non smoking to smoking',
        '189' => 'Pax has pre-reserved exit seat unable to C/I',
        '19' => 'Baggage weight is required',
        '190' => 'Pax cannot be seated together',
        '191' => 'Generic seat change not supported',
        '192' => 'Seat change-request in row change not supported',
        '193' => 'API pax data required',
        '194' => 'Passenger surname not checked in',
        '195' => 'Change of equipment on this flight',
        '196' => 'Time out occured on host 3',
        '197' => 'Error in frequent flyer number',
        '198' => 'Class code required',
        '199' => 'Check-in separately',
        '2' => 'Seat not available on the requested class/zone',
        '20' => 'Bag count conflict - weight update for non-existing bag',
        '200' => 'FQTV number not accepted',
        '201' => 'FQTV number already present',
        '202' => 'Baggage details not updated',
        '203' => 'SSR details not updated',
        '204' => 'Row invalid',
        '205' => 'Short connection baggage',
        '206' => 'Seat change only supported for single passenger',
        '207' => 'Use generic seating only',
        '208' => 'Update separately',
        '209' => 'Flight changes from seating to openseating (freeseating)',
        '21' => 'Seats not available for passenger type',
        '210' => 'Flight changes from openseating (freeseating) to seating',
        '211' => 'Unable to through-check - complexing/COG/codeshare flight',
        '212' => 'API pax data not supported',
        '213' => 'Time invalid - max/min connecting time for though checkin',
        '214' => 'API date of birth required',
        '215' => 'API passport number required',
        '217' => 'API pax first name required',
        '218' => 'API pax gender required',
        '22' => 'Too many connections - need manual tags',
        '223' => 'API infant data required',
        '224' => 'Passenger holds advance boarding pass',
        '225' => 'Seat Map not available as flight operated by another carrier',
        '226' => 'Seat Request not available as flight operated by another carrier',
        '227' => 'Seat change not possible/seats limited in this area',
        '228' => 'Exchange advanced boarding pass - new data',
        '229' => 'Change not performed on subsequent flight(s)',
        '23' => 'Invalid bag destination - need manual tags',
        '230' => 'Unable to seat change - complexing/COG/codeshare flight',
        '231' => 'Passenger not E.T. type',
        '232' => 'Passenger is E.T. type - needs E.T. indicator',
        '233' => 'Passenger is E.T. type - needs E.T. number',
        '234' => 'Unable to through check - E.T. passenger',
        '235' => 'Tier level not accepted',
        '236' => 'Unable to process - codeshare flight',
        '237' => 'Forward seat due connection - no seat change allowed',
        '238' => 'Australian Visa required - use TIETAC entry each pax',
        '239' => 'Advice of handcarry baggage allowance',
        '24' => 'Passenger actual weight required for this flight',
        '240' => 'Emergency contact information required for U.S. citizen',
        '244' => 'Epass passenger - number differs',
        '245' => 'Epass passenger - not authorized',
        '246' => 'Epass passenger - possible status discrepency',
        '247' => 'Message limit exceed',
        '248' => 'Insufficient upgrade balance',
        '249' => 'Reissue bag tags to correct destination',
        '25' => 'Hand baggage details required',
        '250' => 'Add API data - retry Check in',
        '251' => 'Advise visa and/or documentation status',
        '252' => 'Passenger is E.T. type - ticket/reservation conflict',
        '253' => 'Passenger is E.T. type - ticket record not accessible',
        '254' => 'Cascaded query timed out',
        '255' => 'Unable to check-in - Security profile restriction',
        '256' => 'Passport number printed on boarding pass required',
        '26' => 'No seat selection on this flight',
        '264' => 'API pax data not required',
        '265' => 'Missing or invalid airport check-in identification (FOID)',
        '27' => 'Location of departure is invalid',
        '28' => 'Flight rescheduled - through check-in no longer allowed',
        '29' => 'Flight full in the requested class',
        '3' => 'Invalid seat request',
        '30' => 'Passenger surname off-loaded',
        '300' => 'Seat Map not available for unticketed passengers',
        '31' => 'Passenger surname deleted/cancelled from the flight',
        '32' => 'Bag tag number invalid',
        '33' => 'Flight gated - through check-in is not allowed',
        '34' => 'Time invalid - minimum connecting time for check-in violated',
        '35' => 'Flight closed',
        '36' => 'Passenger not accessible in the system (error/protection)',
        '37' => 'Unique reference for passenger is invalid',
        '38' => 'Passenger party reference is invalid',
        '39' => 'Booking/Ticketing class conflict',
        '4' => 'Bag tag number details required',
        '40' => 'Status conflict - status does not exist',
        '41' => 'Frequent flyer number is invalid',
        '42' => 'Booking/Ticketing class invalid',
        '43' => 'Passenger type conflicts with seats held',
        '44' => 'Too many passengers',
        '45' => 'Unable - group names',
        '46' => 'Unable to check-in partial party',
        '47' => 'Passenger status conflict',
        '48' => 'PNR locator unknown in the receiving system',
        '49' => 'Ticket number invalid',
        '5' => 'Invalid flight/Date',
        '50' => 'Pool airline invalid',
        '51' => 'Operating airline invalid',
        '52' => 'Not authorized - company level',
        '53' => 'Not authorized - station level',
        '54' => 'Not authorized - data level',
        '55' => 'Passenger regraded',
        '56' => 'Passenger seated elsewhere than requested',
        '57' => 'Seat not available in the requested class',
        '58' => 'Seat not available in the requested zone',
        '59' => 'Specific seat not available',
        '6' => 'Too many passengers with the same Surname',
        '60' => 'Free seating in the requested flight',
        '61' => 'Too many infants',
        '62' => 'Smoking zone unavailable',
        '63' => 'Non-smoking zone unavailable',
        '64' => 'Indifferent zone unavailable',
        '65' => 'Check visa and/or documentation',
        '66' => 'No baggage update required for this flight',
        '67' => 'Gender weight is required',
        '68' => 'Item conflict',
        '69' => 'Item weight is required',
        '7' => 'Passenger type or gender conflict',
        '70' => 'Modification not possible',
        '700' => 'Item/data not found - data not existing in processing host',
        '701' => 'Invalid format - data does not match EDIFACT rules',
        '702' => 'No action - Processing host can not support the function',
        '71' => 'No common itinerary',
        '72' => 'Unable to give seat',
        '73' => 'Passenger needs initial',
        '74' => 'Passenger needs first name',
        '75' => 'Collect second flight name',
        '76' => 'Check smallpox vaccination',
        '77' => 'Check yellow fever vaccination',
        '78' => 'Check cholera vaccination',
        '79' => 'Passenger has pre-reserved seat',
        '8' => 'More precise gender is required',
        '80' => 'Flight initialised - retry check in',
        '81' => 'Bag through labeling not allowed beyond this station',
        '82' => 'Too many bags',
        '83' => 'Flight operated as',
        '84' => 'Function not supported',
        '85' => 'Invalid reservations booking modifier',
        '86' => 'Invalid compartment designator code',
        '87' => 'Invalid country code',
        '88' => 'Invalid source of business',
        '89' => 'Invalid agent\'s code',
        '9' => 'Flight is not open for through check-in',
        '90' => 'Requester identification required',
        '91' => 'Seat Map Display request is outside system date range',
        '92' => 'Flight does not operate due to weather, mechanical or other operational conditions',
        '93' => 'Flight does not operate on date requested',
        '94' => 'Flight does not operate between requested cities',
        '95' => 'Schedule change in progress',
        '96' => 'Repeat request updating in progress',
        '97' => 'Flight has departed',
        '98' => 'Seating closed due flight under departure control',
        '99' => 'Seat map not available for requested zone, seat may be requested',
    ];
}


<?php
/*
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * This software consists of voluntary contributions made by many individuals
 * and is licensed under the MIT license. For more information, see
 * <http://www.doctrine-project.org>.
 */

namespace Doctrine\Common\Lexer;

/**
 * Base class for writing simple lexers, i.e. for creating small DSLs.
 *
 * @since  2.0
 * @author Guilherme Blanco <guilhermeblanco@hotmail.com>
 * @author Jonathan Wage <jonwage@gmail.com>
 * @author Roman Borschel <roman@code-factory.org>
 */
abstract class AbstractLexer
{
    /**
     * Lexer original input string.
     *
     * @var string
     */
    private $input;

    /**
     * Array of scanned tokens.
     *
     * Each token is an associative array containing three items:
     *  - 'value'    : the string value of the token in the input string
     *  - 'type'     : the type of the token (identifier, numeric, string, input
     *                 parameter, none)
     *  - 'position' : the position of the token in the input string
     *
     * @var array
     */
    private $tokens = array();

    /**
     * Current lexer position in input string.
     *
     * @var integer
     */
    private $position = 0;

    /**
     * Current peek of current lexer position.
     *
     * @var integer
     */
    private $peek = 0;

    /**
     * The next token in the input.
     *
     * @var array
     */
    public $lookahead;

    /**
     * The last matched/seen token.
     *
     * @var array
     */
    public $token;

    /**
     * Sets the input data to be tokenized.
     *
     * The Lexer is immediately reset and the new input tokenized.
     * Any unprocessed tokens from any previous input are lost.
     *
     * @param string $input The input to be tokenized.
     *
     * @return void
     */
    public function setInput($input)
    {
        $this->input  = $input;
        $this->tokens = array();

        $this->reset();
        $this->scan($input);
    }

    /**
     * Resets the lexer.
     *
     * @return void
     */
    public function reset()
    {
        $this->lookahead = null;
        $this->token = null;
        $this->peek = 0;
        $this->position = 0;
    }

    /**
     * Resets the peek pointer to 0.
     *
     * @return void
     */
    public function resetPeek()
    {
        $this->peek = 0;
    }

    /**
     * Resets the lexer position on the input to the given position.
     *
     * @param integer $position Position to place the lexical scanner.
     *
     * @return void
     */
    public function resetPosition($position = 0)
    {
        $this->position = $position;
    }

    /**
     * Retrieve the original lexer's input until a given position.
     *
     * @param integer $position
     *
     * @return string
     */
    public function getInputUntilPosition($position)
    {
        return substr($this->input, 0, $position);
    }

    /**
     * Checks whether a given token matches the current lookahead.
     *
     * @param integer|string $token
     *
     * @return boolean
     */
    public function isNextToken($token)
    {
        return null !== $this->lookahead && $this->lookahead['type'] === $token;
    }

    /**
     * Checks whether any of the given tokens matches the current lookahead.
     *
     * @param array $tokens
     *
     * @return boolean
     */
    public function isNextTokenAny(array $tokens)
    {
        return null !== $this->lookahead && in_array($this->lookahead['type'], $tokens, true);
    }

    /**
     * Moves to the next token in the input string.
     *
     * @return boolean
     */
    public function moveNext()
    {
        $this->peek = 0;
        $this->token = $this->lookahead;
        $this->lookahead = (isset($this->tokens[$this->position]))
            ? $this->tokens[$this->position++] : null;

        return $this->lookahead !== null;
    }

    /**
     * Tells the lexer to skip input tokens until it sees a token with the given value.
     *
     * @param string $type The token type to skip until.
     *
     * @return void
     */
    public function skipUntil($type)
    {
        while ($this->lookahead !== null && $this->lookahead['type'] !== $type) {
            $this->moveNext();
        }
    }

    /**
     * Checks if given value is identical to the given token.
     *
     * @param mixed   $value
     * @param integer $token
     *
     * @return boolean
     */
    public function isA($value, $token)
    {
        return $this->getType($value) === $token;
    }

    /**
     * Moves the lookahead token forward.
     *
     * @return array|null The next token or NULL if there are no more tokens ahead.
     */
    public function peek()
    {
        if (isset($this->tokens[$this->position + $this->peek])) {
            return $this->tokens[$this->position + $this->peek++];
        } else {
            return null;
        }
    }

    /**
     * Peeks at the next token, returns it and immediately resets the peek.
     *
     * @return array|null The next token or NULL if there are no more tokens ahead.
     */
    public function glimpse()
    {
        $peek = $this->peek();
        $this->peek = 0;
        return $peek;
    }

    /**
     * Scans the input string for tokens.
     *
     * @param string $input A query string.
     *
     * @return void
     */
    protected function scan($input)
    {
        static $regex;

        if ( ! isset($regex)) {
            $regex = sprintf(
                '/(%s)|%s/%s',
                implode(')|(', $this->getCatchablePatterns()),
                implode('|', $this->getNonCatchablePatterns()),
                $this->getModifiers()
            );
        }

        $flags = PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_OFFSET_CAPTURE;
        $matches = preg_split($regex, $input, -1, $flags);

        foreach ($matches as $match) {
            // Must remain before 'value' assignment since it can change content
            $type = $this->getType($match[0]);

            $this->tokens[] = array(
                'value' => $match[0],
                'type'  => $type,
                'position' => $match[1],
            );
        }
    }

    /**
     * Gets the literal for a given token.
     *
     * @param integer $token
     *
     * @return string
     */
    public function getLiteral($token)
    {
        $className = get_class($this);
        $reflClass = new \ReflectionClass($className);
        $constants = $reflClass->getConstants();

        foreach ($constants as $name => $value) {
            if ($value === $token) {
                return $className . '::' . $name;
            }
        }

        return $token;
    }

    /**
     * Regex modifiers
     *
     * @return string
     */
    protected function getModifiers()
    {
        return 'i';
    }

    /**
     * Lexical catchable patterns.
     *
     * @return array
     */
    abstract protected function getCatchablePatterns();

    /**
     * Lexical non-catchable patterns.
     *
     * @return array
     */
    abstract protected function getNonCatchablePatterns();

    /**
     * Retrieve token type. Also processes the token value if necessary.
     *
     * @param string $value
     *
     * @return integer
     */
    abstract protected function getType(&$value);
}


<?php
/**
 * Fastly CDN for Magento
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Fastly CDN for Magento End User License Agreement
 * that is bundled with this package in the file LICENSE_FASTLY_CDN.txt.
 *
 * DISCLAIMER
 *
 * Do not edit or add to this file if you wish to upgrade Fastly CDN to newer
 * versions in the future. If you wish to customize this module for your
 * needs please refer to http://www.magento.com for more information.
 *
 * @category    Fastly
 * @package     Fastly_Cdn
 * @copyright   Copyright (c) 2016 Fastly, Inc. (http://www.fastly.com)
 * @license     BSD, see LICENSE_FASTLY_CDN.txt
 */
namespace Fastly\Cdn\Controller\Adminhtml\FastlyCdn\BasicAuthentication;

use Fastly\Cdn\Model\Api;
use Fastly\Cdn\Model\Config;
use Magento\Backend\App\Action;
use Magento\Backend\App\Action\Context;
use Magento\Framework\Controller\Result\JsonFactory;

/**
 * Class CheckAuthDictionary
 *
 * @package Fastly\Cdn\Controller\Adminhtml\FastlyCdn\BasicAuthentication
 */
class CheckAuthDictionary extends Action
{
    /**
     * @var Api
     */
    private $api;
    /**
     * @var JsonFactory
     */
    private $resultJsonFactory;

    /**
     * CheckTlsSetting constructor.
     *
     * @param Context $context
     * @param Api $api
     * @param JsonFactory $resultJsonFactory
     */
    public function __construct(
        Context $context,
        Api $api,
        JsonFactory $resultJsonFactory
    ) {
        $this->api = $api;
        $this->resultJsonFactory = $resultJsonFactory;

        parent::__construct($context);
    }

    /**
     * Check if AUTH dictionary exists
     *
     * @return \Magento\Framework\Controller\Result\Json
     */
    public function execute()
    {
        $result = $this->resultJsonFactory->create();
        try {
            $activeVersion = $this->getRequest()->getParam('active_version');

            $dictionaryName = Config::AUTH_DICTIONARY_NAME;
            $dictionary = $this->api->getSingleDictionary($activeVersion, $dictionaryName);

            if ((is_array($dictionary) && empty($dictionary)) || $dictionary == false) {
                return $result->setData(['status' => false]);
            } else {
                return $result->setData(['status' => true]);
            }
        } catch (\Exception $e) {
            return $result->setData([
                'status'    => false,
                'msg'       => $e->getMessage()
            ]);
        }
    }
}


<?php
/**
 * Fastly CDN for Magento
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Fastly CDN for Magento End User License Agreement
 * that is bundled with this package in the file LICENSE_FASTLY_CDN.txt.
 *
 * DISCLAIMER
 *
 * Do not edit or add to this file if you wish to upgrade Fastly CDN to newer
 * versions in the future. If you wish to customize this module for your
 * needs please refer to http://www.magento.com for more information.
 *
 * @category    Fastly
 * @package     Fastly_Cdn
 * @copyright   Copyright (c) 2016 Fastly, Inc. (http://www.fastly.com)
 * @license     BSD, see LICENSE_FASTLY_CDN.txt
 */
namespace Fastly\Cdn\Controller\Adminhtml\FastlyCdn\Backend;

use Magento\Backend\App\Action;
use Magento\Backend\App\Action\Context;
use Magento\Framework\App\Request\Http;
use Magento\Framework\Controller\Result\JsonFactory;
use Fastly\Cdn\Model\Api;
use Fastly\Cdn\Helper\Vcl;
use Fastly\Cdn\Model\Config;

/**
 * Class ConfigureBackend
 *
 * @package Fastly\Cdn\Controller\Adminhtml\FastlyCdn\Backend
 */
class ConfigureBackend extends Action
{
    /**
     * @var Http
     */
    private $request;
    /**
     * @var JsonFactory
     */
    private $resultJson;
    /**
     * @var Api
     */
    private $api;
    /**
     * @var Vcl
     */
    private $vcl;
    /**
     * @var Config
     */
    private $config;

    /**
     * ConfigureBackend constructor
     *
     * @param Context $context
     * @param Http $request
     * @param JsonFactory $resultJsonFactory
     * @param Api $api
     * @param Vcl $vcl
     * @param Config $config
     */
    public function __construct(
        Context $context,
        Http $request,
        JsonFactory $resultJsonFactory,
        Api $api,
        Vcl $vcl,
        Config $config
    ) {
        $this->request = $request;
        $this->resultJson = $resultJsonFactory;
        $this->api = $api;
        $this->vcl = $vcl;
        $this->config = $config;
        parent::__construct($context);
    }

    /**
     * Upload VCL snippets
     *
     * @return $this|\Magento\Framework\App\ResponseInterface|\Magento\Framework\Controller\ResultInterface
     */
    public function execute()
    {
        $result = $this->resultJson->create();
        try {
            $activate_flag = $this->getRequest()->getParam('activate_flag');
            $activeVersion = $this->getRequest()->getParam('active_version');
            $oldName = $this->getRequest()->getParam('name');
            $params = [
                'name'                  => $this->getRequest()->getParam('name'),
                'shield'                => $this->getRequest()->getParam('shield'),
                'connect_timeout'       => $this->getRequest()->getParam('connect_timeout'),
                'between_bytes_timeout' => $this->getRequest()->getParam('between_bytes_timeout'),
                'first_byte_timeout'    => $this->getRequest()->getParam('first_byte_timeout'),
            ];
            $service = $this->api->checkServiceDetails();
            $this->vcl->checkCurrentVersionActive($service->versions, $activeVersion);
            $currActiveVersion = $this->vcl->getCurrentVersion($service->versions);
            $clone = $this->api->cloneVersion($currActiveVersion);
            $configureBackend = $this->api->configureBackend($params, $clone->number, $oldName);

            if (!$configureBackend) {
                return $result->setData([
                    'status'    => false,
                    'msg'       => 'Failed to update Backend configuration.'
                ]);
            }

            $this->api->validateServiceVersion($clone->number);

            if ($activate_flag === 'true') {
                $this->api->activateVersion($clone->number);
            }
            if ($this->config->areWebHooksEnabled() && $this->config->canPublishConfigChanges()) {
                $this->api->sendWebHook(
                    '*Backend '
                    . $this->getRequest()->getParam('name')
                    . ' has been changed in Fastly version '
                    . $clone->number
                    . '*'
                );
            }

            $comment = ['comment' => 'Magento Module updated the "'.$oldName.'" Backend Configuration'];
            $this->api->addComment($clone->number, $comment);

            return $result->setData([
                'status'            => true,
                'active_version'    => $clone->number
            ]);
        } catch (\Exception $e) {
            return $result->setData([
                'status'    => false,
                'msg'       => $e->getMessage()
            ]);
        }
    }
}


<?php
/**
 * Fastly CDN for Magento
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Fastly CDN for Magento End User License Agreement
 * that is bundled with this package in the file LICENSE_FASTLY_CDN.txt.
 *
 * DISCLAIMER
 *
 * Do not edit or add to this file if you wish to upgrade Fastly CDN to newer
 * versions in the future. If you wish to customize this module for your
 * needs please refer to http://www.magento.com for more information.
 *
 * @category    Fastly
 * @package     Fastly_Cdn
 * @copyright   Copyright (c) 2016 Fastly, Inc. (http://www.fastly.com)
 * @license     BSD, see LICENSE_FASTLY_CDN.txt
 */
namespace Fastly\Cdn\Controller\Adminhtml\FastlyCdn\Maintenance;

use Fastly\Cdn\Model\Config;
use Fastly\Cdn\Model\Api;
use Fastly\Cdn\Helper\Vcl;
use Magento\Backend\App\Action;
use Magento\Backend\App\Action\Context;
use Magento\Framework\Controller\Result\JsonFactory;

/**
 * Class CheckSuSetting
 * @package Fastly\Cdn\Controller\Adminhtml\FastlyCdn\Maintenance
 */
class CheckSuSetting extends Action
{
    /**
     * @var Api
     */
    private $api;
    /**
     * @var Vcl
     */
    private $vcl;
    /**
     * @var Config
     */
    private $config;
    /**
     * @var JsonFactory
     */
    private $resultJsonFactory;

    /**
     * CheckSuSetting constructor.
     * @param Context $context
     * @param Config $config
     * @param Api $api
     * @param Vcl $vcl
     * @param JsonFactory $resultJsonFactory
     */
    public function __construct(
        Context $context,
        Config $config,
        Api $api,
        Vcl $vcl,
        JsonFactory $resultJsonFactory
    ) {
        $this->api = $api;
        $this->vcl = $vcl;
        $this->config = $config;
        $this->resultJsonFactory = $resultJsonFactory;

        parent::__construct($context);
    }

    /**
     * Verifies whether super users are enabled in the magentomodule_config dictionary
     *
     * @return \Magento\Framework\Controller\Result\Json
     */
    public function execute()
    {
        $result = $this->resultJsonFactory->create();
        try {
            $service = $this->api->checkServiceDetails();
            $currActiveVersion = $this->vcl->getCurrentVersion($service->versions);

            $dictionaryName = Config::CONFIG_DICTIONARY_NAME;
            $dictionary = $this->api->getSingleDictionary($currActiveVersion, $dictionaryName);

            if (!$dictionary) {
                return $result->setData([
                    'status' => false
                ]);
            }

            $dictionaryItems = $this->api->dictionaryItemsList($dictionary->id);

            foreach ($dictionaryItems as $item) {
                if ($item->item_key == Config::CONFIG_DICTIONARY_KEY && $item->item_value == 1) {
                    return $result->setData([
                        'status' => true
                    ]);
                }
            }

            return $result->setData([
                'status' => false
            ]);
        } catch (\Exception $e) {
            return $result->setData([
                'status'    => false,
                'msg'       => $e->getMessage()
            ]);
        }
    }
}


<?php
/**
 * Fastly CDN for Magento
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Fastly CDN for Magento End User License Agreement
 * that is bundled with this package in the file LICENSE_FASTLY_CDN.txt.
 *
 * DISCLAIMER
 *
 * Do not edit or add to this file if you wish to upgrade Fastly CDN to newer
 * versions in the future. If you wish to customize this module for your
 * needs please refer to http://www.magento.com for more information.
 *
 * @category    Fastly
 * @package     Fastly_Cdn
 * @copyright   Copyright (c) 2016 Fastly, Inc. (http://www.fastly.com)
 * @license     BSD, see LICENSE_FASTLY_CDN.txt
 */
namespace Fastly\Cdn\Controller\Adminhtml\FastlyCdn\Edge\Dictionary;

use Fastly\Cdn\Model\Api;
use Magento\Backend\App\Action;
use Magento\Backend\App\Action\Context;
use Magento\Framework\App\Request\Http;
use Magento\Framework\Controller\Result\JsonFactory;
use Fastly\Cdn\Model\Config;
use Fastly\Cdn\Helper\Vcl;
use Magento\Framework\Exception\LocalizedException;

/**
 * Class Delete
 *
 * @package Fastly\Cdn\Controller\Adminhtml\FastlyCdn\Edge\Dictionary
 */
class Delete extends Action
{
    /**
     * @var Http
     */
    private $request;
    /**
     * @var JsonFactory
     */
    private $resultJson;
    /**
     * @var Config
     */
    private $config;
    /**
     * @var Api
     */
    private $api;
    /**
     * @var Vcl
     */
    private $vcl;

    /**
     * ForceTls constructor.
     *
     * @param Context $context
     * @param Http $request
     * @param JsonFactory $resultJsonFactory
     * @param Config $config
     * @param Api $api
     * @param Vcl $vcl
     */
    public function __construct(
        Context $context,
        Http $request,
        JsonFactory $resultJsonFactory,
        Config $config,
        Api $api,
        Vcl $vcl
    ) {
        $this->request = $request;
        $this->resultJson = $resultJsonFactory;
        $this->config = $config;
        $this->api = $api;
        $this->vcl = $vcl;

        parent::__construct($context);
    }

    /**
     * Delete dictionary
     *
     * @return $this|\Magento\Framework\App\ResponseInterface|\Magento\Framework\Controller\ResultInterface
     */
    public function execute()
    {
        $result = $this->resultJson->create();

        try {
            $activeVersion = $this->getRequest()->getParam('active_version');
            $activateVcl = $this->getRequest()->getParam('activate_flag');
            $dictionary_o = $this->getRequest()->getParam('dictionary');
            $dictionary = preg_replace('/\s+/', '%20', $dictionary_o);
            $service = $this->api->checkServiceDetails();
            $this->vcl->checkCurrentVersionActive($service->versions, $activeVersion);
            $currActiveVersion = $this->vcl->getCurrentVersion($service->versions);
            $clone = $this->api->cloneVersion($currActiveVersion);
            $used = '';

            $response = $this->api->deleteDictionary($clone->number, $dictionary);

            if ($response == false) {
                return $result->setData([
                    'status'    => false,
                    'msg'       => 'Failed to delete dictionary.'
                ]);
            }
            $validation = $this->api->containerValidateServiceVersion($clone->number);
            if ($validation->status == 'error') {
                $used = $dictionary;
            }
            if ($used != '') {
                throw new LocalizedException(__(
                    'Failed to validate service, the container "' . $used . '" may be in use. '
                ));
            }

            if ($activateVcl === 'true') {
                $this->api->activateVersion($clone->number);
            }

            $comment = ['comment' => 'Magento Module deleted the "'.$dictionary_o.'" Dictionary'];
            $this->api->addComment($clone->number, $comment);

            return $result->setData([
                'status'            => true,
                'active_version'    => $clone->number
            ]);
        } catch (\Exception $e) {
            return $result->setData([
                'status'    => false,
                'msg'       => $e->getMessage()
            ]);
        }
    }
}


<?php
/**
 * Fastly CDN for Magento
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Fastly CDN for Magento End User License Agreement
 * that is bundled with this package in the file LICENSE_FASTLY_CDN.txt.
 *
 * DISCLAIMER
 *
 * Do not edit or add to this file if you wish to upgrade Fastly CDN to newer
 * versions in the future. If you wish to customize this module for your
 * needs please refer to http://www.magento.com for more information.
 *
 * @category    Fastly
 * @package     Fastly_Cdn
 * @copyright   Copyright (c) 2016 Fastly, Inc. (http://www.fastly.com)
 * @license     BSD, see LICENSE_FASTLY_CDN.txt
 */
namespace Fastly\Cdn\Controller\Adminhtml\FastlyCdn\Waf;

use Magento\Backend\App\Action;
use Magento\Backend\App\Action\Context;
use Magento\Framework\App\Request\Http;
use Magento\Framework\Controller\Result\JsonFactory;
use Fastly\Cdn\Model\Config;
use Fastly\Cdn\Model\Api;
use Fastly\Cdn\Helper\Vcl;
use Magento\Framework\Exception\LocalizedException;

/**
 * Class WafAllowlist
 *
 * @package Fastly\Cdn\Controller\Adminhtml\FastlyCdn\Waf
 */
class WafAllowlist extends Action
{
    /**
     * @var Http
     */
    private $request;
    /**
     * @var JsonFactory
     */
    private $resultJson;
    /**
     * @var Config
     */
    private $config;
    /**
     * @var Api
     */
    private $api;
    /**
     * @var Vcl
     */
    private $vcl;

    /**
     * WafAllowlist constructor.
     *
     * @param Context $context
     * @param Http $request
     * @param JsonFactory $resultJsonFactory
     * @param Config $config
     * @param Api $api
     * @param Vcl $vcl
     */
    public function __construct(
        Context $context,
        Http $request,
        JsonFactory $resultJsonFactory,
        Config $config,
        Api $api,
        Vcl $vcl
    ) {
        $this->request = $request;
        $this->resultJson = $resultJsonFactory;
        $this->config = $config;
        $this->api = $api;
        $this->vcl = $vcl;
        parent::__construct($context);
    }

    /**
     * Upload WAF allowlist snippet
     *
     * @return \Magento\Framework\App\ResponseInterface|\Magento\Framework\Controller\Result\Json|\Magento\Framework\Controller\ResultInterface
     */
    public function execute()
    {
        $result = $this->resultJson->create();
        try {
            $activeVersion = $this->getRequest()->getParam('active_version');
            $activateVcl = $this->getRequest()->getParam('activate_flag');
            $service = $this->api->checkServiceDetails();
            $this->vcl->checkCurrentVersionActive($service->versions, $activeVersion);
            $currActiveVersion = $this->vcl->getCurrentVersion($service->versions);
            $clone = $this->api->cloneVersion($currActiveVersion);

            $checkIfSettingExists = $this->api->hasSnippet($activeVersion, Config::WAF_SETTING_NAME);
            $snippet = $this->config->getVclSnippets(
                Config::VCL_WAF_PATH,
                Config::VCL_WAF_ALLOWLIST_SNIPPET
            );
            $acls = $this->prepareAcls($this->config->getWafAllowByAcl());

            $allowedItems = $acls;
            $strippedAllowedItems = substr($allowedItems, 0, strrpos($allowedItems, '||', -1));

            if (!$checkIfSettingExists) {
                // Add WAF allowlist snippet
                foreach ($snippet as $key => $value) {
                    if ($strippedAllowedItems === '') {
                        $value = '';
                    } else {
                        $value = str_replace('####WAF_ALLOWLIST####', $strippedAllowedItems, $value);
                    }

                    $snippetData = [
                        'name'      => Config::FASTLY_MAGENTO_MODULE . '_waf_' . $key,
                        'type'      => $key,
                        'dynamic'   => 1,
                        'priority'  => 10,
                        'content'   => $value
                    ];

                    $this->api->uploadSnippet($clone->number, $snippetData);
                }
            } else {
                // Remove WAF allowlist snippet
                foreach ($snippet as $key => $value) {
                    $name = Config::FASTLY_MAGENTO_MODULE . '_waf_' . $key;
                    if ($this->api->hasSnippet($clone->number, $name) == true) {
                        $this->api->removeSnippet($clone->number, $name);
                    }
                }
            }

            $this->api->validateServiceVersion($clone->number);

            if ($activateVcl === 'true') {
                $this->api->activateVersion($clone->number);
            }

            $this->sendWebhook($checkIfSettingExists, $clone);

            $comment = ['comment' => 'Magento Module turned ON WAF ACL Bypass'];
            if ($checkIfSettingExists) {
                $comment = ['comment' => 'Magento Module turned OFF WAF ACL Bypass'];
            }
            $this->api->addComment($clone->number, $comment);

            return $result->setData([
                'status' => true
            ]);
        } catch (\Exception $e) {
            return $result->setData([
                'status'    => false,
                'msg'       => $e->getMessage()
            ]);
        }
    }

    /**
     * Prepares ACL VCL snippets
     *
     * @param $allowedAcls
     * @return string
     */
    private function prepareAcls($allowedAcls)
    {
        $result = '';

        if ($allowedAcls != null) {
            $allowedAclsPieces = explode(",", $allowedAcls);
            foreach ($allowedAclsPieces as $acl) {
                $result .= ' req.http.Fastly-Client-Ip ~ ' . $acl . ' ||';
            }
        }

        return $result;
    }

    private function sendWebhook($checkIfSettingExists, $clone)
    {
        if ($this->config->areWebHooksEnabled() && $this->config->canPublishConfigChanges()) {
            if ($checkIfSettingExists) {
                $this->api->sendWebHook('
                *WAF ACL Bypass has been turned OFF in Fastly version ' . $clone->number . '*');
            } else {
                $this->api->sendWebHook('*WAF ACL Bypass has been turned ON in Fastly version ' . $clone->number . '*');
            }
        }
    }
}


<?php
/**
 * Fastly CDN for Magento
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Fastly CDN for Magento End User License Agreement
 * that is bundled with this package in the file LICENSE_FASTLY_CDN.txt.
 *
 * DISCLAIMER
 *
 * Do not edit or add to this file if you wish to upgrade Fastly CDN to newer
 * versions in the future. If you wish to customize this module for your
 * needs please refer to http://www.magento.com for more information.
 *
 * @category    Fastly
 * @package     Fastly_Cdn
 * @copyright   Copyright (c) 2016 Fastly, Inc. (http://www.fastly.com)
 * @license     BSD, see LICENSE_FASTLY_CDN.txt
 */
namespace Fastly\Cdn\Controller\Adminhtml\FastlyCdn\Edge\Dictionary;

use Fastly\Cdn\Model\Api;
use Magento\Backend\App\Action;
use Magento\Backend\App\Action\Context;
use Magento\Framework\App\Request\Http;
use Magento\Framework\Controller\Result\JsonFactory;

/**
 * Class ListAll
 *
 * @package Fastly\Cdn\Controller\Adminhtml\FastlyCdn\Edge\Dictionary
 */
class ListAll extends Action
{
    /**
     * @var Http
     */
    private $request;
    /**
     * @var JsonFactory
     */
    private $resultJson;
    /**
     * @var Api
     */
    private $api;

    /**
     * ListAll constructor
     *
     * @param Context $context
     * @param Http $request
     * @param JsonFactory $resultJsonFactory
     * @param Api $api
     */
    public function __construct(
        Context $context,
        Http $request,
        JsonFactory $resultJsonFactory,
        Api $api
    ) {
        $this->request = $request;
        $this->resultJson = $resultJsonFactory;
        $this->api = $api;

        parent::__construct($context);
    }

    /**
     * Get all dictionaries for active version
     *
     * @return $this|\Magento\Framework\App\ResponseInterface|\Magento\Framework\Controller\ResultInterface
     */
    public function execute()
    {
        $result = $this->resultJson->create();

        try {
            $activeVersion = $this->getRequest()->getParam('active_version');
            $dictionaries = $this->api->getDictionaries($activeVersion);

            if (is_array($dictionaries) && empty($dictionaries)) {
                return $result->setData([
                    'status'        => true,
                    'dictionaries'  => []
                ]);
            }

            if (!$dictionaries) {
                return $result->setData([
                    'status'    => false,
                    'msg'       => 'Failed to fetch dictionaries.'
                ]);
            }

            return $result->setData([
                'status'        => true,
                'dictionaries'  => $dictionaries
            ]);
        } catch (\Exception $e) {
            return $result->setData([
                'status'    => false,
                'msg'       => $e->getMessage()
            ]);
        }
    }
}


<?php
/**
 * Fastly CDN for Magento
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Fastly CDN for Magento End User License Agreement
 * that is bundled with this package in the file LICENSE_FASTLY_CDN.txt.
 *
 * DISCLAIMER
 *
 * Do not edit or add to this file if you wish to upgrade Fastly CDN to newer
 * versions in the future. If you wish to customize this module for your
 * needs please refer to http://www.magento.com for more information.
 *
 * @category    Fastly
 * @package     Fastly_Cdn
 * @copyright   Copyright (c) 2016 Fastly, Inc. (http://www.fastly.com)
 * @license     BSD, see LICENSE_FASTLY_CDN.txt
 */
namespace Fastly\Cdn\Model;

use Fastly\Cdn\Helper\CacheTags;
use Magento\Framework\App\Response\Http;
use Fastly\Cdn\Model\Config;

/**
 * Class ResponsePlugin
 *
 * @package Fastly\Cdn\Model
 */
class ResponsePlugin
{
    /**
     * @var Config
     */
    private $config;
    /**
     * @var CacheTags
     */
    private $cacheTags;

    /**
     * ResponsePlugin constructor.
     *
     * @param Config $config
     * @param CacheTags $cacheTags
     */
    public function __construct(
        Config $config,
        CacheTags $cacheTags
    ) {
        $this->config       = $config;
        $this->cacheTags    = $cacheTags;
    }

    /**
     * Alter the X-Magento-Tags header
     *
     * @param Http $subject
     * @param callable $proceed
     * @param array ...$args
     * @return mixed
     */
    public function aroundSetHeader(Http $subject, callable $proceed, ...$args) // @codingStandardsIgnoreLine - unused parameter
    {
        // Is Fastly cache enabled?
        if ($this->config->getType() !== Config::FASTLY) {
            return $proceed(...$args);
        }

        // Is current header X-Magento-Tags
        if (isset($args[0]) == true && $args[0] !== 'X-Magento-Tags') {
            return $proceed(...$args);
        }

        // Make the necessary adjustment
        $args[1] = $this->cacheTags->convertCacheTags(str_replace(',', ' ', $args[1]));
        $tagsSize = $this->config->getXMagentoTagsSize();
        if (strlen($args[1]) > $tagsSize) {
            $trimmedArgs = substr($args[1], 0, $tagsSize);
            $args[1] = substr($trimmedArgs, 0, strrpos($trimmedArgs, ' ', -1));
        }

        // Proceed
        return $proceed(...$args);
    }
}


<?php
/**
 * Fastly CDN for Magento
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Fastly CDN for Magento End User License Agreement
 * that is bundled with this package in the file LICENSE_FASTLY_CDN.txt.
 *
 * DISCLAIMER
 *
 * Do not edit or add to this file if you wish to upgrade Fastly CDN to newer
 * versions in the future. If you wish to customize this module for your
 * needs please refer to http://www.magento.com for more information.
 *
 * @category    Fastly
 * @package     Fastly_Cdn
 * @copyright   Copyright (c) 2016 Fastly, Inc. (http://www.fastly.com)
 * @license     BSD, see LICENSE_FASTLY_CDN.txt
 */
namespace Fastly\Cdn\Controller\Adminhtml\FastlyCdn\Edge\Acl\Item;

use Magento\Backend\App\Action;
use Magento\Backend\App\Action\Context;
use Magento\Framework\App\Request\Http;
use Magento\Framework\Controller\Result\JsonFactory;
use Fastly\Cdn\Model\Config;
use Fastly\Cdn\Model\Api;
use Fastly\Cdn\Helper\Vcl;

/**
 * Class Delete
 *
 * @package Fastly\Cdn\Controller\Adminhtml\FastlyCdn\Edge\Acl\Item
 */
class Delete extends Action
{
    /**
     * @var Http
     */
    private $request;
    /**
     * @var JsonFactory
     */
    private $resultJson;
    /**
     * @var Config
     */
    private $config;
    /**
     * @var Api
     */
    private $api;
    /**
     * @var Vcl
     */
    private $vcl;

    /**
     * ForceTls constructor.
     *
     * @param Context $context
     * @param Http $request
     * @param JsonFactory $resultJsonFactory
     * @param Config $config
     * @param Api $api
     * @param Vcl $vcl
     */
    public function __construct(
        Context $context,
        Http $request,
        JsonFactory $resultJsonFactory,
        Config $config,
        Api $api,
        Vcl $vcl
    ) {
        $this->request = $request;
        $this->resultJson = $resultJsonFactory;
        $this->config = $config;
        $this->api = $api;
        $this->vcl = $vcl;

        parent::__construct($context);
    }

    /**
     * Delete ACL entry
     *
     * @return $this|\Magento\Framework\App\ResponseInterface|\Magento\Framework\Controller\ResultInterface
     */
    public function execute()
    {
        $result = $this->resultJson->create();

        try {
            $aclId = $this->getRequest()->getParam('acl_id');
            $aclItemId = $this->getRequest()->getParam('acl_item_id');

            $deleteItem = $this->api->deleteAclItem($aclId, $aclItemId);

            if (!$deleteItem) {
                return $result->setData(['status' => false]);
            }

            return $result->setData(['status' => true]);
        } catch (\Exception $e) {
            return $result->setData([
                'status'    => false,
                'msg'       => $e->getMessage()
            ]);
        }
    }
}


<?php
/**
 * Fastly CDN for Magento
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Fastly CDN for Magento End User License Agreement
 * that is bundled with this package in the file LICENSE_FASTLY_CDN.txt.
 *
 * DISCLAIMER
 *
 * Do not edit or add to this file if you wish to upgrade Fastly CDN to newer
 * versions in the future. If you wish to customize this module for your
 * needs please refer to http://www.magento.com for more information.
 *
 * @category    Fastly
 * @package     Fastly_Cdn
 * @copyright   Copyright (c) 2016 Fastly, Inc. (http://www.fastly.com)
 * @license     BSD, see LICENSE_FASTLY_CDN.txt
 */
namespace Fastly\Cdn\Controller\Adminhtml\FastlyCdn\ImageOptimization;

use Magento\Backend\App\Action;
use Magento\Backend\App\Action\Context;
use Magento\Framework\App\Request\Http;
use Magento\Framework\Controller\Result\JsonFactory;
use Fastly\Cdn\Model\Api;

/**
 * Class ListAll
 *
 * @package Fastly\Cdn\Controller\Adminhtml\FastlyCdn\ImageOptimization
 */
class ListAll extends Action
{
    /**
     * @var Http
     */
    private $request;
    /**
     * @var JsonFactory
     */
    private $resultJson;
    /**
     * @var Api
     */
    private $api;

    /**
     * ListAll constructor
     *
     * @param Context $context
     * @param Http $request
     * @param JsonFactory $resultJsonFactory
     * @param Api $api
     */
    public function __construct(
        Context $context,
        Http $request,
        JsonFactory $resultJsonFactory,
        Api $api
    ) {
        $this->request = $request;
        $this->resultJson = $resultJsonFactory;
        $this->api = $api;
        parent::__construct($context);
    }

    /**
     * List all image optimization default config options
     *
     * @return $this|\Magento\Framework\App\ResponseInterface|\Magento\Framework\Controller\ResultInterface
     */
    public function execute()
    {
        $result = $this->resultJson->create();

        try {
            $activeVersion = $this->getRequest()->getParam('active_version');
            $ioOptions = $this->api->getImageOptimizationDefaultConfigOptions($activeVersion)->data->attributes;

            if (!$ioOptions) {
                return $result->setData([
                    'status'    => false,
                    'msg'       => 'Failed to fetch image optimization default config options.'
                ]);
            }

            return $result->setData([
                'status'        => true,
                'io_options'    => $ioOptions
            ]);
        } catch (\Exception $e) {
            return $result->setData([
                'status'    => false,
                'msg'       => $e->getMessage()
            ]);
        }
    }
}


<?php
/**
 * Fastly CDN for Magento
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Fastly CDN for Magento End User License Agreement
 * that is bundled with this package in the file LICENSE_FASTLY_CDN.txt.
 *
 * DISCLAIMER
 *
 * Do not edit or add to this file if you wish to upgrade Fastly CDN to newer
 * versions in the future. If you wish to customize this module for your
 * needs please refer to http://www.magento.com for more information.
 *
 * @category    Fastly
 * @package     Fastly_Cdn
 * @copyright   Copyright (c) 2016 Fastly, Inc. (http://www.fastly.com)
 * @license     BSD, see LICENSE_FASTLY_CDN.txt
 */
namespace Fastly\Cdn\Helper;

use Magento\Framework\App\Helper\AbstractHelper;
use Magento\Framework\App\Helper\Context;
use Magento\Framework\App\DeploymentConfig\Reader;
use Magento\Framework\Exception\LocalizedException;

/**
 * Class Vcl
 *
 * @package Fastly\Cdn\Helper
 */
class Vcl extends AbstractHelper
{
    /**
     * @var Reader
     */
    private $configReader;

    /**
     * Templetize constructor.
     * @param Context $context
     * @param Reader $configReader
     */
    public function __construct(
        Context $context,
        Reader $configReader
    ) {
        $this->configReader = $configReader;

        parent::__construct($context);
    }

    /**
     * Fetch current version
     *
     * @param array $versions
     * @return mixed
     * @throws LocalizedException
     */
    public function getCurrentVersion(array $versions)
    {
        if (!empty($versions)) {
            foreach ($versions as $version) {
                if ($version->active) {
                    return $activeVersion = $version->number;
                }
            }
        }

        throw new LocalizedException(__('Error fetching current version.'));
    }

    /**
     * Fetch next version
     *
     * @param array $versions
     * @return int
     * @throws LocalizedException
     */
    public function getNextVersion(array $versions)
    {
        if (isset(end($versions)->number)) {
            return (int) end($versions)->number + 1;
        }

        throw new LocalizedException(__('Error fetching next version.'));
    }

    /**
     * Check if active versions (local and remote) are in sync
     *
     * @param $versions
     * @param $activeVersion
     * @return bool
     * @throws LocalizedException
     */
    public function checkCurrentVersionActive($versions, $activeVersion)
    {
        $current = $this->getCurrentVersion($versions);

        if ($current != $activeVersion) {
            throw new LocalizedException(__('Active versions mismatch.'));
        }

        return true;
    }

    /**
     * Get the admin front name
     *
     * @return mixed
     * @throws \Exception
     * @throws \Magento\Framework\Exception\FileSystemException
     */
    public function getAdminFrontName()
    {
        $config = $this->configReader->load();
        $adminFrontName = $config['backend']['frontName'];

        return $adminFrontName;
    }

    /**
     * Determine currently service active version and the next version in which the active version will be cloned
     *
     * @param array $versions
     * @return array
     */
    public function determineVersions(array $versions)
    {
        $activeVersion = null;
        $nextVersion = null;

        if (!empty($versions)) {
            foreach ($versions as $version) {
                if ($version->active) {
                    $activeVersion = $version->number;
                }
            }

            $nextVersion = (int) end($versions)->number + 1;
        }

        return [
            'active_version'    => $activeVersion,
            'next_version'      => $nextVersion
        ];
    }

    /**
     * Fetches and validates active version
     *
     * @param $service
     * @param $activeVersion
     * @return array
     * @throws LocalizedException
     */
    public function getActiveVersion($service, $activeVersion)
    {
        $currActiveVersion = $this->determineVersions($service->versions);
        if ($currActiveVersion['active_version'] != $activeVersion) {
            throw new LocalizedException(__('Active versions mismatch.'));
        }
        return $currActiveVersion;
    }
}


<?php
/**
 * Fastly CDN for Magento
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Fastly CDN for Magento End User License Agreement
 * that is bundled with this package in the file LICENSE_FASTLY_CDN.txt.
 *
 * DISCLAIMER
 *
 * Do not edit or add to this file if you wish to upgrade Fastly CDN to newer
 * versions in the future. If you wish to customize this module for your
 * needs please refer to http://www.magento.com for more information.
 *
 * @category    Fastly
 * @package     Fastly_Cdn
 * @copyright   Copyright (c) 2016 Fastly, Inc. (http://www.fastly.com)
 * @license     BSD, see LICENSE_FASTLY_CDN.txt
 */
namespace Fastly\Cdn\Controller\Adminhtml\FastlyCdn\BasicAuthentication\Item;

use Magento\Backend\App\Action;
use Magento\Backend\App\Action\Context;
use Magento\Framework\App\Request\Http;
use Magento\Framework\Controller\Result\JsonFactory;
use Fastly\Cdn\Model\Config;
use Fastly\Cdn\Model\Api;
use Fastly\Cdn\Helper\Vcl;

/**
 * Class Create
 *
 * @package Fastly\Cdn\Controller\Adminhtml\FastlyCdn\BasicAuthentication\Item
 */
class Create extends Action
{
    /**
     * @var Http
     */
    private $request;
    /**
     * @var JsonFactory
     */
    private $resultJson;
    /**
     * @var Config
     */
    private $config;
    /**
     * @var Api
     */
    private $api;
    /**
     * @var Vcl
     */
    private $vcl;

    /**
     * ForceTls constructor.
     *
     * @param Context $context
     * @param Http $request
     * @param JsonFactory $resultJsonFactory
     * @param Config $config
     * @param Api $api
     * @param Vcl $vcl
     */
    public function __construct(
        Context $context,
        Http $request,
        JsonFactory $resultJsonFactory,
        Config $config,
        Api $api,
        Vcl $vcl
    ) {
        $this->request = $request;
        $this->resultJson = $resultJsonFactory;
        $this->config = $config;
        $this->api = $api;
        $this->vcl = $vcl;
        parent::__construct($context);
    }

    /**
     * Create auth item
     *
     * @return \Magento\Framework\App\ResponseInterface|\Magento\Framework\Controller\Result\Json|\Magento\Framework\Controller\ResultInterface
     */
    public function execute()
    {
        $result = $this->resultJson->create();

        try {
            $activeVersion = $this->getRequest()->getParam('active_version');

            $dictionary = $this->api->getAuthDictionary($activeVersion);

            if ((is_array($dictionary) && empty($dictionary)) || !isset($dictionary->id)) {
                return $result->setData([
                    'status'    => 'empty',
                    'msg'       => 'Authentication dictionary does not exist.'
                ]);
            }

            $user = $this->getRequest()->getParam('auth_user');
            $pass = $this->getRequest()->getParam('auth_pass');
            $key = base64_encode($user . ':' . $pass);
            $this->api->upsertDictionaryItem($dictionary->id, $key, true);

            return $result->setData(['status' => true]);
        } catch (\Exception $e) {
            return $result->setData([
                'status'    => false,
                'msg'       => $e->getMessage()
            ]);
        }
    }
}