]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - include/SubPanel/SubPanelDefinitions.php
Release 6.4.0
[Github/sugarcrm.git] / include / SubPanel / SubPanelDefinitions.php
1 <?php
2 if (! defined ( 'sugarEntry' ) || ! sugarEntry)
3         die ( 'Not A Valid Entry Point' ) ;
4 /*********************************************************************************
5  * SugarCRM Community Edition is a customer relationship management program developed by
6  * SugarCRM, Inc. Copyright (C) 2004-2011 SugarCRM Inc.
7  * 
8  * This program is free software; you can redistribute it and/or modify it under
9  * the terms of the GNU Affero General Public License version 3 as published by the
10  * Free Software Foundation with the addition of the following permission added
11  * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
12  * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
13  * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
14  * 
15  * This program is distributed in the hope that it will be useful, but WITHOUT
16  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17  * FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
18  * details.
19  * 
20  * You should have received a copy of the GNU Affero General Public License along with
21  * this program; if not, see http://www.gnu.org/licenses or write to the Free
22  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23  * 02110-1301 USA.
24  * 
25  * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
26  * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
27  * 
28  * The interactive user interfaces in modified source and object code versions
29  * of this program must display Appropriate Legal Notices, as required under
30  * Section 5 of the GNU Affero General Public License version 3.
31  * 
32  * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
33  * these Appropriate Legal Notices must retain the display of the "Powered by
34  * SugarCRM" logo. If the display of the logo is not reasonably feasible for
35  * technical reasons, the Appropriate Legal Notices must display the words
36  * "Powered by SugarCRM".
37  ********************************************************************************/
38
39
40
41
42
43 //input
44 //      module directory
45 //constructor
46 //      open the layout_definitions file.
47 //
48 /**
49  * Subpanel implementation
50  * @api
51  */
52 class aSubPanel
53 {
54
55         var $name ;
56         var $_instance_properties ;
57
58         var $mod_strings ;
59         var $panel_definition ;
60         var $sub_subpanels ;
61         var $parent_bean ;
62
63         //module's table name and column fields.
64         var $table_name ;
65         var $db_fields ;
66         var $bean_name ;
67         var $template_instance ;
68
69         function aSubPanel ( $name , $instance_properties , $parent_bean , $reload = false , $original_only = false )
70         {
71
72                 $this->_instance_properties = $instance_properties ;
73                 $this->name = $name ;
74                 $this->parent_bean = $parent_bean ;
75
76                 //set language
77                 global $current_language ;
78                 if (! isset ( $parent_bean->mbvardefs ))
79                 {
80                         $mod_strings = return_module_language ( $current_language, $parent_bean->module_dir ) ;
81                 }
82                 $this->mod_strings = $mod_strings ;
83
84                 if ($this->isCollection ())
85                 {
86                         $this->load_sub_subpanels () ; //load sub-panel definition.
87                 } else
88                 {
89                         if (!is_dir('modules/' . $this->_instance_properties [ 'module' ])){
90                                 _pstack_trace();
91                         }
92                         $def_path = 'modules/' . $this->_instance_properties [ 'module' ] . '/metadata/subpanels/' . $this->_instance_properties [ 'subpanel_name' ] . '.php' ;
93
94                         $orig_exists = is_file($def_path);
95                         $loaded = false;
96                         if ($orig_exists)
97                         {
98                                 require ($def_path);
99                                 $loaded = true;
100                         }
101                         if (is_file("custom/$def_path") && (!$original_only  || !$orig_exists))
102                         {
103                                 require ("custom/$def_path");
104                                 $loaded = true;
105                         }
106
107                         if (! $original_only && isset ( $this->_instance_properties [ 'override_subpanel_name' ] ) && file_exists ( 'custom/modules/' . $this->_instance_properties [ 'module' ] . '/metadata/subpanels/' . $this->_instance_properties [ 'override_subpanel_name' ] . '.php' ))
108                         {
109                                 $cust_def_path = 'custom/modules/' . $this->_instance_properties [ 'module' ] . '/metadata/subpanels/' . $this->_instance_properties [ 'override_subpanel_name' ] . '.php' ;
110                                 require ($cust_def_path) ;
111                                 $loaded = true;
112                         }
113
114                         if (!$loaded)
115                         {
116                                 $GLOBALS['log']->fatal("Failed to load original or custom subpanel data for $name in $def_path");
117                         }
118
119                         // check that the loaded subpanel definition includes a $subpanel_layout section - some, such as projecttasks/default do not...
120                         $this->panel_definition = array () ;
121                         if (isset($subpanel_layout))
122                         {
123                                 $this->panel_definition = $subpanel_layout ;
124
125                         }
126                         $this->load_module_info () ; //load module info from the module's bean file.
127                 }
128
129         }
130
131     /**
132      * is the sub panel default hidden?
133      *
134      * @return bool
135      */
136     public function isDefaultHidden()
137     {
138         if(isset($this->_instance_properties['default_hidden']) && $this->_instance_properties['default_hidden'] == true) {
139             return true;
140         }
141
142         return false;
143     }
144
145
146         function distinct_query ()
147         {
148                 if (isset ( $this->_instance_properties [ 'get_distinct_data' ] ))
149                 {
150                         return !empty($this->_instance_properties['get_distinct_data']) ? true : false;
151                 }
152                 return false ;
153         }
154
155         //return the translated header value.
156         function get_title ()
157         {
158                 if (empty ( $this->mod_strings [ $this->_instance_properties [ 'title_key' ] ] ))
159                 {
160                         return translate ( $this->_instance_properties [ 'title_key' ], $this->_instance_properties [ 'module' ] ) ;
161                 }
162                 return $this->mod_strings [ $this->_instance_properties [ 'title_key' ] ] ;
163         }
164
165         //return the definition of buttons. looks for buttons in 2 locations.
166         function get_buttons ()
167         {
168                 $buttons = array ( ) ;
169                 if (isset ( $this->_instance_properties [ 'top_buttons' ] ))
170                 {
171                         //this will happen only in the case of sub-panels with multiple sources(activities).
172                         $buttons = $this->_instance_properties [ 'top_buttons' ] ;
173                 } else
174                 {
175                         $buttons = $this->panel_definition [ 'top_buttons' ] ;
176                 }
177
178                 // permissions. hide SubPanelTopComposeEmailButton from activities if email module is disabled.
179                 //only email is  being tested becuase other submodules in activites/history such as notes, tasks, meetings and calls cannot be disabled.
180                 //as of today these are the only 2 sub-panels that use the union clause.
181                 $mod_name = $this->get_module_name () ;
182                 if ($mod_name == 'Activities' || $mod_name == 'History')
183                 {
184                         global $modListHeader ;
185                         global $modules_exempt_from_availability_check ;
186                         if (isset ( $modListHeader ) && (! (array_key_exists ( 'Emails', $modListHeader ) or array_key_exists ( 'Emails', $modules_exempt_from_availability_check ))))
187                         {
188                                 foreach ( $buttons as $key => $button )
189                                 {
190                                         foreach ( $button as $property => $value )
191                                         {
192                                                 if ($value === 'SubPanelTopComposeEmailButton' || $value === 'SubPanelTopArchiveEmailButton')
193                                                 {
194                                                         //remove this button from the array.
195                                                         unset ( $buttons [ $key ] ) ;
196                                                 }
197                                         }
198                                 }
199                         }
200                 }
201
202                 return $buttons ;
203         }
204
205
206         //call this function for sub-panels that have unions.
207         function load_sub_subpanels ()
208         {
209
210                 global $modListHeader ;
211                 // added a check for security of tabs to see if an user has access to them
212                 // this prevents passing an "unseen" tab to the query string and pulling up its contents
213                 if (! isset ( $modListHeader ))
214                 {
215                         global $current_user ;
216                         if (isset ( $current_user ))
217                         {
218                                 $modListHeader = query_module_access_list ( $current_user ) ;
219                         }
220                 }
221
222                 global $modules_exempt_from_availability_check ;
223
224                 $listFieldMap = array();
225
226                 if (empty ( $this->sub_subpanels ))
227                 {
228                         $panels = $this->get_inst_prop_value ( 'collection_list' ) ;
229                         foreach ( $panels as $panel => $properties )
230                         {
231                                 if (array_key_exists ( $properties [ 'module' ], $modListHeader ) or array_key_exists ( $properties [ 'module' ], $modules_exempt_from_availability_check ))
232                                 {
233                                         $this->sub_subpanels [ $panel ] = new aSubPanel ( $panel, $properties, $this->parent_bean ) ;
234                                 }
235                         }
236                         //Sync displayed list fields across the subpanels
237                         $display_fields = $this->getDisplayFieldsFromCollection($this->sub_subpanels);
238                         $query_fields = array();
239                         foreach ( $this->sub_subpanels as $key => $subpanel )
240                         {
241                                 $list_fields = $subpanel->get_list_fields();
242                                 $listFieldMap[$key] = array();
243                                 $index = 0;
244                                 foreach($list_fields as $field => $def)
245                                 {
246                                         if (isset($def['vname']) && isset($def['width']))
247                                         {
248                                                 $index++;
249                                                 if(!empty($def['alias']))
250                                                         $listFieldMap[$key][$def['alias']] = $field;
251                                                 else
252                                                         $listFieldMap[$key][$field] = $field;
253                                                 if (!isset($display_fields[$def['vname']]))
254                                                 {
255                                                         if(sizeof($display_fields) > $index)
256                                                         {
257                                                                 //Try to insert the new field in an order that makes sense
258                                                                 $start = array_slice($display_fields, 0, $index);
259                                                                 $end = array_slice($display_fields, $index);
260                                                                 $display_fields = array_merge(
261                                                                         $start,
262                                                                         array($def['vname'] => array('name' => $field, 'vname' => $def['vname'], 'width' => $def['width'] )),
263                                                                         $end
264                                                                 );
265                                                         } else
266                                                         {
267                                                                 $display_fields[$def['vname']] = array(
268                                                                         'name' => empty($def['alias']) ? $field : $def['alias'],
269                                                                         'vname' => $def['vname'],
270                                                                         'width' => $def['width'],
271                                                                 );
272                                                         }
273                                                 }
274                                         } else {
275                                                 $query_fields[$field] = $def;
276                                         }
277                                 }
278                         }
279                         foreach ( $this->sub_subpanels as $key => $subpanel )
280                         {
281                                 $list_fields = array();
282                                 foreach($display_fields as $vname => $def)
283                                 {
284                                         $field = $def['name'];
285                                         $list_key = isset($listFieldMap[$key][$field]) ? $listFieldMap[$key][$field] : $field;
286
287                                         if (isset($subpanel->panel_definition['list_fields'][$field]))
288                                         {
289                                                 $list_fields[$field] = $subpanel->panel_definition['list_fields'][$field];
290                                         }
291                                     else if ($list_key != $field && isset($subpanel->panel_definition['list_fields'][$list_key]))
292                     {
293                         $list_fields[$list_key] = $subpanel->panel_definition['list_fields'][$list_key];
294
295                     }
296                                         else {
297                                                 $list_fields[$field] = $display_fields[$vname];
298                                         }
299                                 }
300                                 foreach($query_fields as $field => $def)
301                                 {
302                                         if (isset($subpanel->panel_definition['list_fields'][$field]))
303                                         {
304                                                 $list_fields[$field] = $subpanel->panel_definition['list_fields'][$field];
305                                         }
306                                         else {
307                                                 $list_fields[$field] = $def;
308                                         }
309                                 }
310                                 $subpanel->panel_definition['list_fields'] = $list_fields;
311                         }
312                 }
313         }
314
315         protected function getDisplayFieldsFromCollection($sub_subpanels)
316         {
317                 $display_fields = array();
318                 foreach ($sub_subpanels as $key => $subpanel )
319                 {
320                         $list_fields = $subpanel->get_list_fields();
321                         $index = 0;
322                         foreach($list_fields as $field => $def)
323                         {
324                                 if (isset($def['vname']) && isset($def['width']))
325                                 {
326                                         $index++;
327                                         if (!isset($display_fields[$def['vname']]))
328                                         {
329                                                 if(sizeof($display_fields) > $index)
330                                                 {
331                                                         //Try to insert the new field in an order that makes sense
332                                                         $start = array_slice($display_fields, 0, $index);
333                                                         $end = array_slice($display_fields, $index);
334                                                         $display_fields = array_merge(
335                                                                 $start,
336                                                                 array($def['vname'] => array('name' => $field, 'vname' => $def['vname'], 'width' => $def['width'] )),
337                                                                 $end
338                                                         );
339                                                 } else
340                                                 {
341                                                         $display_fields[$def['vname']] = array(
342                                                                 'name' => $field,
343                                                                 'vname' => $def['vname'],
344                                                                 'width' => $def['width'],
345                                                         );
346                                                 }
347                                         }
348                                 }
349                         }
350                 }
351         }
352
353         function isDatasourceFunction ()
354         {
355                 if (strpos ( $this->get_inst_prop_value ( 'get_subpanel_data' ), 'function' ) === false)
356                 {
357                         return false ;
358                 }
359                 return true ;
360         }
361         function isCollection ()
362         {
363                 if ($this->get_inst_prop_value ( 'type' ) == 'collection')
364                 return true ; else
365                 return false ;
366         }
367
368         //get value of a property defined at the panel instance level.
369         function get_inst_prop_value ( $name )
370         {
371                 return isset($this->_instance_properties[$name]) ? $this->_instance_properties [ $name ] : null;
372         }
373         //get value of a property defined at the panel definition level.
374         function get_def_prop_value ( $name )
375         {
376                 if (isset ( $this->panel_definition [ $name ] ))
377                 {
378                         return $this->panel_definition [ $name ] ;
379                 } else
380                 {
381                         return null ;
382                 }
383         }
384
385         //if datasource is of the type function then return the function name
386         //else return the value as is.
387         function get_function_parameters ()
388         {
389                 $parameters = array ( ) ;
390                 if ($this->isDatasourceFunction ())
391                 {
392                         $parameters = $this->get_inst_prop_value ( 'function_parameters' ) ;
393                 }
394                 return $parameters ;
395         }
396
397         function get_data_source_name ( $check_set_subpanel_data = false )
398         {
399                 $prop_value = null ;
400                 if ($check_set_subpanel_data)
401                 {
402                         $prop_value = $this->get_inst_prop_value ( 'set_subpanel_data' ) ;
403                 }
404                 if (! empty ( $prop_value ))
405                 {
406                         return $prop_value ;
407                 } else
408                 {
409                         //fall back to default behavior.
410                 }
411                 if ($this->isDatasourceFunction ())
412                 {
413                         return (substr_replace ( $this->get_inst_prop_value ( 'get_subpanel_data' ), '', 0, 9 )) ;
414                 } else
415                 {
416                         return $this->get_inst_prop_value ( 'get_subpanel_data' ) ;
417                 }
418         }
419
420         //returns the where clause for the query.
421         function get_where ()
422         {
423                 return $this->get_def_prop_value ( 'where' ) ;
424         }
425
426         function is_fill_in_additional_fields ()
427         {
428                 // do both. inst_prop returns values from metadata/subpaneldefs.php and def_prop returns from subpanel/default.php
429                 $temp = $this->get_inst_prop_value ( 'fill_in_additional_fields' ) || $this->get_def_prop_value ( 'fill_in_additional_fields' ) ;
430                 return $temp ;
431         }
432
433         function get_list_fields ()
434         {
435                 if (isset ( $this->panel_definition [ 'list_fields' ] ))
436                 {
437                         return $this->panel_definition [ 'list_fields' ] ;
438                 } else
439                 {
440                         return array ( ) ;
441                 }
442         }
443
444         function get_module_name ()
445         {
446                 return $this->get_inst_prop_value ( 'module' ) ;
447         }
448
449         function get_name ()
450         {
451                 return $this->name ;
452         }
453
454         //load subpanel mdoule's table name and column fields.
455         function load_module_info ()
456         {
457                 global $beanList ;
458                 global $beanFiles ;
459
460                 $module_name = $this->get_module_name () ;
461                 if (! empty ( $module_name ))
462                 {
463
464                         $bean_name = $beanList [ $this->get_module_name () ] ;
465
466                         $this->bean_name = $bean_name ;
467
468                         include_once ($beanFiles [ $bean_name ]) ;
469                         $this->template_instance = new $bean_name ( ) ;
470                         $this->template_instance->force_load_details = true ;
471                         $this->table_name = $this->template_instance->table_name ;
472                         //$this->db_fields=$this->template_instance->column_fields;
473                 }
474         }
475         //this function is to be used only with sub-panels that are based
476         //on collections.
477         function get_header_panel_def ()
478         {
479                 if (! empty ( $this->sub_subpanels ))
480                 {
481                         if (! empty ( $this->_instance_properties [ 'header_definition_from_subpanel' ] ) && ! empty ( $this->sub_subpanels [ $this->_instance_properties [ 'header_definition_from_subpanel' ] ] ))
482                         {
483                                 return $this->sub_subpanels [ $this->_instance_properties [ 'header_definition_from_subpanel' ] ] ;
484                         } else
485                         {
486                                 $display_fields = array();
487                                 //If we are not pulling from a specific subpanel, create a list of all list fields and use that.
488                                 foreach($this->sub_subpanels as $subpanel)
489                                 {
490                                         $list_fields = $subpanel->get_list_fields();
491                                         foreach($list_fields as $field => $def)
492                                         {
493
494                                         }
495                                 }
496
497                                 reset ( $this->sub_subpanels ) ;
498                                 return current ( $this->sub_subpanels ) ;
499                         }
500                 }
501                 return null ;
502         }
503
504         /**
505          * Returns an array of current properties of the class.
506          * It will simply give the class name for instances of classes.
507          */
508         function _to_array ()
509         {
510                 return array ( '_instance_properties' => $this->_instance_properties , 'db_fields' => $this->db_fields , 'mod_strings' => $this->mod_strings , 'name' => $this->name , 'panel_definition' => $this->panel_definition , 'parent_bean' => get_class ( $this->parent_bean ) , 'sub_subpanels' => $this->sub_subpanels , 'table_name' => $this->table_name , 'template_instance' => get_class ( $this->template_instance ) ) ;
511         }
512 }
513 ;
514
515 class SubPanelDefinitions
516 {
517
518         var $_focus ;
519         var $_visible_tabs_array ;
520         var $panels ;
521         var $layout_defs ;
522
523         /**
524          * Enter description here...
525          *
526          * @param BEAN $focus - this is the bean you want to get the data from
527          * @param STRING $layout_def_key - if you wish to use a layout_def defined in the default metadata/subpaneldefs.php that is not keyed off of $bean->module_dir pass in the key here
528          * @param ARRAY $layout_def_override - if you wish to override the default loaded layout defs you pass them in here.
529          * @return SubPanelDefinitions
530          */
531         function SubPanelDefinitions ( $focus , $layout_def_key = '' , $layout_def_override = '' )
532         {
533                 $this->_focus = $focus ;
534                 if (! empty ( $layout_def_override ))
535                 {
536                         $this->layout_defs = $layout_def_override ;
537
538                 } else
539                 {
540                         $this->open_layout_defs ( false, $layout_def_key ) ;
541                 }
542         }
543
544         /**
545          * This function returns an ordered list of all "tabs", actually subpanels, for this module
546          * The source list is obtained from the subpanel layout contained in the layout_defs for this module,
547          * found either in the modules metadata/subpaneldefs.php file, or in the modules custom/.../Ext/Layoutdefs/layoutdefs.ext.php file
548          * and filtered through an ACL check.
549          * Note that the keys for the resulting array of tabs are in practice the name of the underlying source relationship for the subpanel
550          * So for example, the key for a custom module's subpanel with Accounts might be 'one_one_accounts', as generated by the Studio Relationship Editor
551          * Although OOB module subpanels have keys such as 'accounts', which might on the face of it appear to be a reference to the related module, in fact 'accounts' is still the relationship name
552          * @param boolean       Optional - include the subpanel title label in the return array (false)
553          * @return array        All tabs that pass an ACL check
554          */
555         function get_available_tabs ($FromGetModuleSubpanels=false)
556         {
557                 global $modListHeader ;
558                 global $modules_exempt_from_availability_check ;
559
560                 if (isset ( $this->_visible_tabs_array ))
561                         return $this->_visible_tabs_array ;
562
563                 if (empty($modListHeader))
564                     $modListHeader = query_module_access_list($GLOBALS['current_user']);
565
566                 $this->_visible_tabs_array = array ( ) ; // bug 16820 - make sure this is an array for the later ksort
567
568                 if (isset ( $this->layout_defs [ 'subpanel_setup' ] )) // bug 17434 - belts-and-braces - check that we have some subpanels first
569                 {
570                         //retrieve list of hidden subpanels
571                         $hidden_panels = $this->get_hidden_subpanels();
572
573                         //activities is a special use case in that if it is hidden,
574                         //then the history tab should be hidden too.
575                         if(!empty($hidden_panels) && is_array($hidden_panels) && in_array('activities',$hidden_panels)){
576                                 //add history to list hidden_panels
577                                 $hidden_panels['history'] = 'history';
578                         }
579
580                         foreach ( $this->layout_defs [ 'subpanel_setup' ] as $key => $values_array )
581                         {
582                                 //exclude if this subpanel is hidden from admin screens
583                 $module = $key;
584                 if ( isset($values_array['module']) )
585                     $module = strtolower($values_array['module']);
586                                  if ($hidden_panels && is_array($hidden_panels) && (in_array($module, $hidden_panels) || array_key_exists($module, $hidden_panels)) ){
587                                         //this panel is hidden, skip it
588                                         continue;
589                                  }
590
591                                 // make sure the module attribute is set, else none of this works...
592                                 if ( !isset($values_array [ 'module' ])) {
593                                         $GLOBALS['log']->debug("SubPanelDefinitions->get_available_tabs(): no module defined in subpaneldefs for '$key' =>" . var_export($values_array,true) . " - ingoring subpanel defintion") ;
594                                         continue;
595                                 }
596
597                                 //check permissions.
598                                 $exempt = array_key_exists ( $values_array [ 'module' ], $modules_exempt_from_availability_check ) ;
599                                 $ok = $exempt || ( (! ACLController::moduleSupportsACL ( $values_array [ 'module' ] ) || ACLController::checkAccess ( $values_array [ 'module' ], 'list', true ) ) ) ;
600
601                                 $GLOBALS [ 'log' ]->debug ( "SubPanelDefinitions->get_available_tabs(): " . $key . "= " . ( $exempt ? "exempt " : "not exempt " .( $ok ? " ACL OK" : "" ) ) ) ;
602
603                                 if ( $ok )
604                                 {
605                                         while ( ! empty ( $this->_visible_tabs_array [ $values_array [ 'order' ] ] ) )
606                                         {
607                                                 $values_array [ 'order' ] ++ ;
608                                         }
609
610                                         $this->_visible_tabs_array [ $values_array ['order'] ] = ($FromGetModuleSubpanels) ? array($key=>$values_array['title_key']) : $key ;
611                                 }
612                         }
613                 }
614
615                 ksort ( $this->_visible_tabs_array ) ;
616                 return $this->_visible_tabs_array ;
617         }
618
619         /**
620          * Load the definition of the a sub-panel.
621          * Also the sub-panel is added to an array of sub-panels.
622          * use of reload has been deprecated, since the subpanel is initialized every time.
623          */
624         function load_subpanel ( $name , $reload = false , $original_only = false )
625         {
626                 if (!is_dir('modules/' . $this->layout_defs [ 'subpanel_setup' ][ strtolower ( $name ) ] [ 'module' ]))
627                   return false;
628                 return new aSubPanel ( $name, $this->layout_defs [ 'subpanel_setup' ] [ strtolower ( $name ) ], $this->_focus, $reload, $original_only ) ;
629         }
630
631         /**
632          * Load the layout def file and associate the definition with a variable in the file.
633          */
634         function open_layout_defs ( $reload = false , $layout_def_key = '' , $original_only = false )
635         {
636                 $layout_defs [ $this->_focus->module_dir ] = array ( ) ;
637                 $layout_defs [ $layout_def_key ] = array ( ) ;
638
639                 if (empty ( $this->layout_defs ) || $reload || (! empty ( $layout_def_key ) && ! isset ( $layout_defs [ $layout_def_key ] )))
640                 {
641                         if (file_exists ( 'modules/' . $this->_focus->module_dir . '/metadata/subpaneldefs.php' ))
642                                 require ('modules/' . $this->_focus->module_dir . '/metadata/subpaneldefs.php') ;
643
644                         if (! $original_only && file_exists ( 'custom/modules/' . $this->_focus->module_dir . '/Ext/Layoutdefs/layoutdefs.ext.php' ))
645                                 require ('custom/modules/' . $this->_focus->module_dir . '/Ext/Layoutdefs/layoutdefs.ext.php') ;
646
647                         if (! empty ( $layout_def_key ))
648                                 $this->layout_defs = $layout_defs [ $layout_def_key ] ;
649                         else
650                                 $this->layout_defs = $layout_defs [ $this->_focus->module_dir ] ;
651
652                 }
653
654         }
655
656         /**
657          * Removes a tab from the list of loaded tabs.
658          * Returns true if successful, false otherwise.
659          * Hint: Used by Campaign's DetailView.
660          */
661         function exclude_tab ( $tab_name )
662         {
663                 $result = false ;
664                 //unset layout definition
665                 if (! empty ( $this->layout_defs [ 'subpanel_setup' ] [ $tab_name ] ))
666                 {
667                         unset ( $this->layout_defs [ 'subpanel_setup' ] [ $tab_name ] ) ;
668                 }
669                 //unset instance from _visible_tab_array
670                 if (! empty ( $this->_visible_tabs_array ))
671                 {
672                         $key = array_search ( $tab_name, $this->_visible_tabs_array ) ;
673                         if ($key !== false)
674                         {
675                                 unset ( $this->_visible_tabs_array [ $key ] ) ;
676                         }
677                 }
678                 return $result ;
679         }
680
681
682         /**
683          * return all available subpanels that belong to the list of tab modules.  You can optionally return all
684          * available subpanels, and also optionally group by module (prepends the key with the bean class name).
685          */
686         function get_all_subpanels( $return_tab_modules_only = true, $group_by_module = false )
687         {
688                 global $moduleList, $beanFiles, $beanList, $module;
689
690                 //use tab controller function to get module list with named keys
691                 require_once("modules/MySettings/TabController.php");
692                 $modules_to_check = TabController::get_key_array($moduleList);
693
694                 //change case to match subpanel processing later on
695                 $modules_to_check = array_change_key_case($modules_to_check);
696         // Append on the CampaignLog module, because that is where the subpanels point, not directly to Campaigns
697         $modules_to_check['campaignlog'] = "CampaignLog";
698
699
700                 $spd = '';
701                 $spd_arr = array();
702                 //iterate through modules and build subpanel array
703                 foreach($modules_to_check as $mod_name){
704
705                         //skip if module name is not in bean list, otherwise get the bean class name
706                         if(!isset($beanList[$mod_name])) continue;
707                         $class = $beanList[$mod_name];
708
709                         //skip if class name is not in file list, otherwise require the bean file and create new class
710                         if(!isset($beanFiles[$class]) || !file_exists($beanFiles[$class])) continue;
711
712                         //retrieve subpanels for this bean
713                         require_once($beanFiles[$class]);
714                         $bean_class = new $class();
715
716                         //create new subpanel definition instance and get list of tabs
717                         $spd = new SubPanelDefinitions($bean_class) ;
718                         $sub_tabs = $spd->get_available_tabs();
719
720                         //add each subpanel to array of total subpanles
721                         foreach( $sub_tabs as $panel_key){
722                                 $panel_key = strtolower($panel_key);
723                 $panel_module = $panel_key;
724                 if ( isset($spd->layout_defs['subpanel_setup'][$panel_key]['module']) )
725                     $panel_module = strtolower($spd->layout_defs['subpanel_setup'][$panel_key]['module']);
726                 //if module_only flag is set, only if it is also in module array
727                                 if($return_tab_modules_only && !array_key_exists($panel_module, $modules_to_check)) continue;
728                                 $panel_key_name = $panel_module;
729
730                                 //group_by_key_name is set to true, then array will hold an entry for each
731                                 //subpanel, with the module name prepended in the key
732                                 if($group_by_module) $panel_key_name = $class.'_'.$panel_key_name;
733                                 //add panel name to subpanel array
734                                 $spd_arr[$panel_key_name] = $panel_module;
735                         }
736                 }
737                 return  $spd_arr;
738         }
739
740         /*
741          * save array of hidden panels to mysettings category in config table
742          */
743         function set_hidden_subpanels($panels){
744                 $administration = new Administration();
745                 $serialized = base64_encode(serialize($panels));
746                 $administration->saveSetting('MySettings', 'hide_subpanels', $serialized);
747         }
748
749         /*
750          * retrieve hidden subpanels
751          */
752         function get_hidden_subpanels(){
753                 global $moduleList;
754
755                 //create variable as static to minimize queries
756                 static $hidden_subpanels = null;
757
758                 // if the static value is not already cached, then retrieve it.
759                 if(empty($hidden_subpanels))
760                 {
761
762                         //create Administration object and retrieve any settings for panels
763                         $administration = new Administration();
764                         $administration->retrieveSettings('MySettings');
765
766                         if(isset($administration->settings) && isset($administration->settings['MySettings_hide_subpanels'])){
767                                 $hidden_subpanels = $administration->settings['MySettings_hide_subpanels'];
768                                 $hidden_subpanels = trim($hidden_subpanels);
769
770                                 //make sure serialized string is not empty
771                                 if (!empty($hidden_subpanels)){
772                                         //decode and unserialize to retrieve the array
773                                         $hidden_subpanels = base64_decode($hidden_subpanels);
774                                         $hidden_subpanels = unserialize($hidden_subpanels);
775
776                                         //Ensure modules saved in the preferences exist.
777                                         //get user preference
778                                         //unserialize and add to array if not empty
779                                         $pref_hidden = array();
780                                         foreach($pref_hidden as $id => $pref_hidden_panel) {
781                                                 $hidden_subpanels[] = $pref_hidden_panel;
782                                         }
783
784
785                                 }else{
786                                         //no settings found, return empty
787                                         return $hidden_subpanels;
788                                 }
789                         }
790                         else
791                         {       //no settings found, return empty
792                                 return $hidden_subpanels;
793                         }
794                 }
795
796                 return $hidden_subpanels;
797         }
798
799
800 }
801 ?>