YetiForceCompany/YetiForceCRM

View on GitHub
app/RecordCollectors/Helper/GusClient.php

Summary

Maintainability
B
5 hrs
Test Coverage
F
0%
<?php
/**
 * Gus client.
 *
 * The file is part of the paid functionality. Using the file is allowed only after purchasing a subscription. File modification allowed only with the consent of the system producer.
 *
 * @package App
 *
 * @see https://api.stat.gov.pl/Home/RegonApi
 *
 * @copyright YetiForce S.A.
 * @license   YetiForce Public License 6.5 (licenses/LicenseEN.txt or yetiforce.com)
 * @author    Adrian Kon <a.kon@yetiforce.com>
 * @author    Mariusz Krzaczkowski <m.krzaczkowski@yetiforce.com>
 */

namespace App\RecordCollectors\Helper;

/**
 * Gus client class.
 */
class GusClient extends \SoapClient
{
    /** @var array Report names for entity. */
    const REPORT_NAME = [
        'F' => [
            '1' => 'BIR11OsFizycznaDzialalnoscCeidg',
            '2' => 'BIR11OsFizycznaDzialalnoscRolnicza',
            '3' => 'BIR11OsFizycznaDzialalnoscPozostala',
            '4' => 'BIR11OsFizycznaDzialalnoscSkreslonaDo20141108',
        ],
        'LF' => 'BIR11OsFizycznaDzialalnoscSkreslonaDo20141108',
        'P' => 'BIR11OsPrawna',
        'LP' => 'BIR11JednLokalnaOsPrawnej',
    ];

    /** @var string[] Mapping field from report to number local field in record. */
    const REPORT_TO_NUMBER_LOCAL = [
        'BIR11OsPrawna' => 'praw_adSiedzNumerNieruchomosci',
        'BIR11OsFizycznaDzialalnoscSkreslonaDo20141108' => 'fiz_adSiedzNumerNieruchomosci',
        'BIR11OsFizycznaDzialalnoscPozostala' => 'fiz_adSiedzNumerNieruchomosci',
        'BIR11OsFizycznaDzialalnoscRolnicza' => 'fiz_adSiedzNumerNieruchomosci',
        'BIR11OsFizycznaDzialalnoscCeidg' => 'fiz_adSiedzNumerNieruchomosci',
    ];

    /** @var string[] Variable for mapping report names to value prefix. */
    const REPORT_PREFIX = [
        'BIR11OsPrawna' => 'praw_',
        'BIR11JednLokalnaOsPrawnej' => 'lokpraw_',
    ];

    /** @var string[] PKD report map. */
    const PKD_REPORTS = [
        'BIR11OsPrawna' => 'BIR11OsPrawnaPkd',
        'BIR11OsFizycznaDzialalnoscCeidg' => 'BIR11OsFizycznaPkd',
        'BIR11OsFizycznaDzialalnoscRolnicza' => 'BIR11OsFizycznaPkd',
        'BIR11OsFizycznaDzialalnoscPozostala' => 'BIR11OsFizycznaPkd',
        'BIR11OsFizycznaDzialalnoscSkreslonaDo20141108' => 'BIR11OsFizycznaPkd',
        'BIR11JednLokalnaOsPrawnej' => 'BIR11JednLokalnaOsPrawnejPkd',
    ];

    /** @var string Namespace for header. */
    const HEADER_NAMESPACE = 'http://www.w3.org/2005/08/addressing';

    /** @var string[] Client connection details. */
    const CONFIG = [
        'apiKey' => 'd2df36a7394c432e88ea',
        'addressToService' => 'https://wyszukiwarkaregon.stat.gov.pl/wsBIR/UslugaBIRzewnPubl.svc',
        'addressToWsdl' => 'https://wyszukiwarkaregon.stat.gov.pl/wsBIR/wsdl/UslugaBIRzewnPubl-ver11-prod.wsdl',
    ];

