]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - include/EditView/EditView2.php
Release 6.5.10
[Github/sugarcrm.git] / include / EditView / EditView2.php
1 <?php
2 /*********************************************************************************
3  * SugarCRM Community Edition is a customer relationship management program developed by
4  * SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
5  * 
6  * This program is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU Affero General Public License version 3 as published by the
8  * Free Software Foundation with the addition of the following permission added
9  * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
10  * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
11  * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
12  * 
13  * This program is distributed in the hope that it will be useful, but WITHOUT
14  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15  * FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
16  * details.
17  * 
18  * You should have received a copy of the GNU Affero General Public License along with
19  * this program; if not, see http://www.gnu.org/licenses or write to the Free
20  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21  * 02110-1301 USA.
22  * 
23  * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
24  * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
25  * 
26  * The interactive user interfaces in modified source and object code versions
27  * of this program must display Appropriate Legal Notices, as required under
28  * Section 5 of the GNU Affero General Public License version 3.
29  * 
30  * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
31  * these Appropriate Legal Notices must retain the display of the "Powered by
32  * SugarCRM" logo. If the display of the logo is not reasonably feasible for
33  * technical reasons, the Appropriate Legal Notices must display the words
34  * "Powered by SugarCRM".
35  ********************************************************************************/
36
37
38
39 require_once('include/TemplateHandler/TemplateHandler.php');
40 require_once('include/EditView/SugarVCR.php');
41
42 /**
43  * New EditView
44  * @api
45  */
46 class EditView
47 {
48     public $th;
49     public $tpl;
50     public $notes;
51     public $id;
52     public $metadataFile;
53     public $headerTpl;
54     public $footerTpl;
55     public $returnAction;
56     public $returnModule;
57     public $returnId;
58     public $isDuplicate;
59     public $focus;
60     public $module;
61     public $fieldDefs;
62     public $sectionPanels;
63     public $view = 'EditView';
64     public $formatFields = true;
65     public $showDetailData = true;
66     public $showVCRControl = true;
67     public $showSectionPanelsTitles = true;
68     public $quickSearchCode;
69     public $ss;
70     public $offset = 0;
71     public $populateBean = true;
72     public $moduleTitleKey;
73     public $viewObject = null;
74     public $formName = '';
75
76     /**
77      * EditView constructor
78      * This is the EditView constructor responsible for processing the new
79      * Meta-Data framework
80      *
81      * @param $module String value of module this Edit view is for
82      * @param $focus An empty sugarbean object of module
83      * @param $id The record id to retrieve and populate data for
84      * @param $metadataFile String value of file location to use in overriding default metadata file
85      * @param tpl String value of file location to use in overriding default Smarty template
86      * @param createFocus bool value to tell whether to create a new bean if we do not have one with an id, this is used from ConvertLead
87      *
88      */
89     function setup($module, $focus = null, $metadataFile = null, $tpl = 'include/EditView/EditView.tpl', $createFocus = true)
90     {
91         $this->th = $this->getTemplateHandler();
92         $this->th->ss =& $this->ss;
93         $this->tpl = $tpl;
94         $this->module = $module;
95         $this->focus = $focus;
96
97         //this logic checks if the focus has an id and if it does not then it will create a new instance of the focus bean
98         //but in convert lead we do not want to create a new instance and do not want to populate id.
99         if ($createFocus)
100         {
101             $this->createFocus();
102         }
103
104         if (empty($GLOBALS['sugar_config']['showDetailData']))
105         {
106             $this->showDetailData = false;
107         }
108         $this->metadataFile = $metadataFile;
109
110         if (isset($GLOBALS['sugar_config']['disable_vcr']))
111         {
112            $this->showVCRControl = !$GLOBALS['sugar_config']['disable_vcr'];
113         }
114
115         if (!empty($this->metadataFile) && file_exists($this->metadataFile))
116         {
117             include($this->metadataFile);
118         }
119         else
120         {
121             //If file doesn't exist we create a best guess
122             if (!file_exists("modules/$this->module/metadata/editviewdefs.php")
123                 && file_exists("modules/$this->module/EditView.html"))
124             {
125                 require_once('include/SugarFields/Parsers/EditViewMetaParser.php');
126
127                 global $dictionary;
128
129                 $htmlFile = "modules/" . $this->module . "/EditView.html";
130                 $parser = new EditViewMetaParser();
131                 if (!file_exists('modules/'.$this->module.'/metadata'))
132                 {
133                    sugar_mkdir('modules/'.$this->module.'/metadata');
134                 }
135
136                 $fp = sugar_fopen('modules/'.$this->module.'/metadata/editviewdefs.php', 'w');
137                 fwrite($fp, $parser->parse($htmlFile, $dictionary[$focus->object_name]['fields'], $this->module));
138                 fclose($fp);
139             }
140
141             //Flag an error... we couldn't create the best guess meta-data file
142             if (!file_exists("modules/$this->module/metadata/editviewdefs.php"))
143             {
144                 global $app_strings;
145
146                 $error = str_replace("[file]", "modules/$this->module/metadata/editviewdefs.php", $app_strings['ERR_CANNOT_CREATE_METADATA_FILE']);
147                 $GLOBALS['log']->fatal($error);
148                 echo $error;
149                 die();
150             }
151
152             require("modules/$this->module/metadata/editviewdefs.php");
153         }
154
155         $this->defs = $viewdefs[$this->module][$this->view];
156         $this->isDuplicate = isset($_REQUEST['isDuplicate']) && $_REQUEST['isDuplicate'] == 'true' && $this->focus->aclAccess('edit');
157     }
158
159     function createFocus()
160     {
161         global $beanList, $beanFiles;
162
163         if (empty($beanList[$this->module])) return;
164         if(!$this->focus )
165         {
166            $bean = $beanList[$this->module];
167            require_once($beanFiles[$bean]);
168            $obj = new $bean();
169            $this->focus = $obj;
170         }
171
172         //If there is no idea, assume we are creating a new instance
173         //and call the fill_in_additional_detail_fields where initialization
174         //code has been moved to
175         if (empty($this->focus->id))
176         {
177             global $current_user;
178
179             $this->focus->fill_in_additional_detail_fields();
180             $this->focus->assigned_user_id = $current_user->id;
181         }
182     }
183
184     function populateBean()
185     {
186         if (!empty($_REQUEST['record']) && $this->populateBean)
187         {
188            global $beanList;
189
190            $bean = $beanList[$this->module];
191            $obj = new $bean();
192            $this->focus = $obj->retrieve($_REQUEST['record']);
193         }
194         else
195         {
196            $GLOBALS['log']->debug("Unable to populate bean, no record parameter found");
197         }
198     }
199
200     /**
201      * enableFormatting
202      * This method is used to manually turn on/off the field formatting
203      * @param $format boolean value to turn on/off field formatting
204      */
205     function enableFormatting($format = true)
206     {
207         $this->formatFields = $format;
208     }
209
210     /**
211      * Enter description here ...
212      */
213     function requiredFirst()
214     {
215         $panels = array('required'=>array());
216         $reqCol = -1;
217         $reqRow = 0;
218         foreach($this->defs['panels'] as $key=>$p)
219         {
220             foreach ($p as $row=>$rowDef)
221             {
222                 foreach($rowDef as $col => $colDef)
223                 {
224                     $field = (is_array($p[$row][$col])) ? $p[$row][$col]['name'] : $p[$row][$col];
225                     if ((!empty($this->focus->field_defs[$field])
226                         && !empty($this->focus->field_defs[$field]['required']))
227                             || (!empty($p[$row][$col]['displayParams']['required'])))
228                     {
229                         $reqCol++;
230                         if ($reqCol == $this->defs['templateMeta']['maxColumns'])
231                         {
232                             $reqCol = -1;
233                             $reqRow++;
234                         }
235
236                         $panels['required'][$reqRow][$reqCol] = $p[$row][$col];
237                     }
238                     else
239                     {
240                         $panels[$key][$row][$col] = $p[$row][$col];
241                     }
242                 }
243             }
244         }
245
246         $this->defs['panels'] = $panels;
247     }
248
249     function render()
250     {
251         $totalWidth = 0;
252         foreach ($this->defs['templateMeta']['widths'] as $col => $def) {
253             foreach ($def as $k => $value) {
254                 $totalWidth += $value;
255             }
256         }
257
258         // calculate widths
259         foreach ($this->defs['templateMeta']['widths'] as $col => $def) {
260             foreach ($def as $k => $value) {
261                 $this->defs['templateMeta']['widths'][$col][$k] = round($value / ($totalWidth / 100), 2);
262             }
263         }
264
265         $this->sectionPanels = array();
266         $this->sectionLabels = array();
267         if (!empty($this->defs['panels']) && count($this->defs['panels']) > 0)
268         {
269            $keys = array_keys($this->defs['panels']);
270            if (is_numeric($keys[0]))
271            {
272                $defaultPanel = $this->defs['panels'];
273                unset($this->defs['panels']); //blow away current value
274                $this->defs['panels'][''] = $defaultPanel;
275            }
276         }
277
278         if ($this->view == 'EditView' && !empty($GLOBALS['sugar_config']['forms']['requireFirst'])){
279             $this->requiredFirst();
280         }
281
282         $maxColumns = isset($this->defs['templateMeta']['maxColumns']) ? $this->defs['templateMeta']['maxColumns'] : 2;
283         $panelCount = 0;
284         static $itemCount = 100; //Start the generated tab indexes at 100 so they don't step on custom ones.
285
286         /* loop all the panels */
287         foreach ($this->defs['panels'] as $key=>$p)
288         {
289             $panel = array();
290
291             if (!is_array($this->defs['panels'][$key])) {
292                $this->sectionPanels[strtoupper($key)] = $p;
293             }
294             else
295             {
296                 foreach ($p as $row=>$rowDef)
297                 {
298                     $columnsInRows = count($rowDef);
299                     $columnsUsed = 0;
300                     foreach ($rowDef as $col => $colDef)
301                     {
302                         $panel[$row][$col] = is_array($p[$row][$col])
303                             ? array('field' => $p[$row][$col])
304                             : array('field' => array('name'=>$p[$row][$col]));
305
306                         $panel[$row][$col]['field']['tabindex'] =
307                             (isset($p[$row][$col]['tabindex']) && is_numeric($p[$row][$col]['tabindex']))
308                                 ? $p[$row][$col]['tabindex']
309                                 : '0';
310
311                         if ($columnsInRows < $maxColumns)
312                         {
313                             if ($col == $columnsInRows - 1)
314                             {
315                                 $panel[$row][$col]['colspan'] = 2 * $maxColumns - ($columnsUsed + 1);
316                             }
317                             else
318                             {
319                                 $panel[$row][$col]['colspan'] = floor(($maxColumns * 2 - $columnsInRows) / $columnsInRows);
320                                 $columnsUsed = $panel[$row][$col]['colspan'];
321                             }
322                         }
323
324                         //Set address types to have colspan value of 2 if colspan is not already defined
325                         if (is_array($colDef) && !empty($colDef['hideLabel']) && !isset($panel[$row][$col]['colspan']))
326                         {
327                             $panel[$row][$col]['colspan'] = 2;
328                         }
329
330                         $itemCount++;
331
332                     }
333                 }
334
335                                 $panel = $this->getPanelWithFillers($panel);
336
337                                 $this->sectionPanels[strtoupper($key)] = $panel;
338                         }
339
340
341                 $panelCount++;
342                 } //foreach
343     }
344
345     /**
346      * Adds fillers to each row if required
347      *
348      * Panel alignment will be off if the panel doesn't have a row with the max column
349      * It will not be aligned to the other panels so we fill out the columns in the last row
350      *
351      * @param array $panel
352      * @return array
353      */
354     protected function getPanelWithFillers($panel)
355     {
356         $addFiller = true;
357         foreach($panel as $row)
358         {
359             if (count($row) == $this->defs['templateMeta']['maxColumns']
360                 || 1 == count($panel))
361             {
362                 $addFiller = false;
363                 break;
364             }
365         }
366
367         if ($addFiller)
368         {
369             $rowCount = count($panel);
370             $filler   = count($panel[$rowCount-1]);
371             while ($filler < $this->defs['templateMeta']['maxColumns'])
372             {
373                 $panel[$rowCount - 1][$filler++] = array('field' => array('name' => ''));
374             }
375         }
376
377         return $panel;
378     }
379
380     function process($checkFormName = false, $formName = '')
381     {
382         global $mod_strings, $sugar_config, $app_strings, $app_list_strings;
383
384         //the retrieve already did this work;
385         //$this->focus->fill_in_relationship_fields();
386         //Bug#53261: If quickeditview is loaded after editview.tpl is created,
387         //           the th->checkTemplate will return true. So, the following
388         //           code prevent avoid rendering popup editview container.
389         if(!empty($this->formName)) {
390             $formName = $this->formName;
391             $checkFormName = true;
392         }
393
394         if (!$this->th->checkTemplate($this->module, $this->view, $checkFormName, $formName))
395         {
396             $this->render();
397         }
398
399         if (isset($_REQUEST['offset']))
400         {
401             $this->offset = $_REQUEST['offset'] - 1;
402         }
403
404         if ($this->showVCRControl)
405         {
406             $this->th->ss->assign('PAGINATION', SugarVCR::menu($this->module, $this->offset, $this->focus->is_AuditEnabled(), ($this->view == 'EditView')));
407         }
408
409         if (isset($_REQUEST['return_module'])) $this->returnModule = $_REQUEST['return_module'];
410         if (isset($_REQUEST['return_action'])) $this->returnAction = $_REQUEST['return_action'];
411         if (isset($_REQUEST['return_id'])) $this->returnId = $_REQUEST['return_id'];
412         if (isset($_REQUEST['return_relationship'])) $this->returnRelationship = $_REQUEST['return_relationship'];
413         if (isset($_REQUEST['return_name'])) $this->returnName = $this->getValueFromRequest($_REQUEST, 'return_name' ) ;
414
415         // handle Create $module then Cancel
416         if (empty($this->returnId))
417         {
418             $this->returnAction = 'index';
419         }
420
421         $is_owner = $this->focus->isOwner($GLOBALS['current_user']->id);
422
423         $this->fieldDefs = array();
424         if ($this->focus)
425         {
426             global $current_user;
427
428             if (!empty($this->focus->assigned_user_id))
429             {
430                 $this->focus->assigned_user_name = get_assigned_user_name($this->focus->assigned_user_id);
431             }
432
433             if (!empty($this->focus->job) && $this->focus->job_function == '')
434             {
435                 $this->focus->job_function = $this->focus->job;
436             }
437
438             foreach ($this->focus->toArray() as $name => $value)
439             {
440                 $valueFormatted = false;
441                 //if ($this->focus->field_defs[$name]['type']=='link')continue;
442
443                 $this->fieldDefs[$name] = (!empty($this->fieldDefs[$name]) && !empty($this->fieldDefs[$name]['value']))
444                     ? array_merge($this->focus->field_defs[$name], $this->fieldDefs[$name])
445                     : $this->focus->field_defs[$name];
446
447                 foreach (array("formula", "default", "comments", "help") as $toEscape)
448                 {
449                     if (!empty($this->fieldDefs[$name][$toEscape]))
450                     {
451                         $this->fieldDefs[$name][$toEscape] = htmlentities($this->fieldDefs[$name][$toEscape], ENT_QUOTES, 'UTF-8');
452                     }
453                 }
454
455                 if (isset($this->fieldDefs[$name]['options']) && isset($app_list_strings[$this->fieldDefs[$name]['options']]))
456                 {
457                     if(isset($GLOBALS['sugar_config']['enable_autocomplete']) && $GLOBALS['sugar_config']['enable_autocomplete'] == true)
458                     {
459                                                 $this->fieldDefs[$name]['autocomplete'] = true;
460                                 $this->fieldDefs[$name]['autocomplete_options'] = $this->fieldDefs[$name]['options']; // we need the name for autocomplete
461                                         } else {
462                         $this->fieldDefs[$name]['autocomplete'] = false;
463                         }
464                         // Bug 57472 - $this->fieldDefs[$name]['autocomplete_options' was set too late, it didn't retrieve the list's name, but the list itself (the developper comment show us that developper expected to retrieve list's name and not the options array)
465                         $this->fieldDefs[$name]['options'] = $app_list_strings[$this->fieldDefs[$name]['options']];
466                 }
467
468                 if(isset($this->fieldDefs[$name]['options']) && is_array($this->fieldDefs[$name]['options']) && isset($this->fieldDefs[$name]['default_empty']) && !isset($this->fieldDefs[$name]['options'][$this->fieldDefs[$name]['default_empty']])) {
469                     $this->fieldDefs[$name]['options'] = array_merge(array($this->fieldDefs[$name]['default_empty']=>$this->fieldDefs[$name]['default_empty']), $this->fieldDefs[$name]['options']);
470                 }
471                                 
472                         if(isset($this->fieldDefs[$name]['function'])) {
473                                 $function = $this->fieldDefs[$name]['function'];
474                                 if(is_array($function) && isset($function['name'])){
475                                         $function = $this->fieldDefs[$name]['function']['name'];
476                                 }else{
477                                         $function = $this->fieldDefs[$name]['function'];
478                                 }
479
480                     if(isset($this->fieldDefs[$name]['function']['include']) && file_exists($this->fieldDefs[$name]['function']['include']))
481                     {
482                                 require_once($this->fieldDefs[$name]['function']['include']);
483                         }
484
485                                 if(!empty($this->fieldDefs[$name]['function']['returns']) && $this->fieldDefs[$name]['function']['returns'] == 'html'){
486                                                 if(!empty($this->fieldDefs[$name]['function']['include'])){
487                                                                 require_once($this->fieldDefs[$name]['function']['include']);
488                                                 }
489                                                 $value = call_user_func($function, $this->focus, $name, $value, $this->view);
490                                                 $valueFormatted = true;
491                                         }else{
492                                                 $this->fieldDefs[$name]['options'] = call_user_func($function, $this->focus, $name, $value, $this->view);
493                                         }
494                         }
495
496                         if(isset($this->fieldDefs[$name]['type']) && $this->fieldDefs[$name]['type'] == 'function' && isset($this->fieldDefs[$name]['function_name'])){
497                                 $value = $this->callFunction($this->fieldDefs[$name]);
498                                 $valueFormatted = true;
499                         }
500
501                         if(!$valueFormatted) {
502                     // $this->focus->format_field($this->focus->field_defs[$name]);
503                    $value = isset($this->focus->$name) ? $this->focus->$name : '';
504                 }
505
506                 if (empty($this->fieldDefs[$name]['value']))
507                 {
508                     $this->fieldDefs[$name]['value'] = $value;
509                 }
510
511
512                 //This code is used for QuickCreates that go to Full Form view.  We want to overwrite the values from the bean
513                 //with values from the request if they are set and either the bean is brand new (such as a create from a subpanels) or the 'full form' button has been clicked
514                 if ((($this->populateBean && empty($this->focus->id)) || (isset($_REQUEST['full_form'])))
515                     && (!isset($this->fieldDefs[$name]['function']['returns']) || $this->fieldDefs[$name]['function']['returns'] != 'html')
516                     && isset($_REQUEST[$name]))
517                 {
518                     $this->fieldDefs[$name]['value'] = $this->getValueFromRequest($_REQUEST, $name);
519                 }
520
521                /*
522                 * Populate any relate fields that are linked by a relationship to the calling module.
523                 * Clicking the create button on a subpanel for example will populate three values in the $_REQUEST:
524                 * 1. return_module => the name of the calling module
525                 * 2. return_id => the id of the record in the calling module that the user was viewing and that should be associated with this new record
526                 * 3. return_name => the display value of the return_id record - the value to show in any relate field in this EditView
527                 * Only do if this fieldDef does not already have a value; if it does it will have been explicitly set, and that should overrule this less specific mechanism
528                 */
529                 if (isset($this->returnModule) && isset($this->returnName)
530                     && empty($this->focus->id) && empty($this->fieldDefs['name']['value']) )
531                 {
532                    if (($this->focus->field_defs[$name]['type'] == 'relate')
533                        && isset($this->focus->field_defs[$name][ 'module' ])
534                        && $this->focus->field_defs[$name][ 'module' ] == $this->returnModule)
535                    {
536                        if (isset( $this->fieldDefs[$name]['id_name'])
537                            && !empty($this->returnRelationship)
538                            && isset($this->focus->field_defs[$this->fieldDefs[$name]['id_name']]['relationship'])
539                            && ($this->returnRelationship == $this->focus->field_defs[$this->fieldDefs[$name]['id_name']]['relationship']))
540                        {
541                            $this->fieldDefs[$name]['value'] =  $this->returnName ;
542                            // set the hidden id field for this relate field to the correct value i.e., return_id
543                            $this->fieldDefs[$this->fieldDefs[$name]['id_name']]['value'] = $this->returnId ;
544                        }
545                    }
546                 }
547             }
548         }
549
550         if (isset($this->focus->additional_meta_fields))
551         {
552             $this->fieldDefs = array_merge($this->fieldDefs, $this->focus->additional_meta_fields);
553         }
554
555         if ($this->isDuplicate)
556         {
557             foreach ($this->fieldDefs as $name=>$defs) {
558                 if (!empty($defs['auto_increment']))
559                 {
560                     $this->fieldDefs[$name]['value'] = '';
561                 }
562             }
563         }
564     }
565
566     
567     /**
568      * display
569      * This method makes the Smarty variable assignments and then displays the
570      * generated view.
571      * @param $showTitle boolean value indicating whether or not to show a title on the resulting page
572      * @param $ajaxSave boolean value indicating whether or not the operation is an Ajax save request
573      * @return HTML display for view as String
574      */
575     function display($showTitle = true, $ajaxSave = false)
576     {
577         global $mod_strings, $sugar_config, $app_strings, $app_list_strings, $theme, $current_user;
578
579         if(isset($this->defs['templateMeta']['javascript']))
580         {
581             if(is_array($this->defs['templateMeta']['javascript']))
582             {
583                 //$this->th->ss->assign('externalJSFile', 'modules/' . $this->module . '/metadata/editvewdefs.js');
584                 $this->th->ss->assign('externalJSFile', $this->defs['templateMeta']['javascript']);
585             }
586             else
587             {
588                 $this->th->ss->assign('scriptBlocks', $this->defs['templateMeta']['javascript']);
589             }
590         }
591
592         $this->th->ss->assign('id', $this->fieldDefs['id']['value']);
593         $this->th->ss->assign('offset', $this->offset + 1);
594         $this->th->ss->assign('APP', $app_strings);
595         $this->th->ss->assign('MOD', $mod_strings);
596         $this->th->ss->assign('fields', $this->fieldDefs);
597         $this->th->ss->assign('sectionPanels', $this->sectionPanels);
598         $this->th->ss->assign('config', $sugar_config);
599         $this->th->ss->assign('returnModule', $this->returnModule);
600         $this->th->ss->assign('returnAction', $this->returnAction);
601         $this->th->ss->assign('returnId', $this->returnId);
602         $this->th->ss->assign('isDuplicate', $this->isDuplicate);
603         $this->th->ss->assign('def', $this->defs);
604         $this->th->ss->assign('useTabs', isset($this->defs['templateMeta']['useTabs']) && isset($this->defs['templateMeta']['tabDefs']) ? $this->defs['templateMeta']['useTabs'] : false);
605         $this->th->ss->assign('maxColumns', isset($this->defs['templateMeta']['maxColumns']) ? $this->defs['templateMeta']['maxColumns'] : 2);
606         $this->th->ss->assign('module', $this->module);
607         $this->th->ss->assign('headerTpl', isset($this->defs['templateMeta']['form']['headerTpl']) ? $this->defs['templateMeta']['form']['headerTpl'] : 'include/' . $this->view . '/header.tpl');
608         $this->th->ss->assign('footerTpl', isset($this->defs['templateMeta']['form']['footerTpl']) ? $this->defs['templateMeta']['form']['footerTpl'] : 'include/' . $this->view . '/footer.tpl');
609         $this->th->ss->assign('current_user', $current_user);
610         $this->th->ss->assign('bean', $this->focus);
611         $this->th->ss->assign('isAuditEnabled', $this->focus->is_AuditEnabled());
612         $this->th->ss->assign('gridline',$current_user->getPreference('gridline') == 'on' ? '1' : '0');
613         $this->th->ss->assign('tabDefs', isset($this->defs['templateMeta']['tabDefs']) ? $this->defs['templateMeta']['tabDefs'] : false);
614         $this->th->ss->assign('VERSION_MARK', getVersionedPath(''));
615
616         global $js_custom_version;
617         global $sugar_version;
618
619         $this->th->ss->assign('SUGAR_VERSION', $sugar_version);
620         $this->th->ss->assign('JS_CUSTOM_VERSION', $js_custom_version);
621
622         //this is used for multiple forms on one page
623         if (!empty($this->formName)) {
624             $form_id = $this->formName;
625             $form_name = $this->formName;
626         }
627         else
628         {
629             $form_id = $this->view;
630             $form_name = $this->view;
631         }
632
633         if ($ajaxSave && empty($this->formName))
634         {
635             $form_id = 'form_'.$this->view .'_'.$this->module;
636             $form_name = $form_id;
637             $this->view = $form_name;
638             //$this->defs['templateMeta']['form']['buttons'] = array();
639             //$this->defs['templateMeta']['form']['buttons']['ajax_save'] = array('id' => 'AjaxSave', 'customCode'=>'<input type="button" class="button" value="Save" onclick="this.form.action.value=\'AjaxFormSave\';return saveForm(\''.$form_name.'\', \'multiedit_form_{$module}\', \'Saving {$module}...\');"/>');
640         }
641
642         $form_name = $form_name == 'QuickCreate' ? "QuickCreate_{$this->module}" : $form_name;
643         $form_id = $form_id == 'QuickCreate' ? "QuickCreate_{$this->module}" : $form_id;
644
645         if (isset($this->defs['templateMeta']['preForm']))
646         {
647             $this->th->ss->assign('preForm', $this->defs['templateMeta']['preForm']);
648         }
649
650         if (isset($this->defs['templateMeta']['form']['closeFormBeforeCustomButtons']))
651         {
652             $this->th->ss->assign('closeFormBeforeCustomButtons', $this->defs['templateMeta']['form']['closeFormBeforeCustomButtons']);
653         }
654
655         if(isset($this->defs['templateMeta']['form']['enctype']))
656         {
657             $this->th->ss->assign('enctype', 'enctype="'.$this->defs['templateMeta']['form']['enctype'].'"');
658         }
659
660         //for SugarFieldImage, we must set form enctype to "multipart/form-data"
661         foreach ($this->fieldDefs as $field)
662         {
663             if (isset($field['type']) && $field['type'] == 'image')
664             {
665                 $this->th->ss->assign('enctype', 'enctype="multipart/form-data"');
666                 break;
667             }
668         }
669
670         $this->th->ss->assign('showDetailData', $this->showDetailData);
671         $this->th->ss->assign('showSectionPanelsTitles', $this->showSectionPanelsTitles);
672         $this->th->ss->assign('form_id', $form_id);
673         $this->th->ss->assign('form_name', $form_name);
674         $this->th->ss->assign('set_focus_block', get_set_focus_js());
675
676         $this->th->ss->assign('form', isset($this->defs['templateMeta']['form']) ? $this->defs['templateMeta']['form'] : null);
677         $this->th->ss->assign('includes', isset($this->defs['templateMeta']['includes']) ? $this->defs['templateMeta']['includes'] : null);
678         $this->th->ss->assign('view', $this->view);
679
680
681         //Calculate time & date formatting (may need to calculate this depending on a setting)
682         global $timedate;
683
684         $this->th->ss->assign('CALENDAR_DATEFORMAT', $timedate->get_cal_date_format());
685         $this->th->ss->assign('USER_DATEFORMAT', $timedate->get_user_date_format());
686         $time_format = $timedate->get_user_time_format();
687         $this->th->ss->assign('TIME_FORMAT', $time_format);
688
689         $date_format = $timedate->get_cal_date_format();
690         $time_separator = ':';
691         if (preg_match('/\d+([^\d])\d+([^\d]*)/s', $time_format, $match))
692         {
693             $time_separator = $match[1];
694         }
695
696         // Create Smarty variables for the Calendar picker widget
697         $t23 = strpos($time_format, '23') !== false ? '%H' : '%I';
698         if (!isset($match[2]) || $match[2] == '')
699         {
700             $this->th->ss->assign('CALENDAR_FORMAT', $date_format . ' ' . $t23 . $time_separator . '%M');
701         }
702         else
703         {
704             $pm = $match[2] == 'pm' ? '%P' : '%p';
705             $this->th->ss->assign('CALENDAR_FORMAT', $date_format . ' ' . $t23 . $time_separator . '%M' . $pm);
706         }
707
708         $this->th->ss->assign('CALENDAR_FDOW', $current_user->get_first_day_of_week());
709         $this->th->ss->assign('TIME_SEPARATOR', $time_separator);
710
711         $seps = get_number_seperators();
712         $this->th->ss->assign('NUM_GRP_SEP', $seps[0]);
713         $this->th->ss->assign('DEC_SEP', $seps[1]);
714
715         if ($this->view == 'EditView')
716         {
717             $height = $current_user->getPreference('text_editor_height');
718             $width  = $current_user->getPreference('text_editor_width');
719
720             $height = isset($height) ? $height : '300px';
721             $width  = isset($width) ? $width : '95%';
722
723             $this->th->ss->assign('RICH_TEXT_EDITOR_HEIGHT', $height);
724             $this->th->ss->assign('RICH_TEXT_EDITOR_WIDTH', $width);
725         }
726         else
727         {
728             $this->th->ss->assign('RICH_TEXT_EDITOR_HEIGHT', '100px');
729             $this->th->ss->assign('RICH_TEXT_EDITOR_WIDTH', '95%');
730         }
731
732         $this->th->ss->assign('SHOW_VCR_CONTROL', $this->showVCRControl);
733
734         $str = $this->showTitle($showTitle);
735
736         //Use the output filter to trim the whitespace
737         $this->th->ss->load_filter('output', 'trimwhitespace');
738         $str .= $this->th->displayTemplate($this->module, $form_name, $this->tpl, $ajaxSave, $this->defs);
739
740         return $str;
741     }
742
743     function insertJavascript($javascript)
744     {
745         $this->ss->assign('javascript', $javascript);
746     }
747
748     function callFunction($vardef)
749     {
750         $can_execute = true;
751         $execute_function = array();
752         $execute_params = array();
753         if (!empty($vardef['function_class']))
754         {
755             $execute_function[] = $vardef['function_class'];
756             $execute_function[] = $vardef['function_name'];
757         }
758         else
759         {
760             $execute_function = $vardef['function_name'];
761         }
762
763         foreach ($vardef['function_params'] as $param )
764         {
765             if (empty($vardef['function_params_source']) or $vardef['function_params_source']=='parent')
766             {
767                 if (empty($this->focus->$param))
768                 {
769                     $can_execute = false;
770                 }
771                 else
772                 {
773                     $execute_params[] = $this->focus->$param;
774                 }
775             }
776             else if ($vardef['function_params_source']=='this')
777             {
778                 if (empty($this->focus->$param))
779                 {
780                     $can_execute = false;
781                 } else {
782                     $execute_params[] = $this->focus->$param;
783                 }
784             }
785             else
786             {
787                 $can_execute = false;
788             }
789         }
790
791         $value = '';
792         if ($can_execute)
793         {
794             if (!empty($vardef['function_require']))
795             {
796                 require_once($vardef['function_require']);
797             }
798
799             $value = call_user_func_array($execute_function, $execute_params);
800         }
801
802         return $value;
803     }
804
805     /**
806      * getValueFromRequest
807      * This is a helper method to extract a value from the request
808      * Array.  We do some special processing for fields that start
809      * with 'date_' by checking to see if they also include time
810      * and meridiem values
811      *
812      * @param request The request Array
813      * @param name The field name to extract value for
814      * @return String value for given name
815      */
816     function getValueFromRequest($request, $name)
817     {
818         //Special processing for date values (combine to one field)
819         if (preg_match('/^date_(.*)$/s', $name, $matches))
820         {
821             $d = $request[$name];
822
823             if (isset($request['time_' . $matches[1]]))
824             {
825                 $d .= ' ' . $request['time_' . $matches[1]];
826                 if (isset($request[$matches[1] . '_meridiem']))
827                 {
828                     $d .= $request[$matches[1] . '_meridiem'];
829                 }
830             }
831             else
832             {
833                 if (isset($request['time_hour_' . $matches[1]])
834                     && isset($request['time_minute_' . $matches[1]]))
835                 {
836                     $d .= sprintf(' %s:%s', $request['time_hour_' . $matches[1]], $request['time_minute_' . $matches[1]]);
837                 }
838
839                 if (isset($request['meridiem']))
840                 {
841                     $d .= $request['meridiem'];
842                 }
843            }
844
845            return $d;
846         }
847
848         if (empty($request[$name]) || !isset($this->fieldDefs[$name]))
849         {
850            return $request[$name];
851         }
852
853         //if it's a bean field - unformat it
854         require_once('include/SugarFields/SugarFieldHandler.php');
855
856         $sfh  = new SugarFieldHandler();
857         $type = !empty($this->fieldDefs[$name]['custom_type'])
858             ? $this->fieldDefs[$name]['custom_type']
859             : $this->fieldDefs[$name]['type'];
860         $sf   = $sfh->getSugarField($type);
861
862         return $sf ? $sf->unformatField($request[$name], $this->fieldDefs[$name]) : $request[$name];
863     }
864
865
866         /**
867          * Allow Subviews to overwrite this method to show custom titles.
868          * Examples: Projects & Project Templates.
869          * params: $showTitle: boolean for backwards compatibility.
870          */
871     public function showTitle($showTitle = false)
872     {
873         global $mod_strings, $app_strings;
874
875         if (is_null($this->viewObject))
876         {
877             $this->viewObject = (!empty($GLOBALS['current_view']))
878                 ? $GLOBALS['current_view']
879                 : new SugarView();
880         }
881
882         if ($showTitle)
883         {
884             return $this->viewObject->getModuleTitle();
885         }
886
887         return '';
888     }
889
890     /**
891      * Get template handler object
892      * @return TemplateHandler
893      */
894     protected function getTemplateHandler()
895     {
896         return new TemplateHandler();
897     }
898 }
899