------------------------------------------------------------
revno: 1111
committer: Roger Martin <[email protected]>
branch nick: aikiframework
timestamp: Sat 2012-02-25 23:20:11 +0100
message:
changing engine_v8
modified:
libs/Engine_v8.php
--
lp:aikiframework
https://code.launchpad.net/~aikiframework-devel/aikiframework/trunk
Your team Aiki Framework Developers is subscribed to branch lp:aikiframework.
To unsubscribe from this branch go to
https://code.launchpad.net/~aikiframework-devel/aikiframework/trunk/+edit-subscription
=== modified file 'libs/Engine_v8.php'
--- libs/Engine_v8.php 2012-02-19 20:19:24 +0000
+++ libs/Engine_v8.php 2012-02-25 22:20:11 +0000
@@ -20,24 +20,273 @@
* update aiki_widgets inner join aiki_widget_porsi on aiki_widgets.father_widget=aiki_widget_porsi.id set parent_widget= aiki_widget_porsi.widget_name
*/
-if (!defined('IN_AIKI')) {
+if (!defined('IN_AIKI')) {
+
die('No direct script access allowed');
-}
+}
+
+
+/*
+ * move to aiki, so all engine case share this code
+ */
+
+function aiki_get_markup_codes($which){
+ /* @TODO this complicate array can be generated by a auxiliary programs, who with a given
+ * syntax ( for example (TAG(TRUE-BLOCK)else(FALSE-BLOCK)TAG) calculate array
+ */
+
+ // 0 begin regex
+ // 1 end regex
+ // 2 else literal
+ // 3 end search string with %s
+ // 4 begin signal (first character of a begin tag)
+ // 5 trim characters that will be deleted from tag.
+ // 6 first character from true-block
+
+ $markups= array (
+ // (TAG()TRUE-BLOCK)else(FALSE-BLOCK)TAG)
+ "aiki" => array("\([A-z0-9_]*\(", "\)[A-z0-9]*\)", ")else(", ")%s)","(", "#\((.*)\(#","" ),
+ // (TAG( para {TRUE-BLOCK}else{FALSE-BLOCK})TAG)
+ "aiki2" => array("\([A-z0-9_]*\(", "\}\)[A-z0-9]*\)", "})else({", "})%s)","(", "#\((.*)\(#","" ),
+ // (TAG(COND){true-block}else{false-block}TAG)
+ "(c)"=> array("\([A-z0-9_]+\(","\}[A-z0-9]+\)", "}else{", "}%s)", "(","#\((.*)\(#", "{" ),
+ // <%TAG(COND){true-block}else{false-block}%>
+ "<%"=> array("<%[A-z0-9_]+\(","\}%>", "}else{", "}%>", "<","#<%(.*)\(#","" )
+ );
+
+ return ( isset ($markups[$which]) ? $markups[$which] : $markups["aiki"] );
+
+}
+
+/**
+ * extract the first markup
+ * return array
+ * 0 => text before tag
+ * 1 => tag
+ * 2 => array of parameters
+ * 3 => true-block
+ * 4 => false-block
+ * 5 => text after tag
+ */
+
+function extract_markup(&$string, $markup) {
+
+ if (!is_array($markup) ){
+ $markup= aiki_get_markup_codes($markup);
+ }
+
+ if ( !preg_match_all(
+ "#{$markup[0]}|{$markup[1]}|". preg_quote($markup[2])."#",
+ $string,
+ $matches,
+ PREG_OFFSET_CAPTURE)) {
+ return $string ;
+ };
+
+ $matches= $matches[0];
+ $max= count($matches);
+ preg_match ( $markup[5], $matches[0][0],$temp);
+ $tag = $temp[1];
+
+ $search= sprintf( $markup[3], $tag );
+ $level = 0;
+ $else = 0; // where start the else block
+
+ for($i=1;$i<$max;$i++){
+ $found = $matches[$i][0]; // for comodity
+ if ( $found==$markup[2] ) {
+ if ($level==0 ){ // else are in the middle
+ $else= $matches[$i][1];
+ }
+ } elseif ($level==0 && $found==$search ) {
+ // we found ending tag
+ $offset= strlen($search);
+ $start = $matches[0][1]+$offset;
+ $elselen= strlen($markup[2]);
+ $trueBlock= ( $else ? substr( $string,$start, $else-$start) : substr( $string,$start, $matches[$i][1]-$start));
+ $parameters = extract_parameters( $trueBlock, $markup[6]);
+ return array(
+ substr( $string,0,$start-$offset ),
+ $tag,
+ $parameters[0],
+ $parameters[1],
+ ( $else ? substr( $string,$else+$elselen, $matches[$i][1]-$else-$elselen) : NULL),
+ substr($string, $matches[$i][1]+$offset));
+ } elseif ( $found[0] =="(" ){
+ $level++;
+ } else {
+ $level--;
+ }
+ }
+ return $string;
+}
+
+
+function eval_parameters( $originals ){
+
+ $ret = array();
+ $temp= false;
+
+ foreach ( $originals as $input){
+ if ( $input==="" ) { $ret[]="";}
+ elseif ( $input==="0" ) { $ret[]=0;}
+ elseif ( $input==="false" ){ $ret[]=false;}
+ elseif ( $input==="true" ){ $ret[]=true;}
+ elseif ( $input[0]=="'" || $input[0]=='"' ) { $ret[]= substr($input,1,-1);}
+ elseif ( preg_match('#^\s*[+\-]?[1-9][0-9]*\s*$#', $input, $temp)) { $ret[]= (int) $input;}
+ elseif ( preg_match('#^\s*[+\-]?[1-9][0-9]*\.[0-9]*\s*$#', $input, $temp)){ $ret[]= (float) $input;}
+ elseif ( preg_match('#^\{\s*"[^"]+"\s*\:\s*"[^"]*"#',$input, $temp)){ $ret[]= json_decode($input);}
+ elseif ( $input[0]=="{") {
+ $temp = extract_parameters( substr($input,1,-1));
+ $ret[]= eval_parameters( $temp[0] );}
+ elseif ( preg_match ('#^\s*aiki\-\>(.*)$#',$input,$temp )){
+ $ret[]= "calling aiki->".$temp[1]; //@TODO implements
+ }elseif ( preg_match ('#^\s*([A-z_0-9]+)\(.*$#', $input, $temp )){
+ // @TODO check if it is a allowed functions
+ $ret[] = "calling {$temp[1]}";
+
+ } else {
+ $ret[]=$input;
+ }
+ }
+
+ return $ret;
+
+}
+
+
+/**
+ * extract the parameters present at the begining of text
+ * @return array
+ * 0 => array of parameters.
+ * 1 => rest of string
+ * example: extract_parameters ( "foo'bar",foo(bar),{foo,bar,foo()} ) rest"
+ * return a array
+ * 0=>array ( "foo'bar", "foo(bar)", "{foo,bar,foo()}")
+ * 1=> " rest"
+ */
+
+function extract_parameters( $string, $find="") {
+
+ $max= strlen($string);
+
+ $state= 0;
+ $current= false;
+ $end = false;
+ $level =0;
+ $ret= array();
+
+
+ for($i=0; $i<$max && !$end; $i++){
+ $add = false;
+ $char = $string[$i];
+
+ switch ( $char ){
+
+ case "'":
+ switch ($state){
+ case 0: $state=1; break;
+ case 1: if ($level==0 && !$escaped ){ $add= true;}
+ }
+ break;
+ case '"':
+ switch ($state){
+ case 0: $state=2; break;
+ case 2: if ( $level==0 && !$escaped ) { $add= true;}
+ }
+ break;
+ // do we found a other arg?
+ case ',':
+ if (($state==0 || $state==3) && $level==0) {
+ $add = true;
+ $char= false;
+ }
+ break;
+
+ // we a begin (
+ case '(':
+ case '{':
+ if ($state==0 || $state==3) {
+ $level++;
+ $state=3;
+ }
+ break;
+
+ // do we found a ending { ?
+ case '}':
+ case ')':
+ if ($state==0 || $state ==3 ) {
+ if ( $level == 0 ) {
+ $add = true;
+ $end = true;
+ $char = false;
+ } elseif ($level==1) {
+ $add = true;
+ $level=0;;
+ } else {
+ $level--;
+ }
+ }
+ break;
+ case " ":
+ break;
+ default :
+ if ( $state== 0 ){
+ $state=3;
+ }
+ }
+
+ if ( $state != 0 ){
+ $current .= $char;
+ }
+
+ if ( $add ){
+ if ( $current !== false ){
+ $ret[] = $current;
+ $current = false;
+ }
+ $state = 0;
+ }
+
+ $escaped= ( $char=="\\" );
+ } // for
+ if ( $current !== false ){
+ $ret[] = $current;
+ }
+
+ // for the (a,b) { begin ..supress the { @TODO improve.
+ if ( $find !="") {
+ $temp = stripos ($string,$find,$i);
+ if ( $temp !==false ){
+ $i=$temp+1;
+ }
+ }
+
+ return array ( $ret, substr( $string,$i));
+}
+
class engine_v8 {
+ // engine parameters
+ private $convert_widgets;
+ private $markup_codes;
+
+ private $parsers; // array of parser (markup=>callback)
+
private $widget_css;
private $widget_html;
-
+
/*
* Create layout
*/
- function layout( $parameters ){
+ function layout( $parameters = NULL ){
global $db, $aiki;
- // Initialize
-
+ // Parameters
+ $this->load_parameters($parameters);
+
// @TODO javascript? id for some elements?
$this->target = array(
"body"=>"" ,
@@ -88,7 +337,7 @@
if ( $parent->have_css == 1) {
$this->target["css"][] = $parent->id;
}
- $this->target[$parent->widget_target] .= $this->parse($parent->id);
+ $this->target[$parent->widget_target] .= $this->parseWidget($parent->id);
// children..
/* @TODO..a function */
@@ -96,17 +345,60 @@
foreach ($descendants as $descendant){
if ( $aiki->url->match($descendant->display_urls) && !$aiki->url->match($descendant->kill_urls) ) {
$this->target["css"][] = $descendant->id;
- $this->target[$descendant->widget_target] .= $this->parse($descendant->id);
+ $this->target[$descendant->widget_target] .= $this->parseWidget($descendant->id);
}
}
}
}
}
+ // finally make html.
return $this->render_html();
}
+ function load_parameters($parameters) {
+ // Parameters
+ if ( is_array( $parameters ) ){
+ $parameters= array();
+ }
+
+ // set markup to use
+ $markup = isset($parmameters['markup']) ? $parmameters['markup'] : 'aiki';
+ $this->markup_codes = aiki_get_markup_codes ($markup ) ;
+
+ // must convert widgets?
+ if (isset($parmameter['convert-widgets'] )) {
+ $this->convert_widgets = 1;
+ $this->markup = 'aiki';
+ }
+
+ // set parsers
+ $this->parsers = array (
+ "" => "parse_vars",
+ "widget" => "parse_widget",
+ "permissions" => "parse_permissions",
+ "view" => "parse_view",
+ "noaiki" => "parse_noaiki",
+ "sql" => "parse_sql",
+ "script" => "parse_script",
+ "t" => "parse_t",
+ "__" => "parse_translate");
+
+ if ( isset($parameters["parsers-allowed"]) ){
+ $this->parsers = array_intersect (
+ $this->parsers ,
+ array_flip(explode(",",$parameters["parsers-allowed"])) );
+ }
+
+ if ( isset($parameters["parsers-disabled"]) ){
+ $this->parsers = array_diff_key (
+ $this->parsers ,
+ array_flip(explode(",",$parameters["parsers-disabled"])) );
+ }
+ }
+
+
function render_html(){
global $aiki;
$html = $aiki->Output->header($this->target['css'], $this->target['header']);
@@ -121,84 +413,68 @@
* parse a given widget
*/
- function parse($widgetID){
+
+ function parseWidget($widgetID){
global $aiki, $db;
- // preParsers and postParser can be:
+ // high level parser can be:
// regex (string) => function | array(object,method).
// a numeric index => function | array(object,method).
+ // @TODO make a structure.
- $preParsers = array (
- '/\[\$([a-z0-9_]+)\]/i' => array( $this, "parse_vars"),
+ $Parsers = array (
+ // preparsers
+ '/\(\([a-z0-9_]\)\)/i' => array( $this, "parse_vars"),
'/\[GET\[([a-z0-9]+)\]\]/i' => array( $this, "parse_get"),
'/\[POST\[([a-z0-9]+)\]\]/i' => array( $this, "parse_post"),
- "/\(template\(([a-z0-9_]*)\)template\)/Ui" => array( $this, "parse_template")) ;
-
- $postParsers =array (
- array ($aiki->languages,"L10n") ) ; // added for test purpose only
-
- // parsers are defined here
- $parsers = array (
- "widget" => "parse_widget",
- "permissions" => "parse_permissions",
- "view" => "parse_view",
- "noaiki" => "parse_noaiki",
- "sql" => "parse_sql",
- "script" => "parse_script",
- "t" => "parse_t",
- "__" => "parse_translate");
-
+ "/\(template\(([a-z0-9_]*)\)template\)/Ui" => array( $this, "parse_template"),
+
+ // here we call the parse
+ 1 => array ($this, "parse" ),
+
+ // post-parser
+ array ($aiki->languages,"L10n") // added for test purpose only
+ ) ;
+
$widgetData = $db->get_row ("SELECT widget,widget_name FROM aiki_widgets WHERE id=" . (int) $widgetID );
$widget = $widgetData->widget;
$widgetName= $widgetData->widget_name;
-
- // process pre-parsers.
- foreach ( $preParsers as $pattern => $callback ){
- if ( is_string($pattern) ){
- $widget = preg_replace_callback ( $pattern, $callback, $widget);
- } else {
- $widget = call_user_func ( $callback, $widget);
- }
- }
-
- // now the normal parser.
- $match = false;
- $offset=0;
- while ( $match = $aiki->outer_markup ( $widget,$offset ) ){
- $parserToCall= $match[2];
- $len = strlen($parserToCall)+2;
-
- // call parser
- if ( isset( $parsers[ $parserToCall]) ){
- $text = substr($widget, $match[0]+ $len,$match[1]-$len );
- $replace= call_user_func( array($this, $parsers[ $parserToCall] ), &$text);
- if (is_int($replace) ){ // necesary for noaki
- $offset += $replace;
- continue;
- }
- } else {
- // @TODO Error
- $replace= t("Parser $parserToCall not found");
- }
-
- //Replacement.
- $widget= substr($widget,0,$match[0]) . $replace . substr($widget,$match[0]+$match[1]+$len) ;
- }
-
-
- // process post-parsers.
- foreach ( $postParsers as $pattern => $callback ){
- if ( is_string($pattern) ){
- $widget = preg_replace_callback ( $pattern, $callback, $widget);
- } else {
- $widget = call_user_func ( $callback, $widget);
- }
- }
-
+
+ foreach ( $Parsers as $pattern => $callback ){
+ if ( is_string($pattern) ){
+ $widget = preg_replace_callback ( $pattern, $callback, $widget);
+ } else {
+ $widget = call_user_func ( $callback, $widget);
+ }
+ }
+
if ( is_debug_on() ){
return "\n<!-- start {$widgetName} ($widgetID) -->" . $widget . "\n<!-- end {$widgetName} ($widgetID) -->";
}
- return $widget;
+
+ }
+
+
+ function parse($text){
+
+ // extract beign,tag,condition & true-block, else-block,rest
+ $match = extract_markup ( $widget,$this->markup_codes );
+ if (!is_array($match) ){
+ return $text;
+ }
+
+ $parserToCall= $match[2]; // for comodity
+
+ if ( isset( $this->parsers[ $parserToCall]) ){
+ $result = call_user_func( array($this, $this->parsers[ $parserToCall] ), &$match[1], &$match[2]);
+ } else {
+ $result = t("Parser $parserToCall not found");
+ }
+
+ // return begin+result+parse the the rest..
+ return $match[0].
+ $result.
+ $this->parse($match[3]);
}
@@ -254,7 +530,7 @@
'[$language]' => $aiki->site->language(),
'[$page]' => $page,
'[$site_name]' => $aiki->site->site_name(),
- '[$site]' => $aiki->site->get_site(),
+ 'site' => $aiki->site->get_site(),
'[$view]' => $aiki->site->view(),
'[$direction]' => $aiki->languages->dir,
'[$insertedby_username]' => $aiki->membership->username,
@@ -298,11 +574,14 @@
return is_null($id) ? "": $db->get_var ("SELECT widget FROM aiki_widgets WHERE id='$id'" );
}
- function parse_script($code){
+ function parse_script($cond,$trueblock,$elseblock){
global $aiki;
- return $aiki->AikiScript->parser($code,false);
+ return $aiki->AikiScript->parser($trueblock,false);
}
+ function parse_if($cond,$trueblock,$elseblock){
+ return ( is_array($cond)? first($cond): $cond ) ? $trueblock : $elseblock ;
+ }
/**
* translation
@@ -323,19 +602,14 @@
}
-
/*
* Parse sql markup
*/
- function parse_sql( &$text){
+ function parse_sql( $para, $true, $else ){
global $db;
- if ( strpos($text,"||")===false){
- return $text;
- }
- list($select,$content)= explode("||", $text,2);
- $results = $db->get_results($select);
+ $results = $db->get_results($para[0]);
$html="";
if ($results) {
@@ -344,8 +618,10 @@
foreach ( $row as $field=>$value ){
$fields[ "[$field]" ]= $value;
}
- $html .= strtr( $content, $fields);
+ $html .= strtr( $true, $fields);
}
+ } else {
+ return $else;
}
return $html;
@@ -356,10 +632,9 @@
* @TODO implements trigger.
*/
- private function parse_hits(&$hidData) {
+ private function parse_hits($hit, $true, $else ) {
global $db;
-
- $hit = explode("|", $hitData);
+
if ( len($hit) == 3 ){
$db->query(
"UPDATE {$hit[0]}".
@@ -372,41 +647,27 @@
}
- function parse_widget( &$text ){
-
- if ( strpos( $widget,"||")!== false ) {
- list($wigetId, $select) = explode("||",$widget,2);
- } else {
- $widgetId= $widget ;
- }
-
- return $this->parse($widgetId, $select);
+ function parse_widget( $cond, $true, $false ){
+ //@TODO
+ //return $this->parse($widgetId, $select);
}
- function parse_view( &$text){
+ function parse_view( $para, $true, $false){
global $aiki;
- if ( strpos($text,"||") !== false ){
- list($filter,$content) = explode("||", $text, 2);
- if ($trim($filter)=="") {
- return $text;
- }
- } else {
- return $text;
- }
- list($view,$language)= exlode("/",$filter."/*",2);
+ list($view,$language)= exlode("/",$filter[1]."/*",2);
if ( match_pair_one( $view, $aiki->site->view()) &&
match_pair_one( $language, $aiki->site->language() )){
- return $content;
+ return $true;
}
- return "";
+ return $false;
}
- function parse_permission($widget){
+ function parse_permission($para, $true, $false){
global $aiki, $db;
if ( strpos($widget,"||") !== false ){
list($filter,$content) = explode("||", $widget, 2);
@@ -434,9 +695,32 @@
return "";
}
- function parse_noaiki(&$text){
- return strlen($text) ;
- }
+ function parse_noaiki(&$cond, &$text, $else){
+ return $text;
+ }
+
+
+ function convert_widget($widget){
+
+ // no_loop
+ if ( trim($widget->normal_select)!="" ){
+ $loop="";
+ $bottom="";
+ $resul=false;
+ if ( preg_match ( "#\(noloop\((.*)\)noloop\)#m",$widget->widget,$resul)){
+ $loop= $resul[1];
+ $widget= str_replace($resul[0],"",$widget->widget);
+ }
+ if ( preg_match ( "#\(noloop_bottom\((.*)\)noloop_bottom\)#m",$widget->widget,$resul)){
+ $bottom= $resul[1];
+ $widget= str_replace($resul[0],"",$widget->widget);
+ }
+
+ $widget->widget = "$loop(sql(\"{$widget->normal_select}\"||{$widget->widget})sql)$bottom";
+ }
+ return $widget;
+ }
+
}
_______________________________________________
Mailing list: https://launchpad.net/~aikiframework-devel
Post to : [email protected]
Unsubscribe : https://launchpad.net/~aikiframework-devel
More help : https://help.launchpad.net/ListHelp