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

<?php

namespace App\Service\PluginGateway;

use App\Entity\Certificate;
use App\Service\Auth\Auth;
use App\Service\Auth\OAuthException;
use App\Service\NcPlugin\InvalidAccessTokenNcApiException;
use App\Service\NcPlugin\NcApiException;
use App\Service\NcPlugin\PluginException;
use App\Service\State\StateUser;
use DOMDocument;
use DOMElement;
use Monolog\Level;
use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\Attribute\Autowire;

class NcCoreApi extends AbstractApi
{
    /**
     * NC API commands
     */
    const CMD_NC_GET_INFO                 = 'namecheap.ssl.getInfo';
    const CMD_NC_ACTIVATE                 = 'namecheap.ssl.activate';
    const CMD_NC_REISSUE                  = 'namecheap.ssl.reissue';
    const CMD_NC_GET_SSL_LIST             = 'namecheap.ssl.getList';
    const CMD_NC_GET_USER_INFO            = 'namecheap.users.getInfo';

    /**
     * Configuration options:
     * <pre>
     * array with following keys:
     *
     *  - [optional if we use oAuth] API user and key for calling NC API (got from NC user account: http://www.namecheap.com/myaccount/modify-profile-api.asp )
     *  'user'          => 'API_USER',
     *  'key'           => 'API_KEY',
     *
     *  - [optional] cPanel related fields
     *  'cpAccountName' => 'cPanelAccountName', //Need only for work with RCC
     *  'cpServerName'  => 'cPanelServerName',  //Need only for work with RCC
     *
     *  - [optional] data for technical params (used for activation/reissue)
     *  'techs'     => array(
     *      'TechEmailAddress'           => 'TechEmailAddress',
     *      'TechFirstName'              => 'TechFirstName',
     *      'TechLastName'               => 'TechLastName',
     *      'TechOrganizationName'       => 'TechOrganizationName',
     *      'TechAddress1'               => 'TechAddress1',
     *      'TechAddress2'               => 'TechAddress2',
     *      'TechJobTitle'               => 'TechJobTitle',
     *      'TechCity'                   => 'TechCity',
     *      'TechStateProvince'          => 'TechStateProvince',
     *      'TechStateProvinceChoice'    => 'TechStateProvinceChoice',
     *      'TechPostalCode'             => 'TechPostalCode',
     *      'TechCountry'                => 'TechCountry',
     *      'TechPhone'                  => 'TechPhone',
     *      'TechPhoneExt'               => 'TechPhoneExt',
     *      'TechFax'                    => 'TechFax',
     *  ),
     *
     *  - [optional] data for billing params, can be the same as technical params (used for activation/reissue)
     *  'bill'      => array(
     *      'BillingEmailAddress'        => 'TechEmailAddress',
     *      'BillingFirstName'           => 'TechFirstName',
     *      'BillingLastName'            => 'TechLastName',
     *      'BillingOrganizationName'    => 'TechOrganizationName',
     *      'BillingAddress1'            => 'TechAddress1',
     *      'BillingAddress2'            => 'TechAddress2',
     *      'BillingJobTitle'            => 'TechJobTitle',
     *      'BillingCity'                => 'TechCity',
     *      'BillingStateProvince'       => 'TechStateProvince',
     *      'BillingStateProvinceChoice' => 'TechStateProvinceChoice',
     *      'BillingPostalCode'          => 'TechPostalCode',
     *      'BillingCountry'             => 'TechCountry',
     *      'BillingPhone'               => 'TechPhone',
     *      'BillingPhoneExt'            => 'TechPhoneExt',
     *      'BillingFax'                 => 'TechFax',
     *  ),
     * </pre>
     * @param StateUser $stateUser
     * @param Auth $auth
     * @param string $apiUrl
     * @param LoggerInterface $ncCoreApiLogger
     */
    public function __construct(
        protected StateUser              $stateUser,
        private readonly Auth            $auth,
        #[Autowire(env: 'NC_CORE_API_URL')]
        private readonly string          $apiUrl,
        protected LoggerInterface        $ncCoreApiLogger
    ) {
        $this->logger = $this->ncCoreApiLogger;
    }

    /**
     * Gets certificates list
     *
     * @param string $list_type - Possible values are ALL,Processing,EmailSent,TechnicalProblem,InProgress,Completed,Deactivated,Active,Cancelled,NewPurchase,NewRenewal.
     * @param string $search_query - Keyword to look for on the SSL list
     * @param string $sort_by - Possible values are PURCHASEDATE, PURCHASEDATE_DESC, SSLTYPE, SSLTYPE_DESC, EXPIREDATETIME, EXPIREDATETIME_DESC,Host_Name, Host_Name_DESC.
     * @return array - array of ssl certificates
     * E.g.:
     * [
     *   [
     *       'id' => '123456',
     *       'common_name' => '',
     *       'type' => 'positivessl free',
     *       'purchase_date' => 1521468127,
     *       'expires' => 0,
     *       'is_expired' => false,
     *       'status' => 'NEWPURCHASE',
     *       'activation_expire_date' => 0,
     *       'years' => '1',
     *   ],
     *   [
     *       'id' => '123457',
     *       'common_name' => 'example.com',
     *       'type' => 'positivessl',
     *       'purchase_date' => 1521468119,
     *       'expires' => 0,
     *       'is_expired' => false,
     *       'status' => 'NEWRENEWAL',
     *       'activation_expire_date' => 0,
     *       'years' => '1',
     *   ],
     * ]
     * @throws InvalidAccessTokenNcApiException
     * @throws NcApiException
     */
    public function getSslList($list_type = 'ALL', $search_query = '', $sort_by = 'PURCHASEDATE_DESC'): array
    {
        $certs  = [];
        $params = [
            'PageSize' => 99,
            'Page' => 1,
            'ListType' => $list_type,
            'SortBy' => $sort_by,
        ];

        if ($search_query != '') {
            $params['SearchTerm'] = $search_query;
        }

        $total_items = 0;
        for ($ii = 0; $ii < 100; $ii++) {
            $response = $this->call(self::CMD_NC_GET_SSL_LIST, $params);
            /** @var $certInfo DOMElement */
            foreach ($response->getElementsByTagName('SSL') as $certInfo) {
                $buf = [
                    'id'                     => $certInfo->hasAttribute('CertificateID')
                        ? $certInfo->getAttribute('CertificateID')
                        : '',
                    'common_name'            => $certInfo->hasAttribute('HostName')
                        ? $certInfo->getAttribute('HostName')
                        : '',
                    'type'                   => $certInfo->hasAttribute('SSLType')
                        ? $certInfo->getAttribute('SSLType')
                        : '',
                    'purchase_date'          => $certInfo->hasAttribute('PurchaseDate')
                        ? $certInfo->getAttribute('PurchaseDate')
                        : '',
                    'expires'                => $certInfo->hasAttribute('ExpireDate')
                        ? $certInfo->getAttribute('ExpireDate')
                        : '',
                    'is_expired'             => $certInfo->hasAttribute('IsExpiredYN') && strtolower($certInfo->getAttribute('IsExpiredYN')) === 'true',
                    'status'                 => $certInfo->hasAttribute('Status')
                        ? strtoupper($certInfo->getAttribute('Status'))
                        : '',
                    'activation_expire_date' => $certInfo->hasAttribute('ActivationExpireDate')
                        ? $certInfo->getAttribute('ActivationExpireDate')
                        : '',
                    'years'                  => $certInfo->hasAttribute('Years')
                        ? $certInfo->getAttribute('Years')
                        : '',
                ];
                $buf['expires'] = $buf['expires'] != ''
                    ? strtotime($buf['expires'])
                    : 0;
                $buf['purchase_date'] = $buf['purchase_date'] != ''
                    ? strtotime($buf['purchase_date'])
                    : 0;
                $buf['activation_expire_date'] = $buf['activation_expire_date'] != ''
                    ? strtotime($buf['activation_expire_date'])
                    : 0;

                if ($buf['status'] === Certificate::NCSTATUS_NEWPURCHASE) {
                    $buf['common_name'] = null;
                }

                $certs[] = $buf;
            }
            if ($total_items === 0) {
                $totalItemsElements = $response->getElementsByTagName('TotalItems');
                if ($totalItemsElements->length > 0) {
                    $total_items = (int)$totalItemsElements->item(0)->nodeValue;
                }
            }
            if (($params['Page'] * $params['PageSize']) >= $total_items || $total_items == 0) {
                break;
            }
            $params['Page'] += 1;
        }

        return $certs;
    }

