Source Code
PHP
How it works
Requests are sent to the file orgInterface.php, which creates an instance of the class OrgChart held in the class file OrgChart.class. The data is passed into the OrgChart object in the form of an array containing the parents name and n number of children.
orgInterface.php
The data posted to the php file is first turned into a string then any html mark-up is removed using first explode and then urldecode functions.
Part of orgInterface.php showing capture of POST data:
list ($data['parents'], $data['children']) = explode (";", $posted);
The data then passes through the createFamilyArray function where it is converted into an array ready to be passed to the instance of OrgChart class where the tree is created.
Part of orgInterface.php showing createFamilyArray() function:
function createFamilyArray($data)
{
// Initialise the return array
$familyArray = "";
// Add parents to the return array
$familyArray['parents'] = $data['parents'];
// Isolate the children and add to a child array
$childArr = explode (",", $data['children']);
// Reset count variable
$childCount = 0;
// Loop through children adding to the return array + counting
foreach ($childArr as $child)
{
$familyArray['children'][] = $child;
$childCount++;
}
// Add the child count to the return array
$familyArray['childCount'] = $childCount;
return $familyArray;
}
The formatted HTML, held in the array that is returned from the OrgChart object is then marked up into a table cell (to make it easier to centre and highlight), in the displayChart() function.
Part of orgInterface.php showing the displayChart() function:
function displayChart($chart)
{
$displayString = "<table style=\"background: #dded86; ";
$displayString .= "padding-top: 5px; padding-bottom: 5px; padding-left: 20px; ";
$displayString .= "padding-right: 20px; margin: auto;\"><tr><td><pre>";
for ($x=1; $x<6; $x++)
{
$displayString = $displayString . $chart[$x] . "<br>";
}
$displayString = $displayString . "</pre> </td> </tr> </table>";
echo $displayString;
}
The full source code for orgInterface.php:
<?php
require_once "OrgChart.class";
function createFamilyArray($data)
{
// Initialise the return array
$familyArray = "";
// Add parents to the return array
$familyArray['parents'] = $data['parents'];
// Isolate the children and add to a child array
$childArr = explode (",", $data['children']);
// Reset count variable
$childCount = 0;
// Loop through children adding to the return array + counting
foreach ($childArr as $child)
{
$familyArray['children'][] = $child;
$childCount++;
}
// Add the child count to the return array
$familyArray['childCount'] = $childCount;
return $familyArray;
}
function displayChart($chart)
{
$displayString = "<table style=\"background: #dded86; ";
$displayString .= "padding-top: 5px; padding-bottom: 5px; padding-left: 20px; ";
$displayString .= "padding-right: 20px; margin: auto;\"><tr><td><pre>";
for ($x=1; $x<6; $x++)
{
$displayString = $displayString . $chart[$x] . "<br>";
}
$displayString = $displayString . "</pre> </td> </tr> </table>";
echo $displayString;
}
// Get just the data posted
$posted = urldecode ( implode ( file ('php://input')));
// Put the data into an array
list ($data['parents'], $data['children']) = explode (";", $posted);
// Put the data into a format that can be used by the application
$familyArray = createFamilyArray($data);
// Create instance of OrgChart
$chart = new OrgChart($familyArray);
// Call method to create the chart and pass to the display function
displayChart($chart->createOrg());
?>
OrgChart.class
On creation the constructor function assigns all values passed to the object into the class variables.
Part of OrgChart.class showing __construct() function and class variables:
private $childCount;
private $parents;
private $children;
function __construct ($family)
{
// Assign class variables
$this->childCount = $family['childCount'];
$this->parents = $family['parents'];
$this->children = $family['children'];
}
When the createOrg() method is called the function calculates what character length to use for the names using the function getLeafLenght(), which returns an un-even length to allow for easier centring.
Part of OrgChart.class showing the function getLeafLength():
function getLeafLength()
{
// Loops through all names and finds common length
// Establish length of parent row (trimmed of spaces at either end)
$leafLen = strlen (trim($this->parents));
// Loop through each child in turn and increase the leaf len size if found bigger
foreach ($this->children as $child)
{
if(strlen(trim($child)) > $leafLen)
{
$leafLen = strlen($child);
}
}
// Add one if even number to help with mid-points
return makeOdd($leafLen);
}
The character length of the complete chart is established by adding each of the children(s) character lengths together and adding three characters for each spacing required between children. The longest row (parent or child), becomes the length of the chart. Padding for the shorter rows is calculated.
The resulting chart is held in an array called $orgLine containing six elements, each holding the lines forming the chart.
Part of OrgChart.class showing padding of strings:
// Add to org chart line adding any padding where required
$orgLine[0] = $parentPad . $parents[0]; // Initial connector |
$orgLine[1] = $parentPad . $parents[1]; // Names
$orgLine[2] = $parentPad . $parents[0]; // Another connector | leading to branches
Each of the children (leafs) are added together and their joining branches (twigs) are added together into strings before being added to the main $orgLine array.
Part of OrgChart.class showing creation of child strings:
// Loop through each child individually adding to temporary strings ($childLine & $connectors)
foreach ($this->children as $child)
{
$branch = $this->makeBranch($child, $leafLen);
$connectors .= $branch[0] . " ";
$childLine .= $branch[1] . " ";
}
// Add strings to the org chart lines leaving space for the line for branches ($orgLine[3])
$orgLine[4] = $connectors;
$orgLine[5] = $childLine;
The branches (containing twigs and leafs) are made using the makeBranch() function, which centres the name and adds a twig connector and padding to make up a block of characters.
Part of OrgChart.class showing the makeBranch() function:
function makeBranch($name, $leafLen)
{
// Returns array formated and ready to add to chart and or row containing other names
$name = $this->padLeaf($name, $leafLen);
$pLen = $leafLen;
// Find middle
$pMid = round($pLen / 2);
// Adjust if rounding up
if (($pMid * 2) != $pLen)
{
$pMid--;
$retString[] = $this->addChars(" ", $pMid) . "|" . $this->addChars(" ", $pMid);
}
else
{
$retString[] = $this->addChars(" ", $pMid) . "|" . $this->addChars(" ", $pMid -1);
}
$retString[] = $name;
return $retString;
}
The padding is achieved using the addChars()function, which adds multiples of a character to a return string.
Part of OrgChart.class showing the addChars()function:
function addChars($char, $no)
{
// Returns a string of characters ($char) determined in length by $no
$retString = "";
for ($x = 0; $x < $no; $x++)
{
$retString = $retString . $char;
}
return $retString;
}
The final part of creating the chart is adding the main branch across the middle of the chart and returning the completed chart in the array to the requester.
Part of OrgChart.class showing the creation of connecters:
// $noBranches holds how many connectors (-+-) will be needed in the org chart
$noBranches = $this->childCount + 1;
// Branches are added to the missing line using the parent and child connector lines
$orgLine[3] = $this->addBranches($orgLine[2], $orgLine[4], $orgLen, $noBranches);
return $orgLine;
The number of connectors required is calculated; one for each child and one for the parents. This is passed with the two array lines containing the parents and children connector (twigs) to the addBranches() function.
Part of OrgChart.class showing the function addBranches():
function addBranches($top, $bottom, $length, $branches)
{
// Loops through rows (top and bottom) and looks for (-+-) and adds the dashes (-) between
// Reset local variables
$crossCount = 0;
$retStr = "";
// Loop through length of lines
for ($x=0; $x<$length; $x++)
{
// Looks for connectors | on top or bottom
if (($top[$x] == '|') || ($bottom[$x] == '|'))
{
// Tests to see if both top and bottom at same place
if (($top[$x] == '|') && ($bottom[$x] == '|'))
{
// Removes one branch that are being searched for
$branches--;
}
// Add a join (-+-)
$retStr = $retStr . "+";
// Increment count of found joins
$crossCount++;
}
else
{
// Check to see if at the start of end of the row
if (($crossCount < 1) || ($crossCount == $branches))
{
// Start or end so add padding
$retStr = $retStr . " ";
}
else
{
// Middle to add dashes
$retStr = $retStr . "-";
}
}
}
The full source code for OrgChart.class:
<?php
require_once "supportFunctions.php";
class OrgChart
{
private $childCount;
private $parents;
private $children;
function __construct ($family)
{
// Assign class variables
$this->childCount = $family['childCount'];
$this->parents = $family['parents'];
$this->children = $family['children'];
}
function createOrg ()
{
$orgLine = "";
$childLine = "";
$connectors = "";
// Establish how many characters are needed to fit all names on chart
$leafLen = $this->getLeafLength();
// Add up children and compare with parents to get length of tree
// Including 3 chars padding between each child
$childrenLen = (($this->childCount -1) * 3) + ($leafLen * $this->childCount);
// Ensure that the length of tree is an odd number to find a mid point
$orgLen = makeOdd($childrenLen);
// Calculate the padding needed for parents and create pad
$padSize = (($orgLen - 1) / 2) - roundDown($leafLen /2);
$parentPad = $this->addChars(" ", $padSize);
// Find mid point of chart
$midLen = makeOdd($orgLen / 2);
// create five array elements containing strings representing rows in completed org chart
// Create the parent lines
$parents = $this->makeBranch($this->parents, $leafLen);
// Add to org chart line adding any padding where required
$orgLine[0] = $parentPad . $parents[0]; // Initial connector |
$orgLine[1] = $parentPad . $parents[1]; // Names
$orgLine[2] = $parentPad . $parents[0]; // Another connector | leading to branches
// Loop through each child individually adding to temporary strings ($childLine & $connectors)
foreach ($this->children as $child)
{
$branch = $this->makeBranch($child, $leafLen);
$connectors .= $branch[0] . " ";
$childLine .= $branch[1] . " ";
}
// Add strings to the org chart lines leaving space for the line for branches ($orgLine[3])
$orgLine[4] = $connectors;
$orgLine[5] = $childLine;
// $noBranches holds how many connectors (-+-) will be needed in the org chart
$noBranches = $this->childCount + 1;
// Branches are added to the missing line using the parent and child connector lines
$orgLine[3] = $this->addBranches($orgLine[2], $orgLine[4], $orgLen, $noBranches);
return $orgLine;
}
function getLeafLength()
{
// Loops through all names and finds common length
// Establish length of parent row (trimmed of spaces at either end)
$leafLen = strlen (trim($this->parents));
// Loop through each child in turn and increase the leaf len size if found bigger
foreach ($this->children as $child)
{
if(strlen(trim($child)) > $leafLen)
{
$leafLen = strlen($child);
}
}
// Add one if even number to help with mid-points
return makeOdd($leafLen);
}
function addChars($char, $no)
{
// Returns a string of characters ($char) determined in length by $no
$retString = "";
for ($x = 0; $x < $no; $x++)
{
$retString = $retString . $char;
}
return $retString;
}
function makeBranch($name, $leafLen)
{
// Returns array formated and ready to add to chart and or row containing other names
$name = $this->padLeaf($name, $leafLen);
$pLen = $leafLen;
// Find middle
$pMid = round($pLen / 2);
// Adjust if rounding up
if (($pMid * 2) != $pLen)
{
$pMid--;
$retString[] = $this->addChars(" ", $pMid) . "|" . $this->addChars(" ", $pMid);
}
else
{
$retString[] = $this->addChars(" ", $pMid) . "|" . $this->addChars(" ", $pMid -1);
}
$retString[] = $name;
return $retString;
}
function padLeaf($name, $leafLen)
{
// Adds spaces before and after text to make all leaf objects same size
// Establish current length of name
$len = strlen($name);
// Calculate how many characters need to be added
$pad = ($leafLen - $len) /2;
// Add characters at front of name
$name = $this->addChars(" ", $pad) . $name;
// Add characters at end of name subtracting length of front padded name from leaf length
$name = $name . $this->addChars(" ", $leafLen - strlen($name));
return $name;
}
function addBranches($top, $bottom, $length, $branches)
{
// Loops through rows (top and bottom) and looks for (-+-) and adds the dashes (-) between
// Reset local variables
$crossCount = 0;
$retStr = "";
// Loop through length of lines
for ($x=0; $x<$length; $x++)
{
// Looks for connectors | on top or bottom
if (($top[$x] == '|') || ($bottom[$x] == '|'))
{
// Tests to see if both top and bottom at same place
if (($top[$x] == '|') && ($bottom[$x] == '|'))
{
// Removes one branch that are being searched for
$branches--;
}
// Add a join (-+-)
$retStr = $retStr . "+";
// Increment count of found joins
$crossCount++;
}
else
{
// Check to see if at the start of end of the row
if (($crossCount < 1) || ($crossCount == $branches))
{
// Start or end so add padding
$retStr = $retStr . " ";
}
else
{
// Middle to add dashes
$retStr = $retStr . "-";
}
}
}
return $retStr;
}
}
?>


