Instantly share code, notes, and snippets.
Last active
December 25, 2015 17:39
-
Save bendo01/7014197 to your computer and use it in GitHub Desktop.
trying to create tree behavior
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
CREATE TABLE app_system.app_menus | |
( | |
id bigserial NOT NULL, | |
name character varying(255) NOT NULL, | |
title character varying(255), | |
url character varying(255) NOT NULL, | |
enable boolean NOT NULL, | |
parent_id bigint, | |
lft bigint, | |
rght bigint, | |
created timestamp without time zone, | |
modified timestamp without time zone, | |
created_by bigint, | |
modified_by bigint, | |
CONSTRAINT app_menus_pkey PRIMARY KEY (id) | |
) | |
WITH ( | |
OIDS=FALSE | |
); | |
ALTER TABLE app_system.app_menus | |
OWNER TO bendo01; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace xPDPT\Models\AppSystem; | |
class AppMenus extends \Phalcon\Mvc\Model | |
{ | |
protected $node; | |
protected $properties; | |
protected $children = array(); | |
/** | |
* | |
* @var integer | |
*/ | |
protected $id; | |
/** | |
* | |
* @var string | |
*/ | |
protected $name; | |
/** | |
* | |
* @var string | |
*/ | |
protected $title; | |
/** | |
* | |
* @var string | |
*/ | |
protected $url; | |
/** | |
* | |
* @var string | |
*/ | |
protected $enable; | |
/** | |
* | |
* @var integer | |
*/ | |
protected $parentId; | |
/** | |
* | |
* @var integer | |
*/ | |
protected $lft; | |
/** | |
* | |
* @var integer | |
*/ | |
protected $rght; | |
/** | |
* | |
* @var string | |
*/ | |
protected $created; | |
/** | |
* | |
* @var string | |
*/ | |
protected $modified; | |
/** | |
* | |
* @var integer | |
*/ | |
protected $createdBy; | |
/** | |
* | |
* @var integer | |
*/ | |
protected $modifiedBy; | |
/** | |
* Method to set the value of field id | |
* | |
* @param integer $id | |
* @return $this | |
*/ | |
public function setId($id) | |
{ | |
$this->id = $id; | |
return $this; | |
} | |
/** | |
* Method to set the value of field name | |
* | |
* @param string $name | |
* @return $this | |
*/ | |
public function setName($name) | |
{ | |
$this->name = $name; | |
return $this; | |
} | |
/** | |
* Method to set the value of field title | |
* | |
* @param string $title | |
* @return $this | |
*/ | |
public function setTitle($title) | |
{ | |
$this->title = $title; | |
return $this; | |
} | |
/** | |
* Method to set the value of field url | |
* | |
* @param string $url | |
* @return $this | |
*/ | |
public function setUrl($url) | |
{ | |
$this->url = $url; | |
return $this; | |
} | |
/** | |
* Method to set the value of field enable | |
* | |
* @param string $enable | |
* @return $this | |
*/ | |
public function setEnable($enable) | |
{ | |
$this->enable = $enable; | |
return $this; | |
} | |
/** | |
* Method to set the value of field parent_id | |
* | |
* @param integer $parent_id | |
* @return $this | |
*/ | |
public function setParentId($parentId) | |
{ | |
$this->parentId = $parentId; | |
return $this; | |
} | |
/** | |
* Method to set the value of field lft | |
* | |
* @param integer $lft | |
* @return $this | |
*/ | |
public function setLft($lft) | |
{ | |
$this->lft = $lft; | |
return $this; | |
} | |
/** | |
* Method to set the value of field rght | |
* | |
* @param integer $rght | |
* @return $this | |
*/ | |
public function setRght($rght) | |
{ | |
$this->rght = $rght; | |
return $this; | |
} | |
/** | |
* Method to set the value of field created | |
* | |
* @param string $created | |
* @return $this | |
*/ | |
public function setCreated($created) | |
{ | |
$this->created = $created; | |
return $this; | |
} | |
/** | |
* Method to set the value of field modified | |
* | |
* @param string $modified | |
* @return $this | |
*/ | |
public function setModified($modified) | |
{ | |
$this->modified = $modified; | |
return $this; | |
} | |
/** | |
* Method to set the value of field created_by | |
* | |
* @param integer $created_by | |
* @return $this | |
*/ | |
public function setCreatedBy($createdBy) | |
{ | |
$this->createdBy = $createdBy; | |
return $this; | |
} | |
/** | |
* Method to set the value of field modified_by | |
* | |
* @param integer $modified_by | |
* @return $this | |
*/ | |
public function setModifiedBy($modifiedBy) | |
{ | |
$this->modified_by = $modified_by; | |
return $this; | |
} | |
/** | |
* Returns the value of field id | |
* | |
* @return integer | |
*/ | |
public function getId() | |
{ | |
return $this->id; | |
} | |
/** | |
* Returns the value of field name | |
* | |
* @return string | |
*/ | |
public function getName() | |
{ | |
return $this->name; | |
} | |
/** | |
* Returns the value of field title | |
* | |
* @return string | |
*/ | |
public function getTitle() | |
{ | |
return $this->title; | |
} | |
/** | |
* Returns the value of field url | |
* | |
* @return string | |
*/ | |
public function getUrl() | |
{ | |
return $this->url; | |
} | |
/** | |
* Returns the value of field enable | |
* | |
* @return string | |
*/ | |
public function getEnable() | |
{ | |
return $this->enable; | |
} | |
/** | |
* Returns the value of field parent_id | |
* | |
* @return integer | |
*/ | |
public function getParentId() | |
{ | |
return $this->parentId; | |
} | |
/** | |
* Returns the value of field lft | |
* | |
* @return integer | |
*/ | |
public function getLft() | |
{ | |
return $this->lft; | |
} | |
/** | |
* Returns the value of field rght | |
* | |
* @return integer | |
*/ | |
public function getRght() | |
{ | |
return $this->rght; | |
} | |
/** | |
* Returns the value of field created | |
* | |
* @return string | |
*/ | |
public function getCreated() | |
{ | |
return $this->created; | |
} | |
/** | |
* Returns the value of field modified | |
* | |
* @return string | |
*/ | |
public function getModified() | |
{ | |
return $this->modified; | |
} | |
/** | |
* Returns the value of field created_by | |
* | |
* @return integer | |
*/ | |
public function getCreatedBy() | |
{ | |
return $this->createdBy; | |
} | |
/** | |
* Returns the value of field modified_by | |
* | |
* @return integer | |
*/ | |
public function getModifiedBy() | |
{ | |
return $this->modifiedBy; | |
} | |
/** | |
* Initialize method for model. | |
*/ | |
public function initialize() | |
{ | |
$this->setSchema("app_system"); | |
} | |
public function getSource() | |
{ | |
return 'app_menus'; | |
} | |
/** | |
* Independent Column Mapping. | |
*/ | |
public function columnMap() { | |
return array( | |
'id' => 'id', | |
'name' => 'name', | |
'title' => 'title', | |
'url' => 'url', | |
'enable' => 'enable', | |
'parent_id' => 'parentId', | |
'lft' => 'lft', | |
'rght' => 'rght', | |
'created' => 'created', | |
'modified' => 'modified', | |
'created_by' => 'createdBy', | |
'modified_by' => 'modifiedBy' | |
); | |
} | |
public function startUp() | |
{ | |
$results = null; | |
if (!isset($this->properties)) { | |
$this->properties = $this->columnMap(); | |
} | |
if (!isset($this->node)) { | |
$results = $this->find( | |
array( | |
'order' => 'lft ASC' | |
) | |
); | |
$this->node = array(); | |
} | |
if (!empty($results)) { | |
foreach ($results as $result) { | |
$this->node[$result->id] = $result; | |
} | |
} | |
} | |
public static function cmpLeft($a, $b) | |
{ | |
return $a->lft > $b->lft; | |
} | |
public function reOrderLookUpArray() | |
{ | |
//usort($this->node, array('ModelBaseName','cmpLeft')); | |
usort($this->node, array($this,"cmpLeft")); | |
} | |
public function getChildren($id = null, $childrenOnly = false, $typeObject = true){ | |
$this->startUp(); | |
$parentHasIn = false; | |
$arrKeys = $this->columnMap(); | |
$returnArray = array(); | |
$children = array(); | |
// if parent node exists in the lookup array OR we're looking for the topmost nodes | |
if (!empty($id) && !empty($this->node[$id])) { | |
foreach ($this->node as $node) { | |
// node's "left" is higher than parent node's "left" | |
// node's "left" is smaller than parent node's "right" | |
if (($node->parentId == $id) && ($this->node[$id]->lft < $node->lft) && ($node->lft < $this->node[$id]->rght)) { | |
if (!$parentHasIn && !$childrenOnly) { | |
$children[] = $this->node[$id]; | |
$parentHasIn = true; | |
} | |
$children[] = $node; | |
} | |
} | |
} | |
$returnArray = $children; | |
if(!$typeObject) { | |
$returnArray = array(); | |
if (!empty($children)) { | |
$i=0; | |
foreach ($children as $child) { | |
foreach ($arrKeys as $key => $value) { | |
$returnArray[$i][$value] = $child->{$value}; | |
} | |
$i++; | |
} | |
} | |
} | |
return $returnArray; | |
} | |
public function getChildrenBasedOnParentId($parentId = null) | |
{ | |
$arrKeys = $this->columnMap(); | |
$returnArray = array(); | |
$children = array(); | |
$this->node = $this->find( | |
array( | |
'conditions' => 'parentId is null' | |
) | |
); | |
if (!empty($parentId)) { | |
$this->node = $this->find( | |
array( | |
'conditions' => 'parentId = '.$parentId | |
) | |
); | |
} | |
if (!empty($this->node)) { | |
foreach ($this->node as $node) { | |
// node's "left" is higher than parent node's "left" | |
// node's "left" is smaller than parent node's "right" | |
if (($node->parentId == $parentId)) { | |
$children[] = $node; | |
} | |
} | |
} | |
if (!empty($children)) { | |
$i=0; | |
foreach ($children as $child) { | |
foreach ($arrKeys as $key => $value) { | |
$returnArray[$i][$value] = $child->{$value}; | |
} | |
$i++; | |
} | |
} | |
return $returnArray; | |
} | |
public function getChildrenCount($id = null) | |
{ | |
$result = 0; | |
$this->startUp(); | |
if (!empty($this->node) && !empty($id)) { | |
$result = 0; | |
foreach ($this->node as $node) { | |
if ($node->parentId == $id) { | |
$result++; | |
} | |
} | |
} | |
return $result; | |
} | |
public function getDescendantsCount($id = null) | |
{ | |
$result = 0; | |
$this->startUp(); | |
if (!empty($this->node) && !empty($id) && !empty($this->node[$id])) { | |
$result = ($this->node[$id]->rght - $this->node[$id]->lft - 1) / 2; | |
} | |
return $result; | |
} | |
public function getParent($id = null) | |
{ | |
$node = null; | |
if (!empty($id)) { | |
$result = $this->findFirst($id); | |
$node = $this->findFirst($result->parentId); | |
} | |
return $node; | |
} | |
public function getPath($id = null) | |
{ | |
$parents = array(); | |
$this->startUp(); | |
if (!empty($id) && !empty($this->node[$id])) { | |
foreach ($this->node as $node) { | |
if( ($node->lft < $this->node[$id]->lft) && ($node->rght > $this->node[$id]->rght)) { | |
$parents[] = $node; | |
} | |
} | |
} | |
return $parents; | |
} | |
public function generateSeparator($name = null, $count = 0, $separator = '-') | |
{ | |
$returnStr = $name; | |
if(!empty($name) && $count > 0) { | |
$tempStr = ''; | |
for($i=0; $i<$count; $i++) { | |
$tempStr.=$separator; | |
} | |
$returnStr = $tempStr.$name; | |
} | |
return $returnStr; | |
} | |
public function getSelectables($separator = '-') | |
{ | |
$this->startUp(); | |
$returnArray = array(); | |
foreach ($this->node as $node) { | |
$returnArray[] = $this->generateSeparator($node->name, count($this->getPath($node->id)), $separator); | |
} | |
return $returnArray; | |
} | |
public function getAllRoot($typeObject = true) | |
{ | |
$returnArray = null; | |
$arrKeys = $this->columnMap(); | |
$rootArr = $this->find( | |
array( | |
'conditions' => 'parentId is null', | |
'order' => 'lft ASC' | |
) | |
); | |
$returnArray = $rootArr; | |
if(!$typeObject) { | |
$returnArray = null; | |
if (!empty($rootArr)) { | |
$i=0; | |
foreach ($rootArr as $root) { | |
foreach ($arrKeys as $key => $value) { | |
$returnArray[$i][$value] = $root->{$value}; | |
} | |
$i++; | |
} | |
} | |
} | |
return $returnArray; | |
} | |
public function getSubtree($childrenData = array()) | |
{ | |
if(!empty($childrenData)) { | |
$i = 0; | |
foreach ($childrenData as $childData) { | |
if ($this->getChildrenCount($childData['id']) > 0 ) { | |
$childrenData[$i]['children'] = $this->getChildren($childData['id'], true, false); | |
$childrenData[$i]['children'] = $this->getSubtree($childrenData[$i]['children']); | |
} | |
$i++; | |
} | |
} | |
return $childrenData; | |
} | |
public function getTree() | |
{ | |
$roots = $this->getAllRoot(false); | |
if (!empty($roots)) { | |
$i=0; | |
foreach ($roots as $root) { | |
if ($this->getChildrenCount($root['id']) > 0 ) { | |
$roots[$i]['children'] = $this->getChildren($root['id'], true, false); | |
$roots[$i]['children'] = $this->getSubtree($roots[$i]['children']); | |
} | |
$i++; | |
} | |
} | |
return $trees; | |
} | |
public function getChildForRebuildTree($parentId = null) | |
{ | |
$returnArray = null; | |
$arrKeys = $this->columnMap(); | |
$returnArray = array(); | |
$children = null; | |
if (!empty($parentId)) { | |
$children = $this->find( | |
array( | |
'conditions' => 'parentId = '.$parentId, | |
'order' => 'id' | |
) | |
); | |
$returnArray = array(); | |
if (!empty($children)) { | |
$i=0; | |
foreach ($children as $child) { | |
foreach ($arrKeys as $key => $value) { | |
$returnArray[$i][$value] = $child->{$value}; | |
} | |
$i++; | |
} | |
} | |
} | |
else { | |
$children = $this->find( | |
array( | |
'conditions' => 'parentId is null', | |
'order' => 'id' | |
) | |
); | |
$returnArray = array(); | |
if (!empty($children)) { | |
$i=0; | |
foreach ($children as $child) { | |
foreach ($arrKeys as $key => $value) { | |
$returnArray[$i][$value] = $child->{$value}; | |
} | |
$i++; | |
} | |
} | |
} | |
/* | |
echo '<pre>'; | |
print_r($returnArray); | |
echo '</pre>'; | |
exit; | |
*/ | |
return $returnArray; | |
} | |
public function hasChildrenForRebuildTree($parentId = null) | |
{ | |
$returnBoolean = false; | |
$count = count($this->getChildForRebuildTree($parentId)); | |
if ($count > 0) { | |
$returnBoolean = true; | |
} | |
return $returnBoolean; | |
} | |
public function rebuildTree($counter = 1, $parentId = null) | |
{ | |
$limit = 100; | |
$children = $this->getChildForRebuildTree($parentId); | |
$hasChildren = (bool)$children; | |
if ($parentId !== null) { | |
if ($hasChildren) { | |
$this->getDi()->get('db')->query('UPDATE '.$this->getSchema().'.'.$this->getSource().' SET lft = '.$counter.' WHERE id = '.$parentId); | |
$counter++; | |
} | |
else { | |
$this->getDi()->get('db')->query('UPDATE '.$this->getSchema().'.'.$this->getSource().' SET lft = '.$counter.', rght = '.($counter+1).' WHERE id = '.$parentId); | |
$counter += 2; | |
} | |
} | |
while ($children) { | |
foreach ($children as $row) { | |
$counter = $this->rebuildTree($counter, $row['id']); | |
} | |
if (count($children) !== $limit) { | |
break; | |
} | |
$children = $this->getChildForRebuildTree($parentId); | |
} | |
if ($parentId !== null && $hasChildren) { | |
$this->getDi()->get('db')->query('UPDATE '.$this->getSchema().'.'.$this->getSource().' SET rght = '.$counter.' WHERE id = '.$parentId); | |
$counter++; | |
} | |
return $counter; | |
} | |
public function addNewNode($data = null) | |
{ | |
//check if node is root (parentId == null) | |
//check if node is child but parentId currently has no children | |
//check if node is child and parentId currently has children | |
} | |
public function editNode() | |
{ | |
//check if update only data and not parentId, left, and right | |
//check if update include change on parentId | |
} | |
public function deleteNode() | |
{ | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment