Viewing File: /usr/local/cpanel/whostmgr/docroot/cgi/ncssl/source/src/Service/Manager/HttpsRedirectManager.php

<?php

namespace App\Service\Manager;

use Psr\Log\LoggerInterface;

/**
 * Manage Domain redirect status
 *
 * @package Managers
 */
class HttpsRedirectManager
{
    public const STATUS_OK = 'ok';
    public const STATUS_FAIL = 'fail';

    private const MESSAGE_FAILED_CHANGE_REDIRECT = 'Can\'t change HTTPS redirect status.';
    private const MESSAGE_CANT_DECODE_JSON_RESULT = 'Can\'t decode json result';

    public const NC_HTTP_REDIRECT_COMMAND = '/usr/local/bin/nc-http-redirect';

    public function __construct(
        private readonly LoggerInterface $logger
    ) {
    }

    /**
     * @param string $domain
     * @param bool $expectedStatus
     *
     * @return array|mixed
     * @throws \JsonException
     */
    public function toggleHttpRedirectStatus(string $domain, bool $expectedStatus): mixed
    {
        $command = $this->createToggleRedirectStatusCommand($domain, $expectedStatus);

        $result = $this->runExec($command);

        $domainStatus = json_decode($result[0], true, 512, JSON_THROW_ON_ERROR);

        if ($domainStatus === null) {
            $this->logger->error('Can`t decode json result',
                [
                    'domainStatus' => $result[0],
                    'json_error' => json_last_error(),
                    'json_error_msg' => json_last_error_msg()
                ]
            );

            return [];
        }

        return $domainStatus;
    }

    /**
     * @param string $domain
     * @param bool $expectedStatus
     *
     * @return array|bool[]
     * @throws \JsonException
     */
    public function toggleHttpRedirect(string $domain, bool $expectedStatus): array
    {
        $cleanDomain = self::getDomainWithoutWww($domain);

        $domainStatus = $this->toggleHttpRedirectStatus($cleanDomain, $expectedStatus);

        if (empty($domainStatus)) {
            $this->logger->error(self::MESSAGE_FAILED_CHANGE_REDIRECT, ['domain' => $domain, 'expectedStatus' => $expectedStatus, 'domainStatus' => $domainStatus]);

            return [
                [],
                'status' => self::STATUS_FAIL
            ];
        }

        $result = [
            $cleanDomain => (bool) $domainStatus[$cleanDomain]
        ];

        if (!isset($result[$cleanDomain]) || $result[$cleanDomain] !== $expectedStatus) {
            $this->logger->error(self::MESSAGE_FAILED_CHANGE_REDIRECT, ['domain' => $domain, 'expectedStatus' => $expectedStatus, ...$result]);

            return [
                ...$result,
                'status' => self::STATUS_FAIL
            ];
        }

        $this->logger->debug('Success toggleHttpRedirect for domain', ['domain' => $domain, 'expectedStatus' => $expectedStatus, ...$result]);

        $result['status'] = self::STATUS_OK;

        return $result;
    }

    /**
     * @param string $domain
     * @return string
     */
    public static function getDomainWithoutWww(string $domain): string
    {
        return (str_starts_with($domain, 'www.')) ? substr($domain, 4) : $domain;
    }

    /**
     * @param array $domains
     *
     * Example array $domains
     * <code>
     *  ['test.com', 'best.ua'];
     * </code>
     *
     * @return array
     */
    public function getHttpsStatuses(array $domains = []): array
    {
        if (count($domains) === 0) {
            return [];
        }

        $httpRedirectStatuses = $this->runExec($this->createGetRedirectStatusesCommand($domains));

        if (!count($httpRedirectStatuses)) {
            return [];
        }

        $result = json_decode($httpRedirectStatuses[0], true);
        if ($result === null) {
            $this->logger->error(self::MESSAGE_CANT_DECODE_JSON_RESULT,
                [
                    'httpRedirectStatuses' => $httpRedirectStatuses[0],
                    'json_error' => json_last_error(),
                    'json_error_msg' => json_last_error_msg()
                ]
            );
            return [];
        }

        return $result;
    }

    /**
     * @param string $command
     *
     * @return array
     */
    private function runExec(string $command): array
    {
        $result = [];
        $return_var = 0;

        exec($command, $result, $return_var);

        if ($return_var !== 0) {
            $this->logger->error('Can`t exec command: "' . $command . '" ', ['return_var' => $return_var]);
            $result = [];
        }

        return $result;
    }

    /**
     * @param string $domain
     * @param bool $expectedStatus
     *
     * @return string
     */
    private function createToggleRedirectStatusCommand(string $domain, bool $expectedStatus): string
    {
        $status = $expectedStatus ? 'on' : 'off';

        return sprintf('%s -d %s --%s', self::NC_HTTP_REDIRECT_COMMAND, $domain, $status);
    }

    /**
     * @param array $domains
     *
     * @return string
     */
    private function createGetRedirectStatusesCommand(array $domains): string
    {
        return sprintf('%s -d %s --status', self::NC_HTTP_REDIRECT_COMMAND, implode(' ', $domains));
    }
}
Back to Directory File Manager