From d819677db218a819f9a09577e0f54cb05f31123b Mon Sep 17 00:00:00 2001 From: konrad Date: Fri, 15 Jan 2010 18:56:44 +0000 Subject: [PATCH] move woc git-svn-id: https://silmor.de/svn/softmagic/pack/trunk@422 6e3c4bff-ac9f-4ac1-96c5-d2ea494d3e33 --- phpbase/autoload.php | 25 +++++ phpbase/exception.php | 16 +++ phpbase/object.php | 28 ++++++ phpbase/schema.php | 171 ++++++++++++++++++++++++++++++++++ phpbase/table.php | 237 +++++++++++++++++++++++++++++++++++++++++++++++ phpbase/transaction.php | 94 +++++++++++++++++++ 6 files changed, 571 insertions(+), 0 deletions(-) create mode 100644 phpbase/autoload.php create mode 100644 phpbase/exception.php create mode 100644 phpbase/object.php create mode 100644 phpbase/schema.php create mode 100644 phpbase/table.php create mode 100644 phpbase/transaction.php diff --git a/phpbase/autoload.php b/phpbase/autoload.php new file mode 100644 index 0000000..158203b --- /dev/null +++ b/phpbase/autoload.php @@ -0,0 +1,25 @@ + +// +---------------------------------------------------------------------- +// | +// | 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 index 0000000..732ac74 --- /dev/null +++ b/phpbase/exception.php @@ -0,0 +1,16 @@ +, (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 index 0000000..57253e1 --- /dev/null +++ b/phpbase/object.php @@ -0,0 +1,28 @@ + +// +---------------------------------------------------------------------- +// | +// | 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 index 0000000..fb368ba --- /dev/null +++ b/phpbase/schema.php @@ -0,0 +1,171 @@ +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 index 0000000..c95eed4 --- /dev/null +++ b/phpbase/table.php @@ -0,0 +1,237 @@ +, (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 index 0000000..09f164d --- /dev/null +++ b/phpbase/transaction.php @@ -0,0 +1,94 @@ +, (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("Request is not a POST Request, Aborting.\n"); + exit(); + } + if(!isset($_SERVER["HTTP_X_WOBREQUEST"])){ + header("X-WobResponse-Status: Error"); + print("Request is not a Wob Request, Aborting.\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("Request is not known, Aborting.\n"); + exit(); + } + + /**called if authentication fails*/ + public function notAuthenticated(){ + header("X-WobResponse-Status: Error"); + print("User is not authenticated or does not have permission to execute this request, Aborting.\n"); + exit(); + } + + /**called if XML parsing fails*/ + public function xmlParserError(){ + header("X-WobResponse-Status: Error"); + print("Error while parsing request XML, Aborting.\n"); + exit(); + } + + /**called for generic exception handling*/ + public function handleException($ex){ + header("X-WobResponse-Status: Error"); + print("".xq($ex->getMessage())."\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("".xq($text)."\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 -- 1.7.2.5