<commit_before><?php

  namespace ActiveCollab\Narrative\StoryElement;

  use ActiveCollab\Narrative\Error\NoValidatorError;
  use ActiveCollab\Narrative\Error\ValidatorParamsError;
  use ActiveCollab\Narrative\Error\ParseJsonError;
  use ActiveCollab\Narrative\Error\RequestMethodError;
  use ActiveCollab\SDK\Exceptions\AppException;
  use ActiveCollab\SDK\Exceptions\CallFailed;
  use ActiveCollab\SDK\Response;
  use Symfony\Component\Console\Output\OutputInterface;
  use Peekmo\JsonPath\JsonStore;

  use ActiveCollab\SDK\Client as API;

  /**
   * HTTP request element
   *
   * @package ActiveCollab\Narrative\StoryElement
   */
  class Request extends StoryElement {

    const GET = 'GET';
    const POST = 'POST';
    const PUT = 'PUT';
    const DELETE = 'DELETE';

    /**
     * Request method
     *
     * @var string
     */
    private $method;

    /**
     * Element source code
     *
     * @var string|array
     */
    protected $source = "{";

    /**
     * @param string $method
     */
    function __construct($method) {
      $this->method = $method;
    }

    /**
     * Execute the command
     *
     * @param OutputInterface $output
     * @return array
     */
    function execute($output) {
      API::setKey('1-TESTTESTTESTTESTTESTTESTTESTTESTTESTTEST');
      API::setUrl('http://activecollab.dev/api.php');

      $response = $request_time = null;

      try {
        switch($this->getMethod()) {
          case self::GET:
            $response = API::get($this->getPath()); break;
          case self::POST:
            $response = API::post($this->getPath(), $this->getPayload(), $this->getAttachments()); break;
          case self::PUT:
            $response = API::put($this->getPath(), $this->getPayload(), $this->getAttachments()); break;
          case self::DELETE:
            $response = API::delete($this->getPath(), $this->getPayload()); break;
          default:
            throw new RequestMethodError($this->getMethod());
        }
      } catch(\Exception $e) {
        if(method_exists($e, 'getHttpCode') && $e->getHttpCode() === 404) {
          $response = 404;
          $request_time = method_exists($e, 'getRequestTime') ? $e->getRequestTime() : null;
        } else {
          $output->writeln('<error>Failed to execute ' . $this->getPath() . '. Reason: ' . $e->getMessage() . '</error>');
        }
      }

      if($response) {
        $passes = $failures = [];

        $this->validate($response, $passes, $failures);
        $this->printRequestStatusLine($response, $passes, $failures, $request_time, $output);

        return [ $response, $passes, $failures ];
      } else {
        return [ null, null, null ];
      }
    }

    /**
     * Output status message
     *
     * @param Response|int $response
     * @param array $passes
     * @param array $failures
     * @param float|null $request_time
     * @param OutputInterface $output
     */
    private function printRequestStatusLine($response, $passes, $failures, $request_time, OutputInterface $output) {
      if(empty($failures)) {
        $color = 'info';
      } else {
        $color = 'error';
        $output->writeln('');
      }

      $http_code = $response instanceof Response ? $response->getHttpCode() : (integer) $response;
      $request_time = $response instanceof Response ? $response->getTotalTime() : (float) $request_time;
      $prep = $this->isPreparation() ? ' <question>[PREP]</question>' : '';

      $output->writeln("<$color>" . $this->getMethod() . ' ' . $this->getPath() . " - {$http_code} in {$request_time} seconds</$color> {$prep}");

      // Output failure lines
      if(count($failures)) {
        foreach($failures as $failure) {
          $output->writeln('<error>- ' . $failure . '</error>');
        }
        $output->writeln('');
      }

      // Output response, if needed
      if(isset($this->source['dump_response']) && $this->source['dump_response']) {
        if($response->isJson()) {
          print_r($response->getJson());
        } else {
          $output->writeln($response->getBody());
        }
      }
    }

    // ---------------------------------------------------
    //  Validator
    // ---------------------------------------------------

    /**
     * Validate response
     *
     * @param Response|int $response
     * @param array $passes<commit_msg>Fixed crash when API returns HTTP code instead of response object<commit_after><?php

  namespace ActiveCollab\Narrative\StoryElement;

  use ActiveCollab\Narrative\Error\NoValidatorError;
  use ActiveCollab\Narrative\Error\ValidatorParamsError;
  use ActiveCollab\Narrative\Error\ParseJsonError;
  use ActiveCollab\Narrative\Error\RequestMethodError;
  use ActiveCollab\SDK\Exceptions\AppException;
  use ActiveCollab\SDK\Exceptions\CallFailed;
  use ActiveCollab\SDK\Response;
  use Symfony\Component\Console\Output\OutputInterface;
  use Peekmo\JsonPath\JsonStore;

  use ActiveCollab\SDK\Client as API;

  /**
   * HTTP request element
   *
   * @package ActiveCollab\Narrative\StoryElement
   */
  class Request extends StoryElement {

    const GET = 'GET';
    const POST = 'POST';
    const PUT = 'PUT';
    const DELETE = 'DELETE';

    /**
     * Request method
     *
     * @var string
     */
    private $method;

    /**
     * Element source code
     *
     * @var string|array
     */
    protected $source = "{";

    /**
     * @param string $method
     */
    function __construct($method) {
      $this->method = $method;
    }

    /**
     * Execute the command
     *
     * @param OutputInterface $output
     * @return array
     */
    function execute($output) {
      API::setKey('1-TESTTESTTESTTESTTESTTESTTESTTESTTESTTEST');
      API::setUrl('http://activecollab.dev/api.php');

      $response = $request_time = null;

      try {
        switch($this->getMethod()) {
          case self::GET:
            $response = API::get($this->getPath()); break;
          case self::POST:
            $response = API::post($this->getPath(), $this->getPayload(), $this->getAttachments()); break;
          case self::PUT:
            $response = API::put($this->getPath(), $this->getPayload(), $this->getAttachments()); break;
          case self::DELETE:
            $response = API::delete($this->getPath(), $this->getPayload()); break;
          default:
            throw new RequestMethodError($this->getMethod());
        }
      } catch(\Exception $e) {
        if(method_exists($e, 'getHttpCode') && $e->getHttpCode() === 404) {
          $response = 404;
          $request_time = method_exists($e, 'getRequestTime') ? $e->getRequestTime() : null;
        } else {
          $output->writeln('<error>Failed to execute ' . $this->getPath() . '. Reason: ' . $e->getMessage() . '</error>');
        }
      }

      if($response) {
        $passes = $failures = [];

        $this->validate($response, $passes, $failures);
        $this->printRequestStatusLine($response, $passes, $failures, $request_time, $output);

        return [ $response, $passes, $failures ];
      } else {
        return [ null, null, null ];
      }
    }

    /**
     * Output status message
     *
     * @param Response|int $response
     * @param array $passes
     * @param array $failures
     * @param float|null $request_time
     * @param OutputInterface $output
     */
    private function printRequestStatusLine($response, $passes, $failures, $request_time, OutputInterface $output) {
      if(empty($failures)) {
        $color = 'info';
      } else {
        $color = 'error';
        $output->writeln('');
      }

      $http_code = $response instanceof Response ? $response->getHttpCode() : (integer) $response;
      $request_time = $response instanceof Response ? $response->getTotalTime() : (float) $request_time;
      $prep = $this->isPreparation() ? ' <question>[PREP]</question>' : '';

      $output->writeln("<$color>" . $this->getMethod() . ' ' . $this->getPath() . " - {$http_code} in {$request_time} seconds</$color> {$prep}");

      // Output failure lines
      if(count($failures)) {
        foreach($failures as $failure) {
          $output->writeln('<error>- ' . $failure . '</error>');
        }
        $output->writeln('');
      }

      // Output response, if needed
      if(isset($this->source['dump_response']) && $this->source['dump_response'] && $response instanceof Response) {
        if($response->isJson()) {
          print_r($response->getJson());
        } else {
          $output->writeln($response->getBody());
        }
      }
    }

    // ---------------------------------------------------
    //  Validator
    // ---------------------------------------------------

    /**
     * Validate response
     *
     * @param Response|int $response
     * @param array $passes
{'fraction_non_alphanumeric': 0.17823469271839146, 'fraction_numerical': 0.0015903669203680562, 'mean_word_length': 2.286300858529302, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 87, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, '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': '2489879', 'n_tokens_mistral': 2619, 'n_tokens_neox': 2542, 'n_words': 494}