<commit_before><?php
/**
 * PHP Deepelopment Framework
 *
 * @package Deepelopment/Net/RPC
 * @license Unlicense http://unlicense.org/
 */

namespace Deepelopment\Net\RPC\Client;

use BadMethodCallException;
use InvalidArgumentException;
use RuntimeException;
use Deepelopment\Logger;
use Deepelopment\Net\Request;
use Deepelopment\Net\RPC\ClientInterface;
use Deepelopment\Net\RPC\ClientLayerNet;

/**
 * Remote Procedure Call JSON client layer,
 * see {@see Deepelopment\Net\RPC}.
 *
 * Based on {@see https://github.com/fguillot/JsonRPC}.
 *
 * @package Deepelopment/Net/RPC
 * @author  deepeloper ({@see https://github.com/deepeloper})
 */
class JSON extends ClientLayerNet implements ClientInterface
{
    /**
     * Version of protocol
     */
    const JSON_RPC_VERSION = '2.0';

    /**
     * Executes remote server method.
     *
     * @param  string  $method
     * @param  array   $params
     * @param  array   $options       {@see
     *                                \Deepelopment\Net\Request::__construct()}
     * @param  bool    $resetOptions  Flag specifying to reset previous options
     * @param  string  $url           Cusrom URL if differs from initialized
     * @return mixed
     */
    public function execute(
        $method,
        array $params = NULL,
        array $options = array(),
        $resetOptions = FALSE,
        $url = ''
    )
    {
        $request = $this->prepareRequest($method, $params);
        $response = $this->sendRequest($request, $options, $resetOptions, $url);

        return $response;
    }

    /**
     * Executes remote server batch.
     *
     * @param  array   $batch         Array containing arrays:
     *                                [
     *                                    'method' => ...(,
     *                                    'params' => array(,,,))
     *                                ]
     * @param  array   $options       {@see
     *                                \Deepelopment\Net\Request::__construct()}
     * @param  bool    $resetOptions  Flag specifying to reset previous options
     * @param  string  $url           Cusrom URL if differs from initialized
     * @return mixed
     */
    public function executeBatch(
        array $batch,
        array $options = array(),
        $resetOptions = FALSE,
        $url = ''
    )
    {
        $request = array();
        foreach ($batch as $command) {
            $params = isset($command['params']) ? $command['params'] : NULL;
            $request[] = $this->prepareRequest($command['method'], $params);
        }
        $response = $this->sendRequest($request, $options, $resetOptions, $url);

        return $response;
    }

    protected function getDefaultOptions()
    {
        return
            array(
                CURLOPT_CUSTOMREQUEST => 'POST'
            );
    }

    /**
     * Patches response.
     *
     * @param  string &$response
     * @return void
     */
    protected function patchResponse(&$response)
    {
    }

    /**
     * Validates response.
     *
     * @param  string &$response
     * @return void
     */
    protected function validateResponse($response)
    {
        if (
            isset($response['code']) &&
            isset($response['message'])
        ) {
            $this->handleError($response);
        }
    }

    /**
     * Prepares request data using calling RPC method and parameters.
     *
     * @param  string $method
     * @param  array  $params
     * @return array
     */
    protected function prepareRequest($method, array $params = NULL)
    {
        $request = array(
            'jsonrpc' => self::JSON_RPC_VERSION,
            'method'  => $method,
            'id'      => mt_rand()
        );
        if (is_array($params)) {
            $request['params'] = $params;
        }

        return $request;
    }

