]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - include/SubPanel/SubPanelDefinitions.php
Release 6.5.10
[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-2013 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     /**
64      * Can we display this subpanel?
65      *
66      * This is set after it loads the def's for the subpanel.  If there are no beans to display in the collection
67      * we don't want to display this as it will just throw errors.
68      *
69      * @var bool
70      */
71     var $canDisplay = true;
72
73         //module's table name and column fields.
74         var $table_name ;
75         var $db_fields ;
76         var $bean_name ;
77         var $template_instance ;
78
79         function aSubPanel ( $name , $instance_properties , $parent_bean , $reload = false , $original_only = false )
80         {
81
82                 $this->_instance_properties = $instance_properties ;
83                 $this->name = $name ;
84                 $this->parent_bean = $parent_bean ;
85
86                 //set language
87                 global $current_language ;
88                 if (! isset ( $parent_bean->mbvardefs ))
89                 {
90                         $mod_strings = return_module_language ( $current_language, $parent_bean->module_dir ) ;
91                 }
92                 $this->mod_strings = $mod_strings ;
93
94         if ($this->isCollection ())
95                 {
96                         $this->canDisplay = $this->load_sub_subpanels () ; //load sub-panel definition.
97                 } else
98                 {
99                         if (!is_dir('modules/' . $this->_instance_properties [ 'module' ])){
100                                 _pstack_trace();
101                         }
102                         $def_path = 'modules/' . $this->_instance_properties [ 'module' ] . '/metadata/subpanels/' . $this->_instance_properties [ 'subpanel_name' ] . '.php' ;
103
104                         $orig_exists = is_file($def_path);
105                         $loaded = false;
106                         if ($orig_exists)
107                         {
108                                 require ($def_path);
109                                 $loaded = true;
110                         }
111                         if (is_file("custom/$def_path") && (!$original_only  || !$orig_exists))
112                         {
113                                 require ("custom/$def_path");
114                                 $loaded = true;
115                         }
116
117                         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' ))
118                         {
119                                 $cust_def_path = 'custom/modules/' . $this->_instance_properties [ 'module' ] . '/metadata/subpanels/' . $this->_instance_properties [ 'override_subpanel_name' ] . '.php' ;
120                                 require ($cust_def_path) ;
121                                 $loaded = true;
122                         }
123
124                         if (!$loaded)
125                         {
126                                 $GLOBALS['log']->fatal("Failed to load original or custom subpanel data for $name in $def_path");
127                 $this->canDisplay = false;
128                         }
129
130             // load module info from the module's bean file
131             $this->load_module_info();
132
133             // check that the loaded subpanel definition includes a $subpanel_layout section - some, such as
134             // projecttasks/default do not...
135             $this->panel_definition = array();
136             if (isset($subpanel_layout) && is_array($subpanel_layout)) {
137                 $this->set_panel_definition($subpanel_layout);
138
139                         }
140                 }
141
142         }
143
144     /**
145      * is the sub panel default hidden?
146      *
147      * @return bool
148      */
149     public function isDefaultHidden()
150     {
151         if(isset($this->_instance_properties['default_hidden']) && $this->_instance_properties['default_hidden'] == true) {
152             return true;
153         }
154
155         return false;
156     }
157
158
159         function distinct_query ()
160         {
161                 if (isset ( $this->_instance_properties [ 'get_distinct_data' ] ))
162                 {
163                         return !empty($this->_instance_properties['get_distinct_data']) ? true : false;
164                 }
165                 return false ;
166         }
167
168         //return the translated header value.
169         function get_title ()
170         {
171                 if (empty ( $this->mod_strings [ $this->_instance_properties [ 'title_key' ] ] ))
172                 {
173                         return translate ( $this->_instance_properties [ 'title_key' ], $this->_instance_properties [ 'module' ] ) ;
174                 }
175                 return $this->mod_strings [ $this->_instance_properties [ 'title_key' ] ] ;
176         }
177
178         //return the definition of buttons. looks for buttons in 2 locations.
179         function get_buttons ()
180         {
181                 $buttons = array ( ) ;
182                 if (isset ( $this->_instance_properties [ 'top_buttons' ] ))
183                 {
184                         //this will happen only in the case of sub-panels with multiple sources(activities).
185                         $buttons = $this->_instance_properties [ 'top_buttons' ] ;
186                 } else
187                 {
188                         $buttons = $this->panel_definition [ 'top_buttons' ] ;
189                 }
190
191                 // permissions. hide SubPanelTopComposeEmailButton from activities if email module is disabled.
192                 //only email is  being tested becuase other submodules in activites/history such as notes, tasks, meetings and calls cannot be disabled.
193                 //as of today these are the only 2 sub-panels that use the union clause.
194                 $mod_name = $this->get_module_name () ;
195                 if ($mod_name == 'Activities' || $mod_name == 'History')
196                 {
197                         global $modListHeader ;
198                         global $modules_exempt_from_availability_check ;
199                         if (isset ( $modListHeader ) && (! (array_key_exists ( 'Emails', $modListHeader ) or array_key_exists ( 'Emails', $modules_exempt_from_availability_check ))))
200                         {
201                                 foreach ( $buttons as $key => $button )
202                                 {
203                                         foreach ( $button as $property => $value )
204                                         {
205                                                 if ($value === 'SubPanelTopComposeEmailButton' || $value === 'SubPanelTopArchiveEmailButton')
206                                                 {
207                                                         //remove this button from the array.
208                                                         unset ( $buttons [ $key ] ) ;
209                                                 }
210                                         }
211                                 }
212                         }
213                 }
214
215                 return $buttons ;
216         }
217
218
219     /**
220      * Load the Sub-Panel objects if it can from the metadata files.
221      *
222      * call this function for sub-panels that have unions.
223      *
224      * @return bool         True by default if the subpanel was loaded.  Will return false if none in the collection are
225      *                      allowed by the current user.
226      */
227         function load_sub_subpanels ()
228         {
229
230                 global $modListHeader ;
231                 // added a check for security of tabs to see if an user has access to them
232                 // this prevents passing an "unseen" tab to the query string and pulling up its contents
233                 if (! isset ( $modListHeader ))
234                 {
235                         global $current_user ;
236                         if (isset ( $current_user ))
237                         {
238                                 $modListHeader = query_module_access_list ( $current_user ) ;
239                         }
240                 }
241
242         //by default all the activities modules are exempt, so hiding them won't affect their appearance unless the 'activity' subpanel itself is hidden.
243         //add email to the list temporarily so it is not affected in activities subpanel
244         global $modules_exempt_from_availability_check ;
245         $modules_exempt_from_availability_check['Emails'] = 'Emails';
246
247                 $listFieldMap = array();
248
249                 if (empty ( $this->sub_subpanels ))
250                 {
251                         $panels = $this->get_inst_prop_value ( 'collection_list' ) ;
252                         foreach ( $panels as $panel => $properties )
253                         {
254                                 if (array_key_exists ( $properties [ 'module' ], $modListHeader ) or array_key_exists ( $properties [ 'module' ], $modules_exempt_from_availability_check ))
255                                 {
256                                         $this->sub_subpanels [ $panel ] = new aSubPanel ( $panel, $properties, $this->parent_bean ) ;
257                                 }
258                         }
259             // if it's empty just dump out as there is nothing to process.
260             if(empty($this->sub_subpanels)) return false;
261                         //Sync displayed list fields across the subpanels
262                         $display_fields = $this->getDisplayFieldsFromCollection($this->sub_subpanels);
263                         $query_fields = array();
264                         foreach ( $this->sub_subpanels as $key => $subpanel )
265                         {
266                                 $list_fields = $subpanel->get_list_fields();
267                                 $listFieldMap[$key] = array();
268                                 $index = 0;
269                                 foreach($list_fields as $field => $def)
270                                 {
271                                         if (isset($def['vname']) && isset($def['width']))
272                                         {
273                                                 $index++;
274                                                 if(!empty($def['alias']))
275                                                         $listFieldMap[$key][$def['alias']] = $field;
276                                                 else
277                                                         $listFieldMap[$key][$field] = $field;
278                                                 if (!isset($display_fields[$def['vname']]))
279                                                 {
280                                                         if(sizeof($display_fields) > $index)
281                                                         {
282                                                                 //Try to insert the new field in an order that makes sense
283                                                                 $start = array_slice($display_fields, 0, $index);
284                                                                 $end = array_slice($display_fields, $index);
285                                                                 $display_fields = array_merge(
286                                                                         $start,
287                                                                         array($def['vname'] => array('name' => $field, 'vname' => $def['vname'], 'width' => $def['width'] )),
288                                                                         $end
289                                                                 );
290                                                         } else
291                                                         {
292                                                                 $display_fields[$def['vname']] = array(
293                                                                         'name' => empty($def['alias']) ? $field : $def['alias'],
294                                                                         'vname' => $def['vname'],
295                                                                         'width' => $def['width'],
296                                                                 );
297                                                         }
298                                                 }
299                                         } else {
300                                                 $query_fields[$field] = $def;
301                                         }
302                                 }
303                         }
304                         foreach ( $this->sub_subpanels as $key => $subpanel )
305                         {
306                                 $list_fields = array();
307                                 foreach($display_fields as $vname => $def)
308                                 {
309                                         $field = $def['name'];
310                                         $list_key = isset($listFieldMap[$key][$field]) ? $listFieldMap[$key][$field] : $field;
311
312                                         if (isset($subpanel->panel_definition['list_fields'][$field]))
313                                         {
314                                                 $list_fields[$field] = $subpanel->panel_definition['list_fields'][$field];
315                                         }
316                                     else if ($list_key != $field && isset($subpanel->panel_definition['list_fields'][$list_key]))
317                     {
318                         $list_fields[$list_key] = $subpanel->panel_definition['list_fields'][$list_key];
319
320                     }
321                                         else {
322                                                 $list_fields[$field] = $display_fields[$vname];
323                                         }
324                                 }
325                                 foreach($query_fields as $field => $def)
326                                 {
327                                         if (isset($subpanel->panel_definition['list_fields'][$field]))
328                                         {
329                                                 $list_fields[$field] = $subpanel->panel_definition['list_fields'][$field];
330                                         }
331                                         else {
332                                                 $list_fields[$field] = $def;
333                                         }
334                                 }
335                                 $subpanel->panel_definition['list_fields'] = $list_fields;
336                         }
337                 }
338
339         return true;
340         }
341
342         protected function getDisplayFieldsFromCollection($sub_subpanels)
343         {
344                 $display_fields = array();
345                 foreach ($sub_subpanels as $key => $subpanel )
346                 {
347                         $list_fields = $subpanel->get_list_fields();
348                         $index = 0;
349                         foreach($list_fields as $field => $def)
350                         {
351                                 if (isset($def['vname']) && isset($def['width']))
352                                 {
353                                         $index++;
354                                         if (!isset($display_fields[$def['vname']]))
355                                         {
356                                                 if(sizeof($display_fields) > $index)
357                                                 {
358                                                         //Try to insert the new field in an order that makes sense
359                                                         $start = array_slice($display_fields, 0, $index);
360                                                         $end = array_slice($display_fields, $index);
361                                                         $display_fields = array_merge(
362                                                                 $start,
363                                                                 array($def['vname'] => array('name' => $field, 'vname' => $def['vname'], 'width' => $def['width'] )),
364                                                                 $end
365                                                         );
366                                                 } else
367                                                 {
368                                                         $display_fields[$def['vname']] = array(
369                                                                 'name' => $field,
370                                                                 'vname' => $def['vname'],
371                                                                 'width' => $def['width'],
372                                                         );
373                                                 }
374                                         }
375                                 }
376                         }
377                 }
378         }
379
380         function isDatasourceFunction ()
381         {
382                 if (strpos ( $this->get_inst_prop_value ( 'get_subpanel_data' ), 'function' ) === false)
383                 {
384                         return false ;
385                 }
386                 return true ;
387         }
388
389     /**
390      * Test to see if the sub panels defs contain a collection
391      *
392      * @return bool
393      */
394         function isCollection ()
395         {
396                 return ($this->get_inst_prop_value ( 'type' ) == 'collection');
397         }
398
399         //get value of a property defined at the panel instance level.
400         function get_inst_prop_value ( $name )
401         {
402                 return isset($this->_instance_properties[$name]) ? $this->_instance_properties [ $name ] : null;
403         }
404         //get value of a property defined at the panel definition level.
405         function get_def_prop_value ( $name )
406         {
407                 if (isset ( $this->panel_definition [ $name ] ))
408                 {
409                         return $this->panel_definition [ $name ] ;
410                 } else
411                 {
412                         return null ;
413                 }
414         }
415
416         //if datasource is of the type function then return the function name
417         //else return the value as is.
418         function get_function_parameters ()
419         {
420                 $parameters = array ( ) ;
421                 if ($this->isDatasourceFunction ())
422                 {
423                         $parameters = $this->get_inst_prop_value ( 'function_parameters' ) ;
424                 }
425                 return $parameters ;
426         }
427
428         function get_data_source_name ( $check_set_subpanel_data = false )
429         {
430                 $prop_value = null ;
431                 if ($check_set_subpanel_data)
432                 {
433                         $prop_value = $this->get_inst_prop_value ( 'set_subpanel_data' ) ;
434                 }
435                 if (! empty ( $prop_value ))
436                 {
437                         return $prop_value ;
438                 } else
439                 {
440                         //fall back to default behavior.
441                 }
442                 if ($this->isDatasourceFunction ())
443                 {
444                         return (substr_replace ( $this->get_inst_prop_value ( 'get_subpanel_data' ), '', 0, 9 )) ;
445                 } else
446                 {
447                         return $this->get_inst_prop_value ( 'get_subpanel_data' ) ;
448                 }
449         }
450
451         //returns the where clause for the query.
452         function get_where ()
453         {
454                 return $this->get_def_prop_value ( 'where' ) ;
455         }
456
457         function is_fill_in_additional_fields ()
458         {
459                 // do both. inst_prop returns values from metadata/subpaneldefs.php and def_prop returns from subpanel/default.php
460                 $temp = $this->get_inst_prop_value ( 'fill_in_additional_fields' ) || $this->get_def_prop_value ( 'fill_in_additional_fields' ) ;
461                 return $temp ;
462         }
463
464         function get_list_fields ()
465         {
466                 if (isset ( $this->panel_definition [ 'list_fields' ] ))
467                 {
468                         return $this->panel_definition [ 'list_fields' ] ;
469                 } else
470                 {
471                         return array ( ) ;
472                 }
473         }
474
475         function get_module_name ()
476         {
477                 return $this->get_inst_prop_value ( 'module' ) ;
478         }
479
480         function get_name ()
481         {
482                 return $this->name ;
483         }
484
485         //load subpanel module's table name and column fields.
486         function load_module_info ()
487         {
488                 global $beanList ;
489                 global $beanFiles ;
490
491                 $module_name = $this->get_module_name () ;
492                 if (! empty ( $module_name ))
493                 {
494
495                         $bean_name = $beanList [ $this->get_module_name () ] ;
496
497                         $this->bean_name = $bean_name ;
498
499                         include_once ($beanFiles [ $bean_name ]) ;
500                         $this->template_instance = new $bean_name ( ) ;
501                         $this->template_instance->force_load_details = true ;
502                         $this->table_name = $this->template_instance->table_name ;
503                         //$this->db_fields=$this->template_instance->column_fields;
504                 }
505         }
506         //this function is to be used only with sub-panels that are based
507         //on collections.
508         function get_header_panel_def ()
509         {
510                 if (! empty ( $this->sub_subpanels ))
511                 {
512                         if (! empty ( $this->_instance_properties [ 'header_definition_from_subpanel' ] ) && ! empty ( $this->sub_subpanels [ $this->_instance_properties [ 'header_definition_from_subpanel' ] ] ))
513                         {
514                                 return $this->sub_subpanels [ $this->_instance_properties [ 'header_definition_from_subpanel' ] ] ;
515                         } else
516                         {
517                                 $display_fields = array();
518                                 //If we are not pulling from a specific subpanel, create a list of all list fields and use that.
519                                 foreach($this->sub_subpanels as $subpanel)
520                                 {
521                                         $list_fields = $subpanel->get_list_fields();
522                                         foreach($list_fields as $field => $def)
523                                         {
524
525                                         }
526                                 }
527
528                                 reset ( $this->sub_subpanels ) ;
529                                 return current ( $this->sub_subpanels ) ;
530                         }
531                 }
532                 return null ;
533         }
534
535         /**
536          * Returns an array of current properties of the class.
537          * It will simply give the class name for instances of classes.
538          */
539         function _to_array ()
540         {
541                 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 ) ) ;
542         }
543
544     /**
545      * Sets definition of the subpanel
546      *
547      * @param array $definition
548      */
549     protected function set_panel_definition(array $definition)
550     {
551         $this->panel_definition = $definition;
552     }
553
554 }
555 ;
556
557 class SubPanelDefinitions
558 {
559
560         var $_focus ;
561         var $_visible_tabs_array ;
562         var $panels ;
563         var $layout_defs ;
564
565         /**
566          * Enter description here...
567          *
568          * @param BEAN $focus - this is the bean you want to get the data from
569          * @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
570          * @param ARRAY $layout_def_override - if you wish to override the default loaded layout defs you pass them in here.
571          * @return SubPanelDefinitions
572          */
573         function SubPanelDefinitions ( $focus , $layout_def_key = '' , $layout_def_override = '' )
574         {
575                 $this->_focus = $focus ;
576                 if (! empty ( $layout_def_override ))
577                 {
578                         $this->layout_defs = $layout_def_override ;
579
580                 } else
581                 {
582                         $this->open_layout_defs ( false, $layout_def_key ) ;
583                 }
584         }
585
586         /**
587          * This function returns an ordered list of all "tabs", actually subpanels, for this module
588          * The source list is obtained from the subpanel layout contained in the layout_defs for this module,
589          * found either in the modules metadata/subpaneldefs.php file, or in the modules custom/.../Ext/Layoutdefs/layoutdefs.ext.php file
590          * and filtered through an ACL check.
591          * Note that the keys for the resulting array of tabs are in practice the name of the underlying source relationship for the subpanel
592          * 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
593          * 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
594          * @param boolean       Optional - include the subpanel title label in the return array (false)
595          * @return array        All tabs that pass an ACL check
596          */
597         function get_available_tabs ($FromGetModuleSubpanels=false)
598         {
599                 global $modListHeader ;
600                 global $modules_exempt_from_availability_check ;
601
602                 if (isset ( $this->_visible_tabs_array ))
603                         return $this->_visible_tabs_array ;
604
605                 if (empty($modListHeader))
606                     $modListHeader = query_module_access_list($GLOBALS['current_user']);
607
608                 $this->_visible_tabs_array = array ( ) ; // bug 16820 - make sure this is an array for the later ksort
609
610                 if (isset ( $this->layout_defs [ 'subpanel_setup' ] )) // bug 17434 - belts-and-braces - check that we have some subpanels first
611                 {
612                         //retrieve list of hidden subpanels
613                         $hidden_panels = $this->get_hidden_subpanels();
614
615                         //activities is a special use case in that if it is hidden,
616                         //then the history tab should be hidden too.
617                         if(!empty($hidden_panels) && is_array($hidden_panels) && in_array('activities',$hidden_panels)){
618                                 //add history to list hidden_panels
619                                 $hidden_panels['history'] = 'history';
620                         }
621
622                         foreach ( $this->layout_defs [ 'subpanel_setup' ] as $key => $values_array )
623                         {
624                                 //exclude if this subpanel is hidden from admin screens
625                 $module = $key;
626                 if ( isset($values_array['module']) )
627                     $module = strtolower($values_array['module']);
628                                  if ($hidden_panels && is_array($hidden_panels) && (in_array($module, $hidden_panels) || array_key_exists($module, $hidden_panels)) ){
629                                         //this panel is hidden, skip it
630                                         continue;
631                                  }
632
633                                 // make sure the module attribute is set, else none of this works...
634                                 if ( !isset($values_array [ 'module' ])) {
635                                         $GLOBALS['log']->debug("SubPanelDefinitions->get_available_tabs(): no module defined in subpaneldefs for '$key' =>" . var_export($values_array,true) . " - ingoring subpanel defintion") ;
636                                         continue;
637                                 }
638
639                                 //check permissions.
640                                 $exempt = array_key_exists ( $values_array [ 'module' ], $modules_exempt_from_availability_check ) ;
641                                 $ok = $exempt || ( (! ACLController::moduleSupportsACL ( $values_array [ 'module' ] ) || ACLController::checkAccess ( $values_array [ 'module' ], 'list', true ) ) ) ;
642
643                                 $GLOBALS [ 'log' ]->debug ( "SubPanelDefinitions->get_available_tabs(): " . $key . "= " . ( $exempt ? "exempt " : "not exempt " .( $ok ? " ACL OK" : "" ) ) ) ;
644
645                                 if ( $ok )
646                                 {
647                                         while ( ! empty ( $this->_visible_tabs_array [ $values_array [ 'order' ] ] ) )
648                                         {
649                                                 $values_array [ 'order' ] ++ ;
650                                         }
651
652                                         $this->_visible_tabs_array [ $values_array ['order'] ] = ($FromGetModuleSubpanels) ? array($key=>$values_array['title_key']) : $key ;
653                                 }
654                         }
655                 }
656
657                 ksort ( $this->_visible_tabs_array ) ;
658                 return $this->_visible_tabs_array ;
659         }
660
661         /**
662          * Load the definition of the a sub-panel.
663          * Also the sub-panel is added to an array of sub-panels.
664          * use of reload has been deprecated, since the subpanel is initialized every time.
665      *
666      * @param string $name              The name of the sub-panel to reload
667      * @param boolean $reload           Reload the sub-panel (unused)
668      * @param boolean $original_only    Only load the original sub-panel and no custom ones
669      * @return boolean|aSubPanel        Returns aSubPanel object or boolean false if one is not found or it can't be
670      *      displayed due to ACL reasons.
671          */
672         function load_subpanel ( $name , $reload = false , $original_only = false )
673         {
674                 if (!is_dir('modules/' . $this->layout_defs [ 'subpanel_setup' ][ strtolower ( $name ) ] [ 'module' ]))
675                   return false;
676
677         $subpanel = new aSubPanel ( $name, $this->layout_defs [ 'subpanel_setup' ] [ strtolower ( $name ) ], $this->_focus, $reload, $original_only ) ;
678
679         // only return the subpanel object if we can display it.
680         if($subpanel->canDisplay == true) {
681             return $subpanel;
682         }
683
684         // by default return false so we don't show anything if it's not required.
685         return false;
686         }
687
688         /**
689          * Load the layout def file and associate the definition with a variable in the file.
690          */
691         function open_layout_defs ( $reload = false , $layout_def_key = '' , $original_only = false )
692         {
693                 $layout_defs [ $this->_focus->module_dir ] = array ( ) ;
694                 $layout_defs [ $layout_def_key ] = array ( ) ;
695
696                 if (empty ( $this->layout_defs ) || $reload || (! empty ( $layout_def_key ) && ! isset ( $layout_defs [ $layout_def_key ] )))
697                 {
698                         if (file_exists ( 'modules/' . $this->_focus->module_dir . '/metadata/subpaneldefs.php' ))
699                                 require ('modules/' . $this->_focus->module_dir . '/metadata/subpaneldefs.php') ;
700
701                         if (! $original_only && file_exists ( 'custom/modules/' . $this->_focus->module_dir . '/Ext/Layoutdefs/layoutdefs.ext.php' ))
702                                 require ('custom/modules/' . $this->_focus->module_dir . '/Ext/Layoutdefs/layoutdefs.ext.php') ;
703
704                         if (! empty ( $layout_def_key ))
705                                 $this->layout_defs = $layout_defs [ $layout_def_key ] ;
706                         else
707                                 $this->layout_defs = $layout_defs [ $this->_focus->module_dir ] ;
708
709                 }
710
711         }
712
713         /**
714          * Removes a tab from the list of loaded tabs.
715          * Returns true if successful, false otherwise.
716          * Hint: Used by Campaign's DetailView.
717          */
718         function exclude_tab ( $tab_name )
719         {
720                 $result = false ;
721                 //unset layout definition
722                 if (! empty ( $this->layout_defs [ 'subpanel_setup' ] [ $tab_name ] ))
723                 {
724                         unset ( $this->layout_defs [ 'subpanel_setup' ] [ $tab_name ] ) ;
725                 }
726                 //unset instance from _visible_tab_array
727                 if (! empty ( $this->_visible_tabs_array ))
728                 {
729                         $key = array_search ( $tab_name, $this->_visible_tabs_array ) ;
730                         if ($key !== false)
731                         {
732                                 unset ( $this->_visible_tabs_array [ $key ] ) ;
733                         }
734                 }
735                 return $result ;
736         }
737
738
739         /**
740          * return all available subpanels that belong to the list of tab modules.  You can optionally return all
741          * available subpanels, and also optionally group by module (prepends the key with the bean class name).
742          */
743         function get_all_subpanels( $return_tab_modules_only = true, $group_by_module = false )
744         {
745                 global $moduleList, $beanFiles, $beanList, $module;
746
747                 //use tab controller function to get module list with named keys
748                 require_once("modules/MySettings/TabController.php");
749                 $modules_to_check = TabController::get_key_array($moduleList);
750
751                 //change case to match subpanel processing later on
752                 $modules_to_check = array_change_key_case($modules_to_check);
753         // Append on the CampaignLog module, because that is where the subpanels point, not directly to Campaigns
754         $modules_to_check['campaignlog'] = "CampaignLog";
755
756
757                 $spd = '';
758                 $spd_arr = array();
759                 //iterate through modules and build subpanel array
760                 foreach($modules_to_check as $mod_name){
761
762                         //skip if module name is not in bean list, otherwise get the bean class name
763                         if(!isset($beanList[$mod_name])) continue;
764                         $class = $beanList[$mod_name];
765
766                         //skip if class name is not in file list, otherwise require the bean file and create new class
767                         if(!isset($beanFiles[$class]) || !file_exists($beanFiles[$class])) continue;
768
769                         //retrieve subpanels for this bean
770                         require_once($beanFiles[$class]);
771                         $bean_class = new $class();
772
773                         //create new subpanel definition instance and get list of tabs
774                         $spd = new SubPanelDefinitions($bean_class) ;
775                         $sub_tabs = $spd->get_available_tabs();
776
777                         //add each subpanel to array of total subpanles
778                         foreach( $sub_tabs as $panel_key){
779                                 $panel_key = strtolower($panel_key);
780                 $panel_module = $panel_key;
781                 if ( isset($spd->layout_defs['subpanel_setup'][$panel_key]['module']) )
782                     $panel_module = strtolower($spd->layout_defs['subpanel_setup'][$panel_key]['module']);
783                 //if module_only flag is set, only if it is also in module array
784                                 if($return_tab_modules_only && !array_key_exists($panel_module, $modules_to_check)) continue;
785                                 $panel_key_name = $panel_module;
786
787                                 //group_by_key_name is set to true, then array will hold an entry for each
788                                 //subpanel, with the module name prepended in the key
789                                 if($group_by_module) $panel_key_name = $class.'_'.$panel_key_name;
790                                 //add panel name to subpanel array
791                                 $spd_arr[$panel_key_name] = $panel_module;
792                         }
793                 }
794                 return  $spd_arr;
795         }
796
797         /*
798          * save array of hidden panels to mysettings category in config table
799          */
800         function set_hidden_subpanels($panels){
801                 $administration = new Administration();
802                 $serialized = base64_encode(serialize($panels));
803                 $administration->saveSetting('MySettings', 'hide_subpanels', $serialized);
804         }
805
806         /*
807          * retrieve hidden subpanels
808          */
809         function get_hidden_subpanels(){
810                 global $moduleList;
811
812                 //create variable as static to minimize queries
813                 static $hidden_subpanels = null;
814
815                 // if the static value is not already cached, then retrieve it.
816                 if(empty($hidden_subpanels))
817                 {
818
819                         //create Administration object and retrieve any settings for panels
820                         $administration = new Administration();
821                         $administration->retrieveSettings('MySettings');
822
823                         if(isset($administration->settings) && isset($administration->settings['MySettings_hide_subpanels'])){
824                                 $hidden_subpanels = $administration->settings['MySettings_hide_subpanels'];
825                                 $hidden_subpanels = trim($hidden_subpanels);
826
827                                 //make sure serialized string is not empty
828                                 if (!empty($hidden_subpanels)){
829                                         //decode and unserialize to retrieve the array
830                                         $hidden_subpanels = base64_decode($hidden_subpanels);
831                                         $hidden_subpanels = unserialize($hidden_subpanels);
832
833                                         //Ensure modules saved in the preferences exist.
834                                         //get user preference
835                                         //unserialize and add to array if not empty
836                                         $pref_hidden = array();
837                                         foreach($pref_hidden as $id => $pref_hidden_panel) {
838                                                 $hidden_subpanels[] = $pref_hidden_panel;
839                                         }
840
841
842                                 }else{
843                                         //no settings found, return empty
844                                         return $hidden_subpanels;
845                                 }
846                         }
847                         else
848                         {       //no settings found, return empty
849                                 return $hidden_subpanels;
850                         }
851                 }
852
853                 return $hidden_subpanels;
854         }
855
856
857 }
858 ?>