    /** @var self[] Namespace for header. */
    public static $cache = [];

    /** @var string Client session. */
    private $sessionId;

    /** @var resource Stream context. */
    private $streamContext;

    /** @var array Params. */
    private $params;

    /**
     * Get instance.
     *
     * @param array $params
     *
     * @return self
     */
    public static function getInstance(array $params = []): self
    {
        $cacheKey = \App\Json::encode($params);
        if (isset(self::$cache[$cacheKey])) {
            return self::$cache[$cacheKey];
        }
        $context = stream_context_create([]);
        $options = \App\RequestHttp::getSoapOptions();
        $options['soap_version'] = SOAP_1_2;
        $options['encoding'] = 'utf-8';
        $options['stream_context'] = $context;
        $instance = new self(self::CONFIG['addressToWsdl'], $options);
        $instance->streamContext = $context;
        $instance->params = $params;
        return self::$cache[$cacheKey] = $instance;
    }

    /** {@inheritdoc} */
    public function __doRequest($req, $location, $action, $version = SOAP_1_2, $oneWay = null): string
    {
        $response = parent::__doRequest($req, self::CONFIG['addressToService'], $action, $version);
        preg_match('/<s:Envelope.*<\\/s:Envelope>/s', $response, $matches);
        return $matches[0];
    }

    /**
     * Get address to action.
     *
     * @param string $action
     *
     * @return string
     */
    public function getAddressToAction(string $action): string
    {
        return 'http://CIS/BIR/PUBL/2014/07/IUslugaBIRzewnPubl/' . $action;
    }

    /**
     * Parsing response.
     *
     * @param string $response
     *
     * @return array
     */
    public function parseResponse(string $response): array
    {
        preg_match_all('/(<([\\w]+)[^>]*>)(.*?)(<\\/\\2>)/', $response, $matches, PREG_SET_ORDER);
        $totalFields = $fields = [];
        foreach ($matches as $val) {
            if (isset($fields[$val[2]])) {
                $totalFields[] = $fields;
                $fields = [];
            }
            $fields[$val[2]] = \App\Purifier::decodeHtml($val[3]);
        }
        $totalFields[] = $fields;
        return $totalFields;
    }

    /**
     * Start session - login.
     *
     * @return void
     */
    public function startSession()
    {
        if (empty($this->sessionId)) {
            $header[] = new \SoapHeader(self::HEADER_NAMESPACE, 'Action', $this->getAddressToAction('Zaloguj'), 0);
            $header[] = new \SoapHeader(self::HEADER_NAMESPACE, 'To', self::CONFIG['addressToService'], 0);
            $this->__setSoapHeaders($header);
            $result = $this->Zaloguj(['pKluczUzytkownika' => self::CONFIG['apiKey']]);
            $this->sessionId = $result->ZalogujResult;
        }
    }

    /**
     * End session - logout.
     *
     * @return void
     */
    public function endSession()
    {
        if (empty($this->register)) {
            register_shutdown_function(function () {
                try {
                    $header[] = new \SoapHeader(self::HEADER_NAMESPACE, 'Action', $this->getAddressToAction('Wyloguj'), 0);
                    $header[] = new \SoapHeader(self::HEADER_NAMESPACE, 'To', self::CONFIG['addressToService'], 0);
                    $this->__setSoapHeaders();
                    $this->__setSoapHeaders($header);
                    $this->Wyloguj(['pIdentyfikatorSesji' => $this->sessionId]);
                } catch (\Throwable $e) {
                    \App\Log::error($e->getMessage() . PHP_EOL . $e->__toString());
                    throw $e;
                }
            });
            $this->register = true;
        }
    }

