------------------------------------------------------------
revno: 1148
committer: Roger Martin <rg1...@gmail.com>
branch nick: aikiframework
timestamp: Tue 2012-03-20 23:49:57 +0100
message:
  eval_expression added
added:
  tests/libs/markup.php
modified:
  libs/Controls.php
  libs/Engine_v2.php
  libs/markup.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/Controls.php'
--- libs/Controls.php	2012-03-17 07:56:19 +0000
+++ libs/Controls.php	2012-03-20 22:49:57 +0000
@@ -27,29 +27,6 @@
 	return  is_array($array) && isset($array[$key]) ? $array[$key]: $ifnotfound;
 }
 
-function htmlAttributes( &$field, $moreAttributes ){
-
-	$allAttributes= array(
-		"class","onchange","onfocus","onblur" );
-
-	if ( !is_null($moreAttributes ) ){
-		$allAttributes = array_merge($allAttributes, explode(" ",$moreAttributes));
-	}
-
-	$ret="";
-	foreach ($allAttributes as $attribute ){
-		if ( isset($field[$attribute]) ){
-			if ( $attribute=="checked" || $attribute=="disabled" ){
-				$ret .= " $attribute";
-			} else {
-				$ret .= " $attribute='". addslashes($field[$attribute]). "'";
-			}
-		}
-	}
-	return $ret;
-}
-
-
 
 
 /*
@@ -75,11 +52,11 @@
 		);
 		$this->last_error ="";
 		// read new parameters.
-		if ( is_array($parameters) ){
-			$this->defaults = $parameters + $defaults;
+		if ( is_array($parameters) && count($parameters)>0 && is_array($parameters[0]) ){
+			$this->defaults = array_shift($parameters) + $defaults;			
+			$this->defaults["fields"]= 	$parameters ;
 		}
 		
-		
 	}
 
 
@@ -109,13 +86,13 @@
         if ( $this->is_set("save") ){			
 			if ( isset($_POST[$this->defaults["save"]]) ){
 				if ( !$this->save_data() ) {
-					$message = $this->message)
+					$message = $this->message(
 						"Error saving/adding record " . ( is_debug_on() ? $this->last_error : "" ),
 						"error");						
 				} elseif ( $this->is_set("pkey") ){
-					$message = $this->message( "Record saved", "ok form-record-saved"),
+					$message = $this->message( "Record saved", "ok form-record-saved");
 				} else {
-					$message = $this->message( "Record added", "ok form-record-add"),
+					$message = $this->message( "Record added", "ok form-record-add");
 				}					
 			}
 			// to avoid re-write the form
@@ -177,6 +154,13 @@
 		return isset($this->defaults[$key]) && $this->defaults[$key];
 	}
 
+	
+	/**
+	 *
+	 * Load data in a form
+	 *
+	 */
+		
 	function load_data(){
 		global $db;
 		
@@ -203,12 +187,11 @@
 		} elseif ( $this->is_set("fields") && is_array($this->defaults["fields"]) ){
 			return $values;
 		}		
-		
-		// @TODO WHAT DO WITH error's
+				
 		$db->last_error = "";
 		$news = $db->get_row($SQL,ARRAY_A);
 		if ( $db->last_error ){
-			$this->last_error = $db->last_error;
+			$this->last_error = t("Error reading data") . (is_debug_on()? ": ".  $db->last_error : "") ;
 			return $values;
 		}
 		
@@ -223,7 +206,7 @@
 			return false;
 		}
 	
-		// check if there is a name
+		// check if there type adequate
 		switch ($field['type']){
 			case 'submit':
 			case 'reset' :
@@ -248,6 +231,7 @@
 		return ( is_null($ret) ? NULL: "'". Controls::unescape_textarea($ret). "'");
 	}
 
