<commit_before><?php
/**
 * WebHemi.
 *
 * PHP version 7.1
 *
 * @copyright 2012 - 2017 Gixx-web (http://www.gixx-web.com)
 * @license   https://opensource.org/licenses/MIT The MIT License (MIT)
 *
 * @link      http://www.gixx-web.com
 */
declare(strict_types = 1);

namespace WebHemi\Environment\ServiceAdapter\Base;

use Exception;
use InvalidArgumentException;
use LayerShifter\TLDExtract\Extract;
use LayerShifter\TLDExtract\Result;
use WebHemi\Configuration\ServiceInterface as ConfigurationInterface;
use WebHemi\Environment\AbstractAdapter;

/**
 * Class ServiceAdapter.
 * @SuppressWarnings(PHPMD.TooManyFields)
 */
class ServiceAdapter extends AbstractAdapter
{
    /** @var Extract */
    private $domainAdapter;

    /**
     * ServiceAdapter constructor.
     *
     * @param ConfigurationInterface $configuration
     * @param array                  $getData
     * @param array                  $postData
     * @param array                  $serverData
     * @param array                  $cookieData
     * @param array                  $filesData
     * @param array                  $optionsData
     * @throws Exception
     */
    public function __construct(
        ConfigurationInterface $configuration,
        array $getData,
        array $postData,
        array $serverData,
        array $cookieData,
        array $filesData,
        array $optionsData
    ) {
        $this->configuration = $configuration->getConfig('applications');
        $this->domainAdapter = new Extract();
        $this->applicationRoot = realpath(__DIR__.'/../../../../../');
        // In case when the backend sources are out of the document root.
        $this->documentRoot = realpath($this->applicationRoot.'/');
        $this->options = $optionsData;

        if (isset($serverData['HTTP_REFERER'])) {
            $serverData['HTTP_REFERER'] = urldecode($serverData['HTTP_REFERER']);
        }

        $this->environmentData = [
            'GET'    => $getData,
            'POST'   => $postData,
            'SERVER' => $serverData,
            'COOKIE' => $cookieData,
            'FILES'  => $filesData,
        ];

        $this->isHttps = isset($this->environmentData['SERVER']['HTTPS']) && $this->environmentData['SERVER']['HTTPS'];
        $this->url = 'http'.($this->isHttps ? 's' : '').'://'
            .$this->environmentData['SERVER']['HTTP_HOST']
            .$this->environmentData['SERVER']['REQUEST_URI']; // contains also the query string

        $this->selectedModule = self::DEFAULT_MODULE;
        $this->selectedApplication = self::DEFAULT_APPLICATION;
        $this->selectedTheme = self::DEFAULT_THEME;
        $this->selectedThemeResourcePath = self::DEFAULT_THEME_RESOURCE_PATH;
        $this->selectedApplicationUri = self::DEFAULT_APPLICATION_URI;

        $this->setDomain()
            ->setApplication();
    }

    /**
     * Gets the request URI
     *
     * @return string
     */
    public function getRequestUri() : string
    {
        return rtrim($this->environmentData['SERVER']['REQUEST_URI'], '/');
    }

    /**
     * Gets the request method.
     *
     * @return string
     */
    public function getRequestMethod(): string
    {
        return $this->environmentData['SERVER']['REQUEST_METHOD'] ?? 'GET';
    }

    /**
     * Gets environment data.
     *
     * @param string $key
     * @return array
     */
    public function getEnvironmentData(string $key) : array
    {
        if (!isset($this->environmentData[$key])) {
            throw new InvalidArgumentException(sprintf('The "%s" is not a valid environment key.', $key));
        }

        return $this->environmentData[$key];
    }

    /**
     * Gets the client IP address.
     *
     * @return string
     */
    public function getClientIp() : string
    {
        $ipAddress = '';

        if (!empty($this->environmentData['SERVER']['HTTP_X_FORWARDED_FOR'])) {
            $ipAddress = $this->environmentData['SERVER']['HTTP_X_FORWARDED_FOR'];
        } elseif (!empty($this->environmentData['SERVER']['REMOTE_ADDR'])) {
            $ipAddress = $this->environmentData['SERVER']['REMOTE_ADDR'];
        }

        return (string) $ipAddress;
    }