    /**
     * Sends request to remote server.
     *
     * @param  array   $request
     * @param  array   $options
     * @param  bool    $resetOptions  Flag specifying to reset previous options
     * @param  string  $url
     * @return mixed
     */
    protected function sendRequest(
        array $request,
        array $options = array(),
        $resetOptions = FALSE,
        $url = ''
    )
    {
        $options['method'] = Request::METHOD_OTHER;
        $options[CURLOPT_POSTFIELDS] = json_encode($request);

        $this->logger->write(
            sprintf(
                "sending request:\n%s",
                get_class($this),
                print_r($request, TRUE)
            ),
            Logger::NOTICE
        );

        $response = $this->send('', $options, $resetOptions, $url);

        $decoded = json_decode($response, TRUE);
        if (!is_array($decoded)) {
            $this->logger->write(
                sprintf(<commit_msg>Logging fixed.<commit_after><?php
/**
 * PHP Deepelopment Framework
 *
 * @package Deepelopment/Net/RPC
 * @license Unlicense http://unlicense.org/
 */

namespace Deepelopment\Net\RPC\Client;

use BadMethodCallException;
use InvalidArgumentException;
use RuntimeException;
use Deepelopment\Logger;
use Deepelopment\Net\Request;
use Deepelopment\Net\RPC\ClientInterface;
use Deepelopment\Net\RPC\ClientLayerNet;

/**
 * Remote Procedure Call JSON client layer,
 * see {@see Deepelopment\Net\RPC}.
 *
 * Based on {@see https://github.com/fguillot/JsonRPC}.
 *
 * @package Deepelopment/Net/RPC
 * @author  deepeloper ({@see https://github.com/deepeloper})
 */
class JSON extends ClientLayerNet implements ClientInterface
{
    /**
     * Version of protocol
     */
    const JSON_RPC_VERSION = '2.0';

    /**
     * Executes remote server method.
     *
     * @param  string  $method
     * @param  array   $params
     * @param  array   $options       {@see
     *                                \Deepelopment\Net\Request::__construct()}
     * @param  bool    $resetOptions  Flag specifying to reset previous options
     * @param  string  $url           Cusrom URL if differs from initialized
     * @return mixed
     */
    public function execute(
        $method,
        array $params = NULL,
        array $options = array(),
        $resetOptions = FALSE,
        $url = ''
    )
    {
        $request = $this->prepareRequest($method, $params);
        $response = $this->sendRequest($request, $options, $resetOptions, $url);

        return $response;
    }

    /**
     * Executes remote server batch.
     *
     * @param  array   $batch         Array containing arrays:
     *                                [
     *                                    'method' => ...(,
     *                                    'params' => array(,,,))
     *                                ]
     * @param  array   $options       {@see
     *                                \Deepelopment\Net\Request::__construct()}
     * @param  bool    $resetOptions  Flag specifying to reset previous options
     * @param  string  $url           Cusrom URL if differs from initialized
     * @return mixed
     */
    public function executeBatch(
        array $batch,
        array $options = array(),
        $resetOptions = FALSE,
        $url = ''
    )
    {
        $request = array();
        foreach ($batch as $command) {
            $params = isset($command['params']) ? $command['params'] : NULL;
            $request[] = $this->prepareRequest($command['method'], $params);
        }
        $response = $this->sendRequest($request, $options, $resetOptions, $url);

        return $response;
    }

    protected function getDefaultOptions()
    {
        return
            array(
                CURLOPT_CUSTOMREQUEST => 'POST'
            );
    }

    /**
     * Patches response.
     *
     * @param  string &$response
     * @return void
     */
    protected function patchResponse(&$response)
    {
    }

    /**
     * Validates response.
     *
     * @param  string &$response
     * @return void
     */
    protected function validateResponse($response)
    {
        if (
            isset($response['code']) &&
            isset($response['message'])
        ) {
            $this->handleError($response);
        }
    }

    /**
     * Prepares request data using calling RPC method and parameters.
     *
     * @param  string $method
     * @param  array  $params
     * @return array
     */
    protected function prepareRequest($method, array $params = NULL)
    {
        $request = array(
            'jsonrpc' => self::JSON_RPC_VERSION,
            'method'  => $method,
            'id'      => mt_rand()
        );
        if (is_array($params)) {
            $request['params'] = $params;
        }

        return $request;
    }

    /**
     * Sends request to remote server.
     *
     * @param  array   $request
     * @param  array   $options
     * @param  bool    $resetOptions  Flag specifying to reset previous options
     * @param  string  $url
     * @return mixed
     */
    protected function sendRequest(
        array $request,
        array $options = array(),
        $resetOptions = FALSE,
        $url = ''
    )
    {
        $options['method'] = Request::METHOD_OTHER;
        $options[CURLOPT_POSTFIELDS] = json_encode($request);

        $this->logger->write(
            sprintf(
                "%s sending request:\n%s",
                get_class($this),
                print_r($request, TRUE)
            ),
            Logger::NOTICE
        );

        $response = $this->send('', $options, $resetOptions, $url);

        $decoded = json_decode($response, TRUE);
        if (!is_array($decoded)) {
            $this->logger->write(
                sprintf(
{'fraction_non_alphanumeric': 0.12141967621419676, 'fraction_numerical': 0.00041511000415110004, 'mean_word_length': 1.7207792207792207, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 35, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 16, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5616040', 'n_tokens_mistral': 2707, 'n_tokens_neox': 2646, 'n_words': 623}