    /**
     * @param $allowedStatuses
     *
     * @return array
     * @throws InvalidAccessTokenNcApiException
     * @throws NcApiException
     */
    public function getSslListWithStatuses($allowedStatuses): array
    {
        $getExpired = false;
        if (false !== ($expiredKey = array_search('EXPIRED', $allowedStatuses))) {
            $getExpired = true;
            unset($allowedStatuses[$expiredKey]);
        }

        $list = [];
        foreach ($allowedStatuses as $status) {
            $list = array_merge($list, $this->getSslList(strtoupper($status)));
        }

        if (!$getExpired) {
            return array_filter($list, function($ssl) {
                return !$ssl['is_expired'];
            });
        }

        return $list;
    }

    /**
     * @param $id
     * @param bool $returnCert
     * @param string $userName
     * @return array
     * @throws NcApiException|InvalidAccessTokenNcApiException
     */
    public function getInfo($id, $returnCert = false, $userName = ''): array
    {
        $params = [
            'CertificateID' => $id,
        ];

        if ($returnCert) {
            $params['returncertificate'] = 'true';
            $params['returntype'] = 'individual';
        }

        $response = $this->call(self::CMD_NC_GET_INFO, $params);

        $ssl_info = $response->getElementsByTagName('SSLGetInfoResult')->item(0);
        $ssl_info_doc = new DomDocument;
        $ssl_info_doc->appendChild($ssl_info_doc->importNode($ssl_info, true));
        $ssl_info_xpath = new \DOMXPath($ssl_info_doc);

        $certificate = [
            'id' => $id,
            'status' => strtoupper($ssl_info?->getAttribute('Status')),
            'status_desc' => $ssl_info?->getAttribute('StatusDescription'),
            'type' => $ssl_info?->getAttribute('Type'),
            'issued_on' => $ssl_info?->getAttribute('IssuedOn'),
            'expires' => $ssl_info?->getAttribute('Expires'),
            'activation_expire_date' => $ssl_info?->getAttribute('ActivationExpireDate'),
            'order_id' => $ssl_info?->getAttribute('OrderId'),
            'sans_count' => $ssl_info?->getAttribute('SANSCount'),
            'replaced_by' => $ssl_info?->getAttribute('ReplacedBy'),
            'approver_email' => $this->getXmlElementValue($ssl_info_doc, 'ApproverEmail'),
            'common_name' => $ssl_info_doc?->getElementsByTagName('CommonName')?->item(0)?->nodeValue,
            'admin_name' => $ssl_info_doc?->getElementsByTagName('AdministratorName')?->item(0)?->nodeValue,
            'admin_email' => $ssl_info_doc?->getElementsByTagName('AdministratorEmail')?->item(0)?->nodeValue,
            'csr' => '',
            'cert_body' => '',
            'ca_certs' => array(),
        ];

        if ($certificate['status'] === Certificate::NCSTATUS_NEWPURCHASE) {
            $certificate['common_name'] = null;
        }

        $certificate['expires'] = $certificate['expires'] != '' ? strtotime($certificate['expires']) : 0;
        $certificate['activation_expire_date'] = $certificate['activation_expire_date'] != '' ? strtotime($certificate['activation_expire_date']) : 0;
        $certificate['issued_on'] = $certificate['issued_on'] != '' ? strtotime($certificate['issued_on']) : 0;


        $csr = $ssl_info_doc->getElementsByTagName('CSR');
        if ($csr->length > 0) {
            $certificate['csr'] = $csr->item(0)->nodeValue;
        }

        $cert = $ssl_info_xpath->query('//CertificateDetails/Certificates/Certificate');
        if ($cert->length > 0) {
            $certificate['cert_body'] = $cert->item(0)->nodeValue;
        }

        $ca_certs = $ssl_info_xpath->query('//CertificateDetails/Certificates/CaCertificates/Certificate/Certificate');
        foreach ($ca_certs as $ca_cert) {
            $certificate['ca_certs'][] = $ca_cert->nodeValue;
        }

        return $certificate;
    }

