Fixed up the documentation, prettied up the code to Campware coding conventions.
This commit is contained in:
parent
d522ccead7
commit
3a90898e3b
|
@ -31,22 +31,27 @@ class M2tree{
|
|||
* Database object container
|
||||
*/
|
||||
var $dbc;
|
||||
|
||||
/**
|
||||
* Configuration tree
|
||||
*/
|
||||
var $config;
|
||||
|
||||
/**
|
||||
* Tree table name
|
||||
*/
|
||||
var $treeTable;
|
||||
|
||||
/**
|
||||
* Structure table name
|
||||
*/
|
||||
var $structTable;
|
||||
|
||||
/**
|
||||
* Root node name
|
||||
*/
|
||||
var $rootNodeName;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
|
@ -61,83 +66,107 @@ class M2tree{
|
|||
$this->treeTable = $config['tblNamePrefix'].'tree';
|
||||
$this->structTable = $config['tblNamePrefix'].'struct';
|
||||
$this->rootNodeName = $config['RootNode'];
|
||||
}
|
||||
} // constructor
|
||||
|
||||
|
||||
/* ======================================================= public methods */
|
||||
/**
|
||||
* Add new object of specified type to the tree under specified parent
|
||||
* node
|
||||
*
|
||||
* @param name string, mnemonic name for new object
|
||||
* @param type string, type of new object
|
||||
* @param parid int, optional, parent id
|
||||
* @param string $name, mnemonic name for new object
|
||||
* @param string $type, type of new object
|
||||
* @param int $parid, optional, parent id
|
||||
* @return int/err - new id of inserted object or PEAR::error
|
||||
*/
|
||||
function addObj($name, $type, $parid=NULL)
|
||||
function addObj($name, $type, $parid = NULL)
|
||||
{
|
||||
if($name=='' || $type=='') return $this->dbc->raiseError(
|
||||
"M2tree::addObj: Wrong name or type", ALIBERR_MTREE
|
||||
);
|
||||
if(is_null($parid)) $parid = $this->getRootNode();
|
||||
if ( ($name == '') || ($type == '') ) {
|
||||
return $this->dbc->raiseError("M2tree::addObj: Wrong name or type", ALIBERR_MTREE);
|
||||
}
|
||||
if (is_null($parid)) {
|
||||
$parid = $this->getRootNode();
|
||||
}
|
||||
// changing name if the same is in the dest. folder:
|
||||
for( ;
|
||||
$xid = $this->getObjId($name, $parid),
|
||||
!is_null($xid) && !$this->dbc->isError($xid);
|
||||
$name .= "_"
|
||||
);
|
||||
if($this->dbc->isError($xid)) return $xid;
|
||||
if ($this->dbc->isError($xid)) {
|
||||
return $xid;
|
||||
}
|
||||
// insert new object record:
|
||||
$this->dbc->query("BEGIN");
|
||||
$oid = $this->dbc->nextId("{$this->treeTable}_id_seq");
|
||||
if($this->dbc->isError($oid)) return $this->_dbRollback($oid);
|
||||
if ($this->dbc->isError($oid)) {
|
||||
return $this->_dbRollback($oid);
|
||||
}
|
||||
$r = $this->dbc->query("
|
||||
INSERT INTO {$this->treeTable} (id, name, type)
|
||||
VALUES ($oid, '$name', '$type')
|
||||
");
|
||||
if($this->dbc->isError($r)) return $this->_dbRollback($r);
|
||||
");
|
||||
if ($this->dbc->isError($r)) {
|
||||
return $this->_dbRollback($r);
|
||||
}
|
||||
$dataArr = array();
|
||||
// build data ($dataArr) for INSERT of structure records:
|
||||
for($p=$parid, $l=1; !is_null($p); $p=$this->getParent($p), $l++){
|
||||
for ($p=$parid, $l=1; !is_null($p); $p=$this->getParent($p), $l++) {
|
||||
$rid = $this->dbc->nextId("{$this->structTable}_id_seq");
|
||||
if($this->dbc->isError($rid)) return $this->_dbRollback($rid);
|
||||
if ($this->dbc->isError($rid)) {
|
||||
return $this->_dbRollback($rid);
|
||||
}
|
||||
$dataArr[] = array($rid, $oid, $p, $l);
|
||||
}
|
||||
// build and prepare INSERT command automatically:
|
||||
$pr = $this->dbc->autoPrepare($this->structTable,
|
||||
array('rid', 'objid', 'parid', 'level'), DB_AUTOQUERY_INSERT);
|
||||
if($this->dbc->isError($pr)) return $this->_dbRollback($pr);
|
||||
if ($this->dbc->isError($pr)) {
|
||||
return $this->_dbRollback($pr);
|
||||
}
|
||||
// execute INSERT command for $dataArr:
|
||||
$r = $this->dbc->executeMultiple($pr, $dataArr);
|
||||
if($this->dbc->isError($r)) return $this->_dbRollback($r);
|
||||
if ($this->dbc->isError($r)) {
|
||||
return $this->_dbRollback($r);
|
||||
}
|
||||
$r = $this->dbc->query("COMMIT");
|
||||
if(PEAR::isError($r)) return $this->_dbRollback($r);
|
||||
if (PEAR::isError($r)) {
|
||||
return $this->_dbRollback($r);
|
||||
}
|
||||
return $oid;
|
||||
}
|
||||
} // fn addObj
|
||||
|
||||
|
||||
/**
|
||||
* Remove specified object
|
||||
*
|
||||
* @param oid int, object id to remove
|
||||
* @param int $oid, object id to remove
|
||||
* @return boolean/err - TRUE or PEAR::error
|
||||
*/
|
||||
function removeObj($oid)
|
||||
{
|
||||
if($oid == $this->getRootNode()){
|
||||
if ($oid == $this->getRootNode()){
|
||||
return $this->dbc->raiseError(
|
||||
"M2tree::removeObj: Can't remove root"
|
||||
);
|
||||
}
|
||||
$dir = $this->getDir($oid);
|
||||
if($this->dbc->isError($dir)) return $dir;
|
||||
foreach($dir as $k=>$ch){
|
||||
if ($this->dbc->isError($dir)) {
|
||||
return $dir;
|
||||
}
|
||||
foreach ($dir as $k => $ch){
|
||||
$r = $this->removeObj($ch['id']);
|
||||
if($this->dbc->isError($r)) return $r;
|
||||
if ($this->dbc->isError($r)) {
|
||||
return $r;
|
||||
}
|
||||
}
|
||||
$r = $this->dbc->query("
|
||||
DELETE FROM {$this->treeTable}
|
||||
WHERE id=$oid
|
||||
");
|
||||
if($this->dbc->isError($r)) return $r;
|
||||
if ($this->dbc->isError($r)) {
|
||||
return $r;
|
||||
}
|
||||
/* done by automatic reference trigger:
|
||||
$r = $this->dbc->query("
|
||||
DELETE FROM {$this->structTable}
|
||||
|
@ -146,13 +175,13 @@ class M2tree{
|
|||
if($this->dbc->isError($r)) return $r;
|
||||
*/
|
||||
return TRUE;
|
||||
}
|
||||
} // fn removeObj
|
||||
|
||||
|
||||
/**
|
||||
* Create copy of specified object and insert copy to new position
|
||||
* recursively
|
||||
*
|
||||
*
|
||||
* @param oid int, source object id
|
||||
* @param newParid int, destination parent id
|
||||
* @param after null, dummy argument for back-compatibility
|
||||
|
@ -160,37 +189,56 @@ class M2tree{
|
|||
*/
|
||||
function copyObj($oid, $newParid, $after=NULL)
|
||||
{
|
||||
if(TRUE === ($r = $this->isChildOf($newParid, $oid, TRUE))){
|
||||
if (TRUE === ($r = $this->isChildOf($newParid, $oid, TRUE))){
|
||||
return $this->dbc->raiseError(
|
||||
"M2tree::copyObj: Can't copy into itself"
|
||||
);
|
||||
}
|
||||
if($this->dbc->isError($r)) return $r;
|
||||
if ($this->dbc->isError($r)) {
|
||||
return $r;
|
||||
}
|
||||
// get name:
|
||||
$name = $this->getObjName($oid);
|
||||
if($this->dbc->isError($name)) return $name;
|
||||
if ($this->dbc->isError($name)) {
|
||||
return $name;
|
||||
}
|
||||
// get parent id:
|
||||
$parid = $this->getParent($oid);
|
||||
if($this->dbc->isError($parid)) return $parid;
|
||||
if($parid == $newParid) $name .= "_copy";
|
||||
if ($this->dbc->isError($parid)) {
|
||||
return $parid;
|
||||
}
|
||||
if ($parid == $newParid) {
|
||||
$name .= "_copy";
|
||||
}
|
||||
// get type:
|
||||
$type = $this->getObjType($oid);
|
||||
if($this->dbc->isError($type)) return $type;
|
||||
if ($this->dbc->isError($type)) {
|
||||
return $type;
|
||||
}
|
||||
// look for children:
|
||||
$dir = $this->getDir($oid, $flds='id');
|
||||
if($this->dbc->isError($dir)) return $dir;
|
||||
$dir = $this->getDir($oid, $flds='id');
|
||||
if ($this->dbc->isError($dir)) {
|
||||
return $dir;
|
||||
}
|
||||
// insert aktual object:
|
||||
$nid = $this->addObj($name, $type, $newParid);
|
||||
if($this->dbc->isError($nid)) return $nid;
|
||||
if ($this->dbc->isError($nid)) {
|
||||
return $nid;
|
||||
}
|
||||
// if no children:
|
||||
if(is_null($dir)) return $nid;
|
||||
if (is_null($dir)) {
|
||||
return $nid;
|
||||
}
|
||||
// optionally insert children recursively:
|
||||
foreach($dir as $k=>$item){
|
||||
foreach ($dir as $k => $item){
|
||||
$r = $this->copyObj($item['id'], $nid);
|
||||
if($this->dbc->isError($r)) return $r;
|
||||
if ($this->dbc->isError($r)) {
|
||||
return $r;
|
||||
}
|
||||
}
|
||||
return $nid;
|
||||
}
|
||||
} // fn copyObj
|
||||
|
||||
|
||||
/**
|
||||
* Move subtree to another node without removing/adding
|
||||
|
@ -202,80 +250,104 @@ class M2tree{
|
|||
*/
|
||||
function moveObj($oid, $newParid, $after=NULL)
|
||||
{
|
||||
if(TRUE === (
|
||||
if (TRUE === (
|
||||
$r = $this->isChildOf($newParid, $oid, TRUE)
|
||||
|| $oid == $newParid
|
||||
)){
|
||||
)) {
|
||||
return $this->dbc->raiseError(
|
||||
"M2tree::moveObj: Can't move into itself"
|
||||
);
|
||||
}
|
||||
if($this->dbc->isError($r)) return $r;
|
||||
if ($this->dbc->isError($r)) {
|
||||
return $r;
|
||||
}
|
||||
// get name:
|
||||
$name0 = $name = $this->getObjName($oid);
|
||||
if($this->dbc->isError($name)) return $name;
|
||||
if ($this->dbc->isError($name)) {
|
||||
return $name;
|
||||
}
|
||||
$this->dbc->query("BEGIN");
|
||||
// cut it from source:
|
||||
$r = $this->_cutSubtree($oid);
|
||||
if($this->dbc->isError($r)) return $this->_dbRollback($r);
|
||||
if ($this->dbc->isError($r)) {
|
||||
return $this->_dbRollback($r);
|
||||
}
|
||||
// changing name if the same is in the dest. folder:
|
||||
for( ;
|
||||
$xid = $this->getObjId($name, $newParid),
|
||||
!is_null($xid) && !$this->dbc->isError($xid);
|
||||
$name .= "_"
|
||||
);
|
||||
if($this->dbc->isError($xid)) return $this->_dbRollback($xid);
|
||||
if($name != $name0){
|
||||
if ($this->dbc->isError($xid)) {
|
||||
return $this->_dbRollback($xid);
|
||||
}
|
||||
if ($name != $name0){
|
||||
$r = $this->renameObj($oid, $name);
|
||||
if($this->dbc->isError($r)) return $this->_dbRollback($r);
|
||||
if ($this->dbc->isError($r)) {
|
||||
return $this->_dbRollback($r);
|
||||
}
|
||||
}
|
||||
// paste it to dest.:
|
||||
$r = $this->_pasteSubtree($oid, $newParid);
|
||||
if($this->dbc->isError($r)) return $this->_dbRollback($r);
|
||||
if ($this->dbc->isError($r)) {
|
||||
return $this->_dbRollback($r);
|
||||
}
|
||||
$r = $this->dbc->query("COMMIT");
|
||||
if(PEAR::isError($r)) return $this->_dbRollback($r);
|
||||
if (PEAR::isError($r)) {
|
||||
return $this->_dbRollback($r);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
} //fn moveObj
|
||||
|
||||
|
||||
/**
|
||||
* Rename of specified object
|
||||
*
|
||||
* @param oid int, object id to rename
|
||||
* @param newName string, new name
|
||||
* @param int $oid, object id to rename
|
||||
* @param string $newName, new name
|
||||
* @return boolean/err - True or PEAR::error
|
||||
*/
|
||||
function renameObj($oid, $newName)
|
||||
{
|
||||
// get parent id:
|
||||
$parid = $this->getParent($oid);
|
||||
if($this->dbc->isError($parid)) return $parid;
|
||||
if ($this->dbc->isError($parid)) {
|
||||
return $parid;
|
||||
}
|
||||
// changing name if the same is in the folder:
|
||||
for( ;
|
||||
$xid = $this->getObjId($newName, $parid),
|
||||
!is_null($xid) && !$this->dbc->isError($xid);
|
||||
$newName .= "_"
|
||||
);
|
||||
if($this->dbc->isError($xid)) return $xid;
|
||||
if ($this->dbc->isError($xid)) {
|
||||
return $xid;
|
||||
}
|
||||
$r = $this->dbc->query("
|
||||
UPDATE {$this->treeTable}
|
||||
SET name='$newName'
|
||||
WHERE id=$oid
|
||||
");
|
||||
if($this->dbc->isError($r)) return $r;
|
||||
if ($this->dbc->isError($r)) {
|
||||
return $r;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
} // fn renameObj
|
||||
|
||||
|
||||
/* --------------------------------------------------------- info methods */
|
||||
/**
|
||||
* Search for child id by name in sibling set
|
||||
*
|
||||
* @param name string, searched name
|
||||
* @param parId int, optional, parent id (default is root node)
|
||||
* @param string $name, searched name
|
||||
* @param int $parId, optional, parent id (default is root node)
|
||||
* @return int/null/err - child id (if found) or null or PEAR::error
|
||||
*/
|
||||
function getObjId($name, $parId=NULL)
|
||||
function getObjId($name, $parId = null)
|
||||
{
|
||||
if($name=='' && is_null($parId)) $name = $this->rootNodeName;
|
||||
if ( ($name == '') && is_null($parId)) {
|
||||
$name = $this->rootNodeName;
|
||||
}
|
||||
$parcond = (is_null($parId) ? "parid is null" :
|
||||
"parid='$parId' AND level=1");
|
||||
$r = $this->dbc->getOne("
|
||||
|
@ -283,15 +355,18 @@ class M2tree{
|
|||
LEFT JOIN {$this->structTable} s ON id=objid
|
||||
WHERE name='$name' AND $parcond"
|
||||
);
|
||||
if($this->dbc->isError($r)) return $r;
|
||||
if ($this->dbc->isError($r)) {
|
||||
return $r;
|
||||
}
|
||||
return $r;
|
||||
}
|
||||
} // fn getObjId
|
||||
|
||||
|
||||
/**
|
||||
* Get one value for object by id (default: get name)
|
||||
*
|
||||
* @param oid int
|
||||
* @param fld string, optional, requested field (default: name)
|
||||
* @param int $oid
|
||||
* @param string $fld, optional, requested field (default: name)
|
||||
* @return string/err
|
||||
*/
|
||||
function getObjName($oid, $fld='name')
|
||||
|
@ -301,23 +376,25 @@ class M2tree{
|
|||
WHERE id=$oid
|
||||
");
|
||||
return $r;
|
||||
}
|
||||
} // fn getObjName
|
||||
|
||||
|
||||
/**
|
||||
* Get object type by id
|
||||
* Get object type by id.
|
||||
*
|
||||
* @param oid int
|
||||
* @param int $oid
|
||||
* @return string/err
|
||||
*/
|
||||
function getObjType($oid)
|
||||
{
|
||||
return $this->getObjName($oid, 'type');
|
||||
}
|
||||
} // fn getObjType
|
||||
|
||||
|
||||
/**
|
||||
* Get parent id
|
||||
*
|
||||
* @param oid int
|
||||
* @param int $oid
|
||||
* @return int/err
|
||||
*/
|
||||
function getParent($oid)
|
||||
|
@ -327,14 +404,15 @@ class M2tree{
|
|||
WHERE objid=$oid AND level=1
|
||||
");
|
||||
return $r;
|
||||
}
|
||||
} // fn getParent
|
||||
|
||||
|
||||
/**
|
||||
* Get array of nodes in object's path from root node
|
||||
*
|
||||
* @param oid int
|
||||
* @param flds string, optional
|
||||
* @param withSelf boolean - flag for include specified object to the path
|
||||
* @param int $oid
|
||||
* @param string $flds, optional
|
||||
* @param boolean $withSelf - flag for include specified object to the path
|
||||
* @return array/err
|
||||
*/
|
||||
function getPath($oid, $flds='id', $withSelf=TRUE)
|
||||
|
@ -356,14 +434,15 @@ class M2tree{
|
|||
array_push($path, $r);
|
||||
}
|
||||
return $path;
|
||||
}
|
||||
} // fn getPath
|
||||
|
||||
|
||||
/**
|
||||
* Get array of childnodes
|
||||
*
|
||||
* @param oid int
|
||||
* @param flds string, optional, comma separated list of requested fields
|
||||
* @param order string, optional, fieldname for order by clause
|
||||
* @param int $oid
|
||||
* @param string $flds, optional, comma separated list of requested fields
|
||||
* @param string $order, optional, fieldname for order by clause
|
||||
* @return array/err
|
||||
*/
|
||||
function getDir($oid, $flds='id', $order='name')
|
||||
|
@ -376,38 +455,44 @@ class M2tree{
|
|||
ORDER BY $order
|
||||
");
|
||||
return $r;
|
||||
}
|
||||
} // fn getDir
|
||||
|
||||
|
||||
/**
|
||||
* Get level of object relatively to specified root
|
||||
*
|
||||
* @param oid int, object id
|
||||
* @param flds string, list of field names for select
|
||||
* @param int $oid, object id
|
||||
* @param string $flds, list of field names for select
|
||||
* (optional - default: 'level')
|
||||
* @param rootId int, root for relative levels
|
||||
* @param int $rootId, root for relative levels
|
||||
* (optional - default: NULL - use root of whole tree)
|
||||
* @return hash-array with field name/value pairs
|
||||
*/
|
||||
function getObjLevel($oid, $flds='level', $rootId=NULL)
|
||||
{
|
||||
if(is_null($rootId)) $rootId = $this->getRootNode();
|
||||
if (is_null($rootId)) {
|
||||
$rootId = $this->getRootNode();
|
||||
}
|
||||
$re = $this->dbc->getRow("
|
||||
SELECT $flds
|
||||
FROM {$this->treeTable}
|
||||
LEFT JOIN {$this->structTable} s ON id=objid AND parid=$rootId
|
||||
WHERE id=$oid
|
||||
");
|
||||
if($this->dbc->isError($re)) return $re;
|
||||
if ($this->dbc->isError($re)) {
|
||||
return $re;
|
||||
}
|
||||
$re['level'] = intval($re['level']);
|
||||
return $re;
|
||||
}
|
||||
|
||||
} // fn getObjLevel
|
||||
|
||||
|
||||
/**
|
||||
* Get subtree of specified node
|
||||
*
|
||||
* @param oid int, optional, default: root node
|
||||
* @param withRoot boolean, optional, include/exclude specified node
|
||||
* @param rootId int, root for relative levels, optional
|
||||
* @param int $oid, optional, default: root node
|
||||
* @param boolean $withRoot, optional, include/exclude specified node
|
||||
* @param int $rootId, root for relative levels, optional
|
||||
* @return array/err
|
||||
*/
|
||||
function getSubTree($oid=NULL, $withRoot=FALSE, $rootId=NULL)
|
||||
|
@ -417,43 +502,60 @@ class M2tree{
|
|||
$r = array();
|
||||
if($withRoot){
|
||||
$r[] = $re = $this->getObjLevel($oid, 'id, name, level', $rootId);
|
||||
}else $re=NULL;
|
||||
if($this->dbc->isError($re)) return $re;
|
||||
} else {
|
||||
$re=NULL;
|
||||
}
|
||||
if ($this->dbc->isError($re)) {
|
||||
return $re;
|
||||
}
|
||||
$dirarr = $this->getDir($oid, 'id, level');
|
||||
if($this->dbc->isError($dirarr)) return $dirarr;
|
||||
foreach($dirarr as $k=>$snod)
|
||||
{
|
||||
if ($this->dbc->isError($dirarr)) {
|
||||
return $dirarr;
|
||||
}
|
||||
foreach ($dirarr as $k => $snod) {
|
||||
$re = $this->getObjLevel($snod['id'], 'id, name, level', $rootId);
|
||||
if($this->dbc->isError($re)) return $re;
|
||||
if($this->dbc->isError($re)) {
|
||||
return $re;
|
||||
}
|
||||
# $re['level'] = intval($re['level'])+1;
|
||||
$r[] = $re;
|
||||
$r = array_merge($r,
|
||||
$this->getSubTree($snod['id'], FALSE, $rootId));
|
||||
}
|
||||
return $r;
|
||||
}
|
||||
} // fn getSubTree
|
||||
|
||||
|
||||
/**
|
||||
* Returns true if first object if child of second one
|
||||
*
|
||||
* @param oid int, object id of tested object
|
||||
* @param parid int, object id of parent
|
||||
* @param indirect boolean, test indirect or only direct relation
|
||||
* @param int $oid, object id of tested object
|
||||
* @param int $parid, object id of parent
|
||||
* @param boolean $indirect, test indirect or only direct relation
|
||||
* @return boolean
|
||||
*/
|
||||
function isChildOf($oid, $parid, $indirect=FALSE)
|
||||
{
|
||||
if(!$indirect){
|
||||
if (!$indirect){
|
||||
$paridD = $this->getParent($oid);
|
||||
if($this->dbc->isError($paridD)) return $paridD;
|
||||
if ($this->dbc->isError($paridD)) {
|
||||
return $paridD;
|
||||
}
|
||||
return ($paridD == $parid);
|
||||
}
|
||||
$path = $this->getPath($oid, 'id', FALSE);
|
||||
if($this->dbc->isError($path)) return $path;
|
||||
if ($this->dbc->isError($path)) {
|
||||
return $path;
|
||||
}
|
||||
$res = FALSE;
|
||||
foreach($path as $k=>$item){ if($item['id'] == $parid) $res = TRUE; }
|
||||
foreach ($path as $k=>$item) {
|
||||
if ($item['id'] == $parid) {
|
||||
$res = TRUE;
|
||||
}
|
||||
}
|
||||
return $res;
|
||||
}
|
||||
} // fn isChildOf
|
||||
|
||||
|
||||
/**
|
||||
* Get id of root node
|
||||
|
@ -463,7 +565,8 @@ class M2tree{
|
|||
function getRootNode()
|
||||
{
|
||||
return $this->getObjId($this->rootNodeName);
|
||||
}
|
||||
} // fn getRootNode
|
||||
|
||||
|
||||
/**
|
||||
* Get all objects in the tree as array of hashes
|
||||
|
@ -475,38 +578,42 @@ class M2tree{
|
|||
return $this->dbc->getAll(
|
||||
"SELECT * FROM {$this->treeTable}"
|
||||
);
|
||||
}
|
||||
} // fn getAllObjects
|
||||
|
||||
|
||||
/* ------------------------ info methods related to application structure */
|
||||
/* (this part should be redefined in extended class to allow
|
||||
* defining/modifying/using application structure)
|
||||
* (only very simple structure definition - in $config - supported now)
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Get child types allowed by application definition
|
||||
* Get child types allowed by application definition
|
||||
*
|
||||
* @param type string
|
||||
* @return array
|
||||
* @param string $type
|
||||
* @return array
|
||||
*/
|
||||
function getAllowedChildTypes($type)
|
||||
{
|
||||
return $this->config['objtypes'][$type];
|
||||
}
|
||||
|
||||
} // fn getAllowedChildTypes
|
||||
|
||||
|
||||
/* ==================================================== "private" methods */
|
||||
|
||||
/**
|
||||
* Cut subtree of specified object from tree.
|
||||
* Preserve subtree structure.
|
||||
*
|
||||
* @param oid int, object id
|
||||
* @param int $oid, object id
|
||||
* @return boolean
|
||||
*/
|
||||
function _cutSubtree($oid)
|
||||
{
|
||||
$lvl = $this->getObjLevel($oid);
|
||||
if($this->dbc->isError($lvl)) return $lvl;
|
||||
if ($this->dbc->isError($lvl)) {
|
||||
return $lvl;
|
||||
}
|
||||
$lvl = $lvl['level'];
|
||||
// release downside structure
|
||||
$r = $this->dbc->query("
|
||||
|
@ -519,65 +626,77 @@ class M2tree{
|
|||
AND s2.parid=1 AND s3.level>(s2.level-$lvl)
|
||||
)
|
||||
");
|
||||
if($this->dbc->isError($r)) return $r;
|
||||
if ($this->dbc->isError($r)) {
|
||||
return $r;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
} // fn _cutSubtree
|
||||
|
||||
|
||||
/**
|
||||
* Paste subtree previously cut by _cutSubtree method into main tree
|
||||
* Paste subtree previously cut by _cutSubtree method into main tree
|
||||
*
|
||||
* @param oid int, object id
|
||||
* @param newParid int, destination object id
|
||||
* @return boolean
|
||||
* @param int $oid, object id
|
||||
* @param int $newParid, destination object id
|
||||
* @return boolean
|
||||
*/
|
||||
function _pasteSubtree($oid, $newParid)
|
||||
{
|
||||
$dataArr = array();
|
||||
// build data ($dataArr) for INSERT:
|
||||
foreach($this->getSubTree($oid, TRUE) as $o){
|
||||
$l=intval($o['level'])+1;
|
||||
for($p=$newParid; !is_null($p); $p=$this->getParent($p), $l++){
|
||||
foreach ($this->getSubTree($oid, TRUE) as $o){
|
||||
$l = intval($o['level'])+1;
|
||||
for ($p = $newParid; !is_null($p); $p=$this->getParent($p), $l++){
|
||||
$rid = $this->dbc->nextId("{$this->structTable}_id_seq");
|
||||
if($this->dbc->isError($rid)) return $rid;
|
||||
if ($this->dbc->isError($rid)) {
|
||||
return $rid;
|
||||
}
|
||||
$dataArr[] = array($rid, $o['id'], $p, $l);
|
||||
}
|
||||
}
|
||||
// build and prepare INSERT command automatically:
|
||||
$pr = $this->dbc->autoPrepare($this->structTable,
|
||||
array('rid', 'objid', 'parid', 'level'), DB_AUTOQUERY_INSERT);
|
||||
if($this->dbc->isError($pr)) return $pr;
|
||||
if ($this->dbc->isError($pr)) {
|
||||
return $pr;
|
||||
}
|
||||
// execute INSERT command for $dataArr:
|
||||
$r = $this->dbc->executeMultiple($pr, $dataArr);
|
||||
if($this->dbc->isError($r)) return $r;
|
||||
if ($this->dbc->isError($r)) {
|
||||
return $r;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
} // _pasteSubtree
|
||||
|
||||
|
||||
/**
|
||||
* Do SQL rollback and return PEAR::error
|
||||
* Do SQL rollback and return PEAR::error
|
||||
*
|
||||
* @param r object/string, error object or error message
|
||||
* @return err
|
||||
* @param object/string $r, error object or error message
|
||||
* @return err
|
||||
*/
|
||||
function _dbRollback($r)
|
||||
{
|
||||
$this->dbc->query("ROLLBACK");
|
||||
if($this->dbc->isError($r)) return $r;
|
||||
elseif(is_string($r)){
|
||||
if ($this->dbc->isError($r)) {
|
||||
return $r;
|
||||
} elseif(is_string($r)) {
|
||||
$msg = basename(__FILE__)."::".get_class($this).": $r";
|
||||
}else{
|
||||
} else {
|
||||
$msg = basename(__FILE__)."::".get_class($this).": unknown error";
|
||||
}
|
||||
return $this->dbc->raiseError($msg, ALIBERR_MTREE, PEAR_ERROR_RETURN);
|
||||
}
|
||||
} // fn _dbRollback
|
||||
|
||||
|
||||
/* ==================================================== auxiliary methods */
|
||||
|
||||
/**
|
||||
* Human readable dump of subtree - for debug
|
||||
*
|
||||
* @param oid int, start object id
|
||||
* @param indstr string, indentation string
|
||||
* @param ind string, aktual indentation
|
||||
* @param int $oid, start object id
|
||||
* @param string $indstr, indentation string
|
||||
* @param string $ind, aktual indentation
|
||||
* @return string
|
||||
*/
|
||||
function dumpTree($oid=NULL, $indstr=' ', $ind='',
|
||||
|
@ -585,23 +704,28 @@ class M2tree{
|
|||
{
|
||||
$r='';
|
||||
foreach($st = $this->getSubTree($oid, $withRoot) as $o){
|
||||
if($this->dbc->isError($st)) return $st;
|
||||
if ($this->dbc->isError($st)) {
|
||||
return $st;
|
||||
}
|
||||
$r .= $ind.str_repeat($indstr, $o['level']).
|
||||
preg_replace(array('|\{name\}|', '|\{id\}|'),
|
||||
array($o['name'], $o['id']), $format).
|
||||
"\n";
|
||||
}
|
||||
return $r;
|
||||
}
|
||||
} // fn dumpTree
|
||||
|
||||
|
||||
/**
|
||||
* Create tables + initialize root node
|
||||
*
|
||||
* Create tables + initialize root node
|
||||
* @return err/void
|
||||
*/
|
||||
function install()
|
||||
{
|
||||
$r = $this->dbc->query("BEGIN");
|
||||
if(PEAR::isError($r)) return $r;
|
||||
if (PEAR::isError($r)) {
|
||||
return $r;
|
||||
}
|
||||
$r = $this->dbc->query("CREATE TABLE {$this->treeTable} (
|
||||
id int not null PRIMARY KEY,
|
||||
name varchar(255) not null default'',
|
||||
|
@ -609,15 +733,23 @@ class M2tree{
|
|||
type varchar(255) not null default'',
|
||||
param varchar(255)
|
||||
)");
|
||||
if($this->dbc->isError($r)) return $r;
|
||||
if ($this->dbc->isError($r)) {
|
||||
return $r;
|
||||
}
|
||||
$r = $this->dbc->createSequence("{$this->treeTable}_id_seq");
|
||||
if($this->dbc->isError($r)) return $r;
|
||||
if ($this->dbc->isError($r)) {
|
||||
return $r;
|
||||
}
|
||||
$r = $this->dbc->query("CREATE UNIQUE INDEX {$this->treeTable}_id_idx
|
||||
ON {$this->treeTable} (id)");
|
||||
if($this->dbc->isError($r)) return $r;
|
||||
if ($this->dbc->isError($r)) {
|
||||
return $r;
|
||||
}
|
||||
$r = $this->dbc->query("CREATE INDEX {$this->treeTable}_name_idx
|
||||
ON {$this->treeTable} (name)");
|
||||
if($this->dbc->isError($r)) return $r;
|
||||
if ($this->dbc->isError($r)) {
|
||||
return $r;
|
||||
}
|
||||
|
||||
$r = $this->dbc->query("CREATE TABLE {$this->structTable} (
|
||||
rid int not null PRIMARY KEY,
|
||||
|
@ -625,48 +757,71 @@ class M2tree{
|
|||
parid int not null REFERENCES {$this->treeTable} ON DELETE CASCADE,
|
||||
level int
|
||||
)");
|
||||
if($this->dbc->isError($r)) return $r;
|
||||
if ($this->dbc->isError($r)) {
|
||||
return $r;
|
||||
}
|
||||
$r = $this->dbc->createSequence("{$this->structTable}_id_seq");
|
||||
if($this->dbc->isError($r)) return $r;
|
||||
if ($this->dbc->isError($r)) {
|
||||
return $r;
|
||||
}
|
||||
$r = $this->dbc->query("CREATE UNIQUE INDEX {$this->structTable}_rid_idx
|
||||
ON {$this->structTable} (rid)");
|
||||
if($this->dbc->isError($r)) return $r;
|
||||
if ($this->dbc->isError($r)) {
|
||||
return $r;
|
||||
}
|
||||
$r = $this->dbc->query("CREATE INDEX {$this->structTable}_objid_idx
|
||||
ON {$this->structTable} (objid)");
|
||||
if($this->dbc->isError($r)) return $r;
|
||||
if ($this->dbc->isError($r)) {
|
||||
return $r;
|
||||
}
|
||||
$r = $this->dbc->query("CREATE INDEX {$this->structTable}_parid_idx
|
||||
ON {$this->structTable} (parid)");
|
||||
if($this->dbc->isError($r)) return $r;
|
||||
if ($this->dbc->isError($r)) {
|
||||
return $r;
|
||||
}
|
||||
$r = $this->dbc->query("CREATE INDEX {$this->structTable}_level_idx
|
||||
ON {$this->structTable} (level)");
|
||||
if($this->dbc->isError($r)) return $r;
|
||||
if ($this->dbc->isError($r)) {
|
||||
return $r;
|
||||
}
|
||||
$r = $this->dbc->query("
|
||||
CREATE UNIQUE INDEX {$this->structTable}_objid_level_idx
|
||||
ON {$this->structTable} (objid, level)
|
||||
");
|
||||
if($this->dbc->isError($r)) return $r;
|
||||
if ($this->dbc->isError($r)) {
|
||||
return $r;
|
||||
}
|
||||
$r = $this->dbc->query("
|
||||
CREATE UNIQUE INDEX {$this->structTable}_objid_parid_idx
|
||||
ON {$this->structTable} (objid, parid)
|
||||
");
|
||||
if($this->dbc->isError($r)) return $r;
|
||||
if ($this->dbc->isError($r)) {
|
||||
return $r;
|
||||
}
|
||||
|
||||
$oid = $this->dbc->nextId("{$this->treeTable}_id_seq");
|
||||
if($this->dbc->isError($oid)) return $oid;
|
||||
if ($this->dbc->isError($oid)) {
|
||||
return $oid;
|
||||
}
|
||||
$r = $this->dbc->query("
|
||||
INSERT INTO {$this->treeTable}
|
||||
(id, name, type)
|
||||
VALUES
|
||||
($oid, '{$this->rootNodeName}', 'RootNode')
|
||||
");
|
||||
if($this->dbc->isError($r)) return $r;
|
||||
if ($this->dbc->isError($r)) {
|
||||
return $r;
|
||||
}
|
||||
$r = $this->dbc->query("COMMIT");
|
||||
if(PEAR::isError($r)) return $r;
|
||||
}
|
||||
if (PEAR::isError($r)) {
|
||||
return $r;
|
||||
}
|
||||
} // fn install
|
||||
|
||||
|
||||
/**
|
||||
* Drop all tables and sequencies
|
||||
*
|
||||
* Drop all tables and sequences.
|
||||
* @return void
|
||||
*/
|
||||
function uninstall()
|
||||
{
|
||||
|
@ -674,31 +829,40 @@ class M2tree{
|
|||
$this->dbc->dropSequence("{$this->structTable}_id_seq");
|
||||
$this->dbc->query("DROP TABLE {$this->treeTable}");
|
||||
$this->dbc->dropSequence("{$this->treeTable}_id_seq");
|
||||
}
|
||||
} // fn uninstall
|
||||
|
||||
|
||||
/**
|
||||
* Uninstall and install
|
||||
*
|
||||
* Uninstall and install.
|
||||
* @return void
|
||||
*/
|
||||
function reinstall()
|
||||
{
|
||||
$this->uninstall();
|
||||
$this->install();
|
||||
}
|
||||
} // fn reinstall
|
||||
|
||||
|
||||
/**
|
||||
* Clean up tree - delete all except root node
|
||||
*
|
||||
* Clean up tree - delete all except the root node.
|
||||
* @return err/void
|
||||
*/
|
||||
function reset()
|
||||
{
|
||||
$rid = $this->getRootNode();
|
||||
if($this->dbc->isError($rid)) return $rid;
|
||||
if ($this->dbc->isError($rid)) {
|
||||
return $rid;
|
||||
}
|
||||
$r = $this->dbc->query("DELETE FROM {$this->structTable}");
|
||||
if($this->dbc->isError($r)) return $r;
|
||||
if ($this->dbc->isError($r)) {
|
||||
return $r;
|
||||
}
|
||||
$r = $this->dbc->query("DELETE FROM {$this->treeTable} WHERE id<>$rid");
|
||||
if($this->dbc->isError($r)) return $r;
|
||||
}
|
||||
if ($this->dbc->isError($r)) {
|
||||
return $r;
|
||||
}
|
||||
} // fn reset
|
||||
|
||||
|
||||
/**
|
||||
* Insert test data to the tree.
|
||||
|
@ -708,12 +872,13 @@ class M2tree{
|
|||
*/
|
||||
function test()
|
||||
{
|
||||
require_once"m2treeTest.php";
|
||||
require_once "m2treeTest.php";
|
||||
$mt = &new M2treeTest($this->dbc, $this->config);
|
||||
$r = $mt->_test();
|
||||
return $r;
|
||||
}
|
||||
|
||||
} // fn test
|
||||
|
||||
|
||||
/**
|
||||
* Insert test data to the tree.
|
||||
* Only for compatibility with previous mtree - will be removed.
|
||||
|
@ -734,6 +899,7 @@ class M2tree{
|
|||
$o['s2c'] = $this->addObj('Section c', 'Section', $o['i2']);
|
||||
$o['pb'] = $this->addObj('Publication B', 'Publication', $o['root']);
|
||||
$this->tdata['tree'] = $o;
|
||||
}
|
||||
}
|
||||
?>
|
||||
} // fn testData
|
||||
|
||||
} // class M2Tree
|
||||
?>
|
Loading…
Reference in New Issue