<commit_before><?php

namespace Meng\AsyncSoap\Guzzle;

use GuzzleHttp\ClientInterface;
use GuzzleHttp\Promise\PromiseInterface;
use Meng\AsyncSoap\SoapClientInterface;
use Meng\Soap\Interpreter;
use Psr\Http\Message\ResponseInterface;

class SoapClient implements SoapClientInterface
{
    private $interpreter;
    private $client;

    public function __construct(ClientInterface $client, PromiseInterface $interpreterPromise)
    {
        $this->interpreter = $interpreterPromise;
        $this->client = $client;
    }

    public function call($name, array $arguments, array $options = null, $inputHeaders = null, array &$outputHeaders = null)
    {
        $response = null;
        $callPromise = $this->callAsync($name, $arguments, $options, $inputHeaders, $outputHeaders)->then(
            function ($result) use (&$response) {
                $response = $result;
            }
        );
        $callPromise->wait();
        return $response;
    }

    public function callAsync($name, array $arguments, array $options = null, $inputHeaders = null, array &$output_headers = null)
    {
        return $this->prepareRequest($name, $arguments, $options, $inputHeaders)
            ->then(
                function (array $request) {
                    list($endpoint, $headers, $body) = $request;
                    return $this->client->requestAsync('POST', $endpoint, ['headers'=>$headers, 'body'=>$body]);
                }
            )
            ->then(
                function (ResponseInterface $response) use ($output_headers) {
                    return $this->interpreter->then(
                        function (Interpreter $interpreter) use ($response, $output_headers) {
                            return $interpreter->response($response->getBody()->getContents(), $outputHeaders);
                        }
                    );
                }
            );
    }

    /**
     * @param string $name
     * @param array $arguments
     * @param array $options
     * @param mixed $inputHeaders
     * @return PromiseInterface
     */
    private function prepareRequest($name, array $arguments, array $options = null, $inputHeaders = null)
    {
        return $this->interpreter->then(
            function (Interpreter $interpreter) use ($name, $arguments, $options, $inputHeaders) {
                $request = $interpreter->request($name, $arguments, $options, $inputHeaders);
                $headers = $this->prepareHeaders($request['Version'], $request['SoapAction'], $request['Envelope']);
                return [$request['Endpoint'], $headers, $request['Envelope']];
            }
        );

    }

    /**
     * @param int $version
     * @param string $soapAction
     * @param string $body
     * @return array
     *
     * @link https://www.w3.org/TR/soap12-part0/#L4697
     */
    private function prepareHeaders($version, $soapAction, $body)
    {
        $headers = [
            'Content-Length' => strlen($body)
        ];

        if ($version === '1') {
            $headers['SOAPAction'] = $soapAction;
            $headers['Content-Type'] = 'text/xml; charset="utf-8"';
        } else {
            // SOSPAction header is removed in SOAP 1.2
            // Content-type header should be "application/soap+xml"
            $headers['Content-Type'] = 'application/soap+xml; charset="utf-8"';
        }<commit_msg>Correct type hinting of $version.<commit_after><?php

namespace Meng\AsyncSoap\Guzzle;

use GuzzleHttp\ClientInterface;
use GuzzleHttp\Promise\PromiseInterface;
use Meng\AsyncSoap\SoapClientInterface;
use Meng\Soap\Interpreter;
use Psr\Http\Message\ResponseInterface;

class SoapClient implements SoapClientInterface
{
    private $interpreter;
    private $client;

    public function __construct(ClientInterface $client, PromiseInterface $interpreterPromise)
    {
        $this->interpreter = $interpreterPromise;
        $this->client = $client;
    }

    public function call($name, array $arguments, array $options = null, $inputHeaders = null, array &$outputHeaders = null)
    {
        $response = null;
        $callPromise = $this->callAsync($name, $arguments, $options, $inputHeaders, $outputHeaders)->then(
            function ($result) use (&$response) {
                $response = $result;
            }
        );
        $callPromise->wait();
        return $response;
    }

    public function callAsync($name, array $arguments, array $options = null, $inputHeaders = null, array &$output_headers = null)
    {
        return $this->prepareRequest($name, $arguments, $options, $inputHeaders)
            ->then(
                function (array $request) {
                    list($endpoint, $headers, $body) = $request;
                    return $this->client->requestAsync('POST', $endpoint, ['headers'=>$headers, 'body'=>$body]);
                }
            )
            ->then(
                function (ResponseInterface $response) use ($output_headers) {
                    return $this->interpreter->then(
                        function (Interpreter $interpreter) use ($response, $output_headers) {
                            return $interpreter->response($response->getBody()->getContents(), $outputHeaders);
                        }
                    );
                }
            );
    }

    /**
     * @param string $name
     * @param array $arguments
     * @param array $options
     * @param mixed $inputHeaders
     * @return PromiseInterface
     */
    private function prepareRequest($name, array $arguments, array $options = null, $inputHeaders = null)
    {
        return $this->interpreter->then(
            function (Interpreter $interpreter) use ($name, $arguments, $options, $inputHeaders) {
                $request = $interpreter->request($name, $arguments, $options, $inputHeaders);
                $headers = $this->prepareHeaders($request['Version'], $request['SoapAction'], $request['Envelope']);
                return [$request['Endpoint'], $headers, $request['Envelope']];
            }
        );

    }

    /**
     * @param string $version
     * @param string $soapAction
     * @param string $body
     * @return array
     *
     * @link https://www.w3.org/TR/soap12-part0/#L4697
     */
    private function prepareHeaders($version, $soapAction, $body)
    {
        $headers = [
            'Content-Length' => strlen($body)
        ];

        if ($version === '1') {
            $headers['SOAPAction'] = $soapAction;
            $headers['Content-Type'] = 'text/xml; charset="utf-8"';
        } else {
            // SOSPAction header is removed in SOAP 1.2
            // Content-type header should be "application/soap+xml"
            $headers['Content-Type'] = 'application/soap+xml; charset="utf-8"';
        }
{'fraction_non_alphanumeric': 0.13423808821360084, 'fraction_numerical': 0.0038353739489600234, 'mean_word_length': 2.2316491897044806, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 47, 'https://': 2, 'lorem ipsum': 0, 'www.': 2, 'xml': 6}, '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': '2979908', 'n_tokens_mistral': 1834, 'n_tokens_neox': 1795, 'n_words': 406}