    /**
     * Parses server data and tries to set domain information.
     *
     * @throws Exception
     * @return ServiceAdapter
     */
    private function setDomain() : ServiceAdapter
    {
        // @codeCoverageIgnoreStart
        if (!defined('PHPUNIT_WEBHEMI_TESTSUITE') &&'dev' == getenv('APPLICATION_ENV')) {
            $this->domainAdapter->setExtractionMode(Extract::MODE_ALLOW_NOT_EXISTING_SUFFIXES);
        }
        // @codeCoverageIgnoreEnd

        /** @var Result $domainParts */
        $domainParts = $this->domainAdapter->parse($this->url);

        if (empty($domainParts->getSuffix())) {
            throw new Exception('This application does not support IP access');
        }

        // Redirecting to www when no subdomain is present
        // @codeCoverageIgnoreStart
        if (!defined('PHPUNIT_WEBHEMI_TESTSUITE') && empty($domainParts->getSubdomain())) {
            $schema = 'http'.($this->isSecuredApplication() ? 's' : '').'://';
            $uri = $this->environmentData['SERVER']['REQUEST_URI'];
            header('Location: '.$schema.'www.'.$domainParts->getFullHost().$uri);
            exit;
        }
        // @codeCoverageIgnoreEnd

        $this->subDomain = $domainParts->getSubdomain();
        $this->mainDomain = $domainParts->getHostname().'.'.$domainParts->getSuffix();
        $this->applicationDomain = $domainParts->getFullHost();

        return $this;
    }<commit_msg>Split function to reduce complexity<commit_after><?php
/**
 * WebHemi.
 *
 * PHP version 7.1
 *
 * @copyright 2012 - 2017 Gixx-web (http://www.gixx-web.com)
 * @license   https://opensource.org/licenses/MIT The MIT License (MIT)
 *
 * @link      http://www.gixx-web.com
 */
declare(strict_types = 1);

namespace WebHemi\Environment\ServiceAdapter\Base;

use Exception;
use InvalidArgumentException;
use LayerShifter\TLDExtract\Extract;
use LayerShifter\TLDExtract\Result;
use WebHemi\Configuration\ServiceInterface as ConfigurationInterface;
use WebHemi\Environment\AbstractAdapter;

/**
 * Class ServiceAdapter.
 * @SuppressWarnings(PHPMD.TooManyFields)
 */
class ServiceAdapter extends AbstractAdapter
{
    /** @var Extract */
    private $domainAdapter;

    /**
     * ServiceAdapter constructor.
     *
     * @param ConfigurationInterface $configuration
     * @param array                  $getData
     * @param array                  $postData
     * @param array                  $serverData
     * @param array                  $cookieData
     * @param array                  $filesData
     * @param array                  $optionsData
     * @throws Exception
     */
    public function __construct(
        ConfigurationInterface $configuration,
        array $getData,
        array $postData,
        array $serverData,
        array $cookieData,
        array $filesData,
        array $optionsData
    ) {
        $this->configuration = $configuration->getConfig('applications');
        $this->domainAdapter = new Extract();
        $this->applicationRoot = realpath(__DIR__.'/../../../../../');
        // In case when the backend sources are out of the document root.
        $this->documentRoot = realpath($this->applicationRoot.'/');
        $this->options = $optionsData;

        if (isset($serverData['HTTP_REFERER'])) {
            $serverData['HTTP_REFERER'] = urldecode($serverData['HTTP_REFERER']);
        }

        $this->environmentData = [
            'GET'    => $getData,
            'POST'   => $postData,
            'SERVER' => $serverData,
            'COOKIE' => $cookieData,
            'FILES'  => $filesData,
        ];

        $this->isHttps = isset($this->environmentData['SERVER']['HTTPS']) && $this->environmentData['SERVER']['HTTPS'];
        $this->url = 'http'.($this->isHttps ? 's' : '').'://'
            .$this->environmentData['SERVER']['HTTP_HOST']
            .$this->environmentData['SERVER']['REQUEST_URI']; // contains also the query string

        $this->selectedModule = self::DEFAULT_MODULE;
        $this->selectedApplication = self::DEFAULT_APPLICATION;
        $this->selectedTheme = self::DEFAULT_THEME;
        $this->selectedThemeResourcePath = self::DEFAULT_THEME_RESOURCE_PATH;
        $this->selectedApplicationUri = self::DEFAULT_APPLICATION_URI;

        $this->setDomain()
            ->setApplication();
    }

    /**
     * Gets the request URI
     *
     * @return string
     */
    public function getRequestUri() : string
    {
        return rtrim($this->environmentData['SERVER']['REQUEST_URI'], '/');
    }

    /**
     * Gets the request method.
     *
     * @return string
     */
    public function getRequestMethod(): string
    {
        return $this->environmentData['SERVER']['REQUEST_METHOD'] ?? 'GET';
    }

    /**
     * Gets environment data.
     *
     * @param string $key
     * @return array
     */
    public function getEnvironmentData(string $key) : array
    {
        if (!isset($this->environmentData[$key])) {
            throw new InvalidArgumentException(sprintf('The "%s" is not a valid environment key.', $key));
        }

        return $this->environmentData[$key];
    }

    /**
     * Gets the client IP address.
     *
     * @return string
     */
    public function getClientIp() : string
    {
        $ipAddress = '';

        if (!empty($this->environmentData['SERVER']['HTTP_X_FORWARDED_FOR'])) {
            $ipAddress = $this->environmentData['SERVER']['HTTP_X_FORWARDED_FOR'];
        } elseif (!empty($this->environmentData['SERVER']['REMOTE_ADDR'])) {
            $ipAddress = $this->environmentData['SERVER']['REMOTE_ADDR'];
        }

        return (string) $ipAddress;
    }

    /**
     * Parses server data and tries to set domain information.
     *
     * @throws Exception
     * @return ServiceAdapter
     */
    private function setDomain() : ServiceAdapter
    {
        $this->setAdapterOptions();

        /** @var Result $domainParts */
        $domainParts = $this->domainAdapter->parse($this->url);

        if (empty($domainParts->getSuffix())) {
            throw new Exception('This application does not support IP access');
        }

        $this->checkSubdomain($domainParts);

        $this->subDomain = $domainParts->getSubdomain();
        $this->mainDomain = $domainParts->getHostname().'.'.$domainParts->getSuffix();
        $this->applicationDomain = $domainParts->getFullHost();

        return $this;
    }

    /**
     * Set some adapter specific options.
     *
     * @return int
     *
     * @codeCoverageIgnore - don't test third party library
     */
    private function setAdapterOptions() : int
    {
        try {
            if (!defined('PHPUNIT_WEBHEMI_TESTSUITE') && 'dev' == getenv('APPLICATION_ENV')) {
                $this->domainAdapter->setExtractionMode(Extract::MODE_ALLOW_NOT_EXISTING_SUFFIXES);
            }
        } catch (\Throwable $exception) {
            return $exception->getCode();
        }
        // @codeCoverageIgnoreEnd

        return 0;
    }

    /**
     * Checks whether the subdomain exists, and rediretcs if no.
     *
     * @param Result $domainParts
     *
     * @codeCoverageIgnore - don't test redirect
     */
    private function checkSubdomain(Result $domainParts) : void
    {
        // Redirecting to www when no subdomain is present
        if (!defined('PHPUNIT_WEBHEMI_TESTSUITE') && empty($domainParts->getSubdomain())) {
            $schema = 'http'.($this->isSecuredApplication() ? 's' : '').'://';
            $uri = $this->environmentData['SERVER']['REQUEST_URI'];
            header('Location: '.$schema.'www.'.$domainParts->getFullHost().$uri);
            exit;
        }
    }
{'fraction_non_alphanumeric': 0.14257993756854806, 'fraction_numerical': 0.0019404370201636717, 'mean_word_length': 2.3762460837368273, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 110, 'https://': 2, 'lorem ipsum': 0, 'www.': 8, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1217251', 'n_tokens_mistral': 3337, 'n_tokens_neox': 3236, 'n_words': 643}