    /**
     * @return array
     *
     * @throws NcApiException
     */
    public function getUserInfo(): array
    {
        $response = $this->call(self::CMD_NC_GET_USER_INFO);

        $user_info = $response->getElementsByTagName('UserGetInfoResult')->item(0);

        $default_addr = $response->getElementsByTagName('DefaultAddress')->item(0);
        $default_addr_doc = new DomDocument;
        $default_addr_doc->appendChild($default_addr_doc->importNode($default_addr, true));

        $profile_addr = $response->getElementsByTagName('ProfileAddress')->item(0);
        $profile_addr_doc = new DomDocument;
        $profile_addr_doc->appendChild($profile_addr_doc->importNode($profile_addr, true));

        return [
            'id' => $user_info->getAttribute('UserID'),
            'login' => $user_info->getAttribute('UserName'),
            'default_address' => array(
                'first_name' => $default_addr_doc->getElementsByTagName('FirstName')->item(0)->nodeValue,
                'last_name' => $default_addr_doc->getElementsByTagName('LastName')->item(0)->nodeValue,
                'email' => $default_addr_doc->getElementsByTagName('EmailAddress')->item(0)->nodeValue,
                'address1' => $default_addr_doc->getElementsByTagName('Address1')->item(0)->nodeValue,
                'address2' => $default_addr_doc->getElementsByTagName('Address2')->item(0)->nodeValue,
                'city' => $default_addr_doc->getElementsByTagName('City')->item(0)->nodeValue,
                'state_province' => $default_addr_doc->getElementsByTagName('StateProvince')->item(0)->nodeValue,
                'state_province_choice' => $default_addr_doc->getElementsByTagName('StateProvinceChoice')->item(0)->nodeValue,
                'zip' => $default_addr_doc->getElementsByTagName('Zip')->item(0)->nodeValue,
                'country' => $default_addr_doc->getElementsByTagName('Country')->item(0)->nodeValue,
                'phone' => $default_addr_doc->getElementsByTagName('Phone')->item(0)->nodeValue,
                'phone_ext' => $default_addr_doc->getElementsByTagName('PhoneExt')->item(0)->nodeValue,
                'fax' => $default_addr_doc->getElementsByTagName('Fax')->item(0)->nodeValue,
                'job_title' => $default_addr_doc->getElementsByTagName('JobTitle')->item(0)->nodeValue,
                'organization' => $default_addr_doc->getElementsByTagName('Organization')->item(0)->nodeValue,
            ),
            'profile_address' => array(
                'first_name' => $this->getXmlElementValue($profile_addr_doc, 'FirstName'),
                'last_name' => $this->getXmlElementValue($profile_addr_doc, 'LastName'),
                'email' => $this->getXmlElementValue($profile_addr_doc, 'EmailAddress'),
                'address1' => $this->getXmlElementValue($profile_addr_doc, 'Address1'),
                'address2' => $this->getXmlElementValue($profile_addr_doc, 'Address2'),
                'city' => $this->getXmlElementValue($profile_addr_doc, 'City'),
                'state_province' => $this->getXmlElementValue($profile_addr_doc, 'StateProvince'),
                'state_province_choice' => $this->getXmlElementValue($profile_addr_doc, 'StateProvinceChoice'),
                'zip' => $this->getXmlElementValue($profile_addr_doc, 'Zip'),
                'country' => $this->getXmlElementValue($profile_addr_doc, 'Country'),
                'phone' => $this->getXmlElementValue($profile_addr_doc, 'Phone'),
                'phone_ext' => $this->getXmlElementValue($profile_addr_doc, 'PhoneExt'),
                'fax' => $this->getXmlElementValue($profile_addr_doc, 'Fax'),
                'job_title' => $this->getXmlElementValue($profile_addr_doc, 'JobTitle'),
                'organization' => $this->getXmlElementValue($profile_addr_doc, 'Organization'),
            ),
        ];
    }

    protected function getXmlElementValue($xml, $tagName)
    {
        $nodeSet = $xml->getElementsByTagName($tagName);
        if (!empty($nodeSet)) {
            $node = $nodeSet->item(0);
            if (!empty($node)) {
                return $node->nodeValue;
            }
        }

        return null;
    }

    /**
     * Activates certificate
     *
     * @param int $certId
     * @param string $csr
     * @param string $webserverType
     * @param array $adminDetails
     * @param string $sslType
     * @return array
     * @throws NcApiException
     */
    public function activate(int $certId, string $csr, string $webserverType, array $adminDetails, string $sslType = ''): array
    {
        return $this->makeActivation(self::CMD_NC_ACTIVATE, $certId, $csr, $webserverType, $adminDetails, $sslType);
    }

    /**
     * Reissues certificate
     *
     * @param int $certId
     * @param string $csr
     * @param string $webserverType
     * @param array $adminDetails
     * @param string $sslType
     * @return array
     * @throws NcApiException
     * @throws InvalidAccessTokenNcApiException
     */
    public function reissue(int $certId, string $csr, string $webserverType, array $adminDetails, string $sslType = ''): array
    {
        return $this->makeActivation(self::CMD_NC_REISSUE, $certId, $csr, $webserverType, $adminDetails, $sslType);
    }

    /**
     * @param string $command
     * @param array $params
     * @param bool $loggerEnabled
     *
     * @return DOMDocument
     *
     * @throws NcApiException
     * @throws InvalidAccessTokenNcApiException
     */
    private function call(string $command, array $params = [], bool $loggerEnabled = true): DOMDocument
    {
        $response = $this->makeCall($command, $params, $loggerEnabled);

        try {
            //Hack to remove warning: The default (no prefix) Namespace URI for XPath queries is always '' and it cannot be redefined to 'http://api.namecheap.com/xml.response'.
            $response = preg_replace('#xmlns\=\"(.+?)\"#', '', $response);

            $dom = new DOMDocument('1.0', 'utf-8');
            // Load Xml Data
            if (!$dom->loadXML($response)) {
                throw new NcApiException('Can\'t get a data from NC probably problem with auth tokens', NcApiException::NC_INVALID_RESPONSE);
            }
        } catch (NcApiException $e) {
            throw new NcApiException(
                'Internal error occurred. Please try again. More Info: ' . $e->getMessage(),
                $e->getCode()
            );
        } catch (\Exception $e) {
            throw new NcApiException(
                'Some error occurred. Please try again. More Info: ' . $e->getMessage(),
                $e->getCode(),
                $e
            );
        }

        if (str_contains($response, '500-UnhandledException')) {
            throw new NcApiException('Can\'t get a data from NC probably problem with auth tokens', NcApiException::NC_INVALID_RESPONSE);
        }

        /** @var DOMElement $apiError */
        $apiError = $dom->getElementsByTagName('Error')->item(0);
        if (!empty($apiError->nodeValue)
            // exception for CREATE command: it should be ignored
            && strtolower(trim($apiError->nodeValue)) != 'certificate cannot be created as the purchasevalidationid already exists.'
        ) {
            if (!stripos($apiError->nodeValue, 'Invalid access token')){
                throw new InvalidAccessTokenNcApiException(
                    'Invalid access token. More Info: ' . $apiError->nodeValue,
                    $apiError->hasAttribute('Number') ? $apiError->getAttribute('Number') : -1
                );
            }

            throw new NcApiException(
                'Service provider error occurred. More Info: ' . $apiError->nodeValue,
                $apiError->hasAttribute('Number') ? $apiError->getAttribute('Number') : -1
            );
        }

        return $dom;
    }

    /**
     * @param string $command
     * @param array $params
     * @param bool $loggerEnabled
     *
     * @return string
     *
     * @throws PluginException|OAuthException
     */
    private function makeCall(string $command, array $params, bool $loggerEnabled): string
    {
        $requestParameters = $this->createRequestParameters($command, $params);
        $response = $this->auth->accessResource($this->apiUrl, $requestParameters);

        if ($loggerEnabled) {
            $this->log(Level::Info, [
                'request' => http_build_query($requestParameters),
                'response' => $response ?: '[empty response]',
            ]);
        }

        return $response;
    }

    /**
     * @param string $command
     * @param array $params
     *
     * @return array
     */
    private function createRequestParameters(string $command, array $params): array
    {
        $username = $this->stateUser->getUser()->getNcLogin();

        return array_merge($params, [
            'Command' => $command,
            'ClientIp' => $this->getClientIp(),
            'UserName' => $username,
            'ApiUser' => $username,
        ]);
    }

    /**
     * Performs activation/reissue operations
     *
     * @param string $command
     * @param int $certId
     * @param string $csr
     * @param string $webserverType
     * @param array $adminDetails
     * @param string $sslType It's better send it to make sure the CA is Comodo and HTTP-validation must be used for parseCsr NC API command
     * @return array
     *@throws NcApiException|InvalidAccessTokenNcApiException
     */
    private function makeActivation(string $command, int $certId, string $csr, string $webserverType, array $adminDetails, string $sslType = ''): array
    {
        $request = $this->getActivateParams($certId, $csr, $webserverType, $adminDetails, $sslType);
        $response = $this->call($command, $request);

        /** @var DOMElement $details */
        if ($command == self::CMD_NC_ACTIVATE) {
            $details = $response->getElementsByTagName('SSLActivateResult')->item(0);
        } else {
            $details = $response->getElementsByTagName('SSLReissueResult')->item(0);
        }

        if (!$details instanceof DOMElement) {
            throw new NcApiException('Cannot get activation result data');
        }

        // we didn't make the parseCsr request or it didn't contain HTTP-validation field
        if (empty($fileName) || empty($fileContent)) {
            $httpValidation = $response->getElementsByTagName('HttpDCValidation')->item(0);

            if (!$httpValidation) {
                if (empty($fileName) && empty($fileContent)) {
                    throw new NcApiException('Cannot get the HTTP validation data');
                } else {
                    throw new NcApiException('HTTP validation data is empty');
                }
            }

            $fileName    = $httpValidation->getElementsByTagName('FileName')->length
                ? trim($httpValidation->getElementsByTagName('FileName')->item(0)->nodeValue)
                : '';
            $fileContent = $httpValidation->getElementsByTagName('FileContent')->length
                ? trim($httpValidation->getElementsByTagName('FileContent')->item(0)->nodeValue)
                : '';

            if (empty($fileName) || empty($fileContent)) {
                throw new NcApiException('HTTP validation data is empty');
            }
        }

        return [
            'ID'                    => $details->getAttribute('ID'),
            'Status'                => 'ORDERCREATED',
            'ValidationFileName'    => $fileName,
            'ValidationFileContent' => $fileContent,
        ];
    }

