<commit_before><?php

namespace atomar\core;
use atomar\Atomar;

/**
 * The api extends the controller to provide some advanced functionality to the api controllers.
 * New api method can be easily defined by adding the prefix "get_" or "post_". Any non-null parameters will be
 * required and the API will automatically notify clients if parameters are missing or malformed.
 */
abstract class ApiController extends Controller {
  private $api_version = '1.0.0';

  function __construct($return_url) {
    parent::__construct($return_url);
  }

  /**
   * This method will be called automatically to handle any exceptions in the class
   *
   * @param \Exception $e the exception
   */
  public function exceptionHandler($e) {
    Logger::log_error($e->getMessage(), $e->getTrace());
    $message = get_class($this) . '->exception_handler: ';
    if(Auth::has_authentication('administer_site') || Atomar::debug()) {
        $message .= $e->getMessage();
    } else {
        $message .= 'An exception has occurred. See the log for details.';
    }
    render_json(array('status' => 'error', 'message' => $message));
  }

  /**
   * Handles all the get requests and provides some basic error handling
   * If you need to perform some operations before hand use setup_get() so you don't to re-write this method
   * @param array $matches
   */
  public function GET($matches = array()) {
    $this->setup_get($matches);
    $this->api_handler('get', $matches);
  }

  /**
   * Allows you to perform any additional actions before get requests are processed
   * @param array $matches
   */
  protected abstract function setup_get($matches = array());

  /**
   * Performs the api handling including name based method parameterisation
   * @param string $prefix the api method prefix
   * @param array $matches the matched parameters from the url route
   */
  private final function api_handler($prefix, $matches) {
    $api = strtolower($matches['api']);
    $method_signature = $prefix . '_' . $api;
    $backwards_compatible_method_signature = strtoupper('_' . $prefix);
    if (method_exists($this, $method_signature)) {
      // execute the api method
      try {
        $response = $this->call_user_func_args($method_signature, $_REQUEST, true);
        $this->respond($response);
      } catch (ParameterException $e) {
        // send any parameter parsing exceptions as an error response
        $this->respond(new MalformedParameters($e->getMessage(), 400));
      }
    } elseif (method_exists($this, $backwards_compatible_method_signature)) {
      // run backwards compatible methods e.g. _POST and _GET if they exist.
      // Exceptions in the backwards compatible methods will bubble up.
      $this->$backwards_compatible_method_signature($matches);
    } else {
      // send error response
      $this->respond(new UnknownAPIError('The method signature "' . $method_signature . '" could not be found for the api call "' . $api . '"', 404));
    }
  }

  /**
   * Calls a function with named arguments.
   * Just written and quite tested. If you find bugs, please provide feedback and I'll update the code.
   * In a sane usage scenario, it will work. If you try your best, you might break it :)
   * If true, $ValidateInput tries to warn you of issues with your Arguments, bad types, nulls where they should not be.
   *
   * @copyright Claudrian
   * @param string $method
   * @param array $arguments<commit_msg>improved error handling for api calls<commit_after><?php

namespace atomar\core;
use atomar\Atomar;

/**
 * The api extends the controller to provide some advanced functionality to the api controllers.
 * New api method can be easily defined by adding the prefix "get_" or "post_". Any non-null parameters will be
 * required and the API will automatically notify clients if parameters are missing or malformed.
 */
abstract class ApiController extends Controller {
  private $api_version = '1.0.0';

  function __construct($return_url) {
    parent::__construct($return_url);
  }

  /**
   * This method will be called automatically to handle any exceptions in the class
   *
   * @param \Exception $e the exception
   */
  public function exceptionHandler($e) {
    Logger::log_error($e->getMessage(), $e->getTrace());
    $message = get_class($this) . '->exception_handler: ';
    if(Auth::has_authentication('administer_site') || Atomar::debug()) {
        $message .= $e->getMessage();
    } else {
        $message .= 'An exception has occurred. See the log for details.';
    }
    render_json(array('status' => 'error', 'message' => $message));
  }

  /**
   * Handles all the get requests and provides some basic error handling
   * If you need to perform some operations before hand use setup_get() so you don't to re-write this method
   * @param array $matches
   */
  public function GET($matches = array()) {
    $this->setup_get($matches);
    $this->api_handler('get', $matches);
  }

  /**
   * Allows you to perform any additional actions before get requests are processed
   * @param array $matches
   */
  protected abstract function setup_get($matches = array());

  /**
   * Performs the api handling including name based method parameterisation
   * @param string $prefix the api method prefix
   * @param array $matches the matched parameters from the url route
   */
  private final function api_handler($prefix, $matches) {
    $api = strtolower($matches['api']);
    $method_signature = $prefix . '_' . $api;
    $backwards_compatible_method_signature = strtoupper('_' . $prefix);
    if (method_exists($this, $method_signature)) {
      // execute the api method
      try {
        $response = $this->call_user_func_args($method_signature, $_REQUEST, true);
        $this->respond($response);
      } catch (ParameterException $e) {
        // send any parameter parsing exceptions as an error response
        $this->respond(new MalformedParameters($e->getMessage(), 400));
      } catch (\Error $e) {
          if(Atomar::debug() || Auth::has_authentication('administer_site')) {
              $this->respond(new ServerError($e->getMessage(), 500));
          } else {
              Logger::log_error($e->getMessage(), $e);
              $this->respond(new ServerError('An error has occurred on the server. See the log for details', 500));
          }
      }
    } elseif (method_exists($this, $backwards_compatible_method_signature)) {
      // run backwards compatible methods e.g. _POST and _GET if they exist.
      // Exceptions in the backwards compatible methods will bubble up.
      $this->$backwards_compatible_method_signature($matches);
    } else {
      // send error response
      $this->respond(new UnknownAPIError('The method signature "' . $method_signature . '" could not be found for the api call "' . $api . '"', 404));
    }
  }

  /**
   * Calls a function with named arguments.
   * Just written and quite tested. If you find bugs, please provide feedback and I'll update the code.
   * In a sane usage scenario, it will work. If you try your best, you might break it :)
   * If true, $ValidateInput tries to warn you of issues with your Arguments, bad types, nulls where they should not be.
   *
   * @copyright Claudrian
   * @param string $method
   * @param array $arguments
{'fraction_non_alphanumeric': 0.11311407733590202, 'fraction_numerical': 0.003302600798128526, 'mean_word_length': 3.3520958083832335, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 35, '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': '4973532', 'n_tokens_mistral': 1985, 'n_tokens_neox': 1955, 'n_words': 719}