[Cs-webapplibs-commits] SF.net SVN: cs-webapplibs:[155] trunk/0.3
Status: Beta
                
                Brought to you by:
                
                    crazedsanity
                    
                
            | 
      
      
      From: <cra...@us...> - 2009-10-29 03:28:46
      
     | 
| Revision: 155
          http://cs-webapplibs.svn.sourceforge.net/cs-webapplibs/?rev=155&view=rev
Author:   crazedsanity
Date:     2009-10-29 03:28:38 +0000 (Thu, 29 Oct 2009)
Log Message:
-----------
Initial work for a generic data linker (database-oriented).
NOTE::: mysql schema not checked for correctness.
Modified Paths:
--------------
    trunk/0.3/setup/schema.mysql.sql
    trunk/0.3/setup/schema.pgsql.sql
    trunk/0.3/tests/testOfCSWebAppLibs.php
Added Paths:
-----------
    trunk/0.3/abstract/cs_gdlAttrib.abstract.class.php
    trunk/0.3/abstract/cs_gdlObject.abstract.class.php
    trunk/0.3/abstract/cs_gdlPath.abstract.class.php
    trunk/0.3/cs_genericDataLinker.class.php
Copied: trunk/0.3/abstract/cs_gdlAttrib.abstract.class.php (from rev 154, trunk/0.3/abstract/cs_phpDB.abstract.class.php)
===================================================================
--- trunk/0.3/abstract/cs_gdlAttrib.abstract.class.php	                        (rev 0)
+++ trunk/0.3/abstract/cs_gdlAttrib.abstract.class.php	2009-10-29 03:28:38 UTC (rev 155)
@@ -0,0 +1,89 @@
+<?php
+/*
+ * Created on Jan 29, 2009
+ * 
+ * FILE INFORMATION:
+ * 
+ * $HeadURL$
+ * $Id$
+ * $LastChangedDate$
+ * $LastChangedBy$
+ * $LastChangedRevision$
+ */
+
+abstract class cs_gdlAttribAbstract extends cs_gdlPathAbstract {
+
+	
+	const table='cswal_gdl_attribute_table';
+	const tableSeq = 'cswal_gdl_attribute_table_attribute_id_seq';	
+	
+	
+	
+	//-------------------------------------------------------------------------
+	public function create_attrib($path, $data, $type=null) {
+		
+		$objectId = $this->get_object_id_from_path($path);
+		
+		$insertString = "";
+		$attribs = array();
+		if(is_array($data) && count($data)) {
+			foreach($data as $n=>$v) {
+				$n = $this->translate_attrib_name($n);
+				$attribs[$n] = $v;
+			}
+		}
+		elseif(!is_null($type)) {
+			$key = $this->translate_attrib_name($type);
+			$attribs = array($key => $data);
+		}
+		else {
+			throw new exception(__METHOD__ .": data was not array and no type set");
+		}
+		
+		if(!is_array($attribs) || !count($attribs)) {
+			throw new exception(__METHOD__ .": failed to create an array of attributes... ". $this->gfObj->debug_print(func_get_args(),0));
+		}
+		
+		$attribs['object_id'] = $objectId;
+		$insertString = $this->gfObj->string_from_array($attribs, 'insert');
+		
+		
+		if(!strlen($insertString)) {
+			throw new exception(__METHOD__ .": invalid insert string (". $insertString .")");
+		}
+		$sql = "INSERT INTO ". self::attrTable ." ". $insertString;
+		
+		try {
+			$retval = $this->db->run_insert($sql, self::attrTableSeq);
+		}
+		catch(exception $e) {
+			throw new exception(__METHOD__ .": failed to perform insert::: ". $e->getMessage() .' ---- '. $sql);
+		}
+		
+		return($retval);
+	}//end create_attrib()
+	//-------------------------------------------------------------------------
+	
+	
+	
+	//-------------------------------------------------------------------------
+	public function translate_attrib_name($name) {
+		$retval = null;
+		foreach($this->validTypes as $type) {
+			if(preg_match('/^'. $type .'/', $name)) {
+				$retval = 'a_'. $type;
+				break;
+			}
+		}
+		
+		if(is_null($retval) || !strlen($retval)) {
+			$this->gfObj->debug_print(__METHOD__ .": name was (". $name ."), retval=(". $retval .")",1);
+			throw new exception(__METHOD__ .": invalid attribute name (". $name .")");
+		}
+		
+		return($retval);
+	}//end translate_attrib_name()
+	//-------------------------------------------------------------------------
+	
+}
+?>
\ No newline at end of file
Copied: trunk/0.3/abstract/cs_gdlObject.abstract.class.php (from rev 154, trunk/0.3/abstract/cs_phpDB.abstract.class.php)
===================================================================
--- trunk/0.3/abstract/cs_gdlObject.abstract.class.php	                        (rev 0)
+++ trunk/0.3/abstract/cs_gdlObject.abstract.class.php	2009-10-29 03:28:38 UTC (rev 155)
@@ -0,0 +1,130 @@
+<?php
+/*
+ * Created on Jan 29, 2009
+ * 
+ * FILE INFORMATION:
+ * 
+ * $HeadURL$
+ * $Id$
+ * $LastChangedDate$
+ * $LastChangedBy$
+ * $LastChangedRevision$
+ */
+
+abstract class cs_gdlObjectAbstract extends cs_webapplibsAbstract {
+
+	
+	const table='cswal_gdl_object_table';
+	const tableSeq = 'cswal_gdl_object_table_object_id_seq';	
+	
+	//-------------------------------------------------------------------------
+	public function get_object_id_from_path($path) {
+		$sql = "SELECT object_id FROM ". self::table ." WHERE object_path='". 
+				$this->clean_path($path) ."'";
+		
+		try {
+			$data = $this->db->run_query($sql);
+			
+			if(is_array($data) && count($data) == 1) {
+				$retval = $data['object_id'];
+			}
+			else {
+				throw new exception(__METHOD__ .": invalid data for path (". $this->clean_path($path) .")::: ". $this->gfObj->debug_var_dump($data,0));
+			}
+		}
+		catch(exception $e) {
+			throw new exception(__METHOD__ .": error retrieving path::: ". $e->getMessage());
+		}
+		
+		return($retval);
+	}//end get_object_id_from_path()
+	//-------------------------------------------------------------------------
+	
+	
+	
+	//-------------------------------------------------------------------------
+	public function create_object($name, $data=null, $type=null) {
+		$sql = "INSERT INTO ". self::table ." (object_name) VALUES ('". 
+				$this->gfObj->cleanString($this->clean_path($name), 'sql_insert') ."')";
+		try {
+			$retval = $this->db->run_insert($sql, self::tableSeq);
+		}
+		catch(exception $e) {
+			throw new exception(__METHOD__ .": failed to perform insert::: ". $e->getMessage());
+		}
+			
+		if(!is_null($data)) {
+			throw new exception(__METHOD__ .": can't create data for objects yet");
+		}
+		return($retval);
+	}//end create_object()
+	//-------------------------------------------------------------------------
+	
+	
+	
+	//-------------------------------------------------------------------------
+	public function build_object_id_list(array $objects) {
+		$this->gfObj->switch_force_sql_quotes(1);
+		$sql = "SELECT * FROM ". self::table ." WHERE object_name IN (".
+				$this->gfObj->string_from_array($objects, null, ',', 'sql') .")";
+		$this->gfObj->switch_force_sql_quotes(0);
+		
+		$retval = array();
+		try {
+			$retval = $this->db->run_query($sql, 'object_name', 'object_id');
+			if(!is_array($retval)) {
+				$retval = array();
+			}
+		}
+		catch(exception $e) {
+			//throw new exception(__METHOD__ .": failed to retrieve list");
+		}
+		
+		return($retval);
+	}//end build_object_id_list()
+	//-------------------------------------------------------------------------
+	
+	
+	
+	//-------------------------------------------------------------------------
+	public function build_object_name_list(array $objectIds) {
+		$this->gfObj->switch_force_sql_quotes(1);
+		$sql = "SELECT * FROM ". self::table ." WHERE object_id IN (".
+				$this->gfObj->string_from_array($objectIds, null, ',', 'sql') .")";
+		$this->gfObj->switch_force_sql_quotes(0);
+		
+		try {
+			$retval = $this->db->run_query($sql, 'object_id', 'object_name');
+			if(!is_array($retval)) {
+				$retval = array();
+			}
+		}
+		catch(exception $e) {
+			throw new exception(__METHOD__ .": failed to retrieve list::: ". $e->getMessage());
+		}
+		
+		return($retval);
+	}//end build_object_id_list()
+	//-------------------------------------------------------------------------
+	
+	
+	
+	//-------------------------------------------------------------------------
+	public function create_objects_enmasse(array $objectList) {
+		$retval = 0;
+		foreach($objectList as $name) {
+			try {
+				$this->create_object($name);
+				$retval++;
+			}
+			catch(exception $e) {
+				//nothing to see here, move along.
+			}
+		}
+		return($retval);
+	}//end create_objects_enmasse()
+	//-------------------------------------------------------------------------
+	
+	
+}
+?>
\ No newline at end of file
Copied: trunk/0.3/abstract/cs_gdlPath.abstract.class.php (from rev 154, trunk/0.3/abstract/cs_phpDB.abstract.class.php)
===================================================================
--- trunk/0.3/abstract/cs_gdlPath.abstract.class.php	                        (rev 0)
+++ trunk/0.3/abstract/cs_gdlPath.abstract.class.php	2009-10-29 03:28:38 UTC (rev 155)
@@ -0,0 +1,121 @@
+<?php
+/*
+ * Created on Jan 29, 2009
+ * 
+ * FILE INFORMATION:
+ * 
+ * $HeadURL$
+ * $Id$
+ * $LastChangedDate$
+ * $LastChangedBy$
+ * $LastChangedRevision$
+ */
+
+abstract class cs_gdlPathAbstract extends cs_gdlObjectAbstract {
+
+	
+	const table='cswal_gdl_path_table';
+	const tableSeq = 'cswal_gdl_path_table_path_id_seq';	
+	
+	
+	
+	
+	
+	//-------------------------------------------------------------------------
+	public function create_path($path) {
+		$idList = $this->create_path_objects($path);
+		$pathIdList = $this->create_id_path($idList);
+		
+		$sql = "INSERT INTO ". self::table ." (path_id_list) VALUES ('". $pathIdList ."')";
+		
+		try {
+			$insertedId = $this->db->run_insert($sql, self::tableSeq);
+			$retval = $pathIdList;
+		}
+		catch(exception $e) {
+			throw new exception(__METHOD__ .": unable to create path::: ". $e->getMessage());
+		}
+		
+		return($retval);
+	}//end create_path()
+	//-------------------------------------------------------------------------
+	
+	
+	
+	//-------------------------------------------------------------------------
+	public function clean_path($path, $appendBase=true) {
+		if(strlen($path)) {
+			if($appendBase === true && !is_null($this->basePath)) {
+				$path = $this->basePath .'/'. $path;
+			}
+			$newPath = preg_replace('/\/{2,}/', '/', $path);
+			
+			if(!strlen($newPath)) {
+				throw new exception(__METHOD__ .": new path is zero-length (". $newPath ."), old path=(". func_get_arg(0) .")");
+			}
+		}
+		else {
+			throw new exception(__METHOD__ .": no valid path given (". $path .")");
+		}
+		
+		return($newPath);
+	}//end clean_path()
+	//-------------------------------------------------------------------------
+	
+	
+	
+	//-------------------------------------------------------------------------
+	public function set_base_path($path) {
+		if(is_null($path) || !strlen($path)) {
+			$this->basePath = null;
+		}
+		else {
+			$this->basePath = $this->clean_path($path,false);
+		}
+	}//end set_base_path()
+	//-------------------------------------------------------------------------
+	
+	
+	
+	//-------------------------------------------------------------------------
+	public function explode_path($path, $appendBase=true) {
+		$path = $this->clean_path($path, $appendBase);
+		$path = preg_replace('/^\//', '', $path);
+		$path = preg_replace('/\/$/', '', $path);
+		
+		return(explode('/', $path));
+	}//end explode_path()
+	//-------------------------------------------------------------------------
+	
+	
+	
+	//-------------------------------------------------------------------------
+	public function create_id_path(array $idList) {
+		$retval = ':'. $this->gfObj->string_from_array($idList, null, '::') .':';
+		return($retval);
+	}//end create_id_path()
+	//-------------------------------------------------------------------------
+	
+	
+	
+	//-------------------------------------------------------------------------
+	public function get_text_path_from_id_path($idPath) {
+		
+		$idList = explode('::', preg_replace('/^:/', '', preg_replace('/:$/', '', $idPath)));
+		
+		$nameList = $this->build_object_name_list($idList);
+		$this->gfObj->debug_var_dump($nameList,1);
+		
+		$retval = "/";
+		foreach($nameList as $id=>$name) {
+			$retval = $this->gfObj->create_list($retval, $name, '/');
+		}
+		
+		$retval = $this->clean_path($retval,false);
+		
+		return($retval);
+	}//end get_text_path_from_id_path()
+	//-------------------------------------------------------------------------
+	
+}
+?>
\ No newline at end of file
Added: trunk/0.3/cs_genericDataLinker.class.php
===================================================================
--- trunk/0.3/cs_genericDataLinker.class.php	                        (rev 0)
+++ trunk/0.3/cs_genericDataLinker.class.php	2009-10-29 03:28:38 UTC (rev 155)
@@ -0,0 +1,101 @@
+<?php
+/*
+ * Created on Oct 27, 2009
+ * 
+ * THE IDEA:::
+ * 		1.) Unix/Linux-like paths lead to an attribute.
+ * 		2.) Multiple paths can lead to the same attribute.
+ * 		3.) An attribute can be linked to its original path.
+ * 		4.) Each "directory" in a path is an object with an ID.
+ * 		5.) Paths themselves are only stored on attributes: intermediate paths may be valid if all objects
+ * 				for that path are also valid (i.e. if "/one/two/three" is valid, so is "/two/one/three" and "/three/two/one").
+ * 		6.) Database...
+ * 			a.) finding an attribute referencing a single object should be straightforward and fast.
+ * 			b.) objects are unique to avoid excess duplicate pathways
+ * 			c.) using id paths with each number wrapped in colons is simple (i.e. ":3342:", ":3342::3::3:"
+ * 
+ * The idea here is to have a class that generically links data together (in a 
+ * database). It is not meant to be a super clean or speedy system, instead meant 
+ * as a way of describing relationships between various pieces of data.
+ * 
+ * Once a path is created (list object_id's, separated by '::'), it should always have an attribute.
+ * 
+ * 
+ * 1::2::3					-> select * from <bla> WHERE path = '2' OR path like '2::%' OR path like '%::2'
+ *   -OR-
+ * :1::2::3:				-> select * from <bla> WHERE path like '%:2:%'
+ * 
+ * If an attribute is created with a small path (like "/test") and the id is 1, the attribute shows ":1:"
+ * 		--> if the id is 7720218, then the attribute shows ":7720218:"
+ * 
+ *
+ *  SVN INFORMATION:::
+ * -------------------
+ * Last Author::::::::: $Author$ 
+ * Current Revision:::: $Revision$ 
+ * Repository Location: $HeadURL$ 
+ * Last Updated:::::::: $Date$
+ */
+
+
+
+class cs_genericDataLinker extends cs_gdlAttribAbstract {
+	
+	const attrTable='cswal_gdl_attribute_table';
+	const attrTableSeq='cswal_gdl_attribute_table_attribute_id_seq';
+	
+	protected $validTypes = array('text', 'int', 'dec', 'bool');
+	protected $gfObj;
+	protected $basePath=null;
+	
+	public $db;
+	
+	//-------------------------------------------------------------------------
+	public function __construct(cs_phpDB $db) {
+		
+		parent::__construct($db);
+		if(!$db->is_connected()) {
+			throw new exception(__METHOD__ .": database not connected");
+		}
+		$this->db = $db;
+		$this->gfObj = new cs_globalFunctions;
+	}//end __construct()
+	//-------------------------------------------------------------------------
+	
+	
+	
+	//-------------------------------------------------------------------------
+	public function create_path_objects($path) {
+		$newPath = $this->clean_path($path);
+		$newPath = preg_replace('/^\//', '', $newPath);
+		
+		//break it into bits.
+		$bits = explode('/', $newPath);
+		
+		$myList = $this->build_object_id_list($bits);
+		if(count($myList) !== count($bits)) {
+			$createThese = array();
+			foreach($bits as $name) {
+				if(!isset($myList[$name])) {
+					$createThese[] = $name;
+				}
+			}
+			$this->create_objects_enmasse($createThese);
+			$myList = $this->build_object_id_list($bits);
+		}
+		
+		$retval = array();
+		foreach($bits as $name) {
+			$retval[$name] = $myList[$name];
+		}
+		
+		if(is_null($retval) || !is_array($retval) || !count($retval)) {
+			throw new exception(__METHOD__ .": failed to build path objects... ". $retval);
+		}
+		
+		return($retval);
+	}//end create_path_objects()
+	//-------------------------------------------------------------------------
+}
+
+?>
Property changes on: trunk/0.3/cs_genericDataLinker.class.php
___________________________________________________________________
Added: svn:keywords
   + Author
