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.
7 * This program is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU Affero General Public License version 3 as published by the
9 * Free Software Foundation with the addition of the following permission added
10 * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
11 * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
12 * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16 * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
19 * You should have received a copy of the GNU Affero General Public License along with
20 * this program; if not, see http://www.gnu.org/licenses or write to the Free
21 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
24 * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
25 * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
27 * The interactive user interfaces in modified source and object code versions
28 * of this program must display Appropriate Legal Notices, as required under
29 * Section 5 of the GNU Affero General Public License version 3.
31 * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
32 * these Appropriate Legal Notices must retain the display of the "Powered by
33 * SugarCRM" logo. If the display of the logo is not reasonably feasible for
34 * technical reasons, the Appropriate Legal Notices must display the words
35 * "Powered by SugarCRM".
36 ********************************************************************************/
38 require_once('include/SubPanel/registered_layout_defs.php');
45 var $hideNewButton = false;
47 var $parent_record_id;
48 var $parent_module; // the name of the parent module
49 var $parent_bean; // the instantiated bean of the parent
52 var $action = 'DetailView';
53 var $show_select_button = true;
54 var $subpanel_define = null; // contains the layout_def.php
56 var $subpanel_query=null;
57 var $layout_def_key='';
58 function SubPanel($module, $record_id, $subpanel_id, $subpanelDef, $layout_def_key='')
60 global $theme, $beanList, $beanFiles, $focus, $app_strings;
62 $this->subpanel_defs=$subpanelDef;
63 $this->subpanel_id = $subpanel_id;
64 $this->parent_record_id = $record_id;
65 $this->parent_module = $module;
66 $this->layout_def_key = $layout_def_key;
68 $this->parent_bean = $focus;
73 $parent_bean_name = $beanList[$module];
74 $parent_bean_file = $beanFiles[$parent_bean_name];
75 require_once($parent_bean_file);
76 $this->parent_bean = new $parent_bean_name();
77 $this->parent_bean->retrieve($this->parent_record_id);
78 $result = $this->parent_bean;
81 if($record_id!='fab4' && $result == null)
83 sugar_die($app_strings['ERROR_NO_RECORD']);
86 if (empty($subpanelDef)) {
87 //load the subpanel by name.
88 if (!class_exists('MyClass')) {
89 require_once 'include/SubPanel/SubPanelDefinitions.php' ;
91 $panelsdef=new SubPanelDefinitions($result,$layout_def_key);
92 $subpanelDef=$panelsdef->load_subpanel($subpanel_id);
93 $this->subpanel_defs=$subpanelDef;
99 function setTemplateFile($template_file)
101 $this->template_file = $template_file;
104 function setBeanList(&$value){
105 $this->bean_list =$value;
108 function setHideNewButton($value){
109 $this->hideNewButton = $value;
113 function getHeaderText( $currentModule){
116 function get_buttons( $panel_query=null)
119 $thisPanel =& $this->subpanel_defs;
120 $subpanel_def = $thisPanel->get_buttons();
122 if(!isset($this->listview)){
123 $this->listview = new ListView();
125 $layout_manager = $this->listview->getLayoutManager();
126 $widget_contents = '<div><table cellpadding="0" cellspacing="0"><tr>';
127 foreach($subpanel_def as $widget_data)
129 $widget_data['action'] = $_REQUEST['action'];
130 $widget_data['module'] = $thisPanel->get_inst_prop_value('module');
131 $widget_data['focus'] = $this->parent_bean;
132 $widget_data['subpanel_definition'] = $thisPanel;
133 $widget_contents .= '<td style="padding-right: 2px; padding-bottom: 2px;">' . "\n";
135 if(empty($widget_data['widget_class']))
137 $widget_contents .= "widget_class not defined for top subpanel buttons";
141 $widget_contents .= $layout_manager->widgetDisplay($widget_data);
144 $widget_contents .= '</td>';
147 $widget_contents .= '</tr></table></div>';
148 return $widget_contents;
152 function ProcessSubPanelListView($xTemplatePath, &$mod_strings)
155 global $current_user;
156 global $sugar_config;
158 if(isset($this->listview)){
159 $ListView =& $this->listview;
161 $ListView = new ListView();
163 $ListView->initNewXTemplate($xTemplatePath,$this->subpanel_defs->mod_strings);
164 $ListView->xTemplateAssign("RETURN_URL", "&return_module=".$this->parent_module."&return_action=DetailView&return_id=".$this->parent_bean->id);
165 $ListView->xTemplateAssign("RELATED_MODULE", $this->parent_module); // TODO: what about unions?
166 $ListView->xTemplateAssign("RECORD_ID", $this->parent_bean->id);
167 $ListView->xTemplateAssign("EDIT_INLINE_PNG", SugarThemeRegistry::current()->getImage('edit_inline','align="absmiddle" border="0"',null,null,'.gif',$app_strings['LNK_EDIT']));
168 $ListView->xTemplateAssign("DELETE_INLINE_PNG", SugarThemeRegistry::current()->getImage('delete_inline','align="absmiddle" border="0"',null,null,'.gif',$app_strings['LBL_DELETE_INLINE']));
169 $ListView->xTemplateAssign("REMOVE_INLINE_PNG", SugarThemeRegistry::current()->getImage('delete_inline','align="absmiddle" border="0"',null,null,'.gif',$app_strings['LBL_ID_FF_REMOVE']));
172 if(is_admin($current_user) && $_REQUEST['module'] != 'DynamicLayout' && !empty($_SESSION['editinplace']))
174 $exploded = explode('/', $xTemplatePath);
175 $file_name = $exploded[sizeof($exploded) - 1];
176 $mod_name = $exploded[sizeof($exploded) - 2];
177 $header_text= " <a href='index.php?action=index&module=DynamicLayout&from_action=$file_name&from_module=$mod_name&mod_lang="
178 .$_REQUEST['module']."'>".SugarThemeRegistry::current()->getImage("EditLayout","border='0' align='bottom'",null,null,'.gif','Edit Layout')."</a>";
180 $ListView->setHeaderTitle('');
181 $ListView->setHeaderText('');
185 $ListView->is_dynamic = true;
186 $ListView->records_per_page = $sugar_config['list_max_entries_per_subpanel'] + 0;
187 if (isset($this->subpanel_defs->_instance_properties['records_per_page'])) {
188 $ListView->records_per_page = $this->subpanel_defs->_instance_properties['records_per_page'] + 0;
190 $ListView->start_link_wrapper = "javascript:showSubPanel('".$this->subpanel_id."','";
191 $ListView->subpanel_id = $this->subpanel_id;
192 $ListView->end_link_wrapper = "',true);";
193 if ( !empty($this->layout_def_key) ) {
194 $ListView->end_link_wrapper = '&layout_def_key='.$this->layout_def_key.$ListView->end_link_wrapper;
198 $ListView->setQuery($where, '', '', '');
199 $ListView->show_export_button = false;
201 //function returns the query that was used to populate sub-panel data.
203 $query=$ListView->process_dynamic_listview($this->parent_module, $this->parent_bean,$this->subpanel_defs);
204 $this->subpanel_query=$query;
205 $ob_contents = ob_get_contents();
215 global $app_list_strings;
218 global $current_language;
220 $result_array = array();
222 $return_string = $this->ProcessSubPanelListView($this->template_file,$result_array);
224 print $return_string;
227 function getModulesWithSubpanels()
230 $dir = dir('modules');
232 while($entry = $dir->read())
234 if(file_exists('modules/' . $entry . '/layout_defs.php'))
236 $modules[$entry] = $entry;
242 function getModuleSubpanels($module){
243 require_once('include/SubPanel/SubPanelDefinitions.php');
244 global $beanList, $beanFiles;
245 if(!isset($beanList[$module])){
249 $class = $beanList[$module];
250 require_once($beanFiles[$class]);
252 $spd = new SubPanelDefinitions($mod);
253 $tabs = $spd->get_available_tabs(true);
255 $reject_tabs = array('history'=>1, 'activities'=>1);
256 foreach($tabs as $key=>$tab){
257 foreach($tab as $k=>$v){
258 if (! isset ( $reject_tabs [$k] )) {
269 //saves overrides for defs
270 function saveSubPanelDefOverride( $panel, $subsection, $override){
271 global $layout_defs, $beanList;
273 //save the new subpanel
274 $name = "subpanel_layout['list_fields']";
276 //bugfix: load looks for moduleName/metadata/subpanels, not moduleName/subpanels
277 $path = 'custom/modules/'. $panel->_instance_properties['module'] . '/metadata/subpanels';
279 //bug# 40171: "Custom subpanels not working as expected"
280 //each custom subpanel needs to have a unique custom def file
281 $filename = $panel->parent_bean->object_name . "_subpanel_" . $panel->name; //bug 42262 (filename with $panel->_instance_properties['get_subpanel_data'] can create problem if had word "function" in it)
282 $oldName1 = '_override' . $panel->parent_bean->object_name .$panel->_instance_properties['module'] . $panel->_instance_properties['subpanel_name'] ;
283 $oldName2 = '_override' . $panel->parent_bean->object_name .$panel->_instance_properties['get_subpanel_data'] ;
284 if (file_exists('custom/Extension/modules/'. $panel->parent_bean->module_dir . "/Ext/Layoutdefs/$oldName1.php")){
285 unlink('custom/Extension/modules/'. $panel->parent_bean->module_dir . "/Ext/Layoutdefs/$oldName1.php");
287 if (file_exists('custom/Extension/modules/'. $panel->parent_bean->module_dir . "/Ext/Layoutdefs/$oldName2.php")){
288 unlink('custom/Extension/modules/'. $panel->parent_bean->module_dir . "/Ext/Layoutdefs/$oldName2.php");
290 $extname = '_override'.$filename;
293 mkdir_recursive($path, true);
294 write_array_to_file( $name, $override,$path.'/' . $filename .'.php');
296 //save the override for the layoutdef
297 //tyoung 10.12.07 pushed panel->name to lowercase to match case in subpaneldefs.php files -
298 //gave error on bad index 'module' as this override key didn't match the key in the subpaneldefs
299 $name = "layout_defs['". $panel->parent_bean->module_dir. "']['subpanel_setup']['" .strtolower($panel->name). "']";
300 // $GLOBALS['log']->debug('SubPanel.php->saveSubPanelDefOverride(): '.$name);
301 $newValue = override_value_to_string($name, 'override_subpanel_name', $filename);
302 mkdir_recursive('custom/Extension/modules/'. $panel->parent_bean->module_dir . '/Ext/Layoutdefs', true);
303 $fp = sugar_fopen('custom/Extension/modules/'. $panel->parent_bean->module_dir . "/Ext/Layoutdefs/$extname.php", 'w');
304 fwrite($fp, "<?php\n//auto-generated file DO NOT EDIT\n$newValue\n?>");
306 require_once('ModuleInstall/ModuleInstaller.php');
307 $moduleInstaller = new ModuleInstaller();
308 $moduleInstaller->silent = true; // make sure that the ModuleInstaller->log() function doesn't echo while rebuilding the layoutdefs
309 $moduleInstaller->rebuild_layoutdefs();
310 if (file_exists('modules/'. $panel->parent_bean->module_dir . '/layout_defs.php'))
311 include('modules/'. $panel->parent_bean->module_dir . '/layout_defs.php');
312 if (file_exists('custom/modules/'. $panel->parent_bean->module_dir . '/Ext/Layoutdefs/layoutdefs.ext.php'))
313 include('custom/modules/'. $panel->parent_bean->module_dir . '/Ext/Layoutdefs/layoutdefs.ext.php');
316 function get_subpanel_setup($module)
318 $subpanel_setup = '';
319 $layout_defs = get_layout_defs();
321 if(!empty($layout_defs) && !empty($layout_defs[$module]['subpanel_setup']))
323 $subpanel_setup = $layout_defs[$module]['subpanel_setup'];
326 return $subpanel_setup;
330 * Retrieve the subpanel definition from the registered layout_defs arrays.
332 function getSubPanelDefine($module, $subpanel_id)
334 $default_subpanel_define = SubPanel::_get_default_subpanel_define($module, $subpanel_id);
335 $custom_subpanel_define = SubPanel::_get_custom_subpanel_define($module, $subpanel_id);
337 $subpanel_define = array_merge($default_subpanel_define, $custom_subpanel_define);
339 if(empty($subpanel_define))
341 print('Could not load subpanel definition for: ' . $subpanel_id);
344 return $subpanel_define;
347 function _get_custom_subpanel_define($module, $subpanel_id)
351 if($subpanel_id != '')
353 $layout_defs = get_layout_defs();
355 if(!empty($layout_defs[$module]['custom_subpanel_defines'][$subpanel_id]))
357 $ret_val = $layout_defs[$module]['custom_subpanel_defines'][$subpanel_id];
364 function _get_default_subpanel_define($module, $subpanel_id)
368 if($subpanel_id != '')
370 $layout_defs = get_layout_defs();
372 if(!empty($layout_defs[$subpanel_id]['default_subpanel_define']))
374 $ret_val = $layout_defs[$subpanel_id]['default_subpanel_define'];