src/Educa/DSB/Client/Curriculum/Term/BaseTerm.php
<?php
/**
* @file
* Contains \Educa\DSB\Client\Curriculum\Term\BaseTerm.
*/
namespace Educa\DSB\Client\Curriculum\Term;
use Educa\DSB\Client\Utils;
class BaseTerm implements EditableTermInterface
{
/**
* The term's parent, if any.
*
* @var \Educa\DSB\Client\Curriculum\Term\EditableTermInterface
*/
protected $parent;
/**
* The term's "previous" sibling, if any.
*
* @var \Educa\DSB\Client\Curriculum\Term\EditableTermInterface
*/
protected $prevSibling;
/**
* The term's "next" sibling, if any.
*
* @var \Educa\DSB\Client\Curriculum\Term\EditableTermInterface
*/
protected $nextSibling;
/**
* The term's children, if any.
*
* @var array
*/
protected $children;
/**
* The term's type.
*
* @var string
*/
protected $type;
/**
* The term's identifier.
*
* @var string
*/
protected $id;
/**
* The term's name, if any.
*
* @var string
*/
protected $name;
public function __construct($type, $id, $name = null)
{
$this->setDescription($type, $id, $name);
$this->children = array();
}
/**
* {@inheritdoc}
*
* @codeCoverageIgnore
*/
public function describe()
{
$description = (object) array(
'type' => $this->type,
'id' => $this->id,
);
if (!empty($this->name)) {
$description->name = $this->name;
}
return $description;
}
/**
* Set the description information.
*
* Update the description information set in the constructor.
*
* @param string $type
* The term type.
* @param string $id
* The term identifier.
* @param array|object $name
* (optional) The term name, in LangString format.
*
* @return this
*/
public function setDescription($type, $id, $name = null)
{
$this->type = $type;
$this->id = $id;
$this->name = is_array($name) ? (object) $name : $name;
return $this;
}
/**
* {@inheritdoc}
*/
public function hasChildren()
{
return !empty($this->children);
}
/**
* {@inheritdoc}
*/
public function getChildren()
{
if ($this->hasChildren()) {
return $this->children;
} else {
throw new TermHasNoChildrenException("Term {$this->type}:{$this->id} has no children.");
}
}
/**
* {@inheritdoc}
*/
public function hasParent()
{
return isset($this->parent);
}
/**
* {@inheritdoc}
*/
public function getParent()
{
if ($this->hasParent()) {
return $this->parent;
} else {
throw new TermHasNoParentException("Term {$this->type}:{$this->id} has no parent.");
}
}
/**
* {@inheritdoc}
*/
public function isRoot()
{
return !$this->hasParent();
}
/**
* {@inheritdoc}
*/
public function getRoot()
{
if (!$this->isRoot()) {
return $this->getParent()->getRoot();
} else {
return $this;
}
}
/**
* {@inheritdoc}
*/
public function hasPrevSibling()
{
return isset($this->prevSibling);
}
/**
* {@inheritdoc}
*/
public function getPrevSibling()
{
if ($this->hasPrevSibling()) {
return $this->prevSibling;
} else {
throw new TermHasNoPrevSiblingException("Term {$this->type}:{$this->id} has no previous sibling.");
}
}
/**
* {@inheritdoc}
*/
public function hasNextSibling()
{
return isset($this->nextSibling);
}
/**
* {@inheritdoc}
*/
public function getNextSibling()
{
if ($this->hasNextSibling()) {
return $this->nextSibling;
} else {
throw new TermHasNoNextSiblingException("Term {$this->type}:{$this->id} has no next sibling.");
}
}
/**
* {@inheritdoc}
*/
public function asciiDump()
{
$recursiveStringify = function($items, $depth = 0) use(&$recursiveStringify) {
$string = '';
foreach ($items as $item) {
// Prepare the indentation, using whitespace. We use 4 spaces
// for each level of depth.
if ($depth) {
$string .= implode('', array_fill(0, $depth * 4, ' '));
}
$string .= ($depth ? '+' : '-') . "-- {$item}\n";
if ($item->hasChildren()) {
$string .= $recursiveStringify($item->getChildren(), $depth+1);
}
}
return $string;
};
return trim($recursiveStringify(array($this)));
}
/**
* {@inheritdoc}
*/
public function addChild(EditableTermInterface $term)
{
// Add the current term as the child's parent.
$term->setParent($this);
// Do we already have children? If so, we need to add the last one as
// the new one's "previous" sibling, and add the new one as the last
// one's "next" sibling.
if (!empty($this->children)) {
// Fetch the last one.
$lastTerm = $this->children[count($this->children)-1];
// Add the "next" sibling to it.
$lastTerm->setNextSibling($term);
// And add it as the "previous" sibling for the new one.
$term->setPrevSibling($lastTerm);
}
// Add it to our children list.
$this->children[] = $term;
// Support method chaining.
return $this;
}
/**
* {@inheritdoc}
*/
public function setParent(TermInterface $term)
{
$this->parent = $term;
// Support method chaining.
return $this;
}
/**
* {@inheritdoc}
*/
public function setPrevSibling(TermInterface $term)
{
$this->prevSibling = $term;
// Support method chaining.
return $this;
}
/**
* {@inheritdoc}
*/
public function setNextSibling(TermInterface $term)
{
$this->nextSibling = $term;
// Support method chaining.
return $this;
}
/**
* {@inheritdoc}
*/
public function findChildByIdentifier($id)
{
foreach ($this->getChildren() as $child) {
if ($child->describe()->id == $id) {
return $child;
}
}
}
/**
* {@inheritdoc}
*/
public function findChildByIdentifierRecursive($id)
{
foreach ($this->getChildren() as $child) {
if ($child->describe()->id == $id) {
return $child;
} elseif ($child->hasChildren()) {
if ($found = $child->findChildByIdentifierRecursive($id)) {
return $found;
}
}
}
}
/**
* {@inheritdoc}
*/
public function findChildrenByName($name)
{
$result = array();
foreach ($this->getChildren() as $child) {
if ($child->describe()->name == $name) {
$result[] = $child;
}
}
return !empty($result) ? $result : null;
}
/**
* {@inheritdoc}
*/
public function findChildrenByNameRecursive($name)
{
$result = array();
foreach ($this->getChildren() as $child) {
if ($child->describe()->name == $name) {
$result[] = $child;
} elseif ($child->hasChildren()) {
if ($found = $child->findChildrenByNameRecursive($name)) {
$result = array_merge($result, $found);
}
}
}
return !empty($result) ? $result : null;
}
/**
* {@inheritdoc}
*/
public function findChildrenByType($type)
{
$result = array();
foreach ($this->getChildren() as $child) {
if ($child->describe()->type == $type) {
$result[] = $child;
}
}
return !empty($result) ? $result : null;
}
/**
* {@inheritdoc}
*/
public function findChildrenByTypeRecursive($type)
{
$result = array();
foreach ($this->getChildren() as $child) {
if ($child->describe()->type == $type) {
$result[] = $child;
} elseif ($child->hasChildren()) {
if ($found = $child->findChildrenByTypeRecursive($type)) {
$result = array_merge($result, $found);
}
}
}
return !empty($result) ? $result : null;
}
public function __toString()
{
return "{$this->type}:{$this->id}";
}
}