Revision
HeadURL
Date
Modified: trunk/0.3/setup/schema.mysql.sql
===================================================================
--- trunk/0.3/setup/schema.mysql.sql	2009-09-29 16:12:49 UTC (rev 154)
+++ trunk/0.3/setup/schema.mysql.sql	2009-10-29 03:28:38 UTC (rev 155)
@@ -166,7 +166,35 @@
   UNIQUE KEY `project_name` (`project_name`)
 ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
 
+
 -- 
+-- Table for cs_genericDataLinker{}.
+-- 
+CREATE TABLE `cswal_gdl_object_table` (
+	`object_id` int(11) NOT NULL PRIMARY KEY auto_increment,
+	`object_name` text NOT NULL UNIQUE
+) ENGINE=InnoDB;
+
+
+CREATE TABLE `cswal_gdl_path_table` (
+	`path_id` int(11) NOT NULL PRIMARY KEY auto_increment,
+	`path_id_list` text NOT NULL
+) ENGINE=InnoDB;
+
+-- 
+-- Store attributes here.
+-- NOTE: fields prefixed with "a_" to avoid clashes with reserved words.
+-- 
+CREATE TABLE `cswal_gdl_attribute_table` (
+	`attribute_id` serial NOT NULL PRIMARY KEY auto_increment,
+	`object_path` text NOT NULL,
+	`a_text` text DEFAULT NULL,
+	`a_int` integer DEFAULT NULL,
+	`a_dec` decimal(10,2) DEFAULT NULL,
+	`a_bool` boolean DEFAULT NULL
+) ENGINE=InnoDB;
+
+-- 
 -- Constraints for dumped tables
 -- 
 
