2 /*********************************************************************************
3 * SugarCRM Community Edition is a customer relationship management program developed by
4 * SugarCRM, Inc. Copyright (C) 2004-2012 SugarCRM Inc.
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.
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
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
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.
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.
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 ********************************************************************************/
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
43 class SugarFieldBase {
44 var $ss; // Sugar Smarty Object
45 var $hasButton = false;
46 function SugarFieldBase($type) {
48 $this->ss = new Sugar_Smarty();
50 function fetch($path){
52 if(!$this->hasButton && !empty($this->button)){
53 $additional .= '<input type="button" class="button" ' . $this->button . '>';
55 if(!empty($this->buttons)){
56 foreach($this->buttons as $v){
57 $additional .= ' <input type="button" class="button" ' . $v . '>';
61 if(!empty($this->image)){
62 $additional .= ' <img ' . $this->image . '>';
64 return $this->ss->fetch($path) . $additional;
67 function findTemplate($view){
68 static $tplCache = array();
70 if ( isset($tplCache[$this->type][$view]) ) {
71 return $tplCache[$this->type][$view];
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);
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;
89 if ( file_exists($tplName) ) {
93 $tplName = 'include/SugarFields/Fields/'. $className .'/'. $view .'.tpl';
94 if ( file_exists('custom/'.$tplName) ) {
95 $tplName = 'custom/'.$tplName;
98 if ( file_exists($tplName) ) {
103 $tplCache[$this->type][$view] = $tplName;
108 public function formatField($rawField, $vardef){
109 // The base field doesn't do any formatting, so override it in subclasses for more specific actions
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;
119 function getSmartyView($parentFieldArray, $vardef, $displayParams, $tabindex = -1, $view){
120 $this->setup($parentFieldArray, $vardef, $displayParams, $tabindex);
123 return $this->fetch($this->findTemplate($view));
126 function getListViewSmarty($parentFieldArray, $vardef, $displayParams, $col) {
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')
132 $parentFieldArray = $this->setupFieldArray($parentFieldArray, $vardef);
136 $vardef['name'] = strtoupper($vardef['name']);
139 $this->setup($parentFieldArray, $vardef, $displayParams, $tabindex, false);
141 $this->ss->left_delimiter = '{';
142 $this->ss->right_delimiter = '}';
143 $this->ss->assign('col',$vardef['name']);
145 return $this->fetch($this->findTemplate('ListView'));
149 * Returns a smarty template for the DetailViews
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
158 function getDetailViewSmarty($parentFieldArray, $vardef, $displayParams, $tabindex) {
159 return $this->getSmartyView($parentFieldArray, $vardef, $displayParams, $tabindex, 'DetailView');
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);
168 function getEditViewSmarty($parentFieldArray, $vardef, $displayParams, $tabindex) {
169 if(!empty($vardef['function']['returns']) && $vardef['function']['returns'] == 'html'){
171 $this->type = 'Base';
172 $result= $this->getDetailViewSmarty($parentFieldArray, $vardef, $displayParams, $tabindex);
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');
181 // ~ jpereira@dri - #Bug49513 - Readonly type not working as expected
182 return $this->getSmartyView($parentFieldArray, $vardef, $displayParams, $tabindex, 'EditView');
185 function getImportViewSmarty($parentFieldArray, $vardef, $displayParams, $tabindex)
187 return $this->getEditViewSmarty($parentFieldArray, $vardef, $displayParams, $tabindex);
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');
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);
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);
210 function displayFromFunc( $displayType, $parentFieldArray, $vardef, $displayParams, $tabindex = 0 ) {
212 if ( ! is_array($vardef['function']) ) {
213 $funcName = $vardef['function'];
216 $returnsHtml = false;
218 $funcName = $vardef['function']['name'];
220 if ( isset($vardef['function']['include']) ) {
221 $includeFile = $vardef['function']['include'];
223 if ( isset($vardef['function']['onListView']) && $vardef['function']['onListView'] == true ) {
228 if ( isset($vardef['function']['returns']) && $vardef['function']['returns'] == 'html' ) {
231 $returnsHtml = false;
235 if ( $displayType == 'ListView'
236 || $displayType == 'popupView'
237 || $displayType == 'searchView'
238 || $displayType == 'wirelessEditView'
239 || $displayType == 'wirelessDetailView'
240 || $displayType == 'wirelessListView'
242 // Traditionally, before 6.0, additional functions were never called, so this code doesn't get called unless the vardef forces it
244 if ( !empty($includeFile) ) {
245 require_once($includeFile);
248 return $funcName($parentFieldArray, $vardef['name'], $parentFieldArray[strtoupper($vardef['name'])], $displayType);
250 $displayTypeFunc = 'get'.$displayType.'Smarty';
251 return $this->$displayTypeFunc($parentFieldArray, $vardef, $displayParams, $tabindex);
254 if ( !empty($displayParams['idName']) ) {
255 $fieldName = $displayParams['idName'];
257 $fieldName = $vardef['name'];
259 if ( $returnsHtml ) {
260 $this->setup($parentFieldArray, $vardef, $displayParams, $tabindex);
261 $tpl = $this->findTemplate($displayType.'Function');
263 // Can't find a function template, just use the base
264 $tpl = $this->findTemplate('DetailViewFunction');
266 return "<span id='{$vardef['name']}_span'>" . $this->fetch($tpl) . '</span>';
268 return '{sugar_run_helper include="'.$includeFile.'" func="'.$funcName.'" bean=$bean field="'.$fieldName.'" value=$fields.'.$fieldName.'.value displayType="'.$displayType.'"}';
273 function getEditView() {
277 * getSearchWhereValue
279 * Checks and returns a sane value based on the field type that can be used when building the where clause in a
282 * @param $value Mixed value being searched on
283 * @return Mixed the value for the where clause used in search
285 function getSearchWhereValue($value) {
292 * This function allows the SugarFields to handle returning the search input value given arguments (typically from $_REQUEST/$_POST)
293 * and a search string.
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
299 function getSearchInput($key='', $args=array())
301 //Nothing specified return empty string
302 if(empty($key) || empty($args))
307 return isset($args[$key]) ? $args[$key] : '';
310 function getQueryLike() {
314 function getQueryIn() {
318 * Setup function to assign values to the smarty template, should be called before every display function
320 function setup($parentFieldArray, $vardef, $displayParams, $tabindex, $twopass=true) {
326 $this->ss->left_delimiter = '{{';
327 $this->ss->right_delimiter = '}}';
331 $this->ss->left_delimiter = '{';
332 $this->ss->right_delimiter = '}';
334 $this->ss->assign('parentFieldArray', $parentFieldArray);
335 $this->ss->assign('vardef', $vardef);
336 $this->ss->assign('tabindex', $tabindex);
338 //for adding attributes to the field
340 if(!empty($displayParams['field'])){
342 foreach($displayParams['field'] as $key=>$value){
343 $plusField .= ' ' . $key . '="' . $value . '"';//bug 27381
345 $displayParams['field'] = $plusField;
347 //for adding attributes to the button
348 if(!empty($displayParams['button'])){
350 foreach($displayParams['button'] as $key=>$value){
351 $plusField .= ' ' . $key . '="' . $value . '"';
353 $displayParams['button'] = $plusField;
354 $this->button = $displayParams['button'];
356 if(!empty($displayParams['buttons'])){
358 foreach($displayParams['buttons'] as $keys=>$values){
359 foreach($values as $key=>$value){
360 $plusField[$keys] .= ' ' . $key . '="' . $value . '"';
363 $displayParams['buttons'] = $plusField;
364 $this->buttons = $displayParams['buttons'];
366 if(!empty($displayParams['image'])){
368 foreach($displayParams['image'] as $key=>$value){
369 $plusField .= ' ' . $key . '="' . $value . '"';
371 $displayParams['image'] = $plusField;
372 $this->image = $displayParams['image'];
374 $this->ss->assign('displayParams', $displayParams);
379 protected function getAccessKey($vardef, $fieldType = null, $module = null) {
383 'accessKey' => array(),
384 'accessKeySelect' => array(),
385 'accessKeyClear' => array(),
388 // Labels are always in uppercase
389 if ( isset($fieldType) ) {
390 $fieldType = strtoupper($fieldType);
393 if ( isset($module) ) {
394 $module = strtoupper($module);
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'];
401 if ( isset($vardef['accessKeySelect']) ) {
402 $labelList['accessKeySelect'][] = $vardef['accessKeySelect'];
404 if ( isset($vardef['accessKeyClear']) ) {
405 $labelList['accessKeyClear'][] = $vardef['accessKeyClear'];
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;
414 if ( isset($module) ) {
415 $labelList['accessKey'][] = 'LBL_ACCESSKEY_'.$module;
416 $labelList['accessKeySelect'][] = 'LBL_ACCESSKEY_SELECT_'.$module;
417 $labelList['accessKeyClear'][] = 'LBL_ACCESSKEY_CLEAR_'.$module;
420 if ( isset($fieldType) ) {
421 $labelList['accessKey'][] = 'LBL_ACCESSKEY_'.$fieldType;
422 $labelList['accessKeySelect'][] = 'LBL_ACCESSKEY_SELECT_'.$fieldType;
423 $labelList['accessKeyClear'][] = 'LBL_ACCESSKEY_CLEAR_'.$fieldType;
426 // Attach the defaults to the ends
427 $labelList['accessKey'][] = 'LBL_ACCESSKEY';
428 $labelList['accessKeySelect'][] = 'LBL_SELECT_BUTTON';
429 $labelList['accessKeyClear'][] = 'LBL_CLEAR_BUTTON';
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(
436 'accessKeyLabel' => '',
437 'accessKeyTitle' => '',
438 'accessKeySelect' => '',
439 'accessKeySelectLabel' => '',
440 'accessKeySelectTitle' => '',
441 'accessKeyClear' => '',
442 'accessKeyClearLabel' => '',
443 'accessKeyClearTitle' => '',
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';
456 return $accessKeyList;
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
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));
470 $bean->$field = $this->unformatField($params[$prefix.$field], $properties);
476 * Check if the field is allowed to be trimmed
478 * @param string $type
481 protected function isTrimmable($type) {
482 return in_array($type, array('varchar', 'name'));
486 * Handles import field sanitizing for an field type
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
494 public function importSanitize(
498 ImportFieldSanitize $settings
501 if( isset($vardef['len']) ) {
502 // check for field length
503 $value = sugar_substr($value, $vardef['len']);
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
515 protected function isRangeSearchView($vardef)
517 return !empty($vardef['enable_range_search']) && !empty($_REQUEST['action']) && $_REQUEST['action']!='Popup';
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.
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
530 protected function setupFieldArray($parentFieldArray, $vardef)
532 $fieldName = $vardef['name'];
533 if ( is_array($parentFieldArray) )
535 $fieldNameUpper = strtoupper($fieldName);
536 if ( isset($parentFieldArray[$fieldNameUpper]))
538 $parentFieldArray[$fieldName] = $this->formatField($parentFieldArray[$fieldNameUpper],$vardef);
540 $parentFieldArray[$fieldName] = '';
542 } elseif (is_object($parentFieldArray)) {
543 if ( isset($parentFieldArray->$fieldName) )
545 $parentFieldArray->$fieldName = $this->formatField($parentFieldArray->$fieldName,$vardef);
547 $parentFieldArray->$fieldName = '';
550 return $parentFieldArray;