]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - include/Dashlets/DashletGeneric.php
Release 6.1.4
[Github/sugarcrm.git] / include / Dashlets / DashletGeneric.php
1 <?php
2 if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
3 /*********************************************************************************
4  * SugarCRM is a customer relationship management program developed by
5  * SugarCRM, Inc. Copyright (C) 2004-2011 SugarCRM Inc.
6  * 
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.
13  * 
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
17  * details.
18  * 
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
22  * 02110-1301 USA.
23  * 
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.
26  * 
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.
30  * 
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  ********************************************************************************/
37
38 require_once('include/Dashlets/Dashlet.php');
39 require_once('include/ListView/ListViewSmarty.php');
40 require_once('include/generic/LayoutManager.php');
41
42 class DashletGeneric extends Dashlet {
43    /**
44      * Fields that are searchable
45      * @var array
46      */
47     var $searchFields;
48     /**
49      * Displayable columns (ones available to display)
50      * @var array
51      */
52     var $columns;
53     /**
54      * Bean file used in this Dashlet
55      * @var bean
56      */
57     var $seedBean;
58     /**
59      * collection of filters to apply
60      * @var array
61      */
62     var $filters = null;
63     /**
64      * Number of Rows to display
65      * @var int
66      */
67     var $displayRows = '5';
68     /**
69      * Actual columns to display, will be a subset of $columns
70      * @var array
71      */
72     var $displayColumns = null;
73     /**
74      * Flag to display only the current users's items.
75      * @var bool
76      */
77     var $myItemsOnly = true;
78     /**
79      * Flag to display "myItemsOnly" checkbox in the DashletGenericConfigure.
80      * @var bool
81      */
82     var $showMyItemsOnly = true;
83     /**
84      * location of Smarty template file for display
85      * @var string
86      */
87     var $displayTpl = 'include/Dashlets/DashletGenericDisplay.tpl';
88     /**
89      * location of smarty template file for configuring
90      * @var string
91      */
92     var $configureTpl = 'include/Dashlets/DashletGenericConfigure.tpl';
93     /**
94      * smarty object for the generic configuration template
95      * @var string
96      */
97     var $configureSS;
98     /** search inputs to be populated in configure template.
99      *  modify this after processDisplayOptions, but before displayOptions to modify search inputs
100      *  @var array
101      */
102     var $currentSearchFields;
103     /**
104      * ListView Smarty Class
105      * @var Smarty
106      */
107     var $lvs;
108     var $layoutManager;
109
110     function DashletGeneric($id, $options = null) {
111         parent::Dashlet($id);
112         $this->isConfigurable = true;
113         if(isset($options)) {
114             if(!empty($options['filters'])) $this->filters = $options['filters'];
115             if(!empty($options['title'])) $this->title = $options['title'];
116             if(!empty($options['displayRows'])) $this->displayRows = $options['displayRows'];
117             if(!empty($options['displayColumns'])) $this->displayColumns = $options['displayColumns'];
118             if(isset($options['myItemsOnly'])) $this->myItemsOnly = $options['myItemsOnly'];
119         }
120
121         $this->layoutManager = new LayoutManager();
122         $this->layoutManager->setAttribute('context', 'Report');
123         // fake a reporter object here just to pass along the db type used in many widgets.
124         // this should be taken out when sugarwidgets change
125         $temp = (object) array('db' => &$GLOBALS['db'], 'report_def_str' => '');
126         $this->layoutManager->setAttributePtr('reporter', $temp);
127         $this->lvs = new ListViewSmarty();
128     }
129
130     /**
131      * Sets up the display options template
132      *
133      * @return string HTML that shows options
134      */
135     function processDisplayOptions() {
136          require_once('include/templates/TemplateGroupChooser.php');
137
138         $this->configureSS = new Sugar_Smarty();
139         // column chooser
140         $chooser = new TemplateGroupChooser();
141
142         $chooser->args['id'] = 'edit_tabs';
143         $chooser->args['left_size'] = 5;
144         $chooser->args['right_size'] = 5;
145         $chooser->args['values_array'][0] = array();
146         $chooser->args['values_array'][1] = array();
147
148         $this->loadCustomMetadata();
149         $this->addCustomFields();
150         if($this->displayColumns) {
151              // columns to display
152              foreach($this->displayColumns as $num => $name) {
153                     // defensive code for array being returned
154                     $translated = translate($this->columns[$name]['label'], $this->seedBean->module_dir);
155                     if(is_array($translated)) $translated = $this->columns[$name]['label'];
156                     $chooser->args['values_array'][0][$name] = trim($translated, ':');
157              }
158              // columns not displayed
159              foreach(array_diff(array_keys($this->columns), array_values($this->displayColumns)) as $num => $name) {
160                     // defensive code for array being returned
161                     $translated = translate($this->columns[$name]['label'], $this->seedBean->module_dir);
162                     if(is_array($translated)) $translated = $this->columns[$name]['label'];
163                     $chooser->args['values_array'][1][$name] = trim($translated, ':');
164              }
165         }
166         else {
167              foreach($this->columns as $name => $val) {
168                 // defensive code for array being returned
169                 $translated = translate($this->columns[$name]['label'], $this->seedBean->module_dir);
170                 if(is_array($translated)) $translated = $this->columns[$name]['label'];
171                 if(!empty($val['default']) && $val['default'])
172                     $chooser->args['values_array'][0][$name] = trim($translated, ':');
173                 else
174                     $chooser->args['values_array'][1][$name] = trim($translated, ':');
175             }
176         }
177
178         $chooser->args['left_name'] = 'display_tabs';
179         $chooser->args['right_name'] = 'hide_tabs';
180         $chooser->args['max_left'] = '6';
181
182         $chooser->args['left_label'] =  $GLOBALS['app_strings']['LBL_DISPLAY_COLUMNS'];
183         $chooser->args['right_label'] =  $GLOBALS['app_strings']['LBL_HIDE_COLUMNS'];
184         $chooser->args['title'] =  '';
185         $this->configureSS->assign('columnChooser', $chooser->display());
186
187         $query = false;
188         $count = 0;
189
190         if(!is_array($this->filters)) {
191             // use default search params
192             $this->filters = array();
193             foreach($this->searchFields as $name => $params) {
194                 if(!empty($params['default']))
195                     $this->filters[$name] = $params['default'];
196             }
197         }
198         foreach($this->searchFields as $name=>$params) {
199             if(!empty($name)) {
200                 $name = strtolower($name);
201                 $currentSearchFields[$name] = array();
202                 $widgetDef = $this->seedBean->field_defs[$name];
203                 if($widgetDef['type'] == 'enum') $widgetDef['remove_blank'] = true; // remove the blank option for the dropdown
204                                 if($widgetDef['name'] == 'assigned_user_name') $widgetDef['name'] = 'assigned_user_id';
205                 $widgetDef['input_name0'] = empty($this->filters[$name]) ? '' : $this->filters[$name];
206                 $currentSearchFields[$name]['label'] = !empty($params['label']) ? translate($params['label'], $this->seedBean->module_dir) : translate($widgetDef['vname'], $this->seedBean->module_dir);
207                 $currentSearchFields[$name]['input'] = $this->layoutManager->widgetDisplayInput($widgetDef, true, (empty($this->filters[$name]) ? '' : $this->filters[$name]));
208             }
209             else { // ability to create spacers in input fields
210                 $currentSearchFields['blank' + $count]['label'] = '';
211                 $currentSearchFields['blank' + $count]['input'] = '';
212                 $count++;
213             }
214         }
215         $this->currentSearchFields = $currentSearchFields;
216
217         $this->configureSS->assign('strings', array('general' => $GLOBALS['mod_strings']['LBL_DASHLET_CONFIGURE_GENERAL'],
218                                      'filters' => $GLOBALS['mod_strings']['LBL_DASHLET_CONFIGURE_FILTERS'],
219                                      'myItems' => $GLOBALS['mod_strings']['LBL_DASHLET_CONFIGURE_MY_ITEMS_ONLY'],
220                                      'displayRows' => $GLOBALS['mod_strings']['LBL_DASHLET_CONFIGURE_DISPLAY_ROWS'],
221                                      'title' => $GLOBALS['mod_strings']['LBL_DASHLET_CONFIGURE_TITLE'],
222                                      'save' => $GLOBALS['app_strings']['LBL_SAVE_BUTTON_LABEL']));
223         $this->configureSS->assign('id', $this->id);
224         $this->configureSS->assign('showMyItemsOnly', $this->showMyItemsOnly);
225         $this->configureSS->assign('myItemsOnly', $this->myItemsOnly);
226         $this->configureSS->assign('searchFields', $this->currentSearchFields);
227         // title
228         $this->configureSS->assign('dashletTitle', $this->title);
229
230         // display rows
231         $displayRowOptions = $GLOBALS['sugar_config']['dashlet_display_row_options'];
232         $this->configureSS->assign('displayRowOptions', $displayRowOptions);
233         $this->configureSS->assign('displayRowSelect', $this->displayRows);
234     }
235     /**
236      * Displays the options for this Dashlet
237      *
238      * @return string HTML that shows options
239      */
240     function displayOptions() {
241         $this->processDisplayOptions();
242         return parent::displayOptions() . $this->configureSS->fetch($this->configureTpl);
243     }
244
245     function buildWhere() {
246         global $current_user;
247
248         $returnArray = array();
249
250         if(!is_array($this->filters)) {
251             // use defaults
252             $this->filters = array();
253             foreach($this->searchFields as $name => $params) {
254                 if(!empty($params['default']))
255                     $this->filters[$name] = $params['default'];
256             }
257         }
258         foreach($this->filters as $name=>$params) {
259             if(!empty($params)) {
260                 if($name == 'assigned_user_id' && $this->myItemsOnly) continue; // don't handle assigned user filter if filtering my items only
261                 $widgetDef = $this->seedBean->field_defs[$name];
262
263                 $widgetClass = $this->layoutManager->getClassFromWidgetDef($widgetDef, true);
264                 $widgetDef['table'] = $this->seedBean->table_name;
265                 $widgetDef['table_alias'] = $this->seedBean->table_name;
266                                 if(!empty($widgetDef['source']) && $widgetDef['source'] == 'custom_fields'){
267                     $widgetDef['table'] = $this->seedBean->table_name."_cstm";
268                     $widgetDef['table_alias'] = $widgetDef['table'];
269                 }
270                 switch($widgetDef['type']) {// handle different types
271                     case 'date':
272                     case 'datetime':
273                     case 'datetimecombo':
274                         if(is_array($params) && !empty($params)) {
275                             if(!empty($params['date']))
276                                 $widgetDef['input_name0'] = $params['date'];
277                             $filter = 'queryFilter' . $params['type'];
278                         }
279                         else {
280                             $filter = 'queryFilter' . $params;
281                         }
282                         array_push($returnArray, $widgetClass->$filter($widgetDef, true));
283                         break;
284                     case 'assigned_user_name':
285                         // This type runs through the SugarWidgetFieldname class, and needs a little extra help to make it through
286                         if ( ! isset($widgetDef['column_key']) ) {
287                             $widgetDef['column_key'] = $name;
288                         }
289                         // No break here, we want to run through the default handler
290                     default:
291                         $widgetDef['input_name0'] = $params;
292                         if(is_array($params) && !empty($params)) { // handle array query
293                             array_push($returnArray, $widgetClass->queryFilterone_of($widgetDef, false));
294                         }
295                         else {
296                             array_push($returnArray, $widgetClass->queryFilterStarts_With($widgetDef, true));
297                         }
298                         $widgetDef['input_name0'] = $params;
299                     break;
300                 }
301             }
302         }
303
304         if($this->myItemsOnly) array_push($returnArray, $this->seedBean->table_name . '.' . "assigned_user_id = '" . $current_user->id . "'");
305
306         return $returnArray;
307     }
308
309         protected function loadCustomMetadata()
310         {
311         $customMetadate = 'custom/modules/'.$this->seedBean->module_dir.'/metadata/dashletviewdefs.php';
312         if ( file_exists ( $customMetadate )){
313                 require($customMetadate);
314                         $this->searchFields = $dashletData[$this->seedBean->module_dir.'Dashlet']['searchFields'];
315                         foreach($this->searchFields  as $key =>$def){
316                                 if($key == 'assigned_user_name'){
317                                         $this->searchFields['assigned_user_id'] = $def;
318                                         unset($this->searchFields['assigned_user_name'] );
319                                         break;
320                                 }
321                         }
322                         
323                 $this->columns = $dashletData[$this->seedBean->module_dir.'Dashlet']['columns'];
324         }
325         }
326         
327     /**
328      * Does all dashlet processing, here's your chance to modify the rows being displayed!
329      */
330     function process($lvsParams = array()) {
331         $currentSearchFields = array();
332         $configureView = true; // configure view or regular view
333         $query = false;
334         $whereArray = array();
335         $lvsParams['massupdate'] = false;
336
337                 $this->loadCustomMetadata();
338         $this->addCustomFields();
339         // apply filters
340         if(isset($this->filters) || $this->myItemsOnly) {
341             $whereArray = $this->buildWhere();
342         }
343
344         $this->lvs->export = false;
345         $this->lvs->multiSelect = false;
346         // columns
347         $displayColumns = array();
348         if(!empty($this->displayColumns)) { // use user specified columns
349                 foreach($this->displayColumns as $name => $val) {
350                 $displayColumns[strtoupper($val)] = $this->columns[$val];
351                 $displayColumns[strtoupper($val)]['label'] = trim($displayColumns[strtoupper($val)]['label'], ':');// strip : at the end of headers
352             } 
353         }
354         else if (isset($this->columns)){ 
355            // use the default
356             foreach($this->columns as $name => $val) {
357                 if(!empty($val['default']) && $val['default']) {
358                     $displayColumns[strtoupper($name)] = $val;
359                     $displayColumns[strtoupper($name)]['label'] = trim($displayColumns[strtoupper($name)]['label'], ':');
360                 }
361             }
362         }
363         $this->lvs->displayColumns = $displayColumns;
364
365         $this->lvs->lvd->setVariableName($this->seedBean->object_name, array());
366         $lvdOrderBy = $this->lvs->lvd->getOrderBy(); // has this list been ordered, if not use default
367         if(!empty($lvsParams['orderBy']) && !empty($lvsParams['sortOrder'])){
368             $lvsParams['overrideOrder'] = true;
369         }
370         else if(empty($lvdOrderBy['orderBy'])) {
371             foreach($displayColumns as $colName => $colParams) {
372                 if(!empty($colParams['defaultOrderColumn'])) {
373                     $lvsParams['overrideOrder'] = true;
374                     $lvsParams['orderBy'] = $colName;
375                     $lvsParams['sortOrder'] = $colParams['defaultOrderColumn']['sortOrder'];
376                 }
377             }
378         }
379
380
381         if(!empty($this->displayTpl))
382         {
383                 //MFH BUG #14296
384             $where = '';
385             if(!empty($whereArray)){
386                 $where = '(' . implode(') AND (', $whereArray) . ')';
387             }            
388             $this->lvs->setup($this->seedBean, $this->displayTpl, $where , $lvsParams, 0, $this->displayRows/*, $filterFields*/);
389             if(in_array('CREATED_BY', array_keys($displayColumns))) { // handle the created by field
390                 foreach($this->lvs->data['data'] as $row => $data) {
391                     $this->lvs->data['data'][$row]['CREATED_BY'] = get_assigned_user_name($data['CREATED_BY']);
392                 }
393             }
394             // assign a baseURL w/ the action set as DisplayDashlet
395             foreach($this->lvs->data['pageData']['urls'] as $type => $url) {
396                 // awu Replacing action=DisplayDashlet with action=DynamicAction&DynamicAction=DisplayDashlet
397                 if($type == 'orderBy')
398                     $this->lvs->data['pageData']['urls'][$type] = preg_replace('/(action=.*&)/Ui', 'action=DynamicAction&DynamicAction=displayDashlet&', $url);
399                 else
400                     $this->lvs->data['pageData']['urls'][$type] = preg_replace('/(action=.*&)/Ui', 'action=DynamicAction&DynamicAction=displayDashlet&', $url) . '&sugar_body_only=1&id=' . $this->id;
401             }
402
403             $this->lvs->ss->assign('dashletId', $this->id);
404
405         }
406     }
407
408    /**
409      * Displays the Dashlet, must call process() prior to calling this
410      *
411      * @return string HTML that displays Dashlet
412      */
413     function display() {
414         return parent::display() . $this->lvs->display(false);
415     }
416
417     /**
418      * Filter the $_REQUEST and only save only the needed options
419      * @param array $req the array to pull options from
420      *
421      * @return array options array
422      */
423     function saveOptions($req) {
424         $options = array();
425
426                 $this->loadCustomMetadata();
427         foreach($req as $name => $value) {
428             if(!is_array($value)) $req[$name] = trim($value);
429         }
430         $options['filters'] = array();
431         foreach($this->searchFields as $name=>$params) {
432             $widgetDef = $this->seedBean->field_defs[$name];
433             if($widgetDef['type'] == 'datetimecombo' || $widgetDef['type'] == 'datetime' || $widgetDef['type'] == 'date') { // special case datetime types
434                 $options['filters'][$widgetDef['name']] = array();
435                 if(!empty($req['type_' . $widgetDef['name']])) { // save the type of date filter
436                     $options['filters'][$widgetDef['name']]['type'] = $req['type_' . $widgetDef['name']];
437                 }
438                 if(!empty($req['date_' . $widgetDef['name']])) { // save the date
439                     $options['filters'][$widgetDef['name']]['date'] = $req['date_' . $widgetDef['name']];
440                 }
441             }
442             elseif(!empty($req[$widgetDef['name']])) {
443                 $options['filters'][$widgetDef['name']] = $req[$widgetDef['name']];
444             }
445         }
446         if(!empty($req['dashletTitle'])) {
447             $options['title'] = $req['dashletTitle'];
448         }
449
450         if(!empty($req['myItemsOnly'])) {
451             $options['myItemsOnly'] = $req['myItemsOnly'];
452         }
453         else {
454            $options['myItemsOnly'] = false;
455         }
456         $options['displayRows'] = empty($req['displayRows']) ? '5' : $req['displayRows'];
457         // displayColumns
458         if(!empty($req['displayColumnsDef'])) {
459             $options['displayColumns'] = explode('|', $req['displayColumnsDef']);
460         }
461         return $options;
462     }
463
464     /**
465      * Internal function to add custom fields
466      *
467      */
468     function addCustomFields() {
469         foreach($this->seedBean->field_defs as $fieldName => $def) {
470             if(!empty($def['type']) && $def['type'] == 'html')
471                 continue;
472             if(isset($def['vname'])) {
473                 $translated = translate($def['vname'], $this->seedBean->module_dir);
474                 if(is_array($translated)) $translated = $def['vname'];
475                 if(!empty($def['source']) && $def['source'] == 'custom_fields') {
476                         if(isset($this->columns[$fieldName]['default']) && $this->columns[$fieldName]['default']){
477                                 $this->columns[$fieldName] = array('width' => '10',
478                                                        'label' => $translated,
479                                                        'default' => 1);
480                         }else{
481                     $this->columns[$fieldName] = array('width' => '10',
482                                                        'label' => $translated);
483                         }
484                     
485                 }
486             }
487         }
488     }
489 }
490 ?>