move woc
authorkonrad <konrad@6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33>
Fri, 15 Jan 2010 18:56:44 +0000 (18:56 +0000)
committerkonrad <konrad@6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33>
Fri, 15 Jan 2010 18:56:44 +0000 (18:56 +0000)
git-svn-id: https://silmor.de/svn/softmagic/pack/trunk@422 6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33

phpbase/autoload.php [new file with mode: 0644]
phpbase/exception.php [new file with mode: 0644]
phpbase/object.php [new file with mode: 0644]
phpbase/schema.php [new file with mode: 0644]
phpbase/table.php [new file with mode: 0644]
phpbase/transaction.php [new file with mode: 0644]

diff --git a/phpbase/autoload.php b/phpbase/autoload.php
new file mode 100644 (file)
index 0000000..158203b
--- /dev/null
@@ -0,0 +1,25 @@
+<?php
+// +----------------------------------------------------------------------
+// | PHP Source                                                           
+// +----------------------------------------------------------------------
+// | Copyright (C) 2009 by Konrad Rosenbaum <konrad@silmor.de>
+// +----------------------------------------------------------------------
+// |
+// | Copyright: See COPYING file that comes with this distribution
+// +----------------------------------------------------------------------
+//
+
+$AUTOCLASS["WobTable"]="inc/wbase/table.php";
+$AUTOCLASS["WobSchemaBase"]="inc/wbase/schema.php";
+$AUTOCLASS["WobTransactionBase"]="inc/wbase/transaction.php";
+$AUTOCLASS["WobXmlException"]="inc/wbase/exception.php";
+$AUTOCLASS["WObject"]="inc/wbase/object.php";
+
+function __autoload($cname)
+{
+       global $AUTOCLASS;
+       if(isset($AUTOCLASS[$cname]))
+               require_once $AUTOCLASS[$cname];
+}
+
+?>
diff --git a/phpbase/exception.php b/phpbase/exception.php
new file mode 100644 (file)
index 0000000..732ac74
--- /dev/null
@@ -0,0 +1,16 @@
+<?
+//
+// PHP Implementation: exception
+//
+// Description: 
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (C) 2009
+//
+// Copyright: See README/COPYING files that come with this distribution
+//
+//
+
+class WobXmlException extends Exception {};
+
+?>
\ No newline at end of file
diff --git a/phpbase/object.php b/phpbase/object.php
new file mode 100644 (file)
index 0000000..57253e1
--- /dev/null
@@ -0,0 +1,28 @@
+<?php
+// +----------------------------------------------------------------------
+// | PHP Source                                                           
+// +----------------------------------------------------------------------
+// | Copyright (C) 2009 by Konrad Rosenbaum <konrad@silmor.de>
+// +----------------------------------------------------------------------
+// |
+// | Copyright: See COPYING file that comes with this distribution
+// +----------------------------------------------------------------------
+//
+
+class WObject {
+       protected function __construct(){}
+       
+       /**helper function that returns only the elements directly beneith the one given as $root*/
+       public static function elementsByTagName($root,$tag)
+       {
+               $list=array();
+               foreach($root->childNodes as $node){
+                       if($node->nodeType == XML_ELEMENT_NODE)
+                               if($node->tagName == $tag)
+                                       $list[]=$node;
+               }
+               return $list;
+       }
+};
+
+?>
diff --git a/phpbase/schema.php b/phpbase/schema.php
new file mode 100644 (file)
index 0000000..fb368ba
--- /dev/null
@@ -0,0 +1,171 @@
+<?
+/**This class parses the high-level description of the database structure generated by woc; access it via $dbScheme*/
+class WobSchemaBase {
+       protected static $scheme;
+       protected static $preset;
+       protected static $sversion;
+       protected static $backup;
+       
+       function __construct()
+       {
+       }
+       
+       /**return the version of this scheme*/
+       public function version(){return $this->sversion;}
+       
+       /**return the tables to be created in order*/
+       public function tableNames()
+       {
+               return array_keys($this->scheme);
+       }
+       
+       /**returns whether a table exists in the schema*/
+       public function hasTable($t)
+       {
+               return in_array($t,array_keys($this->scheme));
+       }
+       
+       /**return the tables that are included in the backup*/
+       public function backupTables()
+       {
+               return $this->backup;
+       }
+       
+       /**return the full definition of a table, or false if it does not exist*/
+       public function tableDefinition($tab)
+       {
+               if(!isset($this->scheme[$tab]))
+                       return false;
+               return $this->scheme[$tab];
+       }
+       
+       /**return the names of all columns of a table, or false if the table does not exist*/
+       public function tableColumns($tab)
+       {
+               if(!isset($this->scheme[$tab]))
+                       return false;
+               $r=array();
+               foreach(array_keys($this->scheme[$tab]) as $c)
+                       if(substr($c,0,1)!=":")
+                               $r[]=$c;
+               return $r;
+       }
+       
+       /**return whether the table has this column*/
+       public function tableHasColumn($tab,$col)
+       {
+               return isset($this->scheme[$tab][$col]);
+       }
+       
+       /**return default lines of the table for the initialization; returns empty array if there are none*/
+       public function tableDefaults($tab)
+       {
+               if(isset($this->preset[$tab]))return $this->preset[$tab];
+               else return array();
+       }
+       
+       /**return the type of a column, or false if it does not exist*/
+       public function columnType($tab,$col)
+       {
+               if(!isset($this->scheme[$tab][$col]))
+                       return false;
+               return $this->scheme[$tab][$col][0];
+       }
+       
+       /**return the flags of a column, empty array if no flags are set, or false if the column does not exist*/
+       public function columnFlags($tab,$col)
+       {
+               if(!isset($this->scheme[$tab][$col]))
+                       return false;
+               $tmp=$this->scheme[$tab][$col];
+               unset($tmp[0]);
+               return array_values($tmp);
+       }
+       
+       /**returns true if the given column is of an integer type*/
+       public function isIntColumn($tab,$col)
+       {
+               if(!isset($this->scheme[$tab][$col]))
+                       return false;
+               $tpa=explode(":",$this->scheme[$tab][$col][0]);
+               switch($tpa[0]){
+                       case "int32":case "seq32":case "int64":case "seq64":case "enum":case "enum32":case "enum64":
+                               return true;
+                       default:
+                               return false;
+               }
+       }
+       
+       /**returns the sequence column name if the table has a sequence, false otherwise*/
+       public function hasSequence($tab)
+       {
+               if(!isset($this->scheme[$tab]))
+                       return false;
+               foreach($this->scheme[$tab] as $cl => $def){
+                       if($def[0] == "seq32" || $def[0] == "seq64")
+                               return $cl;
+               }
+               return false;
+       }
+       
+       /**returns true if the given column is of a string type*/
+       public function isStringColumn($tab,$col)
+       {
+               if(!isset($this->scheme[$tab][$col]))
+                       return false;
+               $tpa=explode(":",$this->scheme[$tab][$col][0]);
+               switch($tpa[0]){
+                       case "string":case "text":
+                               return true;
+                       default:
+                               return false;
+               }
+       }
+
+       /**returns true if the given column is of a blob type*/
+       public function isBlobColumn($tab,$col)
+       {
+               if(!isset($this->scheme[$tab][$col]))
+                       return false;
+               $tpa=explode(":",$this->scheme[$tab][$col][0]);
+               switch($tpa[0]){
+                       case "blob":
+                               return true;
+                       default:
+                               return false;
+               }
+       }
+       
+       /**returns true if the given column is of a bool type*/
+       public function isBoolColumn($tab,$col)
+       {
+               if(!isset($this->scheme[$tab][$col]))
+                       return false;
+               $tpa=explode(":",$this->scheme[$tab][$col][0]);
+               switch($tpa[0]){
+                       case "bool":
+                       case "boolean":
+                               return true;
+                       default:
+                               return false;
+               }
+       }
+       
+       /**returns the names of all primary key columns of the table*/
+       public function primaryKeyColumns($tab)
+       {
+               $r=array();
+               //search for direct mark
+               foreach($this->scheme[$tab] as $col=>$def)
+                       if(in_array("primarykey",$def))
+                               $r[]=$col;
+               //search for special mark
+               if(isset($this->scheme[$tab][":primarykey"]))
+                       foreach($this->scheme[$tab][":primarykey"] as $col)
+                               if(!in_array($col,$r))
+                                       $r[]=$col;
+               //return result
+               return $r;
+       }
+};
+?>
\ No newline at end of file
diff --git a/phpbase/table.php b/phpbase/table.php
new file mode 100644 (file)
index 0000000..c95eed4
--- /dev/null
@@ -0,0 +1,237 @@
+<?
+//
+// PHP Implementation: wob table base class
+//
+// Description: 
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (C) 2009
+//
+// Copyright: See README/COPYING files that come with this distribution
+//
+//
+
+/**thrown by WobTable if a property change is out of range*/
+class ValueOutOfRange extends Exception
+{
+       public function __construct($tab,$col,$val)
+       {
+               $this->message="Value of table '$tab' column '$col' is out of range. Value '$val' not allowed.";
+       }
+};
+
+/**parent class of all tables*/
+abstract class WobTable
+{
+       protected $data;
+       protected $cdata;
+       private $isfromdb;
+       private $table;
+       
+       /**constructs a basic table*/
+       protected function __construct(array $data,$isfromdb,$table)
+       {
+               $this->data=array();
+               if($isfromdb)$this->data=$data;
+               else
+               foreach($data as $k=>$d){
+                       //silently ignore garbage
+                       if(!$this->hasProperty($k))continue;
+                       //verify non-garbage
+                       $vm="verifyValue".$k;
+                       if(method_exists($this,$vm))
+                       if(!$this->$vm($d))
+                               throw ValueOutOfRange($this->table,$k,$d);
+                       //set
+                       $this->data[$k]=$d;
+               }
+               $this->isfromdb=$isfromdb;
+               $this->table=$table;
+               $this->cdata=array();
+       }
+       
+       /**set properties*/
+       public function __set($name,$value)
+       {
+               //check for property
+               if(!$this->hasProperty($name)){
+                       $trace=debug_backtrace();
+                       trigger_error("Trying to set undefined property ".$name." in ".$trace[0]['file']." on line ".$trace[0]['line'],E_USER_NOTICE);
+               }
+               //verify value (TODO: what about NULL?)
+               $vm="verifyValue".$name;
+               if(method_exists($this,$vm))
+                       if(!$this->$vm($value))
+                               throw ValueOutOfRange($this->table,$name,$value);
+               //set
+               $this->cdata[$name]=$value;
+       }
+       
+       /**reverts changes to the property*/
+       public function revert($name)
+       {
+               if(!$this->hasProperty($name)){
+                       $trace=debug_backtrace();
+                       trigger_error("Trying to revert undefined property ".$name." in ".$trace[0]['file']." on line ".$trace[0]['line'],E_USER_NOTICE);
+               }
+               if(array_key_exists($name,$this->cdata))unset($this->cdata[$name]);
+       }
+       
+       /**reverts all changes to properties*/
+       public function revertAll()
+       {
+               $this->cdata=array();
+       }
+       
+       /**returns the name of the table*/
+       public function tableName(){return $this->table;}
+       
+       /**returns whether the table contains a specific column*/
+       public function hasColumn($c)
+       {
+               global $dbScheme;
+               return $dbScheme->tableHasColumn($this->table,$name);
+       }
+       
+       /**overridden by woc, returns true if the property exists*/
+       abstract public function hasProperty($c);
+       
+       /**returns whether this is an auditable table*/
+       public function isAuditable(){return false;}
+       
+       /**overridden by woc, if this an auditable table; used in insert and update*/
+       protected function createAudit(){}
+       
+       /**returns the where clause to find this instance (via primary key columns)*/
+       public function where()
+       {
+               global $dbScheme,$db;
+               $r="";
+               $pk=$dbScheme->primaryKeyColumns($this->table);
+               foreach($pk as $c){
+                       if($r!="")$r.=" AND ";
+                       $r.=$c."=".$db->escapeColumn($this->table,$c,$this->data[$c]);
+               }
+               return $r;
+       }
+       
+       /**returns the property/column*/
+       public function __get($name)
+       {
+               //verify name
+               if(!$this->hasProperty($name)){
+                       $trace=debug_backtrace();
+                       trigger_error("Accessing undefined property ".$name." in ".$trace[0]['file']." on line ".$trace[0]['line'],E_USER_NOTICE);
+               }
+               //return value or null
+               if(array_key_exists($name,$this->cdata))return $this->cdata[$name];
+               if(array_key_exists($name,$this->data))return $this->data[$name];
+               else return null;
+       }
+       
+       /**checks whether a column exists*/
+       public function __isset($name)
+       {
+               global $db;
+               //verify name and return true on existence AND notnull
+               if(array_key_exists($name,$this->cdata))return isset($this->cdata[$name]);
+               if(array_key_exists($name,$this->data))return isset($this->data[$name]);
+               else return false;
+       }
+       
+       /**unsets column-properties to NULL*/
+       public function __unset($name)
+       {
+               global $dbScheme;
+               //reset to null
+               if($this->hasProperty($name))$this->cdata[$name]=null;
+       }
+       
+       /**returns whether any property has changed since the last DB sync*/
+       public function isChanged()
+       {
+               return count($this->cdata)>0;
+       }
+       
+       /**returns whether a specific column has changed since the last DB sync*/
+       public function isColumnChanged($c)
+       {
+               return array_key_exists($c,$this->cdata);
+       }
+       
+       /**insert the object under a new primary key value into the DB (implicitly calls newKey); returns true on success*/
+       public function insert()
+       {
+               global $dbScheme,$db;
+               $this->isfromdb=false;
+               //create new key
+               $this->newKey();
+               //now insert
+               $data=array();
+               foreach($this->data as $k=>$d)$data[$k]=$d;
+               foreach($this->cdata as $k=>$d)$data[$k]=$d;
+               $r=$db->insert($this->table,$data);
+               if($r===false)return false;
+               $this->isfromdb=true;
+               $this->data=$data;
+               $this->cdata=array();
+               $this->createAudit();
+               //assign primary key if sequence (otherwise newKey has done it)
+               $seq=$dbScheme->hasSequence($this->table);
+               if($seq!==false)
+                       $this->data[$seq]=$r;
+               //return success
+               return true;
+       }
+       
+       /**generate a new primary key value for insert and marks the object as not yet in the DB; the default sets the primary key to NULL if it is a sequence; call the original first if you overwrite it*/
+       public function newKey()
+       {
+               global $dbScheme;
+               $this->isfromdb=false;
+               $pk=$dbScheme->hasSequence($this->table);
+               if($pk!==false){
+                       if(array_key_exists($pk,$this->data))unset($this->data[$pk]);
+                       if(array_key_exists($pk,$this->cdata))unset($this->cdata[$pk]);
+               }
+       }
+       
+       /**updates the object in the database; returns true on success; fails if it did not come from the DB - use insertOrUpdate in this case; succeeds without asking the database if nothing has changed*/
+       public function update()
+       {
+               if(!$this->isfromdb)return false;
+               if(count($this->cdata)==0)return true;
+               global $db;
+               $succ=$db->update($this->table,$this->cdata,$this->where())!==false;
+               if($succ){
+                       foreach($this->cdata as $k=>$d)$this->data[$k]=$d;
+                       $this->cdata=array();
+                       $this->createAudit();
+               }
+               return $succ;
+       }
+       
+       /**updates existing object in the database or inserts it if it does not exist in the DB yet*/
+       public function insertOrUpdate()
+       {
+               if($this->isfromdb)return $this->update();
+               else return $this->insert();
+       }
+       
+       /**deletes this instance from the database; returns true if it actually executed*/
+       public function deleteFromDb()
+       {
+               if(!$this->isfromdb)return false;
+               global $db;
+               //obliterate audit data
+               if($this->isAuditable())
+                       $db->deleteRows($this->table."_audit",$this->where());
+               //delete data
+               $db->deleteRows($this->table,$this->where());
+               //mark as outsider
+               $this->isfromdb=false;
+               return true;
+       }
+};
+
+?>
\ No newline at end of file
diff --git a/phpbase/transaction.php b/phpbase/transaction.php
new file mode 100644 (file)
index 0000000..09f164d
--- /dev/null
@@ -0,0 +1,94 @@
+<?
+//
+// PHP Implementation: transaction
+//
+// Description: 
+//
+//
+// Author: Konrad Rosenbaum <konrad@silmor.de>, (C) 2009
+//
+// Copyright: See README/COPYING files that come with this distribution
+//
+//
+
+/**Ancestor of all Transactions*/
+class WobTransactionBase {
+       protected $ainput;
+       protected $tinput;
+       protected $aoutput;
+       protected $toutput;
+       
+       protected static $running="";
+       
+       static public function getExecutingName(){return self::$running;}
+       
+       /**called to determine the correct transaction, aborts the script if there is none.*/
+       static public function getTransactionName(){
+               global $_SERVER;
+               if($_SERVER["REQUEST_METHOD"] != "POST"){
+                       header("X-WobResponse-Status: Error");
+                       print("<WobResponse status=\"error\"><Error type=\"non-post\">Request is not a POST Request, Aborting.</Error></WobResponse>\n");
+                       exit();
+               }
+               if(!isset($_SERVER["HTTP_X_WOBREQUEST"])){
+                       header("X-WobResponse-Status: Error");
+                       print("<WobResponse status=\"error\"><Error type=\"non-wob\">Request is not a Wob Request, Aborting.</Error></WobResponse>\n");
+                       exit();
+               }
+               self::$running=$_SERVER["HTTP_X_WOBREQUEST"];
+               return self::$running;
+       }
+       /**called to determine the session id*/
+       static public function getHeader($hd)
+       {
+               $hd="HTTP_X_".strtoupper(str_replace("-","_",$hd));
+               if(isset($_SERVER[$hd]))return $_SERVER[$hd];
+               else return "";
+       }
+       /**called if the transaction is not known. aborts the script.*/
+       static public function noSuchTransaction()
+       {
+               header("X-WobResponse-Status: Error");
+               print("<WobResponse status=\"error\"><Error type=\"non-wob\">Request is not known, Aborting.</Error></WobResponse>\n");
+               exit();
+       }
+       
+       /**called if authentication fails*/
+       public function notAuthenticated(){
+               header("X-WobResponse-Status: Error");
+               print("<WobResponse status=\"error\"><Error type=\"auth\">User is not authenticated or does not have permission to execute this request, Aborting.</Error></WobResponse>\n");
+               exit();
+       }
+       
+       /**called if XML parsing fails*/
+       public function xmlParserError(){
+               header("X-WobResponse-Status: Error");
+               print("<WobResponse status=\"error\"><Error type=\"xml\">Error while parsing request XML, Aborting.</Error></WobResponse>\n");
+               exit();
+       }
+       
+       /**called for generic exception handling*/
+       public function handleException($ex){
+               header("X-WobResponse-Status: Error");
+               print("<WobResponse status=\"error\"><Error type=\"exception\">".xq($ex->getMessage())."</Error></WobResponse>\n");
+               exit();
+       }
+       
+       /**called to abort a transactions flow
+       \param $type \b optional defines the source of the error (should be only one word, defaults to "server")
+       \param $text the human readable text returned to the client
+       */
+       public function abortWithError($text,$type="server"){
+               header("X-WobResponse-Status: Error");
+               print("<WobResponse status=\"error\"><Error type=\"".xq($type)."\">".xq($text)."</Error></WobResponse>\n");
+               exit();
+       }
+       
+       /**called internally if a transaction is not implemented*/
+       protected function abortNotImplemented()
+       {
+               $this->abortWithError(tr("Transaction not implemented."));
+       }
+};
+
+?>
\ No newline at end of file