Skip to content

Instantly share code, notes, and snippets.

@pkriete
Created February 27, 2009 19:19
Show Gist options
  • Save pkriete/71645 to your computer and use it in GitHub Desktop.
Save pkriete/71645 to your computer and use it in GitHub Desktop.
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
* Scribble
*
* @author Pascal Kriete
* @package Scribble
* @copyright Copyright (c) 2008, Pascal Kriete
*/
// ------------------------------------------------------------------------
/**
* Structure Helper Library
*
* @package Scribble
* @subpackage Libraries
* @category Structure
* @author Pascal Kriete
*/
class Structure {
var $_struct = array();
/**
* Constructor
*
* @access public
*/
function Structure($data)
{
$this->_struct = $data[0];
/* Json:
Structure = {
"4893j4f": {"title":"firsttitle"},
"485hfkd": {"title":"secondtitle"},
"kg84083": {"title":"thirdtitle","children": {
"fkjowi":{"title":"firstchild"},
"8j4tjd":{"title":"secondchild"}
}},
"9088jl": {"title":"fourthtitle"}}
$structure = array(
'4893j4f' => array('title' => 'firsttitle'),
'485hfkd' => array('title' => 'secondtitle'),
'kg84083' => array('title' => 'thirdtitle', 'children' => array(
'fkjowi' => array('title' => 'firstchild'),
'8j4tjd' => array('title' => 'secondchild')
)
),
'9088jl' => array('title' => 'fourthtitle')
);
$this->_struct = $structure;
$this->move_node('8j4tjd', '8j4tjd');
// $this->remove_node('kg84083');
// $this->add_node('abcdef', array('title' => 'NEW NODE!'), '9088jl');
echo '<pre>';
print_r($this->_struct);
echo '</pre>';
exit;
*/
}
// --------------------------------------------------------------------
/**
* Accessor
*
* @access public
*/
function get()
{
return $this->_struct;
}
// --------------------------------------------------------------------
/**
* Add a node to the current structure
*
* @access public
* @param string new node identifier
* @param mixed array of new node data
* @param string parent identifier
*/
function add_node($node_id, $node_data, $parent_id = FALSE)
{
// Parent given?
if ( ! $parent_id)
{
$this->_struct[$node_id] = $node_data;
}
else
{
// Get a path to the new parent
$path = $this->get_path($parent_id);
if ( ! $path)
{
return FALSE;
}
// And now a reference
$ref =& $this->get_reference($path);
$ref['children'][$node_id] = $node_data;
}
return TRUE;
}
// --------------------------------------------------------------------
/**
* Remove a node from the current structure
*
* @access public
* @param string node identifier
* @param bool delete child tree?
*/
function remove_node($node_id, $inherit_children = FALSE)
{
// Does the node even exist?
$path = $this->get_path($node_id);
if ( ! $path)
{
return FALSE;
}
// Get a reference to the parent
$parent =& $this->_struct;
// Not on the root node
if (count($path) > 1)
{
$tmp = array_slice($path, 0, -1, TRUE);
$parent =& $this->get_reference($tmp);
}
// Get a reference to the node
$ref =& $this->get_reference($path);
// If inherit_children is true - save them first
if ($inherit_children && isset($ref['children']))
{
foreach($ref['children'] as $key => &$value)
{
$parent[$key] = $value;
}
}
// And finally kill it
unset($parent[$node_id]);
return TRUE;
}
// --------------------------------------------------------------------
/**
* Move a node to a new position
*
* @access public
* @param string node identifier
* @param string new parent identifier (0 for root)
*/
function move_node($node_id, $new_parent_id)
{
// Nonsense
if ($node_id === $new_parent_id)
{
return TRUE;
}
// Does the node even exist?
$path = $this->get_path($node_id);
$p_path = $this->get_path($new_parent_id);
if ($new_parent_id == '0')
{
$p_path = array();
}
if ( ! $path OR ( ! $p_path AND $new_parent_id != '0'))
{
return FALSE;
}
// Get a reference to the parent(s)
$parent =& $this->_struct;
$new_parent =& $this->get_reference($p_path);
// Not attached to the root node
if (count($path) > 1)
{
$tmp = array_slice($path, 0, -1, TRUE);
$parent =& $this->get_reference($tmp);
}
if ($new_parent_id != '0')
{
// New parent needs a 'children' key
if ( ! isset($new_parent['children']))
{
$new_parent['children'] = array();
}
$new_parent =& $new_parent['children'];
}
// Get a reference to the node
$ref =& $this->get_reference($path);
// Move it to the new parent
$new_parent[$node_id] = $ref;
// And finally kill it
unset($parent[$node_id]);
return TRUE;
}
// --------------------------------------------------------------------
/**
* Get reference to the element at the end of the given path
*
* @access public
* @param array path array
* @return ref reference to the array segment
*/
function &get_reference($path)
{
$subject =& $this->_struct;
foreach($path as $node)
{
$subject =& $subject[$node];
}
return $subject;
}
// --------------------------------------------------------------------
/**
* Get path to the id
*
* @access public
* @param array array to search
* @param int id of the node to find
* @return array array of nodes in the path
*/
function get_path($id)
{
return $this->_get_path_callback($id, $this->_struct);
}
// --------------------------------------------------------------------
/**
* Recursive function that does the work for get_path
*
* @access private
* @param int id of the node to find
* @param array array to search
* @param array recursive path array
* @return array array of nodes in the path
*/
function _get_path_callback($needle, $haystack, $path = array())
{
foreach($haystack as $key => $val)
{
if($key == $needle)
{
$path[] = $key;
return $path;
}
else if ( is_array($val) && $sub_path = $this->_get_path_callback($needle, $val, $path))
{
$path = array_merge($path, Array($key), $sub_path);
return $path;
}
}
return FALSE;
}
}
// END Structure class
/* End of file structure.php */
/* Location: ./application/libraries/structure.php */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment