<?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\App\ResponseInterface;
use Magento\Framework\Controller\Result\JsonFactory;
use Fastly\Cdn\Model\Api;
use Magento\Framework\Controller\ResultInterface;

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

    /**
     * GetBackends 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 backends for active version
     *
     * @return $this|ResponseInterface|ResultInterface
     */
    public function execute()
    {
        $result = $this->resultJson->create();
        try {
            $activeVersion = $this->getRequest()->getParam('active_version');
            $backends = $this->api->getBackends($activeVersion);

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

            return $result->setData([
                'status'    => true,
                'backends'  => $backends
            ]);
        } 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\Purge;

use Fastly\Cdn\Model\Api;
use Magento\Backend\App\Action;
use Magento\Backend\App\Action\Context;
use Magento\Framework\App\Cache\Manager;

/**
 * Class All
 *
 * @package Fastly\Cdn\Controller\Adminhtml\FastlyCdn\Purge
 */
class All extends Action
{
    /**
     * @var Api
     */
    private $api;
    /**
     * @var Manager
     */
    private $cacheManager;

    /**
     * All constructor.
     *
     * @param Context $context
     * @param Api $api
     * @param Manager $cacheManager
     */
    public function __construct(
        Context $context,
        Api $api,
        Manager $cacheManager
    ) {
        $this->api = $api;
        $this->cacheManager = $cacheManager;

        parent::__construct($context);
    }

    /**
     * Performs cache cleanup and purge all on Fastly service.
     * Should be used when "Preserve static assets on purge" is enabled.
     *
     * @return \Magento\Framework\App\ResponseInterface|\Magento\Framework\Controller\ResultInterface
     * @throws \Zend_Uri_Exception
     */
    public function execute()
    {
        // Flush all Magento caches
        $types = $this->cacheManager->getAvailableTypes();
        $types = array_diff($types, ['full_page']); // FPC is Handled separately

        $this->cacheManager->clean($types);

        // Purge everything from Fastly
        $result = $this->api->cleanAll();

        if ($result === true) {
            $this->messageManager->addSuccessMessage(
                __('Full Magento & Fastly Cache has been cleaned.')
            );
        } else {
            $this->getMessageManager()->addErrorMessage(
                __('Full Magento & Fastly Cache was not cleaned successfully.')
            );
        }

        return $this->_redirect('*/cache/index');
    }
}


<?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\SyntheticPages;

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 SaveErrorPageHtml
 *
 * @package Fastly\Cdn\Controller\Adminhtml\FastlyCdn\SyntheticPages
 */
class SaveErrorPageHtml extends Action
{
    /**
     * @var Http
     */
    private $request;
    /**
     * @var JsonFactory
     */
    private $resultJson;
    /**
     * @var Config
     */
    private $config;
    /**
     * @var Api
     */
    private $api;
    /**
     * @var Vcl
     */
    private $vcl;

    /**
     * SaveErrorPageHtml 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);
    }

    /**
     * Save Error Page Html
     *
     * @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');
            $html = $this->getRequest()->getParam('html');
            $service = $this->api->checkServiceDetails();
            $this->vcl->checkCurrentVersionActive($service->versions, $activeVersion);
            $currActiveVersion = $this->vcl->getCurrentVersion($service->versions);
            $clone = $this->api->cloneVersion($currActiveVersion);
            $snippets = $this->config->getVclSnippets(
                Config::VCL_ERROR_SNIPPET_PATH,
                Config::VCL_ERROR_SNIPPET
            );

            foreach ($snippets as $key => $value) {
                $snippetData = [
                    'name'      => Config::FASTLY_MAGENTO_MODULE . '_error_page_' . $key,
                    'type'      => $key,
                    'dynamic'   => '0',
                    'content'   => $value
                ];
                $this->api->uploadSnippet($clone->number, $snippetData);
            }

            $condition = [
                'name' => Config::FASTLY_MAGENTO_MODULE.'_error_page_condition',
                'statement' => 'req.http.ResponseObject == "970"',
                'type' => 'REQUEST',
                'priority' => '9'
            ];

            $createCondition = $this->api->createCondition($clone->number, $condition);
            $response = [
                'name'              => Config::ERROR_PAGE_RESPONSE_OBJECT,
                'request_condition' => $createCondition->name,
                'content'           =>  $html,
                'status'            => "503",
                'content_type'      => "text/html; charset=utf-8",
                'response'          => "Service Temporarily Unavailable"
            ];

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

            if (!$createResponse) {
                return $result->setData([
                    'status'    => false,
                    'msg'       => 'Failed to create a RESPONSE object.'
                ]);
            }

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

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

            if ($this->config->areWebHooksEnabled() && $this->config->canPublishConfigChanges()) {
                $this->api->sendWebHook(
                    '*New Error/Maintenance page has updated and activated under config version ' . $clone->number . '*'
                );
            }

            $comment = ['comment' => 'Magento Module updated Error Page html'];
            $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\Model\Layout;

use \Fastly\Cdn\Model\Config;

/**
 * Class LayoutPlugin
 *
 * @package Fastly\Cdn\Model\Layout
 */
class LayoutPlugin
{
    /**
     * @var \Magento\PageCache\Model\Config
     */
    private $config;
    /**
     * @var \Magento\Framework\App\ResponseInterface
     */
    private $response;
    /**
     * @var \Fastly\Cdn\Helper\CacheTags
     */
    private $cacheTags;

    /**
     * Constructor
     *
     * @param \Magento\Framework\App\ResponseInterface $response
     * @param \Fastly\Cdn\Model\Config $config
     * @param \Fastly\Cdn\Helper\CacheTags $cacheTags
     */
    public function __construct(
        \Magento\Framework\App\ResponseInterface $response,
        Config $config,
        \Fastly\Cdn\Helper\CacheTags $cacheTags
    ) {
        $this->response = $response;
        $this->config = $config;
        $this->cacheTags = $cacheTags;
    }

    /**
     * Set appropriate Cache-Control headers
     * Set Fastly stale headers if configured
     *
     * @param \Magento\Framework\View\Layout $subject
     * @param mixed $result
     * @return mixed
     */
    public function afterGenerateXml(\Magento\Framework\View\Layout $subject, $result)
    {
        // if subject is cacheable, FPC cache is enabled, Fastly module is chosen and general TTL is > 0
        if ($subject->isCacheable() && $this->config->isEnabled()
            && $this->config->getType() == Config::FASTLY && $this->config->getTtl()) {
            // get cache control header
            $header = $this->response->getHeader('cache-control');
            if (($header instanceof \Zend\Http\Header\HeaderInterface) && ($value = $header->getFieldValue())) {
                // append stale values
                if ($ttl = $this->config->getStaleTtl()) {
                    $value .= ', stale-while-revalidate=' . $ttl;
                }
                if ($ttl = $this->config->getStaleErrorTtl()) {
                    $value .= ', stale-if-error=' . $ttl;
                }
                // update cache control header
                $this->response->setHeader($header->getFieldName(), $value, true);
            }
        }

        /*
         * Surface the cacheability of a page. This may expose things like page blocks being set to
         * cacheable = false which makes the whole page uncacheable
         */
        if ($subject->isCacheable()) {
            $this->response->setHeader("fastly-page-cacheable", "YES");
        } else {
            $this->response->setHeader("fastly-page-cacheable", "NO");
        }

        return $result;
    }

    /**
     * Add a debug header to indicate this request has passed through the Fastly Module.
     * This is for ease of debugging
     *
     * @param \Magento\Framework\View\Layout $subject
     * @param mixed $result
     * @return mixed
     */
    public function afterGetOutput(\Magento\Framework\View\Layout $subject, $result) // @codingStandardsIgnoreLine - unused parameter
    {
        if ($this->config->getType() == Config::FASTLY) {
            $this->response->setHeader("Fastly-Module-Enabled", "1.2.99", true);
        }

        return $result;
    }
}


<?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\Controller\Adminhtml\FastlyCdn\Vcl\CheckAuthSetting;
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;

/**
 * Class Delete
 *
 * @package Fastly\Cdn\Controller\Adminhtml\FastlyCdn\BasicAuthentication
 */
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 auth
     *
     * @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');
            $service = $this->api->checkServiceDetails();
            $this->vcl->checkCurrentVersionActive($service->versions, $activeVersion);
            $currActiveVersion = $this->vcl->getCurrentVersion($service->versions);

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

            if ((is_array($dictionary) && empty($dictionary)) || $dictionary == false) {
                return $result->setData([
                    'status'        => false,
                    'not_exists'    => true,
                    'msg'           => 'Authentication dictionary does not exist. Nothing to remove.'
                ]);
            }

            $clone = $this->api->cloneVersion($currActiveVersion);
            $vclPath = Config::VCL_AUTH_SNIPPET_PATH;
            $snippets = $this->config->getVclSnippets($vclPath);

            // Remove snippets
            foreach ($snippets as $key => $value) {
                $name = Config::FASTLY_MAGENTO_MODULE . '_basic_auth_' . $key;
                $this->api->removeSnippet($clone->number, $name);
            }

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

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

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

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

            $comment = ['comment' => 'Magento Module deleted the Basic Authentication 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

namespace Fastly\Cdn\Controller\Adminhtml\FastlyCdn\Manifest;

use Magento\Backend\App\Action;
use Magento\Backend\App\Action\Context;
use Magento\Framework\App\Request\Http;
use Magento\Framework\App\ResponseInterface;
use Magento\Framework\Controller\Result\JsonFactory;
use Magento\Framework\Controller\ResultInterface;
use Magento\Directory\Model\CountryFactory;
use Magento\Directory\Model\Config\Source\Country;
use Fastly\Cdn\Model\Modly\Manifest;

/**
 * Class GetCustomSnippets
 *
 * @package Fastly\Cdn\Controller\Adminhtml\FastlyCdn\Vcl
 */
class GetCountries extends Action
{
    /**
     * @var Http
     */
    private $request;

    /**
     * @var JsonFactory
     */
    private $resultJson;

    /**
     * @var Manifest
     */
    private $manifest;

    /**
     * @var CountryFactory
     */
    private $countryFactory;

    private $countryHelper;

    /**
     * GetCountries constructor.
     *
     * @param Context $context
     * @param Http $request
     * @param JsonFactory $resultJsonFactory
     * @param Manifest $manifest
     * @param CountryFactory $countryFactory
     */
    public function __construct(
        Context $context,
        Http $request,
        JsonFactory $resultJsonFactory,
        Manifest $manifest,
        CountryFactory $countryFactory,
        Country $countryHelper
    ) {
        $this->request = $request;
        $this->resultJson = $resultJsonFactory;
        $this->manifest = $manifest;
        $this->countryFactory = $countryFactory;
        $this->countryHelper = $countryHelper;
        parent::__construct($context);
    }

    /**
     * Gte a list of all modules
     *
     * @return $this|ResponseInterface|ResultInterface
     */
    public function execute()
    {
        $result = $this->resultJson->create();
        try {
            $countries = $this->countryHelper->toOptionArray();
            if (!$countries) {
                return $result->setData([
                    'status'    => false,
                    'msg'       => 'Could not fetch list countries.'
                ]);
            }

            return $result->setData([
                'status'    => true,
                'countries'  => $countries
            ]);
        } 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\Console\Command;

use Fastly\Cdn\Model\Config;
use Fastly\Cdn\Model\Api;
use Fastly\Cdn\Helper\Vcl;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Input\InputOption;
use Magento\Framework\App\Config\Storage\WriterInterface;
use Magento\Framework\App\Cache\Manager;

/**
 * Class EnableCommand
 *
 * @package Fastly\Cdn\Console\Command
 */
class EnableCommand extends Command
{
    /**
     * @var Config
     */
    private $config;

    /**
     * @var Api
     */
    private $api;

    /**
     * @var Vcl
     */
    private $vcl;

    /**
     * @var \Magento\Framework\App\Config\Storage\WriterInterface
     */
    private $configWriter;

    /**
     * @var \Magento\Framework\App\Cache\Manager
     */
    private $cacheManager;

    /**
     * @var OutputInterface
     */
    private $output;

    /**
     * @inheritdoc
     */
    protected function configure() // @codingStandardsIgnoreLine - required by parent class
    {
        $this->setName('fastly:conf:set')
            ->setDescription('Enables Fastly as Full Page Cache Caching Application');

        $this->addOption(
            'enable',
            'e',
            InputOption::VALUE_NONE,
            'Enables Fastly Caching.'
        );

        $this->addOption(
            'disable',
            'd',
            InputOption::VALUE_NONE,
            'Disables Fastly Caching and sets build in cache as default cache.'
        );

        $this->addOption(
            'upload-vcl',
            'u',
            InputOption::VALUE_NONE,
            'Uploads default VCL files, Test connection must pass to proceed with VCL uploading.'
                . ' Add --activate argument to activate new version.'
        );

        $this->addOption(
            'enable-force-tls',
            'f',
            InputOption::VALUE_NONE,
            'Uploads Force TLS snippets, Test connection must pass to proceed with VCL uploading.'
                . ' Add --activate argument to activate new version.'
        );

        $this->addOption(
            'disable-force-tls',
            'l',
            InputOption::VALUE_NONE,
            'Removes Force TLS snippets, Test connection must pass to proceed with VCL snippet removal.'
                . ' Add --activate argument to activate new version.'
        );

        $this->addOption(
            'activate',
            'a',
            InputOption::VALUE_NONE,
            'Activate newly cloned version. Used with VCL upload.'
        );

        $this->addOption(
            'no',
            'N',
            InputOption::VALUE_NONE,
            'Disable option.'
        );

        $this->addOption(
            'test-connection',
            'c',
            InputOption::VALUE_NONE,
            'Tests connection with Fastly.'
        );

        $this->addOption(
            'cache',
            'o',
            InputOption::VALUE_NONE,
            'Cleanse Config Cache.'
        );

        $this->addOption(
            'service-id',
            's',
            InputOption::VALUE_REQUIRED,
            'Sets Fastly Service ID.',
            false
        );

        $this->addOption(
            'token',
            't',
            InputOption::VALUE_REQUIRED,
            'Sets Fastly Token.',
            false
        );

        $this->addOption(
            'admin-path-timeout',
            'A',
            InputOption::VALUE_REQUIRED,
            'Sets Fastly Admin Path Timeout',
            false
        );

        $this->addOption(
            'stale-content-delivery-time',
            'S',
            InputOption::VALUE_REQUIRED,
            'Time in seconds that Fastly will serve stale content while fresh content is being requested.',
            false
        );

        $this->addOption(
            'stale-content-delivery-time-error',
            'B',
            InputOption::VALUE_REQUIRED,
            'Time in seconds that Fastly will continue to serve stale content if your origin is unavailable.',
            false
        );

        $this->addOption(
            'ignored-url-parameters',
            'I',
            InputOption::VALUE_REQUIRED,
            'A comma separated list of ignored query string parameters.',
            false
        );

        $this->addOption(
            'purge-category',
            'C',
            InputOption::VALUE_NONE,
            'Choose to purge all the category assets when saving a change to that category.'
        );

        $this->addOption(
            'purge-product',
            'P',
            InputOption::VALUE_NONE,
            'Choose to purge all the product assets when saving a change to that product.'
        );

        $this->addOption(
            'purge-cms',
            'M',
            InputOption::VALUE_NONE,
            'Choose to purge page content when updating or adding a new page in the Magento CMS.'
        );

        $this->addOption(
            'preserve-static',
            'T',
            InputOption::VALUE_NONE,
            'When flushing cache, flush only dynamic content and preserve static assets.'
        );

        $this->addOption(
            'use-soft-purge',
            'F',
            InputOption::VALUE_NONE,
            'Soft Purge needs to be turned on in order to serve stale content.'
        );

        $this->addOption(
            'enable-geoip',
            'G',
            InputOption::VALUE_NONE,
            'Enable GeoIP for country/language lookup.'
        );

        $this->addOption(
            'geoip-action',
            'O',
            InputOption::VALUE_REQUIRED,
            'GeoIP Action option',
            false
        );
    }

    /**
     * EnableCommand constructor.
     *
     * @param Config $config
     * @param Api $api
     * @param Vcl $vcl
     * @param WriterInterface $configWriter
     * @param Manager $cacheManager
     */
    public function __construct(
        Config $config,
        Api $api,
        Vcl $vcl,
        WriterInterface $configWriter,
        Manager $cacheManager
    ) {
        parent::__construct();
        $this->config = $config;
        $this->api = $api;
        $this->vcl = $vcl;
        $this->configWriter = $configWriter;
        $this->cacheManager = $cacheManager;
    }

    /**
     * @inheritdoc
     */
    protected function execute(InputInterface $input, OutputInterface $output) // @codingStandardsIgnoreLine - required by parent class
    {
        $this->output = $output;
        $options = $input->getOptions();

        if (count(array_unique($options)) === 1) {
            $this->output->writeln('<comment>' . $this->getSynopsis() . '</comment>', OutputInterface::OUTPUT_NORMAL);
            return;
        }

        // Set Service ID
        if ($input->getOption('service-id')) {
            $this->setServiceID($input->getOption('service-id'));
        }

        // Set Token
        if ($input->getOption('token')) {
            $this->setToken($input->getOption('token'));
        }

        // Set Admin Path Timeout
        if ($input->getOption('admin-path-timeout')) {
            $this->setAdminPathTimeout($input->getOption('admin-path-timeout'));
        }

        // Set Stale Content Delivery Time
        if ($input->getOption('stale-content-delivery-time')) {
            $this->setStaleContentDeliveryTime($input->getOption('stale-content-delivery-time'));
        }

        // Set Stale content delivery time in case of backend error
        if ($input->getOption('stale-content-delivery-time-error')) {
            $this->setStaleContentDeliveryTimeError($input->getOption('stale-content-delivery-time-error'));
        }

        // Set ignored url parameters
        if ($input->getOption('ignored-url-parameters')) {
            $this->setIgnoredUrlParameters($input->getOption('ignored-url-parameters'));
        }

        // Enable/disable purge category
        if ($input->getOption('purge-category')) {
            $this->setPurgeCategory($input->getOption('no'));
        }

        // Enable/disable purge product
        if ($input->getOption('purge-product')) {
            $this->setPurgeProduct($input->getOption('no'));
        }

        // Enable/disable purge CMS page
        if ($input->getOption('purge-cms')) {
            $this->setPurgeCms($input->getOption('no'));
        }

        // Enable/disable preserve static assets on purge
        if ($input->getOption('preserve-static')) {
            $this->setPreserveStatic($input->getOption('no'));
        }

        // Enable/disable use soft purge
        if ($input->getOption('use-soft-purge')) {
            $this->setUseSoftPurge($input->getOption('no'));
        }

        // Enable/disable enable geoip
        if ($input->getOption('enable-geoip')) {
            $this->setEnableGeoip($input->getOption('no'));
        }

        // Set geoip action
        if ($input->getOption('geoip-action')) {
            $this->setGeoipAction($input->getOption('geoip-action'));
        }

        // Upload VCL
        if ($input->getOption('upload-vcl')) {
            $this->uploadVcl($input->getOption('activate'));
        }

        // Enable Force TLS snippet
        if ($input->getOption('enable-force-tls')) {
            $this->enableforceTls($input->getOption('activate'));
        }

        // Enable Force TLS snippet
        if ($input->getOption('disable-force-tls')) {
            $this->disableforceTls($input->getOption('activate'));
        }

        // Enable
        if ($input->getOption('enable')) {
            $this->enableFastly();
        }

        // Disable
        if ($input->getOption('disable')) {
            $this->disableFastly();
        }

        // Test Connection
        if ($input->getOption('test-connection')) {
            $this->testConnection();
        }

        // Clean Configuration Cache
        if ($input->getOption('cache')) {
            $this->cleanCache();
        }
    }

    /**
     * Enable Fastly
     */
    private function enableFastly()
    {
        $this->configWriter->save('system/full_page_cache/caching_application', Config::FASTLY);
        $this->output->writeln(
            '<info>Fastly Caching Application Activated.</info>',
            OutputInterface::OUTPUT_NORMAL
        );
    }

    /**
     * Disable Fastly
     */
    private function disableFastly()
    {
        $this->configWriter->save(
            'system/full_page_cache/caching_application',
            \Magento\PageCache\Model\Config::BUILT_IN
        );
        $this->output->writeln(
            '<info>Fastly Caching Application Deactivated, default built in Caching mechanism set.</info>',
            OutputInterface::OUTPUT_NORMAL
        );
    }

    /**
     * Set Fastly Service ID
     * @param $serviceId
     */
    private function setServiceID($serviceId)
    {
        $this->configWriter->save(Config::XML_FASTLY_SERVICE_ID, $serviceId);
        $this->output->writeln(
            '<info>Service ID updated.</info>',
            OutputInterface::OUTPUT_NORMAL
        );
    }

    /**
     * Set Fastly API Token
     * @param $token
     */
    private function setToken($token)
    {
        $this->configWriter->save(Config::XML_FASTLY_API_KEY, $token);
        $this->output->writeln(
            '<info>Token updated.</info>',
            OutputInterface::OUTPUT_NORMAL
        );
    }

    /**
     * @param $adminPathTimeout
     */
    private function setAdminPathTimeout($adminPathTimeout)
    {
        if (!ctype_digit($adminPathTimeout)) {
            $this->output->writeln(
                '<error>The value must be an integer.</error>',
                OutputInterface::OUTPUT_NORMAL
            );
            return;
        }
        $this->configWriter->save(Config::XML_FASTLY_ADMIN_PATH_TIMEOUT, $adminPathTimeout);
        $this->output->writeln(
            '<info>Admin path timeout updated.</info>',
            OutputInterface::OUTPUT_NORMAL
        );
    }

    /**
     * @param $staleContentDeliveryTime
     */
    private function setStaleContentDeliveryTime($staleContentDeliveryTime)
    {
        if (!ctype_digit($staleContentDeliveryTime)) {
            $this->output->writeln(
                '<error>The value must be an integer.</error>',
                OutputInterface::OUTPUT_NORMAL
            );
            return;
        }
        $this->configWriter->save(Config::XML_FASTLY_STALE_TTL, $staleContentDeliveryTime);
        $this->output->writeln(
            '<info>Stale content delivery time updated.</info>',
            OutputInterface::OUTPUT_NORMAL
        );
    }

    /**
     * @param $staleContentDeliveryTimeError
     */
    private function setStaleContentDeliveryTimeError($staleContentDeliveryTimeError)
    {
        if (!ctype_digit($staleContentDeliveryTimeError)) {
            $this->output->writeln(
                '<error>The value must be an integer.</error>',
                OutputInterface::OUTPUT_NORMAL
            );
            return;
        }
        $this->configWriter->save(Config::XML_FASTLY_STALE_ERROR_TTL, $staleContentDeliveryTimeError);
        $this->output->writeln(
            '<info>Stale content delivery time in case of backend error updated.</info>',
            OutputInterface::OUTPUT_NORMAL
        );
    }

    /**
     * @param $ignoredUrlParameters
     */
    private function setIgnoredUrlParameters($ignoredUrlParameters)
    {
        $this->configWriter->save(Config::XML_FASTLY_IGNORED_URL_PARAMETERS, $ignoredUrlParameters);
        $this->output->writeln(
            '<info>Ignored Url Parameters updated.</info>',
            OutputInterface::OUTPUT_NORMAL
        );
    }

    /**
     * @param $no
     */
    private function setPurgeCategory($no)
    {
        if ($no) {
            $this->configWriter->save(Config::XML_FASTLY_PURGE_CATALOG_CATEGORY, 0);
            $this->output->writeln(
                '<info>Purge category disabled.</info>',
                OutputInterface::OUTPUT_NORMAL
            );
        } else {
            $this->configWriter->save(Config::XML_FASTLY_PURGE_CATALOG_CATEGORY, 1);
            $this->output->writeln(
                '<info>Purge category enabled. To disable add the --no argument.</info>',
                OutputInterface::OUTPUT_NORMAL
            );
        }
    }

    /**
     * @param $no
     */
    private function setPurgeProduct($no)
    {
        if ($no) {
            $this->configWriter->save(Config::XML_FASTLY_PURGE_CATALOG_PRODUCT, 0);
            $this->output->writeln(
                '<info>Purge product disabled.</info>',
                OutputInterface::OUTPUT_NORMAL
            );
        } else {
            $this->configWriter->save(Config::XML_FASTLY_PURGE_CATALOG_PRODUCT, 1);
            $this->output->writeln(
                '<info>Purge product enabled. To disable add the --no argument.</info>',
                OutputInterface::OUTPUT_NORMAL
            );
        }
    }

    /**
     * @param $no
     */
    private function setPurgeCms($no)
    {
        if ($no) {
            $this->configWriter->save(Config::XML_FASTLY_PURGE_CMS_PAGE, 0);
            $this->output->writeln(
                '<info>Purge CMS page disabled.</info>',
                OutputInterface::OUTPUT_NORMAL
            );
        } else {
            $this->configWriter->save(Config::XML_FASTLY_PURGE_CMS_PAGE, 1);
            $this->output->writeln(
                '<info>Purge CMS page enabled. To disable add the --no argument.</info>',
                OutputInterface::OUTPUT_NORMAL
            );
        }
    }

    /**
     * @param $no
     */
    private function setPreserveStatic($no)
    {
        if ($no) {
            $this->configWriter->save(Config::XML_FASTLY_PRESERVE_STATIC, 0);
            $this->output->writeln(
                '<info>Preserve static assets on purge disabled.</info>',
                OutputInterface::OUTPUT_NORMAL
            );
        } else {
            $this->configWriter->save(Config::XML_FASTLY_PRESERVE_STATIC, 1);
            $this->output->writeln(
                '<info>Preserve static assets on purge enabled. To disable add the --no argument.</info>',
                OutputInterface::OUTPUT_NORMAL
            );
        }
    }

    /**
     * @param $no
     */
    private function setUseSoftPurge($no)
    {
        if ($no) {
            $this->configWriter->save(Config::XML_FASTLY_SOFT_PURGE, 0);
            $this->output->writeln(
                '<info>Use Soft Purge disabled.</info>',
                OutputInterface::OUTPUT_NORMAL
            );
        } else {
            $this->configWriter->save(Config::XML_FASTLY_SOFT_PURGE, 1);
            $this->output->writeln(
                '<info>Use Soft Purge enabled. To disable add the --no argument.</info>',
                OutputInterface::OUTPUT_NORMAL
            );
        }
    }

    /**
     * @param $no
     */
    private function setEnableGeoip($no)
    {
        if ($no) {
            $this->configWriter->save(Config::XML_FASTLY_GEOIP_ENABLED, 0);
            $this->output->writeln(
                '<info>GeoIP disabled.</info>',
                OutputInterface::OUTPUT_NORMAL
            );
        } else {
            $this->configWriter->save(Config::XML_FASTLY_GEOIP_ENABLED, 1);
            $this->output->writeln(
                '<info>GeoIP enabled. To disable add the --no argument.</info>',
                OutputInterface::OUTPUT_NORMAL
            );
        }
    }

    /**
     * @param $geoipAction
     */
    private function setGeoipAction($geoipAction)
    {
        if (strtolower($geoipAction) === 'dialog') {
            $this->configWriter->save(Config::XML_FASTLY_GEOIP_ACTION, $geoipAction);
            $this->output->writeln(
                '<info>GeoIP Action set to dialog.</info>',
                OutputInterface::OUTPUT_NORMAL
            );
        } elseif (strtolower($geoipAction) === 'redirect') {
            $this->configWriter->save(Config::XML_FASTLY_GEOIP_ACTION, $geoipAction);
            $this->output->writeln(
                '<info>GeoIP Action set to redirect.</info>',
                OutputInterface::OUTPUT_NORMAL
            );
        } else {
            $this->output->writeln(
                '<error>This option requires "dialog" or "redirect" as a value.</error>',
                OutputInterface::OUTPUT_NORMAL
            );
        }
    }

    private function cleanCache()
    {
        $this->cacheManager->clean([\Magento\Framework\App\Cache\Type\Config::TYPE_IDENTIFIER]);
        $this->output->writeln(
            '<info>Configuration Cache Cleaned.</info>',
            OutputInterface::OUTPUT_NORMAL
        );
    }

    /**
     * Upload default VCL, conditions and requests
     *
     * @param $activate
     * @throws \Exception
     */
    private function uploadVcl($activate)
    {
        try {
            $service = $this->api->checkServiceDetails();
            $currActiveVersion = $this->vcl->getCurrentVersion($service->versions);
            $clone = $this->api->cloneVersion($currActiveVersion);
            $snippets = $this->config->getVclSnippets();
            foreach ($snippets as $key => $value) {
                $snippetData = [
                    'name'      => Config::FASTLY_MAGENTO_MODULE . '_' . $key,
                    'type'      => $key,
                    'dynamic'   => "0",
                    'priority'  => 50,
                    'content'   => $value
                ];
                $this->api->uploadSnippet($clone->number, $snippetData);
            }

            $condition = [
                'name'      => Config::FASTLY_MAGENTO_MODULE . '_pass',
                'statement' => 'req.http.x-pass',
                'type'      => 'REQUEST',
                'priority'  => 90
            ];
            $createCondition = $this->api->createCondition($clone->number, $condition);
            $request = [
                'action'            => 'pass',
                'max_stale_age'     => 3600,
                'name'              => Config::FASTLY_MAGENTO_MODULE.'_request',
                'request_condition' => $createCondition->name,
                'service_id'        => $service->id,
                'version'           => $currActiveVersion
            ];

            $this->api->createRequest($clone->number, $request);
            $this->api->validateServiceVersion($clone->number);
            $msg = 'Successfully uploaded VCL. ';

            if ($activate) {
                $this->api->activateVersion($clone->number);
                $msg .= 'Activated Version '. $clone->number;
            }

            if ($this->config->areWebHooksEnabled() && $this->config->canPublishConfigChanges()) {
                $this->api->sendWebHook(
                    '*Upload VCL has been initiated and activated in version ' . $clone->number . '*'
                );
            }

            $this->output->writeln('<info>' . $msg . '</info>', OutputInterface::OUTPUT_NORMAL);
        } catch (\Exception $e) {
            $msg = $e->getMessage();
            $this->output->writeln("<error>$msg</error>", OutputInterface::OUTPUT_NORMAL);
            return;
        }
    }

    /**
     * Uploads the Force TLS VCL snippet
     *
     * @param $activate
     */
    private function enableForceTls($activate)
    {
        try {
            $service = $this->api->checkServiceDetails();
            $currActiveVersion = $this->vcl->getCurrentVersion($service->versions);
            $clone = $this->api->cloneVersion($currActiveVersion);
            $reqName = Config::FASTLY_MAGENTO_MODULE.'_force_tls';
            $snippets = $this->config->getVclSnippets(Config::FORCE_TLS_PATH);

            $request = [
                'name'          => $reqName,
                'service_id'    => $service->id,
                'version'       => $currActiveVersion,
                'force_ssl'     => true
            ];

            $this->api->createRequest($clone->number, $request);

            // Add force TLS snippet
            foreach ($snippets as $key => $value) {
                $snippetData = [
                    'name'      => Config::FASTLY_MAGENTO_MODULE.'_force_tls_'.$key,
                    'type'      => $key,
                    'dynamic'   => "0",
                    'priority'  => 10,
                    'content'   => $value
                ];
                $this->api->uploadSnippet($clone->number, $snippetData);
            }

            $this->api->validateServiceVersion($clone->number);
            $msg = 'Successfully enabled Force TLS. ';

            if ($activate) {
                $this->api->activateVersion($clone->number);
                $msg .= 'Activated Version '. $clone->number;
            }

            if ($this->config->areWebHooksEnabled() && $this->config->canPublishConfigChanges()) {
                $this->api->sendWebHook('*Force TLS has been turned ON in Fastly version '. $clone->number . '*');
            }

            $this->output->writeln('<info>' . $msg . '</info>', OutputInterface::OUTPUT_NORMAL);
        } catch (\Exception $e) {
            $msg = $e->getMessage();
            $this->output->writeln("<error>$msg</error>", OutputInterface::OUTPUT_NORMAL);
            return;
        }
    }

    /**
     * Removes the Force TLS VCL snippet from the current active version
     *
     * @param $activate
     */
    private function disableForceTls($activate)
    {
        try {
            $service = $this->api->checkServiceDetails();
            $currActiveVersion = $this->vcl->getCurrentVersion($service->versions);
            $clone = $this->api->cloneVersion($currActiveVersion);
            $reqName = Config::FASTLY_MAGENTO_MODULE.'_force_tls';
            $snippets = $this->config->getVclSnippets(Config::FORCE_TLS_PATH);

            $request = [
                'name'          => $reqName,
                'service_id'    => $service->id,
                'version'       => $currActiveVersion,
                'force_ssl'     => false
            ];

            $this->api->createRequest($clone->number, $request);

            // Remove Force TLS snippet
            foreach ($snippets as $key => $value) {
                $name = Config::FASTLY_MAGENTO_MODULE.'_force_tls_'.$key;

                if ($this->api->hasSnippet($clone->number, $name)) {
                    $this->api->removeSnippet($clone->number, $name);
                }
            }

            $this->api->validateServiceVersion($clone->number);
            $msg = 'Successfully disabled Force TLS. ';

            if ($activate) {
                $this->api->activateVersion($clone->number);
                $msg .= 'Activated Version '. $clone->number;
            }

            if ($this->config->areWebHooksEnabled() && $this->config->canPublishConfigChanges()) {
                $this->api->sendWebHook('*Force TLS has been turned OFF in Fastly version '. $clone->number . '*');
            }

            $this->output->writeln('<info>' . $msg . '</info>', OutputInterface::OUTPUT_NORMAL);
        } catch (\Exception $e) {
            $msg = $e->getMessage();
            $this->output->writeln("<error>$msg</error>", OutputInterface::OUTPUT_NORMAL);
            return;
        }
    }

    private function testConnection()
    {
        try {
            $service = $this->api->checkServiceDetails();
            $currActiveVersion = $this->vcl->getCurrentVersion($service->versions);
            $this->output->writeln(
                '<info>Status: Connection Successful, current active version: '
                . $currActiveVersion
                . '</info>',
                OutputInterface::OUTPUT_NORMAL
            );
        } catch (\Exception $e) {
            $msg = $e->getMessage();
            $this->output->writeln("<error>$msg</error>", OutputInterface::OUTPUT_NORMAL);
            return;
        }
    }
}


<?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\Config;
use Fastly\Cdn\Model\Api;
use Fastly\Cdn\Helper\Vcl;
use Fastly\Cdn\Model\Product\Image;
use Magento\Framework\Exception\LocalizedException;

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

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

        parent::__construct($context);
    }

    /**
     * Upload Image Optimization settings
     *
     * @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');
            $imageQualityFlag = $this->getRequest()->getParam('image_quality_flag');
            $imageQuality = $this->image->getQuality();
            $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::IMAGE_SETTING_NAME);
            $snippet = $this->config->getVclSnippets(Config::IO_VCL_SNIPPET_PATH, 'recv.vcl');

            if (!$checkIfSettingExists) {
                foreach ($snippet as $key => $value) {
                    $snippetData = [
                        'name' => Config::FASTLY_MAGENTO_MODULE . '_image_optimization_' . $key,
                        'type' => $key,
                        'dynamic' => "0",
                        'content' => $value,
                        'priority' => 10
                    ];

                    $this->api->uploadSnippet($clone->number, $snippetData);

                    $id = $service->id . '-' . $clone->number . '-imageopto';
                    # Make sure we set webp to auto default
                    $imageParams = [
                        'data' => [
                            'id'            => $id,
                            'type'          => 'io_settings',
                            'attributes'    => [
                                'webp'      => true
                            ]
                        ]
                    ];

                    # Set image quality to magento default quality if selected
                    if ($imageQualityFlag === 'true') {
                        $imageParams['data']['attributes']['webp_quality'] = $imageQuality;
                        $imageParams['data']['attributes']['jpeg_quality'] = $imageQuality;
                    }

                    $this->api->configureImageOptimizationDefaultConfigOptions(
                        json_encode($imageParams),
                        $clone->number
                    );
                }
            } else {
                // Remove image optimization snippet
                foreach ($snippet as $key => $value) {
                    $name = Config::FASTLY_MAGENTO_MODULE . '_image_optimization_' . $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 pushed the Image Optimization snippet'];
            if ($checkIfSettingExists) {
                $comment = ['comment' => 'Magento Module removed the Image Optimization snippet'];
            }
            $this->api->addComment($clone->number, $comment);

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

    private function sendWebhook($checkIfSettingExists, $clone)
    {
        if ($this->config->areWebHooksEnabled() && $this->config->canPublishConfigChanges()) {
            if ($checkIfSettingExists) {
                $this->api->sendWebHook(
                    '*Image optimization snippet has been removed in Fastly version ' . $clone->number . '*'
                );
            } else {
                $this->api->sendWebHook(
                    '*Image optimization snippet has been pushed 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\Blocking;

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

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

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

        parent::__construct($context);
    }

    /**
     * Verifies whether or not the blocking settings snippet exists on specified Fastly version
     *
     * @return Json
     */
    public function execute()
    {
        $result = $this->resultJsonFactory->create();
        try {
            $activeVersion = $this->getRequest()->getParam('active_version');
            $snippet = Config::BLOCKING_SETTING_NAME;
            $req = $this->api->hasSnippet($activeVersion, $snippet);

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

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


<?php

namespace Fastly\Cdn\Model\Modly;

use Magento\Framework\HTTP\Client\Curl;
use Fastly\Cdn\Helper\Manifest as Manifests;
use Magento\Framework\Filesystem;
use Fastly\Cdn\Model\Config;

class Manifest
{
    /**
     * @var Curl
     */
    private $curl;

    /**
     * @var Manifests
     */
    private $manifests;

    /**
     * This is a temp thing
     *
     * @var array
     */
    private $urlList = [];

    /**
     * @var Filesystem
     */
    private $filesystem;

    /**
     * @var Config
     */
    private $config;

    /**
     * Manifest constructor.
     *
     * @param Curl $curl
     * @param Manifests $manifests
     * @param Filesystem $filesystem
     * @param Config $config
     */
    public function __construct(
        Curl $curl,
        Manifests $manifests,
        Filesystem $filesystem,
        Config $config
    ) {
        $this->manifests = $manifests;
        $this->curl = $curl;
        $this->filesystem = $filesystem;
        $this->config = $config;
    }

    /**
     * Returns a list of Modly modules and their data stored in the database
     *
     * @return array
     */
    public function getAllModlyManifests()
    {
        $manifests = $this->manifests->getAllModules();
        return $manifests;
    }

    public function getActiveModlyManifests()
    {
        $manifests = $this->manifests->getActiveModules();
        return $manifests;
    }

    public function getModule($id)
    {
        $module = $this->manifests->getModuleData($id);
        return $module;
    }

    /**
     * Fetch all manifests from the repository
     *
     * @return array
     */
    public function getAllRepoManifests()
    {
        $fastlyEdgeModules = $this->config->getFastlyEdgeModules();
        $manifests = [];

        foreach ($fastlyEdgeModules as $key => $value) {
            $decodedManifestData = json_decode($value, true);
            $manifests[] = $decodedManifestData;
        }
        return $manifests;
    }
}


<?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\Configuration;

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

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

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

    /**
     * Check if the Fastly service is already configured
     *
     * @return $this|ResponseInterface|ResultInterface
     */
    public function execute()
    {
        $result = $this->resultJsonFactory->create();
        try {
            $serviceId = $this->config->getServiceId();
            $apiKey = $this->config->getApiKey();

            if ($serviceId == null && $apiKey == null) {
                return $result->setData([
                    'status'    => true,
                    'flag'      => false
                ]);
            }

            return $result->setData([
                'status'    => true,
                'flag'      => 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\Observer;

use Fastly\Cdn\Model\Notification;
use Magento\Backend\Model\Auth\Session;
use Magento\Framework\App\CacheInterface;
use Magento\Framework\Component\ComponentRegistrarInterface;
use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\Component\ComponentRegistrar;
use Magento\Framework\Model\Context;

/**
 * Class CheckVersion
 *
 * Fastly CDN observer for new version notification
 * @package Fastly\Cdn\Observer
 */
class CheckVersion implements ObserverInterface
{
    /**
     * @var Notification
     */
    private $feedFactory;
    /**
     * @var Session
     */
    private $backendAuthSession;
    /**
     * @var ComponentRegistrarInterface
     */
    private $moduleRegistry;
    /**
     * @var CacheInterface
     */
    private $cacheManager;

    /**
     * CheckVersion constructor.
     *
     * @param Notification $feedFactory
     * @param Session $backendAuthSession
     * @param Context $context
     * @param ComponentRegistrarInterface $moduleRegistry
     */
    public function __construct(
        Notification $feedFactory,
        Session $backendAuthSession,
        Context $context,
        ComponentRegistrarInterface $moduleRegistry
    ) {
        $this->moduleRegistry = $moduleRegistry;
        $this->backendAuthSession = $backendAuthSession;
        $this->feedFactory = $feedFactory;
        $this->cacheManager = $context->getCacheManager();
    }

    /**
     * Predispatch admin user login success
     *
     * @param Observer $observer
     * @return $this|void
     */
    public function execute(Observer $observer) // @codingStandardsIgnoreLine - unused parameter
    {
        if ($this->backendAuthSession->isLoggedIn() == false) {
            return;
        }

        if ($this->getFrequency() + $this->getLastUpdate() > time()) {
            return;
        }

        $modulePath = $this->moduleRegistry->getPath(ComponentRegistrar::MODULE, 'Fastly_Cdn');
        $filePath = str_replace(['\\', '/'], DIRECTORY_SEPARATOR, "$modulePath/composer.json");
        $composerData = json_decode(file_get_contents($filePath)); // @codingStandardsIgnoreLine - not user controlled
        $currentVersion = !empty($composerData->version) ? $composerData->version : false;

        if ($currentVersion) {
            $this->feedFactory->checkUpdate($currentVersion);
        }

        $this->setLastUpdate();
    }

    /**
     * Retrieve Last update time
     *
     * @return int
     */
    private function getLastUpdate()
    {
        return $this->cacheManager->load('fastlycdn_admin_notifications_lastcheck');
    }

    /**
     * Set last update time (now)
     *
     * @return $this
     */
    private function setLastUpdate()
    {
        $this->cacheManager->save(time(), 'fastlycdn_admin_notifications_lastcheck');
        return $this;
    }

    /**
     * Retrieve Update Frequency
     *
     * @return int
     */
    private function getFrequency()
    {
        return 86400;
    }
}


<?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\Observer;

use Fastly\Cdn\Model\Config;
use Fastly\Cdn\Model\PurgeCache;
use Magento\Framework\Event\ObserverInterface;

/**
 * Class FlushAllCacheObserver
 *
 * @package Fastly\Cdn\Observer
 */
class FlushAllCacheObserver implements ObserverInterface
{
    /**
     * @var Config
     */
    private $config;
    /**
     * @var PurgeCache
     */
    private $purgeCache;

    /**
     * @param Config $config
     * @param PurgeCache $purgeCache
     */
    public function __construct(Config $config, PurgeCache $purgeCache)
    {
        $this->config = $config;
        $this->purgeCache = $purgeCache;
    }

    /**
     * Flush Fastly CDN cache
     *
     * @param \Magento\Framework\Event\Observer $observer
     * @throws \Zend_Uri_Exception
     */
    public function execute(\Magento\Framework\Event\Observer $observer) // @codingStandardsIgnoreLine - unused parameter
    {
        if ($this->config->getType() == Config::FASTLY && $this->config->isEnabled()) {
            $this->purgeCache->sendPurgeRequest();
        }
    }
}