* @version 0.0.0
* @copyright Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2017 Core Developer Team
* @license GNU GPL 3.0 or any newer version
* @link http://www.shipsimu.org
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
class BaseHelper extends BaseFrameworkSystem {
/**
* Instance to the class which provides field values
*/
private $valueInstance = NULL;
/**
* Extra instance to the class which provides field values
*/
private $extraInstance = NULL;
/**
* Rendered content created by the helper class
*/
private $content = '';
/**
* Array with groups
*/
private $groups = array();
/**
* Array with sub group
*/
private $subGroups = array();
/**
* Previously opened group
*/
private $previousGroupId = '';
/**
* Previously opened sub group
*/
private $previousSubGroupId = '';
/**
* Total counter for groups and sub groups
*/
private $totalCounter = 0;
// Exception constants
const EXCEPTION_GROUP_NOT_OPENED = 0x1e3;
const EXCEPTION_GROUP_ALREADY_FOUND = 0x1e4;
const EXCEPTION_SUB_GROUP_ALREADY_FOUND = 0x1e5;
const EXCEPTION_NO_PREVIOUS_SUB_GROUP_OPENED = 0x1e6;
const EXCEPTION_NO_PREVIOUS_GROUP_OPENED = 0x1e7;
/**
* Protected constructor
*
* @param $className Real name of the class
* @return void
*/
protected function __construct ($className) {
// Call parent constructor
parent::__construct($className);
}
/**
* Adds content directly
*
* @param $newContent New content to add
* @return void
*/
protected final function addContent ($newContent) {
$this->content .= (string) trim($newContent) . PHP_EOL;
}
/**
* Add header content to the helper
*
* @param $content Content to to the base
* @return void
*/
protected function addHeaderContent ($content) {
// Add the header content
$this->groups['header']['content'] = (string) trim($content);
}
/**
* Add footer content to the helper
*
* @param $content Content to to the base
* @return void
*/
protected function addFooterContent ($content) {
// Add the footer content
$this->groups['footer']['content'] = (string) trim($content);
}
/**
* Adds content to the previously opened group or sub group. If a sub group
* was found it will be taken. If no group/sub group is opened at the moment
* the code will be passed to addContent().
*
* @param $newContent New content to add
* @return void
*/
protected final function addContentToPreviousGroup ($newContent) {
// Check for sub/group
if ($this->ifSubGroupOpenedPreviously()) {
// Get sub group id
$subGroupId = $this->getPreviousSubGroupId();
// Add the content
$this->subGroups[$subGroupId]['content'] .= $newContent;
} elseif ($this->ifGroupOpenedPreviously()) {
// Get group id
$groupId = $this->getPreviousGroupId();
// Add the content
$this->groups[$groupId]['content'] .= $newContent;
} else {
// Add it directly
$this->addContent($newContent);
}
}
/**
* Getter for content
*
* @return $content The rendered content by this helper
*/
protected final function getContent () {
return $this->content;
}
/**
* Public setter for extra instance
*
* @param $extraInstance An extra instance of FrameworkInterface to set
* @return void
*/
public final function setExtraInstance (FrameworkInterface $extraInstance) {
$this->extraInstance = $extraInstance;
}
/**
* Assigns a field from the value instance with a template variable
*
* @param $fieldName Name of the field to assign
* @return void
*/
public function assignField ($fieldName) {
// Get the value from value instance
$fieldValue = $this->getValueField($fieldName);
// Assign it with a template variable
$this->getTemplateInstance()->assignVariable('block_' . $fieldName, $fieldValue);
}
/**
* Assigns a field from the value instance with a template variable but
* parses its content through a given filter method of the value instance
*
* @param $fieldName Name of the field to assign
* @param $filterMethod Method name to call of the value instance
* @return void
* @todo Rewrite this method using a helper class for filtering data
*/
public function assignFieldWithFilter ($fieldName, $filterMethod) {
// Get the value
$fieldValue = $this->getValueField($fieldName);
//* DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput($fieldName.'='.$fieldValue);
// Now filter it through the value through the filter method
$filteredValue = call_user_func_array(array($this, 'doFilter' . self::convertToClassName($filterMethod)), array($fieldValue));
// Assign it with a template variable
$this->getTemplateInstance()->assignVariable('block_' . $fieldName, $filteredValue);
}
/**
* Pre-fetches field default values from the given registry key instance into this class
*
* @param $registryKey Registry key which holds an object with values
* @param $extraKey Extra value instance key used if registryKey is null
* @return void
* @throws NullPointerException If recovery of requested value instance failed
*/
public function prefetchValueInstance ($registryKey, $extraKey = NULL) {
//* DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('O:'.$registryKey.'/'.$extraKey);
try {
// Get the required instance
$this->valueInstance = Registry::getRegistry()->getInstance($registryKey);
} catch (NullPointerException $e) {
// Not set in registry
// @TODO Try to log it here
//* DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput($registryKey.'=NULL!');
}
// Shall we get an extra instance?
if (!is_null($extraKey)) {
try {
// Get the extra instance.
$this->extraInstance = Registry::getRegistry()->getInstance($extraKey);
} catch (NullPointerException $e) {
// Try to create it
$this->extraInstance = ObjectFactory::createObjectByConfiguredName($extraKey . '_class', array($this->valueInstance));
}
//* DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput($extraKey.'='.$this->extraInstance.' - EXTRA!');
} // END - if
// Is the value instance valid?
if (is_null($this->valueInstance)) {
// Get the requested instance
$this->valueInstance = ObjectFactory::createObjectByConfiguredName($registryKey . '_class', array($this->extraInstance));
} // END - if
}
/**
* Opens a helper group with given group id and content or throws an
* exception if that group is already found regardless if it is open or
* closed.
*
* @param $groupId Group id to open
* @param $content Initial content to add to the group
* @param $tag HTML tag used to open this group
* @return void
* @throws HelperGroupAlreadyCreatedException If the group was already created before
*/
protected function openGroupByIdContent ($groupId, $content, $tag) {
//* DEBUG: */ echo "OPEN:groupId={$groupId},content=
".htmlentities($content)."
\n";
// Is the group already there?
if (isset($this->groups[$groupId])) {
// Then throw an exception here
throw new HelperGroupAlreadyCreatedException(array($this, $groupId), self::EXCEPTION_GROUP_ALREADY_FOUND);
} // END - if
// Count one up
$this->totalCounter++;
// Add the group to the stack
$this->groups[$this->totalCounter] = $groupId;
$this->groups[$groupId]['opened'] = true;
$this->groups[$groupId]['content'] = sprintf(
'%s' . PHP_EOL,
$groupId,
strlen($content),
$tag,
$content
);
$this->groups[$groupId]['tag'] = $tag;
// Mark this group as previously opened
$this->setPreviousGroupId($groupId);
}
/**
* Closes the previously opened group by added given content to it or
* throws an exception if no previous group was opened
*
* @param $content Content for previously opened group, or empty to use tag of opener
* @return void
* @throws HelperNoPreviousOpenedGroupException If no previously opened group was found
*/
public function closePreviousGroupByContent ($content = '') {
// Check if any sub group was opened before
if ($this->ifSubGroupOpenedPreviously()) {
// Close it automatically
$this->closePreviousSubGroupByContent();
} // END - if
// Check if any group was opened before
if ($this->ifGroupOpenedPreviously() === false) {
// Then throw an exception
throw new HelperNoPreviousOpenedGroupException(array($this, $content), self::EXCEPTION_NO_PREVIOUS_SUB_GROUP_OPENED);
} // END - if
// Get previous group
$groupId = $this->getPreviousGroupId();
// Is the content empty?
if ((empty($content)) && (!empty($this->groups[$groupId]['tag']))) {
// Get it from opener
$content = sprintf(
"%s>",
$groupId,
$this->groups[$groupId]['tag']
);
} // END - if
// Add content to it and mark it as closed
$this->groups[$groupId]['content'] .= sprintf(
"%s\n",
$groupId,
strlen($content),
$this->groups[$groupId]['tag'],
$content
);
$this->groups[$groupId]['opened'] = false;
// Mark previous group as closed
$this->setPreviousGroupId('');
//* DEBUG: */ echo "CLOSE:groupId={$groupId}
\n";
}
/**
* Opens a helper sub group with given group id and content or throws an
* exception if that sub group is already found regardless if it is open or
* closed.
*
* @param $subGroupId Sub group id to open
* @param $content Initial content to add to the sub group
* @param $tag HTML tag used to open this group
* @return void
* @throws HelperSubGroupAlreadyCreatedException If the sub group was already created before
*/
protected function openSubGroupByIdContent ($subGroupId, $content, $tag) {
//* DEBUG: */ echo "OPEN:subGroupId={$subGroupId},content=".htmlentities($content)."
\n";
// Is the group already there?
if (isset($this->subGroups[$subGroupId])) {
// Then throw an exception here
throw new HelperSubGroupAlreadyCreatedException(array($this, $subGroupId), self::EXCEPTION_SUB_GROUP_ALREADY_FOUND);
} // END - if
// Count one up
$this->totalCounter++;
// Add the group to the stack
$this->subGroups[$this->totalCounter] = $subGroupId;
$this->subGroups[$subGroupId]['opened'] = true;
$this->subGroups[$subGroupId]['content'] = sprintf("%s\n", $subGroupId, strlen($content), $tag, $content);
$this->subGroups[$subGroupId]['tag'] = $tag;
// Mark this group as previously opened
$this->setPreviousSubGroupId($subGroupId);
}
/**
* Closes the previously opened sub group by added given content to it or
* throws an exception if no previous sub group was opened
*
* @param $content Content for previously opened sub group, or leave empty to use div/span of openener
* @return void
* @throws HelperNoPreviousOpenedSubGroupException If no previously opened sub group was found
*/
public function closePreviousSubGroupByContent ($content = '') {
// Check if any sub group was opened before
if ($this->ifSubGroupOpenedPreviously() === false) {
// Then throw an exception
throw new HelperNoPreviousOpenedSubGroupException(array($this, $content), self::EXCEPTION_NO_PREVIOUS_SUB_GROUP_OPENED);
} // END - if
// Get previous sub group
$subGroupId = $this->getPreviousSubGroupId();
// Is the content empty?
if ((empty($content)) && (!empty($this->subGroups[$subGroupId]['tag']))) {
// Get it from opener
$content = sprintf('%s>', $subGroupId, $this->subGroups[$subGroupId]['tag']);
} // END - if
// Add content to it and mark it as closed
$this->subGroups[$subGroupId]['content'] .= sprintf('%s' . PHP_EOL, $subGroupId, strlen($content), $this->subGroups[$subGroupId]['tag'], $content);
$this->subGroups[$subGroupId]['opened'] = false
;
// Mark previous sub group as closed
$this->setPreviousSubGroupId('');
//* DEBUG: */ echo "CLOSE:subGroupId={$subGroupId}
\n";
}
/**
* Renders all group and sub group in their order
*
* @return $content Rendered HTML content
*/
public function renderContent () {
// Initialize content
$content = '';
// Is header content there?
if (isset($this->groups['header'])) {
// Then add it
$content .= $this->groups['header']['content'] . PHP_EOL;
} // END - if
// Initiate content
$content .= $this->getContent();
// Now "walk" through all groups and sub-groups
for ($idx = 1; $idx <= $this->totalCounter; $idx++) {
// Is this a sub/group and is it closed?
if ((isset($this->groups[$idx])) && ($this->groups[$this->groups[$idx]]['opened'] === false)) {
// Then add it's content
$groupContent = trim($this->groups[$this->groups[$idx]]['content']);
//* DEBUG: */ echo "group={$this->groups[$idx]},content=".htmlentities($groupContent)."
\n";
$content .= $groupContent;
} elseif ((isset($this->subGroups[$idx])) && ($this->subGroups[$this->subGroups[$idx]]['opened'] === false)) {
// Then add it's content
$subGroupContent = $this->subGroups[$this->subGroups[$idx]]['content'];
//* DEBUG: */ echo "subgroup={$this->subGroups[$idx]},content=".htmlentities($subGroupContent)."
\n";
$content .= trim($subGroupContent);
} else {
// Something went wrong
$this->debugInstance(__METHOD__ . '(): Something unexpected happened here.');
}
} // END - for
// Is footer content there?
if (isset($this->groups['footer'])) {
// Then add it
$content .= $this->groups['footer']['content'] . PHP_EOL;
} // END - if
// Return it
//* DEBUG: */ echo "content=".htmlentities($content)."
(".strlen($content).")
\n";
return $content;
}
/**
* Checks whether the specified group is opened
*
* @param $groupId Id of group to check
* @return $isOpened Whether the specified group is open
*/
protected function ifGroupIsOpened ($groupId) {
// Is the group open?
$isOpened = ((isset($this->groups[$groupId])) && ($this->groups[$groupId]['opened'] === true));
// Return status
return $isOpened;
}
/**
* Getter for direct field values
*
* @param $fieldName Name of the field we shall fetch
* @return $fieldValue Value from field
* @throws NullPointerException Thrown if $valueInstance is null
*/
public function getValueField ($fieldName) {
// Init value
$fieldValue = NULL;
// The $valueInstance attribute should not be null!
if (is_null($this->getValueInstance())) {
// Throws an exception here
throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
} // END - if
// Is the field set?
if ($this->getValueInstance()->isFieldSet($fieldName)) {
// Get the field value
$fieldValue = $this->getValueInstance()->getField($fieldName);
//* DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput($fieldName.'[]='.gettype($fieldValue).'('.strlen($fieldValue).') - Value instance!');
} elseif ((!is_null($this->extraInstance)) && ($this->extraInstance->isFieldSet($fieldName))) {
// So try the extra instance
$fieldValue = $this->extraInstance->getField($fieldName);
//* DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput($fieldName.'[]='.gettype($fieldValue).'('.strlen($fieldValue).') - Extra instance!');
} else {
// Field is not set
$this->debugOutput('[' . __METHOD__ . ':' . __LINE__ . '] fieldName=' . $fieldName . ' is not set! - @TODO');
} // END - if
// Return it
return $fieldValue;
}
/**
* Getter for value instance
*
* @return $valueInstance Instance of the class holding our values
*/
public final function getValueInstance () {
return $this->valueInstance;
}
/**
* Check whether a group was opened previously
*
* @return $groupOpened Whether any group was opened before
*/
protected final function ifGroupOpenedPreviously () {
$groupOpened = (!empty($this->previousGroupId));
return $groupOpened;
}
/**
* Check whether a group was opened previously
*
* @return $subGroupOpened Whether any group was opened before
*/
protected final function ifSubGroupOpenedPreviously () {
$subGroupOpened = (!empty($this->previousSubGroupId));
return $subGroupOpened;
}
/**
* Getter for previous group id
*
* @return $previousGroupId Id of previously opened group
*/
protected final function getPreviousGroupId () {
return $this->previousGroupId;
}
/**
* Setter for previous group id
*
* @param $previousGroupId Id of previously opened group
* @return void
*/
protected final function setPreviousGroupId ($previousGroupId) {
$this->previousGroupId = (string) $previousGroupId;
}
/**
* Getter for previous sub group id
*
* @return $previousSubGroupId Id of previously opened sub group
*/
protected final function getPreviousSubGroupId () {
return $this->previousSubGroupId;
}
/**
* Setter for previous sub group id
*
* @param $previousSubGroupId Id of previously opened sub group
* @return void
*/
protected final function setPreviousSubGroupId ($previousSubGroupId) {
$this->previousSubGroupId = (string) $previousSubGroupId;
}
}