Odyssey
CompassMenu.php
1 <?php
2 /**
3  * CompassMenu class
4  * @copyright HomeCu 05/2019
5  *
6  * Create the upper right menu in home banking, now called the Compass menu.
7  * This concrete exists to customize params both from eternal elements and
8  * internal calculations.
9  *
10  * See the foot of CreateMenu for usage and documentation.
11  *
12  * As an extension no constructor is needed unless you need to do something on startup. :-)
13  */
14 class CompassMenu extends CreateMenu
15 {
16  /** @var array the array of params passed to makeMenu() */
17  protected $compass_params = [];
18 
19  /** @var array, after decoding JSON config store here for access */
20  protected $json_array = [];
21 
22  /**
23  * ENTRY POINT.
24  * Set up our menu array, send to makeMenu(), and output the HTML. CreateMenu validates
25  * the JSON template path.
26  * @param string $json_path
27  * @param string $menu_json, global json data
28  * @param string $append_html
29  * @return string
30  */
31  public function composeCompassMenu($json_path = '', $menu_json = '', $append_html = '')
32  {
33  try {
34  $menu = $this
35  ->setMenuJsonArray($menu_json)
36  ->setCompassParamsArray($json_path)
37  ->addUserInfoIcons()
38  ->makeMenu($this->compass_params);
39 
40  return $this->addHiddenContent($menu, $append_html);
41 
42  } catch (Exception $e) {
43  return "<p>Exception creating menu: {$e->getMessage()}</p>";
44  }
45  }
46 
47  public function singleCompassMenuNode($json_path = '', $menu_json = '', $node_id = '', $full_node = false)
48  {
49  return $this
50  ->setMenuJsonArray($menu_json)
51  ->setCompassParamsArray($json_path)
52  ->addUserInfoIcons()
53  ->makeSingleMenuNode($node_id, $this->compass_params, $full_node);
54  }
55 
56  /**
57  * A "temporary measure" that may or may not have use in the future. Append the menu with
58  * any content we need to add to the DOM It will be wrapped in a hidden div by default.
59  * @param string HTML $menu
60  * @param string HTML $append_html
61  * @return string
62  */
63  protected function addHiddenContent($menu, $append_html = '')
64  {
65  if (empty($append_html)) {
66  return $menu;
67  }
68 
69  return $menu . "
70  <div id=\"compass-append-menu\" style=\"display:none;\">
71  $append_html
72  </div>
73  ";
74 
75  }
76 
77  /**
78  * If we have no CU and user, no need to output anything.
79  * @return bool
80  */
81  public function isCuAndUser()
82  {
83  return (
84  isset($this->HB_ENV['Cu']) &&
85  (strlen($this->HB_ENV['Cu']) > 0) &&
86  isset($this->HB_ENV['Uid']) &&
87  (strlen($this->HB_ENV['Uid']) > 0)
88  );
89 
90  }
91 
92  /**
93  * Set the JSON into the internal array.
94  * @param string $json
95  * @throws Exception
96  * @return $this
97  */
98  protected function setMenuJsonArray($json = '')
99  {
100  $this->json_array = json_decode($json, 1);
101 
102  if ($this->json_array === false) {
103  throw new Exception("Could not decode global JSON array in CompassMenu.");
104  }
105 
106  return $this;
107  }
108 
109  /**
110  * Sets the array to inject into the parent makeMenu() method from dynamic external params.
111  * It looks complex, but is pretty straightforward. Visualize html elements
112  *
113  * <p id="some-div" class="this that">
114  * <a href="somwhere.html" id="somewhere-link" title="" class="the other">Text</a>
115  * </p>
116  *
117  * Can be referenced with nested dot syntax by **element Id."
118  *
119  * 'some-div.attributes.class.this' = false // turns OFF "this" class
120  * 'somewhere-link.attributes.title' = 'My Title' // populates anchor title
121  * 'somewhere-link.attributes.class.the' = false // turns off 'the' class
122  * 'somewhere-link.content' = 'Use Meaningful Text' // Exchanges 'Text' for this value
123  *
124  * Keys must exist in the JSON structure, they will not be added (in this version)
125  * See head of CreateMenu for full documentation.
126  *
127  * @param string $json_path, path to JSON template
128  * @return $this
129  */
130  protected function setCompassParamsArray($json_path = '')
131  {
132  $compass_count = $this->countAllWarnings();
133 
134  $this->compass_params = [
135  'json_path' => $json_path,
136  'substitute_values' => [
137  'compass-menu-badge.display' => ($compass_count > 0)? true : false,
138  //'compass-menu-badge.content' => $compass_count,
139  //'compass-menu-badge.content' => '&nbsp;',
140  'user-activity.attributes.class.hcu-navbar-alert' => $this->setBoolFromCount('activity'),
141  'user-activity-link.attributes.href' => $this->setMenuUrl('activity'),
142  'activity-link-text.content' => $this->getNestedTwoDeep('activity', 'display'),
143  'user-activity-badge.display' => $this->setBoolFromCount('activity'),
144  'user-activity-badge.content' => $this->setDisplayNum('activity', 9),
145  'secure-email-item.attributes.class.hcu-navbar-alert' => $this->setBoolFromCount('messages'),
146  'secure-email-link.attributes.href' => $this->setMenuUrl('messages'),
147  'secure-email-link-text.content' => $this->getNestedTwoDeep('messages', 'display'),
148  'secure-email-badge.display' => $this->setBoolFromCount('messages'),
149  'secure-email-badge.content' => $this->setDisplayNum('messages', 9),
150  'user-status.attributes.class.hcu-navbar-alert' => $this->setBoolFromCount('status'),
151  'user-status-badge.display' => $this->setBoolFromCount('status'),
152  'user-status-badge.content' => $this->setDisplayNum('status', 9),
153  'user-status-dropdown-link.attributes.href' => $this->getNestedTwoDeep('status', 'endpoint'),
154  'status-link-text.content' => $this->getNestedTwoDeep('status', 'display'),
155  'failed-login-k-b.attributes.class.hcu-warning-color' => $this->isErrorEnableClass('status', 'fail', true),
156  'failed-login-summary-desc-label.content' => $this->getNestedThreeDeep('status', 'fail', 'title'),
157  'failed-login-summary-desc-p.content' => $this->getNestedThreeDeep('status', 'fail', 'date'),
158  'last-login-summary-desc-label.content' => $this->getNestedThreeDeep('status', 'prior', 'title'),
159  'last-login-summary-value-label.content' => $this->getNestedThreeDeep('status', 'prior', 'date'),
160  'acct-status-summary-desc.display' => $this->isLiveEnvironment(),
161  'acct-status-summary-desc-label.content' => $this->getNestedThreeDeep('status', 'system', 'title'),
162  'acct-status-summary-p.content' => $this->getNestedThreeDeep('status', 'system', 'date'),
163  'user-dropdown.attributes.class.hcu-navbar-alert' => $this->setBoolFromCount('user'),
164  'user-menu-badge.display' => $this->setBoolFromCount('user'),
165  'user-menu-badge.content' => $this->setDisplayNum('user', 9),
166  'user-link-text.content' => $this->getNestedTwoDeep('user', 'display'),
167  'update-password.display' => $this->setAlertDivDisplay('password'),
168  'update-password-icon-block' => $this->getNestedThreeDeep('user', 'password', 'icon'),
169  'update-password-alert-text.content' => $this->getNestedThreeDeep('user', 'password', 'message'),
170  'update-password-link.attributes.href' => $this->getNestedThreeDeep('user', 'password', 'url'),
171  'update-password-link.content' => $this->getNestedThreeDeep('user', 'password', 'link'),
172  'update-security.display' => $this->setAlertDivDisplay('security'),
173  'security-expiring-text.content' => $this->getNestedThreeDeep('user', 'security', 'message'),
174  'update-security-link.attributes.href' => $this->getNestedThreeDeep('user', 'security', 'url'),
175  'update-security-link.content' => $this->getNestedThreeDeep('user', 'security', 'link'),
176  'email-message-p.content' => $this->getNestedThreeDeep('user', 'email', 'message'),
177  'email-message-title.content' => $this->getNestedThreeDeep('user', 'email', 'title'),
178  'update-email-link.attributes.href' => $this->getNestedThreeDeep('user', 'email', 'url'),
179  'update-email-link.content' => $this->getNestedThreeDeep('user', 'email', 'link'),
180  'quicknav-logout-link.attributes.href' => $this->setMenuUrl('logout'),
181  'logout-link-text.content' => $this->getNestedTwoDeep('logout', 'display'),
182  ]
183  ];
184 
185  return $this;
186  }
187 
188  /**
189  * Specialized method just for the user menu. The icons can vary, get what comes from
190  * $this->json_array from hcuFunctions.i and use the icon specified by that output.
191  * @return $this
192  */
193  protected function addUserInfoIcons()
194  {
195  $icon_ids = [
196  'security' => 'security-expiring-icon',
197  'password' => 'update-password-icon',
198  'email' => 'email-alert-icon'
199  ];
200 
201  foreach ($icon_ids as $key => $icon_id) {
202 
203  if ($this->isUserInfoArrayMembers($key)) {
204 
205  $icon = 'fa-' . $this->json_array['user'][$key]['icon'];
206  $level = $this->json_array['user'][$key]['level'];
207 
208  if (in_array($level, ['warning', 'error'])) {
209 
210  $parent = 'update-' . $key;
211  $parent_class = ($level == 'error')? 'k-error-colored' : 'hcu-warning-color';
212  $this->compass_params['substitute_values']["$parent.attributes.class.$parent_class"] = true;
213  }
214 
215  $this->compass_params['substitute_values']["$icon_id.attributes.class.$icon"] = true;
216  }
217  }
218 
219  return $this;
220  }
221 
222  /**
223  * Helper for addUserInfoIcons(), check for valid member we need in the input json_array.
224  * @param string $key
225  * @return bool
226  */
227  protected function isUserInfoArrayMembers($key)
228  {
229  return
230  isset($this->json_array['user'][$key]['level']) &&
231  isset($this->json_array['user'][$key]['icon']) &&
232  in_array($this->json_array['user'][$key]['level'], ['info', 'warning', 'error']);
233 
234  }
235 
236  /**
237  * Used only for the top level compass menu.
238  * @return int
239  */
240  protected function countAllWarnings()
241  {
242  $count = 0;
243 
244  $arr = ['logout', 'activity', 'messages', 'status', 'user'];
245 
246  foreach ($arr as $key) {
247 
248  // Happens on logout for some reason.
249  if (! array_key_exists($key, $this->json_array)) {
250  continue;
251  }
252 
253  $count += $this->getArrayCount($this->json_array[$key]);
254 
255  foreach ($this->json_array[$key] as $value) {
256  if (is_array($value)) {
257 
258  $count += $this->getArrayCount($value);
259  }
260  }
261 
262  }
263 
264  if ($count > 8) {
265  return '9+';
266  }
267 
268  return $count;
269  }
270 
271  /**
272  * @param $arr
273  * @return int
274  */
275  protected function getArrayCount($arr)
276  {
277  if (isset($arr['count'])) {
278  return $arr['count'];
279  }
280 
281  return 0;
282  }
283 
284  /**
285  * Looks for the key 'count' in array member $key and returns true if > 0
286  * @param string $key
287  * @return bool
288  */
289  protected function setBoolFromCount($key)
290  {
291  if (! isset($this->json_array[$key]['count'])) {
292  return false;
293  }
294 
295  return ($this->json_array[$key]['count'] > 0)? true : false;
296  }
297 
298  /**
299  * Utility for building a URL from input params.
300  * @param string $key
301  * @return string|null
302  */
303  protected function setMenuUrl($key)
304  {
305  if (isset($this->json_array[$key]['url'])) {
306  return $this->json_array[$key]['url'];
307  }
308 
309  if (isset($this->json_array[$key]['script'])) {
310  return "{$this->HB_ENV['loginpath']}/{$this->json_array[$key]['script']}?{$this->HB_ENV['cuquery']}";
311  }
312 
313  return null;
314  }
315 
316  /**
317  * Set a display number for the menus, if > $max output "$max+"
318  * @param string $key
319  * @param int $max
320  * @return string
321  */
322  protected function setDisplayNum($key, $max = 5)
323  {
324  if (! isset($this->json_array[$key]['count'])) {
325  return '0';
326  }
327 
328  return ($this->json_array[$key]['count'] > $max)? $max . '+' : $this->json_array[$key]['count'];
329  }
330 
331  /**
332  * Reach into an array value nested two deep and return if it exists.
333  * @param string $parent
334  * @param string $key
335  * @return string|null
336  */
337  protected function getNestedTwoDeep($parent = '', $key = '')
338  {
339  if (isset($this->json_array[$parent][$key])) {
340 
341  return $this->json_array[$parent][$key];
342  }
343 
344  return null;
345  }
346 
347  /**
348  * Reach into a array value nested three deep and return if it exists. These members may not
349  * exist, whereas others used here will always exist.
350  * @param string $parent
351  * @param string $child
352  * @param string $key
353  * @return string|null
354  */
355  protected function getNestedThreeDeep($parent = '', $child = '', $key = '')
356  {
357  if (isset($this->json_array[$parent][$child][$key])) {
358 
359  if ($key == 'icon') {
360  return 'fa-' . $this->json_array[$parent][$child][$key];
361  }
362 
363  return $this->json_array[$parent][$child][$key];
364  }
365 
366  return null;
367  }
368 
369  /**
370  * Our method of determining environment.
371  * @return bool
372  */
373  protected function isLiveEnvironment()
374  {
375  return $this->HB_ENV['live'];
376  }
377 
378  /**
379  * If there is an error, enable the error class in the menu JSON. A default class that generally
380  * always displays unless there is an error sends $enable_if_error = false (disables the class
381  * if there is an error: this method returns false.) A normally disabled class that needs to
382  * display if there is an error sends $enable_if_error = true (is enabled if there is an
383  * error, this method returns true.)
384  * @param string $parent
385  * @param string $child
386  * @param bool $enable_if_error
387  * @return bool
388  */
389  protected function isErrorEnableClass($parent, $child = '', $enable_if_error = false)
390  {
391  $array = $this->isErrorArray($parent, $child);
392 
393  if (isset($array['level']) && in_array($array['level'], ['warning', 'error'])) {
394  return ($enable_if_error)? true : false;
395  }
396 
397  return ($enable_if_error)? false : true;
398  }
399 
400  /**
401  * Helper for above.
402  * @param string $parent
403  * @param string $child
404  * @return array
405  */
406  function isErrorArray($parent, $child)
407  {
408  if (
409  isset($this->json_array[$parent]) &&
410  isset($this->json_array[$parent][$child]) &&
411  ! empty ($child)
412  ) {
413  return $this->json_array[$parent][$child];
414  }
415 
416  if (isset($this->json_array[$parent])) {
417  return $this->json_array[$parent];
418  }
419 
420  return [];
421  }
422 
423  /**
424  * Set whether a given parent div should display.
425  * @param string $key
426  * @return bool
427  */
428  protected function setAlertDivDisplay($key)
429  {
430  return isset($this->json_array['user'][$key]) && is_array($this->json_array['user'][$key]);
431  }
432 
433 }
setMenuUrl($key)
setDisplayNum($key, $max=5)
composeCompassMenu($json_path='', $menu_json='', $append_html='')
Definition: CompassMenu.php:31
setAlertDivDisplay($key)
getNestedThreeDeep($parent='', $child='', $key='')
isErrorEnableClass($parent, $child='', $enable_if_error=false)
getNestedTwoDeep($parent='', $key='')
setMenuJsonArray($json='')
Definition: CompassMenu.php:98
setCompassParamsArray($json_path='')
isUserInfoArrayMembers($key)
addHiddenContent($menu, $append_html='')
Definition: CompassMenu.php:63
setBoolFromCount($key)
getArrayCount($arr)
isErrorArray($parent, $child)