]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - include/SugarFields/Fields/Base/SugarFieldBase.php
Release 6.5.3
[Github/sugarcrm.git] / include / SugarFields / Fields / Base / SugarFieldBase.php
1 <?php
2 /*********************************************************************************
3  * SugarCRM Community Edition is a customer relationship management program developed by
4  * SugarCRM, Inc. Copyright (C) 2004-2012 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  * SugarFieldBase translates and displays fields from a vardef definition into different formats
39  * including DetailView, ListView, EditView. It also provides Search Inputs and database queries
40  * to handle searching
41  *
42  */
43 class SugarFieldBase {
44     var $ss; // Sugar Smarty Object
45     var $hasButton = false;
46     function SugarFieldBase($type) {
47         $this->type = $type;
48         $this->ss = new Sugar_Smarty();
49     }
50     function fetch($path){
51         $additional = '';
52         if(!$this->hasButton && !empty($this->button)){
53                 $additional .= '<input type="button" class="button" ' . $this->button . '>';
54         }
55         if(!empty($this->buttons)){
56             foreach($this->buttons as $v){
57                 $additional .= ' <input type="button" class="button" ' . $v . '>';
58             }
59
60         }
61         if(!empty($this->image)){
62             $additional .= ' <img ' . $this->image . '>';
63         }
64         return $this->ss->fetch($path) . $additional;
65     }
66
67     function findTemplate($view){
68         static $tplCache = array();
69
70         if ( isset($tplCache[$this->type][$view]) ) {
71             return $tplCache[$this->type][$view];
72         }
73
74         $lastClass = get_class($this);
75         $classList = array($this->type,str_replace('SugarField','',$lastClass));
76         while ( $lastClass = get_parent_class($lastClass) ) {
77             $classList[] = str_replace('SugarField','',$lastClass);
78         }
79
80         $tplName = '';
81         foreach ( $classList as $className ) {
82             global $current_language;
83             if(isset($current_language)) {
84                 $tplName = 'include/SugarFields/Fields/'. $className .'/'. $current_language . '.' . $view .'.tpl';
85                 if ( file_exists('custom/'.$tplName) ) {
86                     $tplName = 'custom/'.$tplName;
87                     break;
88                 }
89                 if ( file_exists($tplName) ) {
90                     break;
91                 }
92             }
93             $tplName = 'include/SugarFields/Fields/'. $className .'/'. $view .'.tpl';
94             if ( file_exists('custom/'.$tplName) ) {
95                 $tplName = 'custom/'.$tplName;
96                 break;
97             }
98             if ( file_exists($tplName) ) {
99                 break;
100             }
101         }
102
103         $tplCache[$this->type][$view] = $tplName;
104
105         return $tplName;
106     }
107
108     public function formatField($rawField, $vardef){
109         // The base field doesn't do any formatting, so override it in subclasses for more specific actions
110         return $rawField;
111     }
112
113
114     public function unformatField($formattedField, $vardef){
115         // The base field doesn't do any formatting, so override it in subclasses for more specific actions
116         return $formattedField;
117     }
118
119     function getSmartyView($parentFieldArray, $vardef, $displayParams, $tabindex = -1, $view){
120         $this->setup($parentFieldArray, $vardef, $displayParams, $tabindex);
121
122
123         return $this->fetch($this->findTemplate($view));
124     }
125
126     function getListViewSmarty($parentFieldArray, $vardef, $displayParams, $col) {
127         $tabindex = 1;
128         //fixing bug #46666: don't need to format enum and radioenum fields 
129         //because they are already formated in SugarBean.php in the function get_list_view_array() as fix of bug #21672
130         if ($this->type != 'Enum' && $this->type != 'Radioenum')
131         {
132             $parentFieldArray = $this->setupFieldArray($parentFieldArray, $vardef);
133         }
134                 else
135         {
136                 $vardef['name'] = strtoupper($vardef['name']);
137         }
138         
139         $this->setup($parentFieldArray, $vardef, $displayParams, $tabindex, false);
140
141         $this->ss->left_delimiter = '{';
142         $this->ss->right_delimiter = '}';
143         $this->ss->assign('col',$vardef['name']);
144
145         return $this->fetch($this->findTemplate('ListView'));
146     }
147
148     /**
149      * Returns a smarty template for the DetailViews
150      *
151      * @param parentFieldArray string name of the variable in the parent template for the bean's data
152      * @param vardef vardef field defintion
153      * @param displayParam parameters for display
154      *      available paramters are:
155      *      * labelSpan - column span for the label
156      *      * fieldSpan - column span for the field
157      */
158     function getDetailViewSmarty($parentFieldArray, $vardef, $displayParams, $tabindex) {
159         return $this->getSmartyView($parentFieldArray, $vardef, $displayParams, $tabindex, 'DetailView');
160     }
161
162         // 99% of all fields will just format like a listview, but just in case, it's here to override
163     function getChangeLogSmarty($parentFieldArray, $vardef, $displayParams, $tabindex) {
164         return $this->formatField($parentFieldArray[$vardef['name']],$vardef);
165     }
166
167
168     function getEditViewSmarty($parentFieldArray, $vardef, $displayParams, $tabindex) {
169         if(!empty($vardef['function']['returns']) && $vardef['function']['returns'] == 'html'){
170                 $type = $this->type;
171                 $this->type = 'Base';
172                 $result= $this->getDetailViewSmarty($parentFieldArray, $vardef, $displayParams, $tabindex);
173                 $this->type = $type;
174                 return $result;
175         }
176         // jpereira@dri - #Bug49513 - Readonly type not working as expected
177         // If readonly is set in displayParams, the vardef will be displayed as in DetailView.
178         if (isset($displayParams['readonly']) && $displayParams['readonly']) {
179                 return $this->getSmartyView($parentFieldArray, $vardef, $displayParams, $tabindex, 'DetailView');
180         }       
181         // ~ jpereira@dri - #Bug49513 - Readonly type not working as expected
182        return $this->getSmartyView($parentFieldArray, $vardef, $displayParams, $tabindex, 'EditView');
183     }
184
185     function getImportViewSmarty($parentFieldArray, $vardef, $displayParams, $tabindex)
186     {
187         return $this->getEditViewSmarty($parentFieldArray, $vardef, $displayParams, $tabindex);
188     }
189
190
191
192     function getSearchViewSmarty($parentFieldArray, $vardef, $displayParams, $tabindex) {
193                 if(!empty($vardef['auto_increment']))$vardef['len']=255;
194         return $this->getSmartyView($parentFieldArray, $vardef, $displayParams, $tabindex, 'EditView');
195     }
196
197     function getPopupViewSmarty($parentFieldArray, $vardef, $displayParams, $tabindex){
198          if (is_array($displayParams) && !isset($displayParams['formName']))
199                      $displayParams['formName'] = 'popup_query_form';
200              else if (empty($displayParams))
201                      $displayParams = array('formName' => 'popup_query_form');
202                  return $this->getSearchViewSmarty($parentFieldArray, $vardef, $displayParams, $tabindex);
203     }
204
205     public function getEmailTemplateValue($inputField, $vardef, $context = null){
206         // This does not return a smarty section, instead it returns a direct value
207         return $this->formatField($inputField,$vardef);
208     }
209
210     function displayFromFunc( $displayType, $parentFieldArray, $vardef, $displayParams, $tabindex = 0 ) {
211
212         if ( ! is_array($vardef['function']) ) {
213             $funcName = $vardef['function'];
214             $includeFile = '';
215             $onListView = false;
216             $returnsHtml = false;
217         } else {
218             $funcName = $vardef['function']['name'];
219             $includeFile = '';
220             if ( isset($vardef['function']['include']) ) {
221                 $includeFile = $vardef['function']['include'];
222             }
223             if ( isset($vardef['function']['onListView']) && $vardef['function']['onListView'] == true ) {
224                 $onListView = true;
225             } else {
226                 $onListView = false;
227             }
228             if ( isset($vardef['function']['returns']) && $vardef['function']['returns'] == 'html' ) {
229                 $returnsHtml = true;
230             } else {
231                 $returnsHtml = false;
232             }
233         }
234
235         if ( $displayType == 'ListView'
236                 || $displayType == 'popupView'
237                 || $displayType == 'searchView'
238                 || $displayType == 'wirelessEditView'
239                 || $displayType == 'wirelessDetailView'
240                 || $displayType == 'wirelessListView'
241                 ) {
242             // Traditionally, before 6.0, additional functions were never called, so this code doesn't get called unless the vardef forces it
243             if ( $onListView ) {
244                 if ( !empty($includeFile) ) {
245                     require_once($includeFile);
246                 }
247
248                 return $funcName($parentFieldArray, $vardef['name'], $parentFieldArray[strtoupper($vardef['name'])], $displayType);
249             } else {
250                 $displayTypeFunc = 'get'.$displayType.'Smarty';
251                 return $this->$displayTypeFunc($parentFieldArray, $vardef, $displayParams, $tabindex);
252             }
253         } else {
254             if ( !empty($displayParams['idName']) ) {
255                 $fieldName = $displayParams['idName'];
256             } else {
257                 $fieldName = $vardef['name'];
258             }
259             if ( $returnsHtml ) {
260                 $this->setup($parentFieldArray, $vardef, $displayParams, $tabindex);
261                 $tpl = $this->findTemplate($displayType.'Function');
262                 if ( $tpl == '' ) {
263                     // Can't find a function template, just use the base
264                     $tpl = $this->findTemplate('DetailViewFunction');
265                 }
266                 return "<span id='{$vardef['name']}_span'>" . $this->fetch($tpl) . '</span>';
267             } else {
268                 return '{sugar_run_helper include="'.$includeFile.'" func="'.$funcName.'" bean=$bean field="'.$fieldName.'" value=$fields.'.$fieldName.'.value displayType="'.$displayType.'"}';
269             }
270         }
271     }
272
273     function getEditView() {
274     }
275
276     /**
277      * getSearchWhereValue
278      *
279      * Checks and returns a sane value based on the field type that can be used when building the where clause in a
280      * search form.
281      *
282      * @param $value Mixed value being searched on
283      * @return Mixed the value for the where clause used in search
284      */
285     function getSearchWhereValue($value) {
286         return $value;
287     }
288
289     /**
290      * getSearchInput
291      *
292      * This function allows the SugarFields to handle returning the search input value given arguments (typically from $_REQUEST/$_POST)
293      * and a search string.
294      *
295      * @param $key String value of key to search for
296      * @param $args Mixed value containing haystack to search for value in
297      * @return $value Mixed value that the SugarField should return
298      */
299     function getSearchInput($key='', $args=array())
300     {
301         //Nothing specified return empty string
302         if(empty($key) || empty($args))
303         {
304                 return '';
305         }
306
307         return isset($args[$key]) ? $args[$key] : '';
308     }
309
310     function getQueryLike() {
311
312     }
313
314     function getQueryIn() {
315     }
316
317     /**
318      * Setup function to assign values to the smarty template, should be called before every display function
319      */
320     function setup($parentFieldArray, $vardef, $displayParams, $tabindex, $twopass=true) {
321         $this->button = '';
322         $this->buttons = '';
323         $this->image = '';
324         if ($twopass)
325         {
326             $this->ss->left_delimiter = '{{';
327             $this->ss->right_delimiter = '}}';
328         }
329         else
330         {
331             $this->ss->left_delimiter = '{';
332             $this->ss->right_delimiter = '}';
333         }
334         $this->ss->assign('parentFieldArray', $parentFieldArray);
335         $this->ss->assign('vardef', $vardef);
336         $this->ss->assign('tabindex', $tabindex);
337
338         //for adding attributes to the field
339
340         if(!empty($displayParams['field'])){
341                 $plusField = '';
342                 foreach($displayParams['field'] as $key=>$value){
343                         $plusField .= ' ' . $key . '="' . $value . '"';//bug 27381
344                 }
345                 $displayParams['field'] = $plusField;
346         }
347         //for adding attributes to the button
348         if(!empty($displayParams['button'])){
349                 $plusField = '';
350                 foreach($displayParams['button'] as $key=>$value){
351                         $plusField .= ' ' . $key . '="' . $value . '"';
352                 }
353                 $displayParams['button'] = $plusField;
354                 $this->button = $displayParams['button'];
355         }
356         if(!empty($displayParams['buttons'])){
357             $plusField = '';
358             foreach($displayParams['buttons'] as $keys=>$values){
359                 foreach($values as $key=>$value){
360                     $plusField[$keys] .= ' ' . $key . '="' . $value . '"';
361                 }
362             }
363             $displayParams['buttons'] = $plusField;
364             $this->buttons = $displayParams['buttons'];
365         }
366         if(!empty($displayParams['image'])){
367             $plusField = '';
368             foreach($displayParams['image'] as $key=>$value){
369                 $plusField .= ' ' . $key . '="' . $value . '"';
370             }
371             $displayParams['image'] = $plusField;
372             $this->image = $displayParams['image'];
373         }
374         $this->ss->assign('displayParams', $displayParams);
375
376
377     }
378
379     protected function getAccessKey($vardef, $fieldType = null, $module = null) {
380         global $app_strings;
381
382         $labelList = array(
383             'accessKey' => array(),
384             'accessKeySelect' => array(),
385             'accessKeyClear' => array(),
386         );
387
388         // Labels are always in uppercase
389         if ( isset($fieldType) ) {
390             $fieldType = strtoupper($fieldType);
391         }
392
393         if ( isset($module) ) {
394             $module = strtoupper($module);
395         }
396
397         // The vardef is the most specific, then the module + fieldType, then the module, then the fieldType
398         if ( isset($vardef['accessKey']) ) {
399             $labelList['accessKey'][] = $vardef['accessKey'];
400         }
401         if ( isset($vardef['accessKeySelect']) ) {
402             $labelList['accessKeySelect'][] = $vardef['accessKeySelect'];
403         }
404         if ( isset($vardef['accessKeyClear']) ) {
405             $labelList['accessKeyClear'][] = $vardef['accessKeyClear'];
406         }
407
408         if ( isset($fieldType) && isset($module) ) {
409             $labelList['accessKey'][] = 'LBL_ACCESSKEY_'.$fieldType.'_'.$module;
410             $labelList['accessKeySelect'][] = 'LBL_ACCESSKEY_SELECT_'.$fieldType.'_'.$module;
411             $labelList['accessKeyClear'][] = 'LBL_ACCESSKEY_CLEAR_'.$fieldType.'_'.$module;
412         }
413
414         if ( isset($module) ) {
415             $labelList['accessKey'][] = 'LBL_ACCESSKEY_'.$module;
416             $labelList['accessKeySelect'][] = 'LBL_ACCESSKEY_SELECT_'.$module;
417             $labelList['accessKeyClear'][] = 'LBL_ACCESSKEY_CLEAR_'.$module;
418         }
419
420         if ( isset($fieldType) ) {
421             $labelList['accessKey'][] = 'LBL_ACCESSKEY_'.$fieldType;
422             $labelList['accessKeySelect'][] = 'LBL_ACCESSKEY_SELECT_'.$fieldType;
423             $labelList['accessKeyClear'][] = 'LBL_ACCESSKEY_CLEAR_'.$fieldType;
424         }
425
426         // Attach the defaults to the ends
427         $labelList['accessKey'][] = 'LBL_ACCESSKEY';
428         $labelList['accessKeySelect'][] = 'LBL_SELECT_BUTTON';
429         $labelList['accessKeyClear'][] = 'LBL_CLEAR_BUTTON';
430
431         // Figure out the label and the key for the button.
432         // Later on we may attempt to make sure there are no two buttons with the same keys, but for now we will just use whatever is specified.
433         $keyTypes = array('accessKey','accessKeySelect','accessKeyClear');
434         $accessKeyList = array(
435             'accessKey' => '',
436             'accessKeyLabel' => '',
437             'accessKeyTitle' => '',
438             'accessKeySelect' => '',
439             'accessKeySelectLabel' => '',
440             'accessKeySelectTitle' => '',
441             'accessKeyClear' => '',
442             'accessKeyClearLabel' => '',
443             'accessKeyClearTitle' => '',
444         );
445         foreach( $keyTypes as $type ) {
446             foreach ( $labelList[$type] as $tryThis ) {
447                 if ( isset($app_strings[$tryThis.'_KEY']) && isset($app_strings[$tryThis.'_TITLE']) && isset($app_strings[$tryThis.'_LABEL']) ) {
448                     $accessKeyList[$type] = $tryThis.'_KEY';
449                     $accessKeyList[$type.'Title'] = $tryThis.'_TITLE';
450                     $accessKeyList[$type.'Label'] = $tryThis.'_LABEL';
451                     break;
452                 }
453             }
454         }
455
456         return $accessKeyList;
457     }
458
459         /**
460      * This should be called when the bean is saved. The bean itself will be passed by reference
461      * @param SugarBean bean - the bean performing the save
462      * @param array params - an array of paramester relevant to the save, most likely will be $_REQUEST
463      */
464     public function save($bean, $params, $field, $properties, $prefix = '') {
465          if ( isset($params[$prefix.$field]) ) {
466              if(isset($properties['len']) && isset($properties['type']) && $this->isTrimmable($properties['type'])){
467                  $bean->$field = trim($this->unformatField($params[$prefix.$field], $properties));
468              }
469              else {
470                  $bean->$field = $this->unformatField($params[$prefix.$field], $properties);
471                  }
472          }
473      }
474
475      /**
476       * Check if the field is allowed to be trimmed
477       *
478       * @param string $type
479       * @return boolean
480       */
481      protected function isTrimmable($type) {
482          return in_array($type, array('varchar', 'name'));
483      }
484
485     /**
486      * Handles import field sanitizing for an field type
487      *
488      * @param  $value    string value to be sanitized
489      * @param  $vardefs  array
490      * @param  $focus    SugarBean object
491      * @param  $settings ImportFieldSanitize object
492      * @return string sanitized value or boolean false if there's a problem with the value
493      */
494     public function importSanitize(
495         $value,
496         $vardef,
497         $focus,
498         ImportFieldSanitize $settings
499         )
500     {
501         if( isset($vardef['len']) ) {
502             // check for field length
503             $value = sugar_substr($value, $vardef['len']);
504         }
505
506         return $value;
507     }
508
509     /**
510      * isRangeSearchView
511      * This method helps determine whether or not to display the range search view code for the sugar field
512      * @param array $vardef entry representing the sugar field's definition
513      * @return boolean true if range search view should be displayed, false otherwise
514      */
515     protected function isRangeSearchView($vardef)
516     {
517         return !empty($vardef['enable_range_search']) && !empty($_REQUEST['action']) && $_REQUEST['action']!='Popup';
518     }
519
520     /**
521      * setupFieldArray
522      * This method takes the $parentFieldArray mixed variable which may be an Array or object and attempts
523      * to call any custom fieldSpecific formatting to the value depending on the field type.
524      *
525      * @see SugarFieldEnum.php, SugarFieldInt.php, SugarFieldFloat.php, SugarFieldRelate.php
526      * @param   mixed   $parentFieldArray Array or Object of data where the field's value comes from
527      * @param   array   $vardef The vardef entry linked to the SugarField instance
528      * @return  array   $parentFieldArray The formatted $parentFieldArray with the formatField method possibly applied
529      */
530     protected function setupFieldArray($parentFieldArray, $vardef)
531     {
532         $fieldName = $vardef['name'];
533         if ( is_array($parentFieldArray) )
534         {
535             $fieldNameUpper = strtoupper($fieldName);
536             if ( isset($parentFieldArray[$fieldNameUpper]))
537             {
538                 $parentFieldArray[$fieldName] = $this->formatField($parentFieldArray[$fieldNameUpper],$vardef);
539             } else {
540                 $parentFieldArray[$fieldName] = '';
541             }
542         } elseif (is_object($parentFieldArray)) {
543             if ( isset($parentFieldArray->$fieldName) )
544             {
545                 $parentFieldArray->$fieldName = $this->formatField($parentFieldArray->$fieldName,$vardef);
546             } else {
547                 $parentFieldArray->$fieldName = '';
548             }
549         }
550         return $parentFieldArray;
551     }
552
553 }
554 ?>