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.
7 * This program is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU Affero General Public License version 3 as published by the
9 * Free Software Foundation with the addition of the following permission added
10 * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
11 * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
12 * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16 * FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
19 * You should have received a copy of the GNU Affero General Public License along with
20 * this program; if not, see http://www.gnu.org/licenses or write to the Free
21 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
24 * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
25 * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
27 * The interactive user interfaces in modified source and object code versions
28 * of this program must display Appropriate Legal Notices, as required under
29 * Section 5 of the GNU Affero General Public License version 3.
31 * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
32 * these Appropriate Legal Notices must retain the display of the "Powered by
33 * SugarCRM" logo. If the display of the logo is not reasonably feasible for
34 * technical reasons, the Appropriate Legal Notices must display the words
35 * "Powered by SugarCRM".
36 ********************************************************************************/
38 $GLOBALS['studioReadOnlyFields'] = array('date_entered'=>1, 'date_modified'=>1, 'created_by'=>1, 'id'=>1, 'modified_user_id'=>1);
41 The view is the context this field will be used in
53 var $required = false;
55 var $default_value = null;
56 var $type = 'varchar';
65 var $importable = 'true' ;
66 var $duplicate_merge=0;
67 var $new_field_definition;
68 var $reportable = true;
69 var $label_value = '';
73 var $vardef_map = array(
76 // bug 15801 - need to ALWAYS keep default and default_value consistent as some methods/classes use one, some use another...
77 'default_value'=>'default',
78 'default'=>'default_value',
79 'display_default'=>'default_value',
80 // 'default_value'=>'default_value',
81 // 'default'=>'default_value',
83 'required'=>'required',
86 'massupdate'=>'massupdate',
89 'comments'=>'comment',
90 'importable'=>'importable',
91 'duplicate_merge'=>'duplicate_merge',
92 'duplicate_merge_dom_value'=>'duplicate_merge_dom_value', //bug #14897
93 'merge_filter'=>'merge_filter',
94 'reportable' => 'reportable',
99 //'disable_num_format'=>'ext3',
101 'label_value'=>'label_value',
108 if(!empty($GLOBALS['studioReadOnlyFields'][$this->name]))$view = 'detail';
110 case 'search':return $this->get_html_search();
111 case 'edit': return $this->get_html_edit();
112 case 'list': return $this->get_html_list();
113 case 'detail': return $this->get_html_detail();
117 function set($values){
118 foreach($values as $name=>$value){
119 $this->$name = $value;
124 function get_html_edit(){
125 return 'not implemented';
128 function get_html_list(){
129 return $this->get_html_detail();
132 function get_html_detail(){
133 return 'not implemented';
136 function get_html_search(){
137 return $this->get_html_edit();
139 function get_html_label(){
141 $label = "{MOD." .$this->vname . "}";
142 if(!empty($GLOBALS['app_strings'][$this->vname])){
143 $label = "{APP." .$this->label . "}";
145 if($this->view == 'edit' && $this->is_required()){
146 $label .= '<span class="required">*</span>';
148 if($this->view == 'list'){
149 if(isset($this->bean)){
150 if(!empty($this->id)){
151 $name = $this->bean->table_name . '_cstm.'. $this->name;
152 $arrow = $this->bean->table_name . '_cstm_'. $this->name;
154 $name = $this->bean->table_name . '.'. $this->name;
155 $arrow = $this->bean->table_name . '_'. $this->name;
161 $label = "<a href='{ORDER_BY}$name' class='listViewThLinkS1'>{MOD.$this->label}{arrow_start}{".$arrow."_arrow}{arrow_end}</a>";
171 function get_xtpl($bean = false){
175 if(!empty($GLOBALS['studioReadOnlyFields'][$this->name]))$view = 'detail';
177 case 'search':return $this->get_xtpl_search();
178 case 'edit': return $this->get_xtpl_edit();
179 case 'list': return $this->get_xtpl_list();
180 case 'detail': return $this->get_xtpl_detail();
185 function get_xtpl_edit(){
186 return '/*not implemented*/';
189 function get_xtpl_list(){
190 return get_xtpl_detail();
193 function get_xtpl_detail(){
194 return '/*not implemented*/';
197 function get_xtpl_search(){
198 //return get_xtpl_edit();
201 function is_required(){
216 function get_db_type(){
217 switch($GLOBALS['db']->dbType){
218 case 'oci8': return " varchar2($this->len)";
219 case 'mssql': return !empty($GLOBALS['db']->isFreeTDS) ? " nvarchar($this->len)" : " varchar($this->len)";
220 default: return " varchar($this->len)";
224 function get_db_default($modify=false){
225 $GLOBALS['log']->debug('get_db_default(): default_value='.$this->default_value);
226 if (!$modify or empty($this->new_field_definition['default_value']) or $this->new_field_definition['default_value'] != $this->default_value ) {
227 if(!is_null($this->default_value)){ // add a default value if it is not null - we want to set a default even if default_value is '0', which is not null, but which is empty()
228 if(NULL == trim($this->default_value)){
229 return " DEFAULT NULL";
232 return " DEFAULT '$this->default_value'";
241 * Return the required clause for this field
242 * Confusingly, when modifying an existing field ($modify=true) there are two exactly opposite cases:
243 * 1. if called by Studio, only $this->required is set. If set, we return "NOT NULL" otherwise we return "NULL"
244 * 2. if not called by Studio, $this->required holds the OLD value of required, and new_field_definition['required'] is the NEW
245 * So if not called by Studio we want to return NULL if required=true (because we are changing FROM this setting)
248 function get_db_required($modify=false){
249 // $GLOBALS['log']->debug('get_db_required required='.$this->required." and ".(($modify)?"true":"false")." and ".print_r($this->new_field_definition,true));
253 if (!empty($this->new_field_definition['required'])) {
254 if ($this->required and $this->new_field_definition['required'] != $this->required) {
260 $req = ($this->required) ? " NOT NULL " : ''; // bug 17184 tyoung - set required correctly when modifying custom field in Studio
265 if (empty($this->new_field_definition['required']) or $this->new_field_definition['required'] != $this->required ) {
266 if(!empty($this->required) && $this->required){
275 /* function get_db_required($modify=false){
276 $GLOBALS['log']->debug('get_db_required required='.$this->required." and ".(($modify)?"true":"false")." and ".print_r($this->new_field_definition,true));
278 if (!empty($this->new_field_definition['required'])) {
279 if ($this->required and $this->new_field_definition['required'] != $this->required) {
285 if (empty($this->new_field_definition['required']) or $this->new_field_definition['required'] != $this->required ) {
286 if(!empty($this->required) && $this->required){
294 * Oracle Support: do not set required constraint if no default value is supplied.
295 * In this case the default value will be handled by the application/sugarbean.
297 function get_db_add_alter_table($table)
299 return $GLOBALS['db']->getHelper()->addColumnSQL($table, $this->get_field_def(), true);
302 function get_db_delete_alter_table($table)
304 return $GLOBALS['db']->getHelper()->dropColumnSQL(
306 $this->get_field_def()
311 * mysql requires the datatype caluse in the alter statment.it will be no-op anyway.
313 function get_db_modify_alter_table($table){
315 $db_default=$this->get_db_default(true);
316 $db_required=$this->get_db_required(true);
317 switch ($GLOBALS['db']->dbType) {
320 //Bug 21772: MSSQL handles alters in strange ways. Defer to DBHelpers guidance.
321 $query = $db->helper->alterColumnSQL($table, $this->get_field_def());
326 $query="ALTER TABLE $table MODIFY $this->name " .$this->get_db_type();
329 $query="ALTER TABLE $table MODIFY $this->name " .$this->get_db_type();;
333 if (!empty($db_default) && !empty($db_required)) {
334 $query .= $db_default . $db_required ;
335 } else if (!empty($db_default)) {
336 $query .= $db_default;
346 function get_field_def(){
348 'required'=>$this->convertBooleanValue($this->required),
349 'source'=>'custom_fields',
351 'vname'=>$this->vname,
353 'massupdate'=>$this->massupdate,
354 'default'=>$this->default,
355 'comments'=> (isset($this->comments)) ? $this->comments : '',
356 'help'=> (isset($this->help)) ? $this->help : '',
357 'importable'=>$this->importable,
358 'duplicate_merge'=>$this->duplicate_merge,
359 'duplicate_merge_dom_value'=> isset($this->duplicate_merge_dom_value) ? $this->duplicate_merge_dom_value : $this->duplicate_merge,
360 'audited'=>$this->convertBooleanValue($this->audited),
361 'reportable'=>$this->convertBooleanValue($this->reportable),
363 if(!empty($this->len)){
364 $array['len'] = $this->len;
366 if(!empty($this->size)){
367 $array['size'] = $this->size;
369 $this->get_dup_merge_def($array);
373 protected function convertBooleanValue($value)
375 if ($value === 'true' || $value === '1' || $value === 1)
377 else if ($value === 'false' || $value === '0' || $value === 0)
384 /* if the field is duplicate merge enabled this function will return the vardef entry for the same.
386 function get_dup_merge_def(&$def) {
388 switch ($def['duplicate_merge_dom_value']) {
390 $def['duplicate_merge']='disabled';
393 $def['duplicate_merge']='enabled';
396 $def['merge_filter']='enabled';
397 $def['duplicate_merge']='enabled';
400 $def['merge_filter']='selected';
401 $def['duplicate_merge']='enabled';
404 $def['merge_filter']='enabled';
405 $def['duplicate_merge']='disabled';
417 if(empty($this->id)){
418 $this->id = $this->name;
424 * This function supports setting the values of all TemplateField instances.
425 * @param $row The Array key/value pairs from fields_meta_data table
427 function populateFromRow($row=array()) {
428 $fmd_to_dyn_map = array('comments' => 'comment', 'require_option' => 'required', 'label' => 'vname',
429 'mass_update' => 'massupdate', 'max_size' => 'len', 'default_value' => 'default', 'id_name' => 'ext3');
430 if(!is_array($row)) {
431 $GLOBALS['log']->error("Error: TemplateField->populateFromRow expecting Array");
433 //Bug 24189: Copy fields from FMD format to Field objects
434 foreach ($fmd_to_dyn_map as $fmd_key => $dyn_key) {
435 if (isset($row[$fmd_key])) {
436 $this->$dyn_key = $row[$fmd_key];
439 foreach($row as $key=>$value) {
440 $this->$key = $value;
444 function populateFromPost(){
445 foreach($this->vardef_map as $vardef=>$field){
446 if(isset($_REQUEST[$vardef])){
447 $this->$vardef = $_REQUEST[$vardef];
448 if($vardef != $field){
449 $this->$field = $this->$vardef;
453 $this->applyVardefRules();
454 $GLOBALS['log']->debug('populate: '.print_r($this,true));
458 protected function applyVardefRules()
462 function get_additional_defs(){
466 function delete($df){
467 $df->deleteField($this);
471 // $GLOBALS['log']->debug('saving field: '.print_r($this,true));
472 $df->addFieldObject($this);