    /**
     * Get data from API.
     *
     * @param string $type
     * @param array  $params
     *
     * @return array
     */
    public function getData(string $type, array $params): array
    {
        if (empty($this->sessionId)) {
            $this->startSession();
        }
        $header[] = new \SoapHeader(self::HEADER_NAMESPACE, 'Action', $this->getAddressToAction($type), true);
        $header[] = new \SoapHeader(self::HEADER_NAMESPACE, 'To', self::CONFIG['addressToService'], true);
        stream_context_set_option($this->streamContext, ['http' => ['header' => 'sid: ' . $this->sessionId]]);
        $this->__setSoapHeaders();
        $this->__setSoapHeaders($header);
        $result = $this->{$type}($params);
        return $this->parseResponse($result->{"{$type}Result"});
    }

    /**
     * Search entity.
     *
     * @param string|null $vatId
     * @param string|null $ncr
     * @param string|null $taxNumber
     *
     * @return array
     */
    public function search(?string $vatId, ?string $ncr = null, ?string $taxNumber = null): array
    {
        if (!$vatId && !$taxNumber && !$ncr) {
            return [];
        }
        $response = $this->getData('DaneSzukajPodmioty', ['pParametryWyszukiwania' => ['Nip' => $vatId,  'Krs' => $ncr, 'Regon' => $taxNumber]]);
        foreach ($response as &$info) {
            $this->getAdvanceData($info);
        }
        $this->endSession();
        return $response;
    }