    /**
     * @param int $certId
     * @param string $csr
     * @param string $webServerType
     * @param array $adminDetails
     * @param string $sslType
     *
     * @return array
     */
    private function getActivateParams(int $certId, string $csr, string $webServerType, array $adminDetails, string $sslType = ''): array
    {
        $orgCertificates = array('premiumssl wildcard', 'instantssl', 'instantssl pro', 'premiumssl');

        $request = array(
            'HTTPDCValidation' => 'TRUE',
            'CertificateID'    => $certId,
            'csr'              => $csr,
            'WebServerType'    => $webServerType,
        );
        if (!empty($sslType) && in_array(strtolower($sslType), $orgCertificates)) {
            $orgRepPhone = ($adminDetails['OrganizationRepPhoneno'] != '')
                ? $adminDetails['OrganizationRepPhoneExt'] . '.' . $adminDetails['OrganizationRepPhoneno']
                : '';
            $orgRepFax   = ($adminDetails['OrganizationRepFaxno'] != '')
                ? $adminDetails['OrganizationRepFaxExt'] . '.' . $adminDetails['OrganizationRepFaxno']
                : '';
            $ovData      = array(
                'OrganizationRepPhone' => $orgRepPhone,
                'OrganizationRepFax'   => $orgRepFax
            );
            $request     = array_merge($request, $ovData);
            if ($adminDetails['OrganizationRepCallbackDestinationSame'] == 'Yes') {
                unset($adminDetails['OrganizationRepLegalName']);
                unset($adminDetails['OrganizationRepAddress1']);
                unset($adminDetails['OrganizationRepAddress2']);
                unset($adminDetails['OrganizationRepCity']);
                unset($adminDetails['OrganizationRepStateProvince']);
                unset($adminDetails['OrganizationRepPostalCode']);
                unset($adminDetails['OrganizationRepCountry']);
                unset($adminDetails['OrganizationRepDUNS']);
                unset($adminDetails['OrganizationRepPostOfficeBox']);
            }
            unset($adminDetails['OrganizationRepPhoneExt']);
            unset($adminDetails['OrganizationRepPhoneno']);
            unset($adminDetails['OrganizationRepFaxExt']);
            unset($adminDetails['OrganizationRepFaxno']);
        }
        if (isset($adminDetails['OrganizationPhoneNum'])) {
            $adminDetails['OrganizationPhone'] = $adminDetails['OrganizationPhoneCode'] . '.'
                . $adminDetails['OrganizationPhoneNum'];
            unset($adminDetails['OrganizationPhoneCode']);
            unset($adminDetails['OrganizationPhoneNum']);
        }
        if (isset($adminDetails['OrganizationFaxNum'])) {
            $adminDetails['OrganizationFax'] = !empty($adminDetails['OrganizationFaxNum'])
                ? $adminDetails['OrganizationFaxCode'] . '.' . $adminDetails['OrganizationFaxNum']
                : '';
            unset($adminDetails['OrganizationFaxCode']);
            unset($adminDetails['OrganizationFaxNum']);
        }

        return array_filter(array_merge($request, $adminDetails), static function($var) {
            return $var !== null;
        });
    }

    /**
     * @return string
     */
    private function getClientIp(): string
    {
        return $_SERVER['REMOTE_ADDR'] ?? $_SERVER['HTTP_HOST'] ?? '127.0.0.1';
    }
}
Back to Directory File Manager