+
 	function save_data(){
 		global $db;
 
@@ -329,26 +313,62 @@
 
 class Controls {
 
+	/**
+	 * return the htm attributes for a input control
+	 * 
+	 * @param array Fields defintion
+	 * @param array moreAttributes.
+	 * 
+	 * @return string attributes list ( foo='bar' bar='foo'
+	 * 
+	 */
+
+	function htmlAttributes( &$field, $moreAttributes ){
+
+
+		// this is the common attribute list supported by all inputs.
+		$allAttributes= array("class","onchange","onfocus","onblur" );
+
+		if ( !is_null($moreAttributes )  ){			
+			if ( is_array($moreAttributes)  ){
+				$allAttributes = array_merge($allAttributes, $moreAttributes);
+			} else {			
+				$allAttributes = array_merge($allAttributes, explode(" ",$moreAttributes));
+			}
+		}
+
+		$ret="";
+		foreach ($allAttributes as $attribute ){
+			if ( isset($field[$attribute]) ){
+				if ( $attribute=="checked" || $attribute=="disabled" ){
+					$ret .= " $attribute";
+				} else {
+					$ret .= " $attribute='". addslashes($field[$attribute]). "'";
+				}
+			}
+		}
+		return $ret;
+	}
+
+
 	function make_list(&$list){
 		global $db;
 		if ( is_array($list) ) {
 			return $list;
 		}
 
-		if ( substr($list,0,4)=="SQL:" ){
-			$ret= array();
-			if ($results= $db->query( substr($list,5), N_ARRAY )){
-				foreach ($results as $result){
-					$ret[$resul[0]]= $resul[1];
-				}
-			}
-			return $ret;
-		} elseif ( $list=="gender")  {
+		if ( $list=="gender")  {
 			return array("Male", "Female");
 		} elseif ( $list=="yn"){
 			return array("Yes", "No");
+		} 
+		$ret= array();
+		if ($results= $db->query( $list, ARRAY_A )){
+			foreach ($results as $result){
+				$ret[$resul[0]]= $resul[1];
+			}
 		}
-		return explode("|",$list);
+		return $ret;		
 	}
 
 
@@ -358,22 +378,55 @@
      *
      */
 
-	function input_hidden($field,$value){
+	function input_hidden($field){
 		$name = $field['name'];
-		$value= addslashes($value);
-		return "<input type='hidden' name='{$field['name']}' value='$value'>";
+		if (!$name) {
+			return "";
+		}
+		
+		$value   = 	byDefault($field,"default" ,NULL);
+		if ( is_null($value)){
+			$value= byDefault($values,$name,NULL);
+		}
+				
+		$value = is_null($value) ? "": addslashes($value);
+		return "<input type='hidden' name='{$name}' value='{$value}'>";
 	}
 
+	/**
+	 *
+	 * Escape a string to insert it in html value attribute
+     *
+     */
+
 	function escape_value($value){
 		return htmlentities($value, ENT_QUOTES);
 	}
 
+	/**
+	 *
+	 * Escape a string to insert it a html textarea controls
+     *
+     * Textarea allow html tag,quotes but not another textarea, so this
+     * tag is transformed in <text-area>.
+     * 
+     */
+
 	function escape_textarea($value){
 		return strtr( 
 			$value,
 			array("<textarea"=>"<text-area", "</textarea>"=>"</text-area>"));
 	}
 	
+	/**
+	 *
+	 * Unscape a string to insert it a html textarea controls
+     *
+     * As textarea doesn't allow <textarea>, this function reverts all previous converted <text-area>
+     * in <textarea>
+     * 
+     */
+	
 	function unescape_textarea($value){
 		return strtr( 
 			$value,
@@ -412,7 +465,7 @@
 		"image" =>"value src",
 		"month" =>"value",
 		"number" =>"value min max step",
-		"password" =>"value",
+		"password" =>"value size maxlength",
 		"radio" =>"checked disabled value",
 		"range" =>"",
 		"reset" =>"value",
@@ -425,7 +478,6 @@
 		"week" =>"value"
 	);
 
-
 	if ( is_null($form) ){
 		$layout = bydefault($field,'layout','table');
 		$formID = bydefault($field,'form',"aiki_form");
@@ -444,7 +496,7 @@
 	// first, discard hidden, and find field label
 	switch ( $type ) {
 		case "hidden":
-			return Controls::input_hidden($field,$value);
+			return Controls::input_hidden($field);
 		case "radios":
 			$label = "<span class='label'>$label</span>";
 			break;
@@ -454,8 +506,7 @@
 
 	// now the hard work, input;
 	$input="";	
-
-	$attributes = htmlAttributes( $field, isset($defined[$type]) ? $defined[$type] : NULL );
+	$attributes = Controls::htmlAttributes( $field, isset($defined[$type]) ? $defined[$type] : NULL );
 
 	switch ( $type ){
 		case "radios":
@@ -502,7 +553,7 @@
 			}
 			// no break
 		default:
-			$attributes = htmlAttributes( $field, isset($defined[$type]) ? $defined[$type] : NULL );
+
 			$temp = Controls::escape_value($value);
 			$input = "<input type='$type' value='$temp' name='$name' id='{$formID}_$name'$attributes>";		
 			break;
@@ -531,15 +582,34 @@
      *
      */
 	function inputs( &$inputs, $form, &$values){
-		$hidden = "";
-		$ret = ""	;
+		$hidden   = "";
+		$ret      = "";
+		$fieldset = "";
+		$layout    = is_null($form->layout) ? 'table' : $form->layout;
+		
+		
 		foreach($inputs as $input) {
 			if ( !is_array($input) ){
 				continue;
 			}
-
-			//hidden values
-			switch ($input["type"]){				
+							
+			switch ($input["type"]){	
+				case "fieldset":
+					if  ($fieldset!="") {
+						$ret    .= "\n</fieldset>";
+					}
+					$fieldset= ( isset($input["name"])? $input["name"] : uniqid("fieldset"));
+					if ($fieldset !="" ){
+						$ret .= "\n<fieldset ". Controls::htmlAttributes($input,array("id")). ">";
+						if ( isset($input["legend"]) && $input["legend"] ){
+							$ret .= "\<legend>{$input['legend']}</legend>";
+						}
+					}
+					break;			
+				case "hidden":
+					$hidden = Controls::input_hidden($input);
+					break;
+							
 				case "html":
 					$ret .= $input["html"];
 					break;
@@ -551,6 +621,12 @@
 			}
 		}
 
+        // close all open fieldset
+		if  ($fieldset!="") {
+			$ret    .= "</fieldset>";
+		}
+
+        // layout for all fieldset
 		$layouts= array(
 			"table"    => "\n<table>\$inputs</table>",
 			"none"  => "\$inputs",
@@ -561,7 +637,7 @@
 		$layout    = is_null($form->layout) ? 'table' : $form->layout ;
 		$useLayout = isset($layouts[$layout]) ?  $layouts[$layout] : $layouts['table'];
 
-		return $hidden.str_replace ( '$inputs', $ret, $useLayout);
+		return str_replace ( '$inputs', $ret, $useLayout);
 	}
 
 }

=== modified file 'libs/Engine_v2.php'
--- libs/Engine_v2.php	2012-03-17 07:56:19 +0000
+++ libs/Engine_v2.php	2012-03-20 22:49:57 +0000
@@ -261,9 +261,7 @@
 				'site_name' => $aiki->site->site_name(),
 				'site'	       => $aiki->site->get_site(),
 				'view'	  => $aiki->site->view(),
-				'direction' => $aiki->languages->dir,
-				'insertedby_username' => $aiki->membership->username,
-				'insertedby_userid' => $aiki->membership->userid,
+				'direction' => $aiki->languages->dir,			
 				'current_month' => $current_month,
 				'current_year' => $current_year,
 				'current_day' => $current_day,
@@ -643,10 +641,8 @@
 	 * forms
 	 */
 
-	function parse_forms( $para, $true, $false){
-		$formParameters = array_shift($para) ;
-		$formParameters["fields"]= $para;		
-		$form= new Forms2($formParameters);	
+	function parse_forms( $para, $true, $false){		
+		$form= new Forms2($para);		
 		return $form->render();
 	}
 
@@ -662,17 +658,15 @@
 	 * if
 	 */
 	function parse_if($condition,$trueblock,$elseblock){
-		if (isset($condtion[0]) && $condition[0]) {
-			return $trueblock;
+		
+		if (isset($condition[0]) && $condition[0]) {
+			return $trueblock ;
 		} else {
 			return $elseblock  ;
 		}
 	}
 
 
-
-
-
 	function convert_widget($widget){
 
 		// no_loop

=== modified file 'libs/markup.php'
--- libs/markup.php	2012-03-17 07:56:19 +0000
+++ libs/markup.php	2012-03-20 22:49:57 +0000
@@ -355,3 +355,141 @@
 		
 	return array ( $ret, substr( $string,$i));
 }
+
+
+
+function eval_expression($expr) {
+		global $aiki_space_vars;
+		$matches = 0;		
+		$operators= "\.\+\-\\/%\*=<>!&\|"; //quoted operators
+			
+		if ($expr == "") {
+			return 0;
+		} else {
+			// note: its very important to trim all trailing space.
+			$expr= trim($expr);
+		}
+		
+		// check if it is a integer
+		if (preg_match('/^[+-]?[0-9]*$/', $expr, $matches)) {
+			return (integer) $expr;
+		
+		// check if it is a number
+		} elseif (preg_match('/^[+-]?[0-9]*(\.[0-9]*)?$/', $expr, $matches)) {
+			return (float) $expr;
+		
+		// check if it is false
+		} elseif ( $expr===false || $expr == "false" ) {
+			return false;
+		
+		// check if it is true	
+		} elseif ( $expr===true || $expr == "true" ) {
+			return true;		
+		
+		/* check if it is a string . Thanks tohttp://blog.stevenlevithan.com/archives/match-quoted-string
+		} elseif (preg_match( "#^([\"'])(?:\\\1|.)*?\1\$#", $expr ) ){
+				return $expr;
+		*/
+		// check if it is a string delimited by simple quotes.		
+		} elseif (preg_match('/^\'([^\']*)\'$/', $expr, $matches)) {
+			return $matches[1];
+		
+		// check if it is a string delimited by double quotes.
+		} elseif (preg_match('/^"([^"]*)"$/', $expr, $matches)) {
+			return $matches[1];
+		
+		// check if it is a var	
+		} elseif (preg_match('/^([a-z_]+[a-z_0-9]*)$/i', $expr, $matches)) {					
+			return ( isset($aiki_space_vars[$matches[1]]) ? $aiki_space_vars[$matches[1]] : 0);
+		
+		// check if it is a parenthesis
+		} elseif (preg_match('~^\((.*)\)(.*)$~', $expr, $matches)){
+			$op1=eval_expression( $matches[1]);			
+			return eval_expression ( "$op1{$matches[2]}");						
+		
+		// check if it call function
+		} elseif (preg_match('~^(trim|substr|str_replace)\s*\((.*)$~', $expr, $matches)){			
+			$para= extract_parameters($matches[2]);
+			foreach ($para[0] as $toEval ){
+				$real[] = eval_expression($toEval);
+			}		
+			$temp=call_user_func_array($matches[1],$real);										
+			return eval_expression ( (is_string($temp)? "'$temp'": $temp) .$para[1]);
+		
+		// boolean operators. (\|\||OR|AND|&&)
+		} elseif (preg_match("~^(.*)\s*(\|\||OR|AND|&&)\s*(.*)\$~u", $expr, $matches)) {
+			 
+			 $op1= eval_expression(trim($matches[1]));
+			 $operator = $matches[2]; 
+									
+			 // Lazy evaluation of AND
+			 if ( ($operator=="AND" || $operator=="&&") && !$op1) {	
+				 return false;						 	 
+			 }
+			 
+			 // Lazy evaluation of OR
+			 if ( ($operator=="OR" || $operator=="||") && $op1) {
+				 return true;
+			 }
+			 
+			 $op2= eval_expression(trim($matches[3]));
+			 if( is_null($op1) || is_null($op2) ) {				
+				 return NULL;
+			 }			 
+			 			 			 
+			 switch ($operator){				 				
+				 case "AND": return (bool) $op2; //lazy evaluation: op1 is true
+				 case "&&" : return (bool) $op2;
+				 case "OR" : return (bool) $op2; //lazy evaluation: op1 is false
+				 case "||" : return (bool) $op2;
+						 
+			 }
+		
+		// check a *, \ division, \ entire division, % rest of division
+		} elseif (preg_match("~^([^$operators]*)\s*([\*\/\\%])\s*([^$operators].*)\$~", $expr, $matches)) {
+			 $op1= eval_expression($matches[1]);
+			 $op2= eval_expression($matches[3]);
+			 switch ($matches[2] ){
+				 case "*" : return $op1*$op2;
+				 case "/" : return (int)($op1/$op2);
+				 case "\\": return $op1/$op2;
+				 case "%" : return $op1%$op2;
+			 }
+			 
+		// check a sum,rest
+		} elseif (preg_match("~^([^$operators]*)\s*([+-])\s*([^$operators].*)\$~", $expr, $matches)) {
+			 $op1= eval_expression(trim($matches[1]));
+			 $op2= eval_expression(trim($matches[3]));
+			 return $matches[2]=="+" ? $op1+$op2 : $op1-$op2;			 			
+
+
+        // check comparison operators
+		} elseif (preg_match("~^([^$operators]*)\s*([\<\>\!\=\.]{1,2})\s*([+-]?[^$operators].*)\$~", $expr, $matches)) {
+			$op1= eval_expression($matches[1]);	
+			$op2= eval_expression($matches[3]);					 
+			
+			if( is_null($op1) || is_null($op2) ) {	
+				 return NULL;
+			 }			
+			$operator = trim($matches[2]);
+		
+			switch ($operator){
+				 case "." : return $op1.$op2;								
+				 case ">" : return $op1 > $op2;
+				 case ">=": return $op1 >= $op2;
+				 case "<" : return $op1 < $op2;
+				 case "<=": return $op1 <= $op2;				 
+				 case "==": return $op1 == $op2;
+				 case "<>": return $op1 <> $op2;
+				 case "!=": return $op1 <> $op2;	
+			}	 				 
+			return "";
+	
+		// check if it a function with one parameter
+		} elseif (preg_match('/^(trim)\((.*)\)$/i', $expr, $matches)) {
+			return meval($matches[1] . meval($matches[2],$aiki_space_vars) . $matches[3], $aiki_space_vars);
+
+        
+		}		
+		return NULL;
+	}

=== added file 'tests/libs/markup.php'
--- tests/libs/markup.php	1970-01-01 00:00:00 +0000
+++ tests/libs/markup.php	2012-03-20 22:49:57 +0000
@@ -0,0 +1,169 @@
+<?php
+
+/** Aiki Framework Tests (PHP)
+ *
+ * Tests the markup library
+ *
+ * LICENSE
+ *
+ * This source file is subject to the AGPL-3.0 license that is bundled
+ * with this package in the file LICENSE.
+ *
+ * @author      Roger Martin 
+ * @copyright   (c) 2008-2011 Aiki Lab Pte Ltd
+ * @license     http://www.fsf.org/licensing/licenses/agpl-3.0.html
+ * @link        http://www.aikiframework.org
+ * @category    Aiki
+ * @package     Tests
+ * @filesource */
+
+
+define("IN_AIKI","testing");
+
+error_reporting(E_ALL);
+   
+include_once("../../libs/markup.php");
+
+// require_once 'PHPUnit/Autoload.php';
+		
+class MarkupTest { // extends PHPUnit_Framework_TestCase {
+	
+	public function testEval_expression() {
+		global $complete;
+		
+		// tests
+        $tests= array (
+			
+			// primitive values
+			"'hello'"  => "hello",
+			'"hello"'  => "hello",
+			"Joes"     => "Joes",
+			"2"=>2,
+			"false"=>false,
+			"true" =>true,
+			"''"   =>"",
+			"-3" => -3,
+			"+5" => 5,
+			"1.5" => 1.5,
+			
+			// same as above with space
+			//" 'hello' " => "hello",
+			" 2 "=>2,
+			" false " =>false,
+			" true " =>true,
+			"'' "   =>"",
+			" -3 " => -3,
+			" 1.5 " => 1.5,
+			
+			// aritmetric operation
+			"2 + 1"=>3,
+			"2+1"=>3,
+			" 2 + 1 "=>3,
+
+			// string operations
+			"'hello '.'world'"=> "hello world",			
+			
+			// vars
+			"x"=> 5,
+			// non existants variable.			
+			"z"=> 0,			
+			"x + 1"=> 6,
+			"9 - y" => 2,
+			
+			// precendence and ()
+			"(2)" =>2,
+			"( 2 + 1 ) * 5 "=>15,
+			"x+2*y"   => 19,
+			"x+(2*y)" => 19,
+			"(x+2)*y" => 49,
+
+			// comparison with sorroundig space
+			"5 > 11" => false,
+			"5>1"    => true,
+			"5 < 11" => true,
+			"5<1"    => false,
+			"5<=11"  => true,
+			"5<=1"   => false,		
+			"5>=11"  => false,
+			"5>=1"   => true,
+			
+			// not equals
+			"5 <> 11" => true,
+			"5<>11" => true,
+			"5!=1" => true,
+			" 5 <> 5 " =>false,
+			"5<>5" =>false,
+			"5<>+5" =>false,
+			"5 != 5" =>false,
+
+			"5==5" =>true,
+			"5==+5" =>true,
+			"+5==5" =>true,
+		
+			// operations with var
+			"y>11" =>false,
+			"y>=11" =>false,
+			"x>4" => true,
+			"x>=4" => true,
+			"y==x" => false,
+			"(y+1)>x" => true,
+			"(y+1)<x" => false,
+
+			// boolean operators 
+			"y>2 AND x>3" => true,
+			"y>20 AND x>3" => false,
+			"y > 20   AND  x > 3" => false,
+			"y>20 OR x>3" => true,
+			"y>20 OR x>30" => false,
+			
+			"y>2 && x>3" => true,
+			"y>20 && x>3" => false,
+			"y > 20   &&  x > 3" => false,
+			"y>20 || x>3" => true,
+			"y>20 || x>30" => false,
+			
+			// function call
+			"substr('hello',2)" =>'llo',
+			"trim('   hello  ')"=>'hello',
+			"trim('   hello  ').' world'" =>'hello world',
+			"substr('foo.png',-3)=='png'" =>true,
+			 );
+            
+            
+            
+        $error=0; 
+        
+		foreach ( $tests as $test=>$result){            
+			if ( eval_expression($test)!= $result ){
+			    echo "<br><strong>fails</strong> |$test|"," expected ", var_dump($result), " given ", var_dump(eval_expression($test));
+			    $error++;
+			} elseif ( $complete ){
+				echo "<br>|$test| ok ($result)";
+			}
+			//$this->assertEquals( eval_expression($test), $result);
+		}
+		if ( !$error ){
+		   echo "<p>eval_expression passed all test (", count($tests) ,")";	
+		} else {
+		  echo "<p>eval_expression fails in $error of ", count($tests), " tests" ;
+		}
+                                    
+    }
+           
+} // end class
+
+
+// initialize some data.
+global $aiki_space_vars, $complete;
+$aiki_space_vars= array("x"=>5, "y" =>7 );	
+$complete = ( isset($_GET["complete"]) && $_GET["complete"]=='1' ? true: false);
+
+// making the test
+$suite  = new MarkupTest();
+$suite->testEval_expression();
+
+if ( $complete){
+	echo "<p><a href='markup.php?'>see only errors</a>";
+} else {
+	echo "<p><a href='markup.php?complete=1'>see complete test </a>";
+}

_______________________________________________
Mailing list: https://launchpad.net/~aikiframework-devel
Post to     : aikiframework-devel@lists.launchpad.net
Unsubscribe : https://launchpad.net/~aikiframework-devel
More help   : https://help.launchpad.net/ListHelp

Reply via email to