<commit_before><?php
namespace MapasCulturais\Traits;

use MapasCulturais\App;
use Doctrine\ORM\Tools\Pagination\Paginator;

use MapasCulturais\ApiQuery;

trait ControllerAPI{

    /**
     * Array with key => value of params for the API find DQL
     *
     * @var array
     */
    private $_apiFindParamList = [];

    public $_lastQueryMetadata;

    protected $_subsiteEntityIds;

    public static function usesAPI(){
        return true;
    }

    /**
     * Returns the ApiOutput Object.
     *
     * @return \MapasCulturais\ApiOutput
     */
    protected function getApiOutput(){
        $app = App::i();
        $type = key_exists('@type',$this->data) ? $this->data['@type'] : $app->config['app.defaultApiOutput'];
        $responder = $app->getRegisteredApiOutputById($type);

        if(!$responder){
            echo sprintf(\MapasCulturais\i::__("tipo %s não está registrado."), $type);
            App::i()->stop();
        }else{
            return $responder;
        }
    }

    /*
     * Outputs an API Error Response
     *
     */
    protected function apiErrorResponse($error_message){
        $responder = $this->getApiOutput();
        $responder->outputError($error_message);
        App::i()->stop();
    }

    protected function apiResponse($data){
        if(is_array($data))
            $this->apiArrayResponse($data);
        else
            $this->apiItemResponse($data);
    }

    /**
     * Outputs an API Array Respose
     *
     * @param array $data
     * @param string $singular_name the singular name of the response itens
     * @param string $plural_name the plural name of the response itens
     */
    protected function apiArrayResponse(array $data, $singular_name = 'Entity', $plural_name = 'Entities'){
        $responder = $this->getApiOutput();
        $responder->outputArray($data, $singular_name, $plural_name);
        App::i()->stop();
    }

    protected function apiAddHeaderMetadata($qdata, $data, $count){
        if (headers_sent())
            return;

        $response_meta = [
            'count' => $count,
            'page' => isset($qdata['@page']) ? $qdata['@page'] : 1,
            'limit' => isset($qdata['@limit']) ? $qdata['@limit'] : null,
            'numPages' => isset($qdata['@limit']) ? intval($count / $qdata['@limit']) + 1 : 1,
            'keyword' => isset($qdata['@keyword']) ? $qdata['@keyword'] : '',
            'order' => isset($qdata['@order']) ? $qdata['@order'] : ''
        ];

        $this->_lastQueryMetadata = (object) $response_meta;

        header('API-Metadata: ' . json_encode($response_meta));
    }

    function getLastQueryMetadata(){
        return $this->_lastQueryMetadata;
    }

    /**
     * Ouputs an API Item Reponse
     *
     * @param mixed $data
     * @param string $singular_name the singular name of the response itens
     * @param string $plural_name the plural name of the response itens
     */
    protected function apiItemResponse($data, $singular_name = 'Entity', $plural_name = 'Entities'){
        $responder = $this->getApiOutput();
        $responder->outputItem($data, $singular_name, $plural_name);
        App::i()->stop();
    }

    /**
     * A generic API findOne method.
     *
     * This action finds one entity by the requested params and send the result to the API Responder.
     *
     * @see \MapasCulturais\ApiOutput::outputItem()
     */
    public function API_findOne(){
        $entity = $this->apiQuery($this->getData, ['findOne' => true]);
        $this->apiItemResponse($entity);
    }

    public function API_find(){
        $data = $this->apiQuery($this->getData);
        $this->apiResponse($data);
    }

    public function API_describe(){
        $class = $this->entityClassName;
        $this->apiResponse($class::getPropertiesMetadata());
    }

    public function getApiCacheId($qdata, $options = []){
        return $this->id . '::' . md5(serialize($qdata + ['__OPTIONS__' => $options]));
    }

    public function apiCacheExists($cache_id){
        $app = App::i();

        if(!$app->config['app.useApiCache'])
            return false;

        return $app->cache->contains($cache_id);
    }

    public function apiCacheResponse($cache_id){
        if($this->apiCacheExists($cache_id)){
            $app = App::i();
                $cache = $app->cache->fetch($cache_id);

            $app->contentType($cache['contentType']);
            echo $cache['output'];

            $app->stop();
            return true;
        }else{
            return false;
        }
    }

    public function getApiCacheLifetime(){
        $app = App::i();
        $default_lifetime = $app->config['app.apiCache.lifetime'];
        $by_controller_lifetime = $app->config['app.apiCache.lifetimeByController'];

        if(isset($by_controller_lifetime[$this->id]))
            return (int) $by_controller_lifetime[$this->id];
        else
            return (int) $default_lifetime;
    }

