Issues (4069)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

include/SubPanel/SubPanelTiles.php (4 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
3
/*********************************************************************************
4
 * SugarCRM Community Edition is a customer relationship management program developed by
5
 * SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
6
7
 * SuiteCRM is an extension to SugarCRM Community Edition developed by Salesagility Ltd.
8
 * Copyright (C) 2011 - 2014 Salesagility Ltd.
9
 *
10
 * This program is free software; you can redistribute it and/or modify it under
11
 * the terms of the GNU Affero General Public License version 3 as published by the
12
 * Free Software Foundation with the addition of the following permission added
13
 * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
14
 * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
15
 * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
16
 *
17
 * This program is distributed in the hope that it will be useful, but WITHOUT
18
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
19
 * FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
20
 * details.
21
 *
22
 * You should have received a copy of the GNU Affero General Public License along with
23
 * this program; if not, see http://www.gnu.org/licenses or write to the Free
24
 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25
 * 02110-1301 USA.
26
 *
27
 * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
28
 * SW2-130, Cupertino, CA 95014, USA. or at email address [email protected].
29
 *
30
 * The interactive user interfaces in modified source and object code versions
31
 * of this program must display Appropriate Legal Notices, as required under
32
 * Section 5 of the GNU Affero General Public License version 3.
33
 *
34
 * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
35
 * these Appropriate Legal Notices must retain the display of the "Powered by
36
 * SugarCRM" logo and "Supercharged by SuiteCRM" logo. If the display of the logos is not
37
 * reasonably feasible for  technical reasons, the Appropriate Legal Notices must
38
 * display the words  "Powered by SugarCRM" and "Supercharged by SuiteCRM".
39
 ********************************************************************************/
40
41
42
require_once('include/SubPanel/SubPanel.php');
43
require_once('include/SubPanel/SubPanelTilesTabs.php');
44
require_once('include/SubPanel/SubPanelDefinitions.php');
45
46
/**
47
 * Subpanel tiles
48
 * @api
49
 */
50
class SubPanelTiles
51
{
52
	var $id;
53
	var $module;
54
	var $focus;
55
	var $start_on_field;
56
	var $layout_manager;
57
	var $layout_def_key;
58
	var $show_tabs = false;
59
60
	var $subpanel_definitions;
61
62
	var $hidden_tabs=array(); //consumer of this class can array of tabs that should be hidden. the tab name
63
							//should be the array.
64
65
	function __construct(&$focus, $layout_def_key='', $layout_def_override = '')
66
	{
67
		$this->focus = $focus;
68
		$this->id = $focus->id;
69
		$this->module = $focus->module_dir;
70
		$this->layout_def_key = $layout_def_key;
71
		$this->subpanel_definitions=new SubPanelDefinitions($focus, $layout_def_key, $layout_def_override);
72
	}
73
74
    /**
75
     * @deprecated deprecated since version 7.6, PHP4 Style Constructors are deprecated and will be remove in 7.8, please update your code, use __construct instead
76
     */
77
    function SubPanelTiles(&$focus, $layout_def_key='', $layout_def_override = ''){
78
        $deprecatedMessage = 'PHP4 Style Constructors are deprecated and will be remove in 7.8, please update your code';
79
        if(isset($GLOBALS['log'])) {
80
            $GLOBALS['log']->deprecated($deprecatedMessage);
81
        }
82
        else {
83
            trigger_error($deprecatedMessage, E_USER_DEPRECATED);
84
        }
85
        self::__construct($focus, $layout_def_key, $layout_def_override);
86
    }
87
88
89
	/*
90
	 * Return the current selected or requested subpanel tab
91
	 * @return	string	The identifier for the selected subpanel tab (e.g., 'Other')
92
	 */
93
    function getSelectedGroup()
94
    {
95
        global $current_user;
96
97
        if(isset($_REQUEST['subpanelTabs']))
98
            $_SESSION['subpanelTabs'] = $_REQUEST['subpanelTabs'];
99
100
        // include/tabConfig.php in turn includes the customized file at custom/include/tabConfig.php
101
        require 'include/tabConfig.php';
102
103
        $subpanelTabsPref = $current_user->getPreference('subpanel_tabs');
104
        if(!isset($subpanelTabsPref)) $subpanelTabsPref = $GLOBALS['sugar_config']['default_subpanel_tabs'];
105
        if(!empty($GLOBALS['tabStructure']) && (!empty($_SESSION['subpanelTabs']) || !empty($sugar_config['subpanelTabs']) || !empty($subpanelTabsPref)))
0 ignored issues
show
The variable $sugar_config seems to never exist, and therefore empty should always return true. Did you maybe rename this variable?

This check looks for calls to isset(...) or empty() on variables that are yet undefined. These calls will always produce the same result and can be removed.

This is most likely caused by the renaming of a variable or the removal of a function/method parameter.

Loading history...
106
        {
107
            // Determine selected group
108
            if(!empty($_REQUEST['subpanel']))
109
            {
110
                $selected_group = $_REQUEST['subpanel'];
111
            }
112
            elseif(!empty($_COOKIE[$this->module.'_sp_tab']))
113
            {
114
                $selected_group = $_COOKIE[$this->module.'_sp_tab'];
115
            }
116
            elseif(!empty($_SESSION['parentTab']) && !empty($GLOBALS['tabStructure'][$_SESSION['parentTab']]) && in_array($this->module, $GLOBALS['tabStructure'][$_SESSION['parentTab']]['modules']))
117
            {
118
                $selected_group = $_SESSION['parentTab'];
119
            }
120
            else
121
            {
122
                $selected_group = '';
123
                foreach($GLOBALS['tabStructure'] as $mainTab => $group)
124
                {
125
                    if(in_array($this->module, $group['modules']))
126
                    {
127
                        $selected_group = $mainTab;
128
                        break;
129
                    }
130
                }
131
                if(!$selected_group)
132
                {
133
                    $selected_group = 'All';
134
                }
135
            }
136
        }
137
        else
138
        {
139
        	$selected_group = '';
140
        }
141
        return $selected_group;
142
    }
143
144
    /*
145
     * Determine which subpanels should be shown within the selected tab group (e.g., 'Other');
146
     * @param boolean $showTabs		True if we should call the code to render each visible tab
147
     * @param string $selectedGroup	The requested tab group
148
     * @return array Visible tabs
149
     */
150
    function getTabs($showTabs = true, $selectedGroup='')
151
    {
152
        global $current_user;
153
154
        //get all the "tabs" - this actually means all the subpanels available for display within a tab
155
        $tabs = $this->subpanel_definitions->get_available_tabs();
156
157
        if(!empty($selectedGroup))
158
        {
159
            // Bug #44344 : Custom relationships under same module only show once in subpanel tabs
160
            // use object property instead new object to have ability run unit test (can override subpanel_definitions)
161
            $objSubPanelTilesTabs = new SubPanelTilesTabs($this->focus);
162
            $tabs = $objSubPanelTilesTabs->getTabs($tabs, $showTabs, $selectedGroup);
163
            unset($objSubPanelTilesTabs);
164
            return $tabs;
165
	    }
166
        else
167
        {
168
            // see if user current user has custom subpanel layout
169
			$objSubPanelTilesTabs = new SubPanelTilesTabs($this->focus);
170
            $tabs = $objSubPanelTilesTabs->applyUserCustomLayoutToTabs($tabs);
171
172
            /* Check if the preference is set now,
173
             * because there's no point in executing this code if
174
             * we aren't going to render anything.
175
             */
176
            $subpanelLinksPref = $current_user->getPreference('subpanel_links');
177
            if(!isset($subpanelLinksPref)) $subpanelLinksPref = $GLOBALS['sugar_config']['default_subpanel_links'];
178
179
            if($showTabs && $subpanelLinksPref){
180
               require_once('include/SubPanel/SugarTab.php');
181
               $sugarTab = new SugarTab();
182
183
               $displayTabs = array();
184
185
               foreach($tabs as $tab){
186
    	           $displayTabs []= array('key'=>$tab, 'label'=>translate($this->subpanel_definitions->layout_defs['subpanel_setup'][$tab]['title_key']));
187
    	           //echo '<td nowrap="nowrap"><a class="subTabLink" href="#' . $tab . '">' .  translate($this->subpanel_definitions->layout_defs['subpanel_setup'][$tab]['title_key']) .  '</a></td><td> | </td>';
188
    	       }
189
               $sugarTab->setup(array(),array(),$displayTabs);
190
               $sugarTab->display();
191
            }
192
            //echo '<td width="100%">&nbsp;</td></tr></table>';
193
        }
194
	    return $tabs;
195
196
	}
197
	function display($showContainer = true, $forceTabless = false)
198
	{
199
		global $layout_edit_mode, $sugar_version, $sugar_config, $current_user, $app_strings;
200
		if(isset($layout_edit_mode) && $layout_edit_mode){
201
			return;
202
		}
203
204
		global $modListHeader;
205
206
		ob_start();
207
    echo '<script type="text/javascript" src="'. getJSPath('include/SubPanel/SubPanelTiles.js') . '"></script>';
208
?>
209
<script>
210
if(document.DetailView != null &&
211
   document.DetailView.elements != null &&
212
   document.DetailView.elements.layout_def_key != null &&
213
   typeof document.DetailView.elements['layout_def_key'] != 'undefined'){
214
    document.DetailView.elements['layout_def_key'].value = '<?php echo $this->layout_def_key; ?>';
215
}
216
</script>
217
<?php
218
219
		$tabs = array();
220
		$default_div_display = 'inline';
221
		if(!empty($sugar_config['hide_subpanels_on_login'])){
222
			if(!isset($_SESSION['visited_details'][$this->focus->module_dir])){
223
				setcookie($this->focus->module_dir . '_divs', '',0,null,null,false,true);
224
				unset($_COOKIE[$this->focus->module_dir . '_divs']);
225
				$_SESSION['visited_details'][$this->focus->module_dir] = true;
226
227
			}
228
			$default_div_display = 'none';
229
		}
230
		$div_cookies = get_sub_cookies($this->focus->module_dir . '_divs');
231
232
233
		//Display the group header. this section is executed only if the tabbed interface is being used.
234
		$current_key = '';
235
		if (! empty($this->show_tabs))
236
		{
237
			require_once('include/tabs.php');
238
    		$tab_panel = new SugarWidgetTabs($tabs, $current_key, 'showSubPanel');
239
			echo get_form_header('Related', '', false);
240
			echo "<br />" . $tab_panel->display();
241
		}
242
243
        if(empty($_REQUEST['subpanels']))
244
        {
245
            $selected_group = $forceTabless?'':$this->getSelectedGroup();
246
            $usersLayout = $current_user->getPreference('subpanelLayout', $this->focus->module_dir);
247
248
            // we need to use some intelligence here when restoring the user's layout, as new modules with new subpanels might have been installed since the user's layout was recorded
249
            // this means that we can't just restore the old layout verbatim as the new subpanels would then go walkabout
250
            // so we need to do a merge while attempting as best we can to preserve the sense of the specified order
251
            // this is complicated by the different ordering schemes used in the two sources for the panels: the user's layout uses an ordinal layout, the panels from getTabs have an explicit ordering driven by the 'order' parameter
252
            // it's not clear how to best reconcile these two schemes; so we punt on it, and add all new panels to the end of the user's layout. At least this will give them a clue that something has changed...
253
            // we also now check for tabs that have been removed since the user saved his or her preferences.
254
255
            $tabs = $this->getTabs($showContainer, $selected_group) ;
256
257
            if(!empty($usersLayout))
258
            {
259
                $availableTabs = $tabs ;
260
                $tabs = array_intersect ( $usersLayout , $availableTabs ) ; // remove any tabs that have been removed since the user's layout was saved
261
                foreach (array_diff ( $availableTabs , $usersLayout ) as $tab)
262
                    $tabs [] = $tab ;
263
            }
264
        }
265
        else
266
        {
267
        	$tabs = explode(',', $_REQUEST['subpanels']);
268
        }
269
270
        $tab_names = array();
271
272
        if($showContainer)
273
        {
274
            echo '<ul class="noBullet" id="subpanel_list">';
275
        }
276
        //echo "<li id='hidden_0' style='height: 5px' class='noBullet'>&nbsp;&nbsp;&nbsp;</li>";
277
        if (empty($GLOBALS['relationships'])) {
278
        	if (!class_exists('Relationship')) {
279
        		require('modules/Relationships/Relationship.php');
280
        	}
281
        	$rel= new Relationship();
282
	        $rel->load_relationship_meta();
283
        }
284
285
        // this array will store names of sub-panels that can contain items
286
        // of each module
287
        $module_sub_panels = array();
288
289
        foreach ($tabs as $tab)
290
		{
291
			//load meta definition of the sub-panel.
292
			$thisPanel=$this->subpanel_definitions->load_subpanel($tab);
293
            if ($thisPanel === false)
294
                continue;
295
			//this if-block will try to skip over ophaned subpanels. Studio/MB are being delete unloaded modules completely.
296
			//this check will ignore subpanels that are collections (activities, history, etc)
297
			if (!isset($thisPanel->_instance_properties['collection_list']) and isset($thisPanel->_instance_properties['get_subpanel_data']) ) {
298
				//ignore when data source is a function
299
300
				if (!isset($this->focus->field_defs[$thisPanel->_instance_properties['get_subpanel_data']])) {
301
					if (stripos($thisPanel->_instance_properties['get_subpanel_data'],'function:') === false) {
302
						$GLOBALS['log']->fatal("Bad subpanel definition, it has incorrect value for get_subpanel_data property " .$tab);
303
						continue;
304
					}
305
				} else {
306
					$rel_name='';
307
					if (isset($this->focus->field_defs[$thisPanel->_instance_properties['get_subpanel_data']]['relationship'])) {
308
						$rel_name=$this->focus->field_defs[$thisPanel->_instance_properties['get_subpanel_data']]['relationship'];
309
					}
310
311
					if (empty($rel_name) or !isset($GLOBALS['relationships'][$rel_name])) {
312
						$GLOBALS['log']->fatal("Missing relationship definition " .$rel_name. ". skipping " .$tab ." subpanel");
313
						continue;
314
					}
315
				}
316
			}
317
318
            if ($thisPanel->isCollection()) {
319
                // collect names of sub-panels that may contain items of each module
320
                $collection_list = $thisPanel->get_inst_prop_value('collection_list');
321
                if (is_array($collection_list)) {
322
                    foreach ($collection_list as $data) {
323
                        if (!empty($data['module'])) {
324
                            $module_sub_panels[$data['module']][$tab] = true;
325
                        }
326
                    }
327
                }
328
            } else {
329
                $module = $thisPanel->get_module_name();
330
                if (!empty($module)) {
331
                    $module_sub_panels[$module][$tab] = true;
332
                }
333
            }
334
335
			echo '<li class="noBullet" id="whole_subpanel_' . $tab . '">';
336
337
			$display= 'none';
338
			$div_display = $default_div_display;
339
			$cookie_name =   $tab . '_v';
340
341
			if (isset($thisPanel->_instance_properties['collapsed']) && $thisPanel->_instance_properties['collapsed'])
342
			{
343
				$div_display = 'none';
344
			}
345
346
			if(isset($div_cookies[$cookie_name])){
347
				//If defaultSubPanelExpandCollapse is set, ignore the cookie that remembers whether the panel is expanded or collapsed.
348
				//To be used with the above 'collapsed' metadata setting so they will always be set the same when the page is loaded.
349
				if(!isset($sugar_config['defaultSubPanelExpandCollapse']) || $sugar_config['defaultSubPanelExpandCollapse'] == false)
350
					$div_display = 	$div_cookies[$cookie_name];
351
			}
352
			if(!empty($sugar_config['hide_subpanels'])){
353
				$div_display = 'none';
354
			}
355
            if($thisPanel->isDefaultHidden()) {
356
                $div_display = 'none';
357
            }
358
			if($div_display == 'none'){
359
				$opp_display  = 'inline';
360
			}else{
361
				$opp_display  = 'none';
362
			}
363
364
            if (!empty($this->layout_def_key) ) {
365
                $layout_def_key = $this->layout_def_key;
366
            } else {
367
                $layout_def_key = '';
368
            }
369
370
			if (empty($this->show_tabs))
371
			{
372
				$show_icon_html = SugarThemeRegistry::current()->getImage( 'advanced_search', 'border="0" align="absmiddle"',null,null,'.gif',translate('LBL_SHOW'));
373
				$hide_icon_html = SugarThemeRegistry::current()->getImage( 'basic_search', 'border="0" align="absmiddle"',null,null,'.gif',translate('LBL_HIDE'));
374
375
 		 		$max_min = "<a name=\"$tab\"> </a><span id=\"show_link_".$tab."\" style=\"display: $opp_display\"><a href='#' class='utilsLink' onclick=\"current_child_field = '".$tab."';showSubPanel('".$tab."',null,null,'".$layout_def_key."');document.getElementById('show_link_".$tab."').style.display='none';document.getElementById('hide_link_".$tab."').style.display='';return false;\">"
376
 		 			. "" . $show_icon_html . "</a></span>";
377
				$max_min .= "<span id=\"hide_link_".$tab."\" style=\"display: $div_display\"><a href='#' class='utilsLink' onclick=\"hideSubPanel('".$tab."');document.getElementById('hide_link_".$tab."').style.display='none';document.getElementById('show_link_".$tab."').style.display='';return false;\">"
378
				 . "" . $hide_icon_html . "</a></span>";
379
				echo '<div id="subpanel_title_' . $tab . '"';
380
                if(empty($sugar_config['lock_subpanels']) || $sugar_config['lock_subpanels'] == false) echo ' onmouseover="this.style.cursor = \'move\';"';
381
                echo '>' . get_form_header( $thisPanel->get_title(), $max_min, false) . '</div>';
382
			}
383
384
            echo <<<EOQ
385
<div cookie_name="$cookie_name" id="subpanel_$tab" style="display:$div_display">
386
    <script>document.getElementById("subpanel_$tab" ).cookie_name="$cookie_name";</script>
387
EOQ;
388
            $display_spd = '';
389
            if($div_display != 'none'){
390
            	echo "<script>SUGAR.util.doWhen(\"typeof(markSubPanelLoaded) != 'undefined'\", function() {markSubPanelLoaded('$tab');});</script>";
391
            	$old_contents = ob_get_contents();
392
            	@ob_end_clean();
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
393
394
            	ob_start();
395
            	include_once('include/SubPanel/SubPanel.php');
396
            	$subpanel_object = new SubPanel($this->module, $_REQUEST['record'], $tab,$thisPanel,$layout_def_key);
397
            	$subpanel_object->setTemplateFile('include/SubPanel/SubPanelDynamic.html');
398
            	$subpanel_object->display();
399
            	$subpanel_data = ob_get_contents();
400
            	@ob_end_clean();
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
401
402
            	ob_start();
403
            	echo $this->get_buttons($thisPanel,$subpanel_object->subpanel_query);
404
            	$buttons = ob_get_contents();
405
            	@ob_end_clean();
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
406
407
            	ob_start();
408
            	echo $old_contents;
409
            	//echo $buttons;
410
                $display_spd = $subpanel_data;
411
            }
412
            echo <<<EOQ
413
    <div id="list_subpanel_$tab">$display_spd</div>
414
</div>
415
EOQ;
416
        	array_push($tab_names, $tab);
417
        	echo '</li>';
418
        } // end $tabs foreach
419
        if($showContainer)
420
        {
421
        	echo '</ul>';
422
423
424
            if(!empty($selected_group))
425
            {
426
                // closing table from tpls/singletabmenu.tpl
427
                echo '</td></tr></table>';
428
            }
429
        }
430
        // drag/drop code
431
        $tab_names = '["' . join($tab_names, '","') . '"]';
432
        global $sugar_config;
433
434
        if(empty($sugar_config['lock_subpanels']) || $sugar_config['lock_subpanels'] == false) {
435
            echo <<<EOQ
436
    <script>
437
    	var SubpanelInit = function() {
438
    		SubpanelInitTabNames({$tab_names});
439
    	}
440
        var SubpanelInitTabNames = function(tabNames) {
441
    		subpanel_dd = new Array();
442
    		j = 0;
443
    		for(i in tabNames) {
444
    			subpanel_dd[j] = new ygDDList('whole_subpanel_' + tabNames[i]);
445
    			subpanel_dd[j].setHandleElId('subpanel_title_' + tabNames[i]);
446
    			subpanel_dd[j].onMouseDown = SUGAR.subpanelUtils.onDrag;
447
    			subpanel_dd[j].afterEndDrag = SUGAR.subpanelUtils.onDrop;
448
    			j++;
449
    		}
450
451
    		YAHOO.util.DDM.mode = 1;
452
    	}
453
    	currentModule = '{$this->module}';
454
    	SUGAR.util.doWhen(
455
    	    "typeof(SUGAR.subpanelUtils) == 'object' && typeof(SUGAR.subpanelUtils.onDrag) == 'function'" +
456
    	        " && document.getElementById('subpanel_list')",
457
    	    SubpanelInit
458
    	);
459
    </script>
460
EOQ;
461
        }
462
463
        $module_sub_panels = array_map('array_keys', $module_sub_panels);
464
        $module_sub_panels = json_encode($module_sub_panels);
465
        echo <<<EOQ
466
<script>
467
var ModuleSubPanels = $module_sub_panels;
468
</script>
469
EOQ;
470
471
		$ob_contents = ob_get_contents();
472
		ob_end_clean();
473
		return $ob_contents;
474
	}
475
476
477
	function getLayoutManager()
478
	{
479
		require_once('include/generic/LayoutManager.php');
480
	  	if ( $this->layout_manager == null) {
481
	    	$this->layout_manager = new LayoutManager();
482
	  	}
483
	  	return $this->layout_manager;
484
	}
485
486
	function get_buttons($thisPanel,$panel_query=null)
487
	{
488
		$subpanel_def = $thisPanel->get_buttons();
489
        $layout_manager = $this->getLayoutManager();
490
491
        //for action button at the top of each subpanel
492
        // bug#51275: smarty widget to help provide the action menu functionality as it is currently sprinkled throughout the app with html
493
        $buttons = array();
494
        $widget_contents = '';
495
		foreach($subpanel_def as $widget_data)
496
		{
497
498
			$widget_data['action'] = $_REQUEST['action'];
499
			$widget_data['module'] =  $thisPanel->get_inst_prop_value('module');
500
			$widget_data['focus'] = $this->focus;
501
			$widget_data['subpanel_definition'] = $thisPanel;
502
			$widget_contents .= '<td class="buttons">' . "\n";
503
504
			if(empty($widget_data['widget_class']))
505
			{
506
				$buttons[] = "widget_class not defined for top subpanel buttons";
507
			}
508
			else
509
			{
510
                $button = $layout_manager->widgetDisplay($widget_data);
511
                if ($button) {
512
                    $buttons[] = $button;
513
                }
514
			}
515
516
        }
517
        require_once('include/Smarty/plugins/function.sugar_action_menu.php');
518
        $widget_contents = smarty_function_sugar_action_menu(array(
519
            'buttons' => $buttons,
520
            'class' => 'clickMenu fancymenu',
521
        ), $this->xTemplate);
522
        return $widget_contents;
523
	}
524
}
525
?>
526