<?php
require_once(__DIR__.SLASH.'..'.SLASH.'WidgetElement.class.php');
class Treatment extends WidgetElement{
	public $source;
	public $TABLE_NAME = 'statistic_treatment';
	public $javascript = 'function(){stats_element_init("treatment");}';
	public $icon = 'fas fa-code';
	public $typeLabel = 'Code';

	function __construct(){
		parent::__construct();
		$this->fields['source'] = 'longstring';
		$this->fieldMapping = $this->field_mapping($this->fields);
	}



	function editor(){
		if($this->source == '') $this->source = '//tableau des données du précédent élement'.PHP_EOL.'return $data; ';
		$html = '<label>
					<i class="fas fa-code"></i> Code
				</label> - <small>Données disponibles dans <strong>$data</strong>, filtres dans <strong>$filters</strong></small>
				<div class="prev-custom-treatment float-right btn btn-small mb-2 ml-2" onclick="stats_element_preview(this,function(){$(\'#output-tab\').click()});"><i class="fas fa-play-circle"></i> Exécuter</div>
				<div id="server-status" class="d-inline-block float-right"></div>
				<div class="clear"></div>
				<textarea id="source">'.$this->source.'</textarea>';
		return $html;
	}


	function preview($data = array(),$filters = array()){
		$response = array('data'=>array());

		ob_start();
		$source = html_entity_decode($this->source,ENT_QUOTES);
		$forbidden = self::forbidden($source);
		if(count($forbidden)!=0) throw new Exception("Mot clés interdits: ".implode(',',$forbidden));

			eval('$method = function($data,$filters){'.$source.'};');

	    $output = ob_get_clean();
	    if($output!='') throw new Exception(strip_tags($output));

		$response['data'] = $method($data,$filters);

		return $response;
	}

	//Fonction de sécurisation du eval, evite toutes les fonctions non spécifiées ci dessous et toutes les intrcutions type include, class...

	public static function forbidden($source){

		$ignore_terms = array();
		////Ajoute des fonctions autorisées dans les traitements statistiques ex : 	$ignore_terms[] = 'Plugin::need'; $ignore_terms[] = 'Business::amount';
		Plugin::callHook('statistic_allowed_macro',array(&$ignore_terms));
		$source = str_replace($ignore_terms,'',$source);

		$tokens = token_get_all('<?php '.$source.' ?>');

		$forbiddens = array();

		$allowed_functions_generic = array(
		    'ucfirst',
		    'strto.*',
		    'str_.*',
		    'date',
		    'intval',
		    'count',
		    'time',
		    'array_.*',
		    'base64_*',
		    '.sort',
		    'asort',
		    'sort',
		    'addslashes',
		    'json_decode',
		    'json_encode',
		    'implode',
		    'explode',
		    'utf8_decode',
		    'utf8_encode',
		    'html_entity_decode',
		    'htmlspecialchars',
		    'strip_tags',
		    'is_null',
		    'is_int',
		    'substr',
		    'max',
		    'true',
		    'false',
		    'null',
		    'strlen',
		    'round',
		    'in_array',
		    'is_numeric'
		);

		$allowed_functions_specific = array(
		    '__ROOT__',
		    'PLUGIN_PATH',
		    'SLASH',
		    'html_decode_utf8',
		    'Dictionary',
		    'fullName',
		    'loadAll',
		    'getById',
		    'bySlug',
		    'slugToArray',
		    'id',
		    'label',
		    'value',
		    'color',
		    'Partner',
		    'Product',
		    'number_format',
		    'display_price',
		    'ranking',
		    'function'
		);

		$allowed_functions = array_merge($allowed_functions_generic, $allowed_functions_specific);


		foreach($tokens as $i=>$token){

			if(is_string($token))continue;
		  	list($id, $text,$line) = $token;

		  	if(in_array($id, array(T_FUNCTION,T_FUNC_C,T_EVAL,T_STRING))){
		  		$allowed = false;
		  		foreach ($allowed_functions as $function) {
		  			preg_match('/'.$function.'/i', $text, $matches);
		  			if(count($matches)!=0){
		  				$allowed = true;
		  				break;
		  			}
		  		}
		  		if(!$allowed) $forbiddens[] = $text.' L'.$line.token_name($id);
		    }

		    if(in_array($id, array(
			    	T_INCLUDE,
			    	T_EXTENDS,
			    	T_CLONE,
			    	T_EXIT,
			    	T_GLOBAL,
			    	T_HALT_COMPILER,
			    	T_IMPLEMENTS,
			    	T_INCLUDE_ONCE,
			    	T_REQUIRE,
			    	//T_REQUIRE_ONCE,
			    	T_IMPLEMENTS
			    )
			)){
   				$forbiddens[] = $text.' L'.$line;
		    }
		}
		return $forbiddens;
	}
}

?>