    public function apiQuery($api_params, $options = []){
        $app = App::i();
        $findOne =  key_exists('findOne', $options) ? $options['findOne'] : false;
        $counting = key_exists('@count', $api_params);
        if($counting){
            unset($api_params['@count']);
        }

        $app->applyHookBoundTo($this, "API.{$this->action}({$this->id}).params", [&$api_params]);

        $query = new ApiQuery($this->entityClassName, $api_params);
        
        if($counting){
            $result = $query->getCountResult();
        } elseif( $findOne ) {
            $result = $query->getFindOneResult();
        } else {<commit_msg>use @version=1 to use version 1 of api<commit_after><?php
namespace MapasCulturais\Traits;

use MapasCulturais\App;
use Doctrine\ORM\Tools\Pagination\Paginator;

use MapasCulturais\ApiQuery;

trait ControllerAPI{

    /**
     * Array with key => value of params for the API find DQL
     *
     * @var array
     */
    private $_apiFindParamList = [];

    public $_lastQueryMetadata;

    protected $_subsiteEntityIds;

    public static function usesAPI(){
        return true;
    }

    /**
     * Returns the ApiOutput Object.
     *
     * @return \MapasCulturais\ApiOutput
     */
    protected function getApiOutput(){
        $app = App::i();
        $type = key_exists('@type',$this->data) ? $this->data['@type'] : $app->config['app.defaultApiOutput'];
        $responder = $app->getRegisteredApiOutputById($type);

        if(!$responder){
            echo sprintf(\MapasCulturais\i::__("tipo %s não está registrado."), $type);
            App::i()->stop();
        }else{
            return $responder;
        }
    }

    /*
     * Outputs an API Error Response
     *
     */
    protected function apiErrorResponse($error_message){
        $responder = $this->getApiOutput();
        $responder->outputError($error_message);
        App::i()->stop();
    }

    protected function apiResponse($data){
        if(is_array($data))
            $this->apiArrayResponse($data);
        else
            $this->apiItemResponse($data);
    }

    /**
     * Outputs an API Array Respose
     *
     * @param array $data
     * @param string $singular_name the singular name of the response itens
     * @param string $plural_name the plural name of the response itens
     */
    protected function apiArrayResponse(array $data, $singular_name = 'Entity', $plural_name = 'Entities'){
        $responder = $this->getApiOutput();
        $responder->outputArray($data, $singular_name, $plural_name);
        App::i()->stop();
    }

    protected function apiAddHeaderMetadata($qdata, $data, $count){
        if (headers_sent())
            return;

        $response_meta = [
            'count' => $count,
            'page' => isset($qdata['@page']) ? $qdata['@page'] : 1,
            'limit' => isset($qdata['@limit']) ? $qdata['@limit'] : null,
            'numPages' => isset($qdata['@limit']) ? intval($count / $qdata['@limit']) + 1 : 1,
            'keyword' => isset($qdata['@keyword']) ? $qdata['@keyword'] : '',
            'order' => isset($qdata['@order']) ? $qdata['@order'] : ''
        ];

        $this->_lastQueryMetadata = (object) $response_meta;

        header('API-Metadata: ' . json_encode($response_meta));
    }

    function getLastQueryMetadata(){
        return $this->_lastQueryMetadata;
    }

    /**
     * Ouputs an API Item Reponse
     *
     * @param mixed $data
     * @param string $singular_name the singular name of the response itens
     * @param string $plural_name the plural name of the response itens
     */
    protected function apiItemResponse($data, $singular_name = 'Entity', $plural_name = 'Entities'){
        $responder = $this->getApiOutput();
        $responder->outputItem($data, $singular_name, $plural_name);
        App::i()->stop();
    }

    /**
     * A generic API findOne method.
     *
     * This action finds one entity by the requested params and send the result to the API Responder.
     *
     * @see \MapasCulturais\ApiOutput::outputItem()
     */
    public function API_findOne(){
        $entity = $this->apiQuery($this->getData, ['findOne' => true]);
        $this->apiItemResponse($entity);
    }

    public function API_find(){
        $data = $this->apiQuery($this->getData);
        $this->apiResponse($data);
    }

    public function API_describe(){
        $class = $this->entityClassName;
        $this->apiResponse($class::getPropertiesMetadata());
    }

    public function getApiCacheId($qdata, $options = []){
        return $this->id . '::' . md5(serialize($qdata + ['__OPTIONS__' => $options]));
    }

    public function apiCacheExists($cache_id){
        $app = App::i();

        if(!$app->config['app.useApiCache'])
            return false;

        return $app->cache->contains($cache_id);
    }

    public function apiCacheResponse($cache_id){
        if($this->apiCacheExists($cache_id)){
            $app = App::i();
                $cache = $app->cache->fetch($cache_id);

            $app->contentType($cache['contentType']);
            echo $cache['output'];

            $app->stop();
            return true;
        }else{
            return false;
        }
    }

    public function getApiCacheLifetime(){
        $app = App::i();
        $default_lifetime = $app->config['app.apiCache.lifetime'];
        $by_controller_lifetime = $app->config['app.apiCache.lifetimeByController'];

        if(isset($by_controller_lifetime[$this->id]))
            return (int) $by_controller_lifetime[$this->id];
        else
            return (int) $default_lifetime;
    }

    public function apiQuery($api_params, $options = []){
        if(isset($api_params['@version']) == 1){
            unset($api_params['@version']);
            return $this->apiQueryV1($api_params, $options);
        }
        
        $app = App::i();
        $findOne =  key_exists('findOne', $options) ? $options['findOne'] : false;
        $counting = key_exists('@count', $api_params);
        if($counting){
            unset($api_params['@count']);
        }

        $app->applyHookBoundTo($this, "API.{$this->action}({$this->id}).params", [&$api_params]);

        $query = new ApiQuery($this->entityClassName, $api_params);
        
        if($counting){
            $result = $query->getCountResult();
        } elseif( $findOne ) {
            $result = $query->getFindOneResult();
        } else {
{'fraction_non_alphanumeric': 0.15670464504820333, 'fraction_numerical': 0.0010517090271691498, 'mean_word_length': 2.4620752427184467, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 112, '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': '982951', 'n_tokens_mistral': 3425, 'n_tokens_neox': 3381, 'n_words': 683}