<?php

/**
 * Execute an action (request which no need html view response: ajax,json etc...) and manage automatically
 * access rights, exceptions and json response.
 *
 * @author  Valentin CARRUESCO
 *
 * @category Core
 *
 * @license cc by nc sa
 */
class Action {
    /**
     * Execute an action
     * #### Example
     * ```php
     * Action::write(function(&$response){
     *  $response['custom'] = 'hello world!';
     * },array('user'=>'u','plugin'=>'d')); //User must have user update right and delete plugin right to perform this action
     * ```.
     *
     * @param function action/code to execute
     * @param array Array wich contain right to execute action
     *
     * @return print json response
     */
    public static function write($f, $p=array()) {
        global $myUser;
        header('content-type:application/json');
        $response = array();
        set_error_handler(function ($level, $error, $file, $line) { throw new Exception($error." \r\n\r\n  ".$file.' - L '.$line.'');});
        try {
            foreach ($p as $scope => $right) {
                if (!$myUser->can($scope, $right)) throw new Exception('Vous ne disposez pas des droits suffisants pour effectuer cette action');
            }
            $f($response);
        } catch (Exception $e) {
            $response['error'] = $e->getMessage();
            $response['errorCode'] = $e->getCode();
            $response['trace'] = exception_trace($e);

            if($myUser->superadmin || $_SERVER['HTTP_HOST'] == '127.0.0.1'){
                $traces = $e->getTrace();
                $traceIndex = 0;

                //Si c'est une erreur de bound sql / data  ou une erreur de syntaxe sql
                if($e->getCode() == 'HY093' || $e->getCode() == '42000'){

                    //On recupere la premiere trace qui n'est pas Entity ou Action (trace significative)
                    foreach($traces as $i => $currentTrace){
                        if(isset($currentTrace['file']) && in_array(basename($currentTrace['file']), array('Entity.class.php','Action.class.php'))) continue;
                        $traceIndex = $i;
                        break;
                    }

                    //On affiche la requete et les datas
                    if(isset($traces[1]) && $traces[1]['function']=='customQuery'){

                        if(isset($traces[1]['args'])) $response['error'] .= '<code class="d-block">'.(is_string($traces[1]['args'][0]) ? $traces[1]['args'][0]:json_encode($traces[1]['args'][0])).'</code>';
                        if(isset($traces[1]['args']) && isset($traces[1]['args'][1])){
                            $plainTrace = $traces[1]['args'][1];
                            if(is_array($plainTrace)) $plainTrace = implode(',',$plainTrace);
                            if(is_object($plainTrace)) $plainTrace =  implode(',',(array)$plainTrace);
                            $response['error'] .= '<hr><code>['.$plainTrace.']</code>';
                        }
                    }
                }
                $response['line'] = isset($traces[$traceIndex]['line']) ? $traces[$traceIndex]['line'] : 0;
                $response['file'] = isset( $traces[$traceIndex]['file'])? $traces[$traceIndex]['file'] : '';
                $response['trace'] = '<pre class="text-light" style="overflow:initial;">'.exception_trace($e).'</pre>';
            }
        }
        echo json_encode($response);
        restore_error_handler();
    }

    public static function register($name,$f) {
        $GLOBALS['actions'][$name] = $f;
    }

    public static function run($name, &$response) {
        if(!isset($GLOBALS['actions'][$name])) return;
        $functionName = $GLOBALS['actions'][$name];
        call_user_func_array($functionName, array(&$response));
    }
}