Modified: trunk/0.3/setup/schema.pgsql.sql
===================================================================
--- trunk/0.3/setup/schema.pgsql.sql	2009-09-29 16:12:49 UTC (rev 154)
+++ trunk/0.3/setup/schema.pgsql.sql	2009-10-29 03:28:38 UTC (rev 155)
@@ -120,3 +120,29 @@
 );
 
 
+-- 
+-- Table for cs_genericDataLinker{}.
+-- 
+CREATE TABLE cswal_gdl_object_table (
+	object_id serial NOT NULL PRIMARY KEY,
+	object_name text NOT NULL UNIQUE
+);
+
+
+CREATE TABLE cswal_gdl_path_table (
+	path_id serial NOT NULL PRIMARY KEY,
+	path_id_list text NOT NULL
+);
+
+-- 
+-- Store attributes here.
+-- NOTE: fields prefixed with "a_" to avoid clashes with reserved words.
+-- 
+CREATE TABLE cswal_gdl_attribute_table (
+	attribute_id serial NOT NULL PRIMARY KEY,
+	object_path text NOT NULL,
+	a_text text DEFAULT NULL,
+	a_int integer DEFAULT NULL,
+	a_dec decimal(10,2) DEFAULT NULL,
+	a_bool boolean DEFAULT NULL
+);
Modified: trunk/0.3/tests/testOfCSWebAppLibs.php
===================================================================
--- trunk/0.3/tests/testOfCSWebAppLibs.php	2009-09-29 16:12:49 UTC (rev 154)
+++ trunk/0.3/tests/testOfCSWebAppLibs.php	2009-10-29 03:28:38 UTC (rev 155)
@@ -11,13 +11,15 @@
  * $LastChangedRevision$
  */
 