    /**
     * Get data for record fields from gus reports.
     *
     * @param array $response
     *
     * @return void
     */
    public function getAdvanceData(array &$response): void
    {
        if (isset($response['Typ'], $response['SilosID']) && ($reportName = $this->getReportName($response['Typ'], $response['SilosID']))) {
            $responseFromGus = $this->getData('DanePobierzPelnyRaport', ['pRegon' => $response['Regon'], 'pNazwaRaportu' => $reportName]);
            if (empty($responseFromGus)) {
                return;
            }
            $responseFromGus = reset($responseFromGus);
            $prefixName = self::REPORT_PREFIX[$reportName] ?? 'fiz_';
            if ('fiz_' === $prefixName) {
                $resultFiz = $this->DanePobierzPelnyRaport(['pRegon' => $response['Regon'], 'pNazwaRaportu' => 'BIR11OsFizycznaDaneOgolne']);
                $responseFromGusFiz = $this->parseResponse($resultFiz->DanePobierzPelnyRaportResult);
                $responseFromGusFiz = reset($responseFromGusFiz);
                $responseFromGus = array_merge($responseFromGus, $responseFromGusFiz);
            }
            $response['NumerBudynku'] = $responseFromGus[self::REPORT_TO_NUMBER_LOCAL[$reportName]] ?? '';
            $response['NumerLokalu'] = $responseFromGus[$prefixName . 'adSiedzNumerLokalu'] ?? '';
            $response['Krs'] = $responseFromGus[$prefixName . 'numerWrejestrzeEwidencji'] ?? '';
            $response['Kraj'] = $responseFromGus[$prefixName . 'adSiedzKraj_Nazwa'] ?? '';
            $response['Kraj'] = 'POLSKA' === $response['Kraj'] ? 'Poland' : $response['Kraj'];
            $response['NumerTelefonu'] = $responseFromGus[$prefixName . 'numerTelefonu'] ?? '';
            $response['NumerFaksu'] = $responseFromGus[$prefixName . 'numerFaksu'] ?? '';
            $response['AdresEmail'] = mb_strtolower($responseFromGus[$prefixName . 'adresEmail'] ?? '');
            $response['AdresStronyInternetowej'] = mb_strtolower($responseFromGus[$prefixName . 'adresStronyinternetowej'] ?? '');
            $response['PodstawowaFormaPrawnaNazwa'] = mb_convert_case($responseFromGus[$prefixName . 'podstawowaFormaPrawna_Nazwa'] ?? '', MB_CASE_TITLE, 'UTF-8');
            $response['PodstawowaFormaPrawnaKod'] = $responseFromGus[$prefixName . 'podstawowaFormaPrawna_Symbol'] ?? '';
            $response['PodstawowaFormaPrawna'] = "{$response['PodstawowaFormaPrawnaKod']} - {$response['PodstawowaFormaPrawnaNazwa']}";
            $response['SzczegolnaFormaPrawnaNazwa'] = mb_convert_case($responseFromGus[$prefixName . 'szczegolnaFormaPrawna_Nazwa'] ?? '', MB_CASE_TITLE, 'UTF-8');
            $response['SzczegolnaFormaPrawnaKod'] = $responseFromGus[$prefixName . 'szczegolnaFormaPrawna_Symbol'] ?? '';
            $response['SzczegolnaFormaPrawna'] = "{$response['SzczegolnaFormaPrawnaKod']} - {$response['SzczegolnaFormaPrawnaNazwa']}";
            $response['DataRozpoczeciaDzialalnosci'] = $responseFromGus[$prefixName . 'dataRozpoczeciaDzialalnosci'] ?? '';
            $response['FormaFinansowania'] = $responseFromGus[$prefixName . 'formaFinansowania_Nazwa'] ?? '';
            $response['FormaWlasnosci'] = $responseFromGus[$prefixName . 'formaWlasnosci_Nazwa'] ?? '';
            $response['DataPowstania'] = $responseFromGus[$prefixName . 'dataPowstania'] ?? '';
            $response['DataWpisuDoREGON'] = $responseFromGus[$prefixName . 'dataWpisuDoREGON'] ?? '';
            $response['DataZawieszeniaDzialalnosci'] = $responseFromGus[$prefixName . 'dataZawieszeniaDzialalnosci'] ?? '';
            $response['DataWznowieniaDzialalnosci'] = $responseFromGus[$prefixName . 'dataWznowieniaDzialalnosci'] ?? '';
            $response['DataZaistnieniaZmiany'] = $responseFromGus[$prefixName . 'dataZaistnieniaZmiany'] ?? '';
            $response['DataZakonczeniaDzialalnosci'] = $responseFromGus[$prefixName . 'dataZakonczeniaDzialalnosci'] ?? '';
            $response['DataWpisuDoRejestruEwidencji'] = $responseFromGus[$prefixName . 'dataWpisuDoRejestruEwidencji'] ?? '';
            $response['DataSkresleniazRegon'] = $responseFromGus[$prefixName . 'dataSkresleniazRegon'] ?? '';
            if (isset($responseFromGus[$prefixName . 'nip'])) {
                $response['Nip'] = $responseFromGus[$prefixName . 'nip'];
            }
            if (\in_array('pkd', $this->params)) {
                $result = $this->DanePobierzPelnyRaport(['pRegon' => $response['Regon'], 'pNazwaRaportu' => self::PKD_REPORTS[$reportName]]);
                $additional = [];
                foreach ($this->parseResponse($result->DanePobierzPelnyRaportResult) as $value) {
                    $name = mb_convert_case($value[$prefixName . 'pkdNazwa'] ?? '', MB_CASE_TITLE, 'UTF-8');
                    if ($value[$prefixName . 'pkdPrzewazajace']) {
                        $response['PKDPodstawowyKod'] = $value[$prefixName . 'pkdKod'];
                        $response['PKDPodstawowyNazwa'] = $name;
                    } else {
                        $additional[] = "{$value[$prefixName . 'pkdKod']} - {$name}";
                    }
                }
                $response['PKDPozostale'] = implode(' ## ', $additional);
            }
        } else {
            $response = [];
        }
    }

    /**
     * Undocumented function.
     *
     * @param string $type
     * @param string $silosId
     *
     * @return string
     */
    private function getReportName(string $type, string $silosId): string
    {
        $name = '';
        if ('F' === $type && isset(self::REPORT_NAME[$type][$silosId])) {
            $name = self::REPORT_NAME[$type][$silosId];
        } elseif (isset(self::REPORT_NAME[$type])) {
            $name = self::REPORT_NAME[$type];
        }
        return $name;
    }
}