Some updates:
[core.git] / framework / main / classes / helper / class_BaseHelper.php
1 <?php
2 // Own namespace
3 namespace Org\Mxchange\CoreFramework\Helper;
4
5 // Import framework stuff
6 use Org\Mxchange\CoreFramework\Factory\ObjectFactory;
7 use Org\Mxchange\CoreFramework\Generic\FrameworkInterface;
8 use Org\Mxchange\CoreFramework\Generic\NullPointerException;
9 use Org\Mxchange\CoreFramework\Object\BaseFrameworkSystem;
10 use Org\Mxchange\CoreFramework\Registry\Registry;
11
12 /**
13  * A generic helper class with generic methods
14  *
15  * @author              Roland Haeder <webmaster@shipsimu.org>
16  * @version             0.0.0
17 <<<<<<< HEAD:framework/main/classes/helper/class_BaseHelper.php
18  * @copyright   Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2017 Core Developer Team
19 =======
20  * @copyright   Copyright (c) 2007, 2008 Roland Haeder, 2009 - 2016 Core Developer Team
21 >>>>>>> Some updates::inc/main/classes/helper/class_BaseHelper.php
22  * @license             GNU GPL 3.0 or any newer version
23  * @link                http://www.shipsimu.org
24  *
25  * This program is free software: you can redistribute it and/or modify
26  * it under the terms of the GNU General Public License as published by
27  * the Free Software Foundation, either version 3 of the License, or
28  * (at your option) any later version.
29  *
30  * This program is distributed in the hope that it will be useful,
31  * but WITHOUT ANY WARRANTY; without even the implied warranty of
32  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
33  * GNU General Public License for more details.
34  *
35  * You should have received a copy of the GNU General Public License
36  * along with this program. If not, see <http://www.gnu.org/licenses/>.
37  */
38 abstract class BaseHelper extends BaseFrameworkSystem {
39         /**
40          * Instance to the class which provides field values
41          */
42         private $valueInstance = NULL;
43
44         /**
45          * Extra instance to the class which provides field values
46          */
47         private $extraInstance = NULL;
48
49         /**
50          * Rendered content created by the helper class
51          */
52         private $content = '';
53
54         /**
55          * Array with groups
56          */
57         private $groups = array();
58
59         /**
60          * Array with sub group
61          */
62         private $subGroups = array();
63
64         /**
65          * Previously opened group
66          */
67         private $previousGroupId = '';
68
69         /**
70          * Previously opened sub group
71          */
72         private $previousSubGroupId = '';
73
74         /**
75          * Total counter for groups and sub groups
76          */
77         private $totalCounter = 0;
78
79         // Exception constants
80         const EXCEPTION_GROUP_NOT_OPENED             = 0x1e3;
81         const EXCEPTION_GROUP_ALREADY_FOUND          = 0x1e4;
82         const EXCEPTION_SUB_GROUP_ALREADY_FOUND      = 0x1e5;
83         const EXCEPTION_NO_PREVIOUS_SUB_GROUP_OPENED = 0x1e6;
84         const EXCEPTION_NO_PREVIOUS_GROUP_OPENED     = 0x1e7;
85
86         /**
87          * Protected constructor
88          *
89          * @param       $className      Real name of the class
90          * @return      void
91          */
92         protected function __construct ($className) {
93                 // Call parent constructor
94                 parent::__construct($className);
95         }
96
97         /**
98          * Adds content directly
99          *
100          * @param       $newContent             New content to add
101          * @return      void
102          */
103         protected final function addContent ($newContent) {
104                 $this->content .= (string) trim($newContent) . PHP_EOL;
105         }
106
107         /**
108          * Add header content to the helper
109          *
110          * @param       $content        Content to to the base
111          * @return      void
112          */
113         protected function addHeaderContent ($content) {
114                 // Add the header content
115                 $this->groups['header']['content'] = (string) trim($content);
116         }
117
118         /**
119          * Add footer content to the helper
120          *
121          * @param       $content        Content to to the base
122          * @return      void
123          */
124         protected function addFooterContent ($content) {
125                 // Add the footer content
126                 $this->groups['footer']['content'] = (string) trim($content);
127         }
128
129         /**
130          * Adds content to the previously opened group or sub group. If a sub group
131          * was found it will be taken. If no group/sub group is opened at the moment
132          * the code will be passed to addContent().
133          *
134          * @param       $newContent             New content to add
135          * @return      void
136          */
137         protected final function addContentToPreviousGroup ($newContent) {
138                 // Check for sub/group
139                 if ($this->ifSubGroupOpenedPreviously()) {
140                         // Get sub group id
141                         $subGroupId = $this->getPreviousSubGroupId();
142
143                         // Add the content
144                         $this->subGroups[$subGroupId]['content'] .= $newContent;
145                 } elseif ($this->ifGroupOpenedPreviously()) {
146                         // Get group id
147                         $groupId = $this->getPreviousGroupId();
148
149                         // Add the content
150                         $this->groups[$groupId]['content'] .= $newContent;
151                 } else {
152                         // Add it directly
153                         $this->addContent($newContent);
154                 }
155         }
156
157         /**
158          * Getter for content
159          *
160          * @return      $content        The rendered content by this helper
161          */
162         protected final function getContent () {
163                 return $this->content;
164         }
165
166         /**
167          * Public setter for extra instance
168          *
169          * @param       $extraInstance  An extra instance of FrameworkInterface to set
170          * @return      void
171          */
172         public final function setExtraInstance (FrameworkInterface $extraInstance) {
173                 $this->extraInstance = $extraInstance;
174         }
175
176         /**
177          *  Assigns a field from the value instance with a template variable
178          *
179          * @param       $fieldName      Name of the field to assign
180          * @return      void
181          */
182         public function assignField ($fieldName) {
183                 // Get the value from value instance
184                 $fieldValue = $this->getValueField($fieldName);
185
186                 // Assign it with a template variable
187                 $this->getTemplateInstance()->assignVariable('block_' . $fieldName, $fieldValue);
188         }
189
190         /**
191          * Assigns a field from the value instance with a template variable but
192          * parses its content through a given filter method of the value instance
193          *
194          * @param       $fieldName              Name of the field to assign
195          * @param       $filterMethod   Method name to call of the value instance
196          * @return      void
197          * @todo        Rewrite this method using a helper class for filtering data
198          */
199         public function assignFieldWithFilter ($fieldName, $filterMethod) {
200                 // Get the value
201                 $fieldValue = $this->getValueField($fieldName);
202                 //* DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput($fieldName.'='.$fieldValue);
203
204                 // Now filter it through the value through the filter method
205                 $filteredValue = call_user_func_array(array($this, 'doFilter' . self::convertToClassName($filterMethod)), array($fieldValue));
206
207                 // Assign it with a template variable
208                 $this->getTemplateInstance()->assignVariable('block_' . $fieldName, $filteredValue);
209         }
210
211         /**
212          * Pre-fetches field default values from the given registry key instance into this class
213          *
214          * @param       $registryKey    Registry key which holds an object with values
215          * @param       $extraKey               Extra value instance key used if registryKey is null
216          * @return      void
217          * @throws      NullPointerException    If recovery of requested value instance failed
218          */
219         public function prefetchValueInstance ($registryKey, $extraKey = NULL) {
220                 //* DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput('O:'.$registryKey.'/'.$extraKey);
221                 try {
222                         // Get the required instance
223                         $this->valueInstance = Registry::getRegistry()->getInstance($registryKey);
224                 } catch (NullPointerException $e) {
225                         // Not set in registry
226                         // @TODO Try to log it here
227                         //* DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput($registryKey.'=NULL!');
228                 }
229
230                 // Shall we get an extra instance?
231                 if (!is_null($extraKey)) {
232                         try {
233                                 // Get the extra instance.
234                                 $this->extraInstance = Registry::getRegistry()->getInstance($extraKey);
235                         } catch (NullPointerException $e) {
236                                 // Try to create it
237                                 $this->extraInstance = ObjectFactory::createObjectByConfiguredName($extraKey . '_class', array($this->valueInstance));
238                         }
239                         //* DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput($extraKey.'='.$this->extraInstance.' - EXTRA!');
240                 } // END - if
241
242                 // Is the value instance valid?
243                 if (is_null($this->valueInstance)) {
244                         // Get the requested instance
245                         $this->valueInstance = ObjectFactory::createObjectByConfiguredName($registryKey . '_class', array($this->extraInstance));
246                 } // END - if
247         }
248
249         /**
250          * Opens a helper group with given group id and content or throws an
251          * exception if that group is already found regardless if it is open or
252          * closed.
253          *
254          * @param       $groupId        Group id to open
255          * @param       $content        Initial content to add to the group
256          * @param       $tag            HTML tag used to open this group
257          * @return      void
258          * @throws      HelperGroupAlreadyCreatedException      If the group was already created before
259          */
260         protected function openGroupByIdContent ($groupId, $content, $tag) {
261                 //* DEBUG: */ echo "OPEN:groupId={$groupId},content=<pre>".htmlentities($content)."</pre>\n";
262                 // Is the group already there?
263                 if (isset($this->groups[$groupId])) {
264                         // Then throw an exception here
265                         throw new HelperGroupAlreadyCreatedException(array($this, $groupId), self::EXCEPTION_GROUP_ALREADY_FOUND);
266                 } // END - if
267
268                 // Count one up
269                 $this->totalCounter++;
270
271                 // Add the group to the stack
272                 $this->groups[$this->totalCounter] = $groupId;
273                 $this->groups[$groupId]['opened']  = true;
274                 $this->groups[$groupId]['content'] = sprintf(
275                         '<!-- group %s opened (length: %s, tag: %s) //-->%s' . PHP_EOL,
276                         $groupId,
277                         strlen($content),
278                         $tag,
279                         $content
280                 );
281                 $this->groups[$groupId]['tag'] = $tag;
282
283                 // Mark this group as previously opened
284                 $this->setPreviousGroupId($groupId);
285         }
286
287         /**
288          * Closes the previously opened group by added given content to it or
289          * throws an exception if no previous group was opened
290          *
291          * @param       $content        Content for previously opened group, or empty to use tag of opener
292          * @return      void
293          * @throws      HelperNoPreviousOpenedGroupException    If no previously opened group was found
294          */
295         public function closePreviousGroupByContent ($content = '') {
296                 // Check if any sub group was opened before
297                 if ($this->ifSubGroupOpenedPreviously()) {
298                         // Close it automatically
299                         $this->closePreviousSubGroupByContent();
300                 } // END - if
301
302                 // Check if any group was opened before
303                 if ($this->ifGroupOpenedPreviously() === false) {
304                         // Then throw an exception
305                         throw new HelperNoPreviousOpenedGroupException(array($this, $content), self::EXCEPTION_NO_PREVIOUS_SUB_GROUP_OPENED);
306                 } // END - if
307
308                 // Get previous group
309                 $groupId = $this->getPreviousGroupId();
310
311                 // Is the content empty?
312                 if ((empty($content)) && (!empty($this->groups[$groupId]['tag']))) {
313                         // Get it from opener
314                         $content = sprintf(
315                                 "<!-- group %s auto-closed //--></%s>",
316                                 $groupId,
317                                 $this->groups[$groupId]['tag']
318                         );
319                 } // END - if
320
321                 // Add content to it and mark it as closed
322                 $this->groups[$groupId]['content'] .= sprintf(
323                         "<!-- group %s closed (length: %s, tag: %s) //-->%s\n",
324                         $groupId,
325                         strlen($content),
326                         $this->groups[$groupId]['tag'],
327                         $content
328                 );
329                 $this->groups[$groupId]['opened'] = false;
330
331                 // Mark previous group as closed
332                 $this->setPreviousGroupId('');
333                 //* DEBUG: */ echo "CLOSE:groupId={$groupId}<br />\n";
334         }
335
336         /**
337          * Opens a helper sub group with given group id and content or throws an
338          * exception if that sub group is already found regardless if it is open or
339          * closed.
340          *
341          * @param       $subGroupId             Sub group id to open
342          * @param       $content                Initial content to add to the sub group
343          * @param       $tag                    HTML tag used to open this group
344          * @return      void
345          * @throws      HelperSubGroupAlreadyCreatedException   If the sub group was already created before
346          */
347         protected function openSubGroupByIdContent ($subGroupId, $content, $tag) {
348                 //* DEBUG: */ echo "OPEN:subGroupId={$subGroupId},content=".htmlentities($content)."<br />\n";
349                 // Is the group already there?
350                 if (isset($this->subGroups[$subGroupId])) {
351                         // Then throw an exception here
352                         throw new HelperSubGroupAlreadyCreatedException(array($this, $subGroupId), self::EXCEPTION_SUB_GROUP_ALREADY_FOUND);
353                 } // END - if
354
355                 // Count one up
356                 $this->totalCounter++;
357
358                 // Add the group to the stack
359                 $this->subGroups[$this->totalCounter] = $subGroupId;
360                 $this->subGroups[$subGroupId]['opened']  = true;
361                 $this->subGroups[$subGroupId]['content'] = sprintf("<!-- sub-group %s opened (length: %s, tag: %s) //-->%s\n", $subGroupId, strlen($content), $tag, $content);
362                 $this->subGroups[$subGroupId]['tag'] = $tag;
363
364                 // Mark this group as previously opened
365                 $this->setPreviousSubGroupId($subGroupId);
366         }
367
368         /**
369          * Closes the previously opened sub group by added given content to it or
370          * throws an exception if no previous sub group was opened
371          *
372          * @param       $content        Content for previously opened sub group, or leave empty to use div/span of openener
373          * @return      void
374          * @throws      HelperNoPreviousOpenedSubGroupException If no previously opened sub group was found
375          */
376         public function closePreviousSubGroupByContent ($content = '') {
377                 // Check if any sub group was opened before
378                 if ($this->ifSubGroupOpenedPreviously() === false) {
379                         // Then throw an exception
380                         throw new HelperNoPreviousOpenedSubGroupException(array($this, $content), self::EXCEPTION_NO_PREVIOUS_SUB_GROUP_OPENED);
381                 } // END - if
382
383                 // Get previous sub group
384                 $subGroupId = $this->getPreviousSubGroupId();
385
386                 // Is the content empty?
387                 if ((empty($content)) && (!empty($this->subGroups[$subGroupId]['tag']))) {
388                         // Get it from opener
389                         $content = sprintf('<!-- sub-group %s auto-closed //--></%s>', $subGroupId, $this->subGroups[$subGroupId]['tag']);
390                 } // END - if
391
392                 // Add content to it and mark it as closed
393                 $this->subGroups[$subGroupId]['content'] .= sprintf('<!-- sub-group %s closed (length: %s, tag: %s) //-->%s' . PHP_EOL, $subGroupId, strlen($content), $this->subGroups[$subGroupId]['tag'], $content);
394                 $this->subGroups[$subGroupId]['opened'] = false
395                 ;
396
397                 // Mark previous sub group as closed
398                 $this->setPreviousSubGroupId('');
399                 //* DEBUG: */ echo "CLOSE:subGroupId={$subGroupId}<br />\n";
400         }
401
402         /**
403          * Renders all group and sub group in their order
404          *
405          * @return      $content        Rendered HTML content
406          */
407         public function renderContent () {
408                 // Initialize content
409                 $content = '';
410
411                 // Is header content there?
412                 if (isset($this->groups['header'])) {
413                         // Then add it
414                         $content .= $this->groups['header']['content'] . PHP_EOL;
415                 } // END - if
416
417                 // Initiate content
418                 $content .= $this->getContent();
419
420                 // Now "walk" through all groups and sub-groups
421                 for ($idx = 1; $idx <= $this->totalCounter; $idx++) {
422                         // Is this a sub/group and is it closed?
423                         if ((isset($this->groups[$idx])) && ($this->groups[$this->groups[$idx]]['opened'] === false)) {
424                                 // Then add it's content
425                                 $groupContent = trim($this->groups[$this->groups[$idx]]['content']);
426                                 //* DEBUG: */ echo "group={$this->groups[$idx]},content=<pre>".htmlentities($groupContent)."</pre><br />\n";
427                                 $content .= $groupContent;
428                         } elseif ((isset($this->subGroups[$idx])) && ($this->subGroups[$this->subGroups[$idx]]['opened'] === false)) {
429                                 // Then add it's content
430                                 $subGroupContent = $this->subGroups[$this->subGroups[$idx]]['content'];
431                                 //* DEBUG: */ echo "subgroup={$this->subGroups[$idx]},content=<pre>".htmlentities($subGroupContent)."</pre><br />\n";
432                                 $content .= trim($subGroupContent);
433                         } else {
434                                 // Something went wrong
435                                 $this->debugInstance(__METHOD__ . '(): Something unexpected happened here.');
436                         }
437                 } // END - for
438
439                 // Is footer content there?
440                 if (isset($this->groups['footer'])) {
441                         // Then add it
442                         $content .= $this->groups['footer']['content'] . PHP_EOL;
443                 } // END - if
444
445                 // Return it
446                 //* DEBUG: */ echo "content=<pre>".htmlentities($content)."</pre> (".strlen($content).")<br />\n";
447                 return $content;
448         }
449
450         /**
451          * Checks whether the specified group is opened
452          *
453          * @param       $groupId        Id of group to check
454          * @return      $isOpened       Whether the specified group is open
455          */
456         protected function ifGroupIsOpened ($groupId) {
457                 // Is the group open?
458                 $isOpened = ((isset($this->groups[$groupId])) && ($this->groups[$groupId]['opened'] === true));
459
460                 // Return status
461                 return $isOpened;
462         }
463
464         /**
465          * Getter for direct field values
466          *
467          * @param       $fieldName              Name of the field we shall fetch
468          * @return      $fieldValue             Value from field
469          * @throws      NullPointerException    Thrown if $valueInstance is null
470          */
471         public function getValueField ($fieldName) {
472                 // Init value
473                 $fieldValue = NULL;
474
475                 // The $valueInstance attribute should not be null!
476                 if (is_null($this->getValueInstance())) {
477                         // Throws an exception here
478                         throw new NullPointerException($this, self::EXCEPTION_IS_NULL_POINTER);
479                 } // END - if
480
481                 // Is the field set?
482                 if ($this->getValueInstance()->isFieldSet($fieldName)) {
483                         // Get the field value
484                         $fieldValue = $this->getValueInstance()->getField($fieldName);
485                         //* DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput($fieldName.'[]='.gettype($fieldValue).'('.strlen($fieldValue).') - Value instance!');
486                 } elseif ((!is_null($this->extraInstance)) && ($this->extraInstance->isFieldSet($fieldName))) {
487                         // So try the extra instance
488                         $fieldValue = $this->extraInstance->getField($fieldName);
489                         //* DEBUG: */ self::createDebugInstance(__CLASS__, __LINE__)->debugOutput($fieldName.'[]='.gettype($fieldValue).'('.strlen($fieldValue).') - Extra instance!');
490                 } else {
491                         // Field is not set
492                         $this->debugOutput('[' . __METHOD__ . ':' . __LINE__ . '] fieldName=' . $fieldName . ' is not set! - @TODO');
493                 } // END - if
494
495                 // Return it
496                 return $fieldValue;
497         }
498
499         /**
500          * Getter for value instance
501          *
502          * @return      $valueInstance  Instance of the class holding our values
503          */
504         public final function getValueInstance () {
505                 return $this->valueInstance;
506         }
507
508         /**
509          * Check whether a group was opened previously
510          *
511          * @return      $groupOpened    Whether any group was opened before
512          */
513         protected final function ifGroupOpenedPreviously () {
514                 $groupOpened = (!empty($this->previousGroupId));
515                 return $groupOpened;
516         }
517
518         /**
519          * Check whether a group was opened previously
520          *
521          * @return      $subGroupOpened         Whether any group was opened before
522          */
523         protected final function ifSubGroupOpenedPreviously () {
524                 $subGroupOpened = (!empty($this->previousSubGroupId));
525                 return $subGroupOpened;
526         }
527
528         /**
529          * Getter for previous group id
530          *
531          * @return      $previousGroupId        Id of previously opened group
532          */
533         protected final function getPreviousGroupId () {
534                 return $this->previousGroupId;
535         }
536
537         /**
538          * Setter for previous group id
539          *
540          * @param       $previousGroupId        Id of previously opened group
541          * @return      void
542          */
543         protected final function setPreviousGroupId ($previousGroupId) {
544                 $this->previousGroupId = (string) $previousGroupId;
545         }
546
547         /**
548          * Getter for previous sub group id
549          *
550          * @return      $previousSubGroupId             Id of previously opened sub group
551          */
552         protected final function getPreviousSubGroupId () {
553                 return $this->previousSubGroupId;
554         }
555
556         /**
557          * Setter for previous sub group id
558          *
559          * @param       $previousSubGroupId             Id of previously opened sub group
560          * @return      void
561          */
562         protected final function setPreviousSubGroupId ($previousSubGroupId) {
563                 $this->previousSubGroupId = (string) $previousSubGroupId;
564         }
565
566 }