-
 class testOfCSWebAppLibs extends UnitTestCase {
 	
 	//--------------------------------------------------------------------------
 	function __construct() {
 		$this->gfObj = new cs_globalFunctions;
 		$this->gfObj->debugPrintOpt=1;
+		if(!defined('CS_UNITTEST')) {
+			throw new exception(__METHOD__ .": FATAL: constant 'CS_UNITTEST' not set, can't do testing safely");
+		}
 	}//end __construct()
 	//--------------------------------------------------------------------------
 	
@@ -45,7 +47,8 @@
 		$tableList = array(
 			'cswal_auth_token_table', 'cswal_version_table', 'cswal_attribute_table', 
 			'cswal_category_table', 'cswal_class_table', 'cswal_event_table', 
-			'cswal_log_attribute_table', 'cswal_log_table', 'cswal_session_store_table'
+			'cswal_log_attribute_table', 'cswal_log_table', 'cswal_session_store_table',
+			'cswal_gdl_object_table', 'cswal_gdl_attribute_table', 'cswal_gdl_path_table'
 		);
 		
 		$db = $this->create_dbconn();
@@ -199,6 +202,250 @@
 	
 	
 	//--------------------------------------------------------------------------
+	function test_genericDataLinker() {
+		
+		$x = new gdlTester($this->create_dbconn());
+		
+		//test objects & paths first.
+		{
+			$myPath = '/character/sheet///Tetra Tealeaf';
+			
+			$this->assertEqual(array('character', 'sheet', 'Tetra Tealeaf'), $x->explode_path($myPath));
+			$x->set_base_path('/testing');
+			$this->assertEqual('/testing/character/sheet/Tetra Tealeaf', $x->clean_path($myPath));
+			$this->assertEqual(array('testing', 'character', 'sheet', 'Tetra Tealeaf'), $x->explode_path($myPath));
+			$x->set_base_path(null);
+			$this->assertNotEqual(array('testing', 'character', 'sheet', 'Tetra Tealeaf'), $x->explode_path($myPath));
+			$this->assertEqual(array('character', 'sheet', 'Tetra Tealeaf'), $x->explode_path($myPath));
+			$this->assertEqual('/character/sheet/Tetra Tealeaf', $x->clean_path($myPath));
+			
+			//now create some objects.
+			$pathBits = array();
+			foreach($x->explode_path($myPath) as $name) {
+				$pathBits[$x->create_object($name)] = $name;
+			}
+			$newPathIdList = $x->create_path($myPath);
+			$myPathIdList = ':'. $this->gfObj->string_from_array(array_keys($pathBits), null, '::') .':';
+			$this->assertEqual($newPathIdList, $myPathIdList);
+			
+			$newId = $x->create_object('testing');
+			$t = array_keys($pathBits);
+			$t = array_pop($t);
+			$lastPathId = $t;
+			$this->assertEqual($newId, ($lastPathId +1));
+			
+			$oldBits = $pathBits;
+			$pathBits = array();
+			$pathBits[$newId] = 'testing';
+			foreach($oldBits as $id=>$name) {
+				$pathBits[$id] = $name;
+			}
+			
+			$newPathIdList = $x->create_path('/testing/'. $myPath);
+			$myPathIdList = ':'. $this->gfObj->string_from_array(array_flip($pathBits), null, '::') .':';
+			$this->assertEqual($newPathIdList, $myPathIdList);
+		}
+		
+		
+		/*/basic tests for building text-based paths vs. id-based paths.
+		{
+			$myPath = '/character/sheet/Tetra Tealeaf';
+			
+			
+			$idList = $x->createPathObjects($myPath);
+			
+			$testObjectIdList = explode('/', preg_replace('/^\//', '', $myPath));
+			$this->assertEqual($idList, $x->build_object_id_list($testObjectIdList));
+			
+			$idList2 = $x->create_path($myPath);
+			$this->assertEqual($x->create_id_path(array_values($idList)), $idList2);
+			
+			$this->assertEqual($myPath, $x->get_text_path_from_id_path($x->create_id_path($idList)));
+			$this->gfObj->debug_var_dump($x->get_text_path_from_id_path($x->create_id_path($idList)));
+			
+			$this->gfObj->debug_var_dump($idList);
+			$this->gfObj->debug_var_dump($idList2);
+			
+			$this->assertEqual(':1::2::3:', $idList2);
+			$this->assertEqual($idList2, ':'. $this->gfObj->string_from_array($idList, null, '::') .':');
+			
+			$this->assertEqual(':1::2::3:', $x->create_id_path($idList));
+			
+			$this->assertEqual(':1:', $x->create_id_path(array(1)));
+			$this->assertEqual(':000010:', $x->create_id_path(array('000010')));
+			
+		}
+		
+		
+		// now REALLY test paths.
+		{
+			#$gdl = new gdlTester($this->create_dbconn());
+			
+			$myBasePath = '/character/sheet/Xander Cage';
+			$x->set_base_path($myBasePath);
+			
+			//now add something that should be BENEATH that path.
+			$idList = $x->create_path('attributes/str');
+			
+			$this->gfObj->debug_var_dump($idList);
+		}
+		#*/
+		
+		
+		
+		
+		/*/test some basics first.
+		$translations = array(
+			'good'	=> array(
+				'a_int'		=> array('int', 'integer', 'integraIsACarNotAnArgument'),
+				'a_dec'		=> array('dec', 'decimal', 'decemberIsAMonth'),
+				'a_bool'	=> array('bool', 'boolean', 'boolJustLooksLikeSomethingJiggly'),
+				'a_text'	=> array('text', 'textual', 'textPaperJustLooksPink')
+			),
+			'bad'	=> array(
+				'a_int'		=> array('num', 'a_int', 'nittedStuff'),
+				'a_dec'		=> array('dce', 'a_dec', 'dceStuff'),
+				'a_bool'	=> array('bolo', 'a_bool', 'boloMeansBeOnLookOut'),
+				'a_text'	=> array('txt', 'a_text', 'txtIsABadAbbreviation')
+			)
+		);
+		
+		foreach($translations as $goodBad=>$matchesArray) {
+			foreach($matchesArray as $matchThis => $tryThese) {
+				foreach($tryThese as $k) {
+					try {
+						$this->assertEqual($matchThis, $x->translate_attrib_name($k));
+					}
+					catch(exception $e) {
+						if($goodBad == 'good') {
+							$this->assertFalse(true, "test (". $k .") should have been good, but was bad::: ". $e->getMessage());
+						}
+					}
+				}
+			}
+		}
+		$testData = array(
+			'skills/Appraise/cc'		=> array('bool' => true),
+			'skills/Appraise/mod'		=> array('int' => 3),
+			'skills/Appraise/ab_mod'	=> array('int' => 3),
+			'skills/Appraise/rank'		=> array('int' => 3),
+			'skills/Appraise/misc_mod'	=> array('int' => 3),
+			'skills/Appraise/notes'		=> array('text' => "Lorem ipsum dolor sit amet, consectetur adipiscing elit."),
+			'skills/Appraise/test'		=> array(
+				'text'	=> "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
+				'bool'	=> true,
+				'dec'	=> 0.03
+			),
+		);
+		
+		
+		$myBasePath = '/characters/Tetra Tealeaf/';
+		$x->set_base_path($myBasePath);
+		foreach($testData as $path=>$subData) {
+			$this->assertEqual($myBasePath . $path, $x->clean_path($path));
+			$this->assertTrue(is_numeric($x->create_object($path, $subData)));
+		}
+		
+		//get each individual item about the skill 'Appraise' individually.
+		$x->get_object_attribs('skills/Appraise/cc', 'bool');
+		$x->get_object_attribs('skills/Appraise/mod', 'int');
+		$x->get_object_attribs('skills/Appraise/ab_mod', 'int');
+		$x->get_object_attribs('skills/Appraise/rank', 'int');
+		$x->get_object_attribs('skills/Appraise/misc_mod', 'int');
+		$x->get_object_attribs('skills/Appraise/notes', 'text');
+		$x->get_object_attribs('skills/Appraise/test',	array('text', 'bool', 'dec'));
+		$returnVal = array(
+			'text'		=> "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
+			'bool'		=> true,
+			'dec'		=> 0.03
+		);
+		
+		
+		//another way to retrieve it, without caring about what types are returned:::
+		$returnVal = $x->get_all_object_attribs('skills/Appraise', false);
+		$returnVal = array(
+			'cc'	=> array(
+						'test'	=> null,
+						'bool'	=> true,
+						'int'	=> null,
+						'dec'	=> null
+					),
+			'mod'	=> array(
+						'test'	=> null,
+						'bool'	=> null,
+						'int'	=> 10,
+						'dec'	=> null
+					),
+			'ab_mod'	=> array(
+						'test'	=> null,
+						'bool'	=> null,
+						'int'	=> 3,
+						'dec'	=> null
+					),
+			'rank'	=> array(
+						'test'	=> null,
+						'bool'	=> null,
+						'int'	=> 6,
+						'dec'	=> null
+					),
+			'misc_mod'	=> array(
+						'test'	=> null,
+						'bool'	=> null,
+						'int'	=> 1,
+						'dec'	=> null
+					),
+			'notes'	=> array(
+						'test'	=> "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
+						'bool'	=> null,
+						'int'	=> null,
+						'dec'	=> null
+					),
+			'test'	=> array(
+						'text'	=> "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
+						'bool'	=> true,
+						'int'	=> null,
+						'dec'	=> 0.03
+					)
+		);
+		
+		//a better way to retrieve that data:
+		$returnVal = $x->get_all_object_attribs('skills/Appraise', false);
+		$returnVal = array(
+			'cc'		=> true,
+			'mod'		=> 10,
+			'ab_mod'	=> 3,
+			'rank'		=> 6,
+			'misc_mod'	=> 1,
+			'notes'		=> "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
+			'test'		=> array(
+							'text'	=> "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
+							'bool'	=> true,
+							'dec'	=> 0.03
+						)
+		);
+		
+		//if we don't want all that junk in test, we can specify what to get for EACH one:
+		$types = array(
+			'cc'	=> "bool",
+			'test'	=> "dec"
+		);
+		$returnVal = $x->get_all_object_attribs('skills/Appraise', false, $types);
+		$returnVal = array(
+			'cc'		=> true,
+			'mod'		=> 10,
+			'ab_mod'	=> 3,
+			'rank'		=> 6,
+			'misc_mod'	=> 1,
+			'notes'		=> "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
+			'test'		=> 0.03
+		);
+		#*/
+	}//end test_genericDataLinker()
+	//--------------------------------------------------------------------------
+	
+	
+	
+	//--------------------------------------------------------------------------
 	private function do_tokenTest(array $tokenData, $uid, $checksum) {
 		
 		if($this->assertTrue(is_array($tokenData)) && $this->assertTrue(is_numeric($uid)) && $this->assertTrue(strlen($checksum))) {
@@ -213,6 +460,7 @@
 		
 	}//end do_tokenTest()
 	//--------------------------------------------------------------------------
+	
 }
 
 
@@ -226,4 +474,17 @@
 		return($this->create_hash_string($tokenId, $uid, $checksum, $hash));
 	}
 }
+
+class gdlTester extends cs_genericDataLinker {
+	public $isTest = true;
+	
+	public function __construct($db) {
+		parent::__construct($db);
+	}
+	
+	public function createPathObjects($path) {
+		return($this->create_path_objects($path));
+	}
+}
+
 ?>
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
 |