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