Wednesday, November 24, 2010

SugarCrm - Change max size of default name field in module builder

The following posting and the indicated modifications to code is based on the 5.5.2 release of SugarCrm CE edition.

Objective
SugarCRM allows defining Max Size for "Text Field" field types in Module Builder. We need to add feature to define/change html display size attribute for the Text Field from Module Builder. 

The changes will affect following fields:
1.    For custom Text Field
2.    For pre-defined TextField i.e.  name

Purpose
By default the display size for the Text Field is 30 characters but it can hold up to 255 characters. When you are creating or editing a record in EditView some times if the text you are editing in a text field is long enough it becomes awkward. This problem can be avoided by increasing the display size of the TextField.

Currently the TextField for name field in EditView will be rendered as:

<input type="text" maxlength="" size="30" id="name" title="" value="" name="name" />

I would like to be able to change this when I define a new module in Module Builder.


This change is not upgrade safe.

Files need to be changed

(I have marked the hack with comments in each individual section below)

1.    /modules/DynamicFields/DynamicField.php
function addFieldObject(&$field){
        $GLOBALS['log']->debug('adding field');
        $object_name = $this->module;
        $db_name = $field->name;
        
        $fmd = new FieldsMetaData();
        $id =  $fmd->retrieve($object_name.$db_name,true, false);
        $is_update = false;
        $label = $field->label;
        if(!empty($id)){
            $is_update = true;
        }else{
            $db_name = $this->getDBName($field->name);
            $field->name = $db_name;
        }
         $this->createCustomTable();
        $fmd->id = $object_name.$db_name;
        $fmd->custom_module= $object_name;
        $fmd->name = $db_name;
        $fmd->vname = $label;
        $fmd->type = $field->type;
        $fmd->help = $field->help;
        //Hack:Allow for changing the individual textboxes html size setting
        $fmd->size = $field->size;
        //Hack:Allow for changing the individual textboxes html size setting
        if (!empty($field->len))
           $fmd->len = $field->len; // tyoung bug 15407 - was being set to $field->size so changes weren't being saved
        $fmd->required = ($field->required ? 1 : 0);
        $fmd->default_value = $field->default;
        $fmd->ext1 = $field->ext1;
        $fmd->ext2 = $field->ext2;
        $fmd->ext3 = $field->ext3;
        $fmd->ext4 = (isset($field->ext4) ? $field->ext4 : '');
        $fmd->comments = $field->comment;
        $fmd->massupdate = $field->massupdate;
        $fmd->importable = ( isset ( $field->importable ) ) ? $field->importable : null ;
        $fmd->duplicate_merge = $field->duplicate_merge;
        $fmd->audited =$field->audited;
        $fmd->reportable = ($field->reportable ? 1 : 0);
        if(!$is_update){
            $fmd->new_with_id=true;
        }
        $fmd->save();
        $this->buildCache($this->module);
        if($field){
            if(!$is_update){
                $query = $field->get_db_add_alter_table($this->bean->table_name . '_cstm');
            }else{
                $query = $field->get_db_modify_alter_table($this->bean->table_name . '_cstm');
            }
            if(!empty($query)){
                $GLOBALS['db']->query($query);
            }
        }
        return true;
    }

function addField($name,$label='', $type='Text',$max_size='255',$size='',$required_option='optional', $default_value='', $ext1='', $ext2='', $ext3='',$audited=0, $mass_update = 0 , $ext4='', $help='',$duplicate_merge=0, $comment=''){
        require_once('modules/DynamicFields/templates/Fields/TemplateField.php');
        $field = new TemplateField();
        $field->label = $label;
        if(empty($field->label)){
            $field->label = $name;
        }
        $field->name = $name;
        $field->type = $type;
        $field->len = $max_size;
        $field->required = (!empty($required_option) && $required_option != 'optional');
        $field->default = $default_value;
        $field->ext1 = $ext1;
        $field->ext2 = $ext2;
        $field->ext3 = $ext3;
        $field->ext4 = $ext4;
        $field->help = $help;
        //Hack:Allow for changing the individual textboxes html size setting
        $field->size = $size;
        //Hack:Allow for changing the individual textboxes html size setting
        $field->comments = $comment;
        $field->massupdate = $mass_update;
        $field->duplicate_merge = $duplicate_merge;
        $field->audited = $audited;
        $field->reportable = 1;
        return $this->addFieldObject($field);
    }


2.    /modules/DynamicFields/templates/Fields/TemplateField.php
class TemplateField{
    /*
        The view is the context this field will be used in
        -edit
        -list
        -detail
        -search
    */
    var $view = 'edit';
    var $name = '';
    var $vname = '';
    var $id = '';
    // Hack:Allow for changing the individual textboxes html size setting
    var $size = '';
    // Hack:Allow for changing the individual textboxes html size setting

    var $len = '255';
    var $required = false;
    var $default = null;
    var $default_value = null;

function get_field_def(){
        $array =  array(
            'required'=>$this->required,
            'source'=>'custom_fields',
            'name'=>$this->name,
            'vname'=>$this->vname,
            'type'=>$this->type,
            'massupdate'=>$this->massupdate,
            'default'=>$this->default,
            'comments'=> (isset($this->comments)) ? $this->comments : '',
            'help'=> (isset($this->help)) ?  $this->help : '',
            // Hack:Allow for changing the individual textboxes html size setting
            'size'=>$this->size,
            // Hack:Allow for changing the individual textboxes html size setting
            'importable'=>$this->importable,
            'duplicate_merge'=>$this->duplicate_merge,
            'duplicate_merge_dom_value'=>$this->duplicate_merge, //nsingh: bug #14897 The UI did not get updated according to $app_list_strings['custom_fields_merge_dup_dom'], so include an extra field for the dom and leave the original duplicate_merge logic intact.
            'audited'=>($this->audited ? 1 : 0),
            'reportable'=>($this->reportable ? 1 : 0),
            );
            if(!empty($this->len)){
                $array['len'] = $this->len;
            }
            $this->get_dup_merge_def($array);
            return $array;
    }

3.    /modules/DynamicFields/templates/Fields/Forms/varchar.tpl

{else}
        <input type='hidden' name='len' value='{$vardef.len}'>{$vardef.len}
    {/if}
    </td>
</tr>

{* Hack:Allow for changing the individual textboxes html size setting *}
<tr>
    <td class='mbLBL'>{$MOD.COLUMN_TITLE_SIZE}: </td>
    <td>
        <input type="text" name="size" value="{$vardef.size}">
    </td>
</tr>
{* Hack:Allow for changing the individual textboxes html size setting *}
{include file="modules/DynamicFields/templates/Fields/Forms/coreBottom.tpl"}

4.    /modules/EditCustomFields/EditCustomFields.php

function add_custom_field($name, $label, $data_type, $max_size,$size,
        $required_option, $default_value, $deleted, $ext1, $ext2, $ext3, $audited, $mass_update=0, $duplicate_merge=0, $reportable = true)
    {
        $module_name = $this->module_name;

        $fields_meta_data = new FieldsMetaData();
        $fields_meta_data->name = $name;
        $fields_meta_data->label = $label;
        $fields_meta_data->module = $module_name;
        $fields_meta_data->data_type = $data_type;
        $fields_meta_data->max_size = $max_size;
        //Hack:Allow for changing the individual textboxes html size setting
        $fields_meta_data->size = $size;
        //Hack:Allow for changing the individual textboxes html size setting    
        $fields_meta_data->required_option = $required_option;
        $fields_meta_data->default_value = $default_value;
        $fields_meta_data->deleted = $deleted;

5.    /modules/EditCustomFields/EditView.html

<tr><td nowrap="nowrap">{MOD.COLUMN_TITLE_DATA_TYPE}:</td><td><select name="data_type" id='data_type' onchange="typeChanged(this);" {NOEDIT}>{data_type_options}</select></td></tr>

<tr><td nowrap="nowrap">{MOD.COLUMN_TITLE_MAX_SIZE}:</td><td><input type="text" name="max_size" value="{max_size}" /></td></tr>

<!-- Hack: Allow for changing the individual textboxes html size setting -->
<tr><td nowrap="nowrap">{MOD.COLUMN_TITLE_SIZE}:</td><td><input type="text" name="size" value="{size}" /></td></tr>
<!-- Hack: Allow for changing the individual textboxes html size setting -->    

<tr><td nowrap="nowrap">{MOD.COLUMN_TITLE_REQUIRED_OPTION}:</td><td><input type="checkbox" name="required_option" value="{required_option}" {REQUIRED_CHECKED}/></td></tr>

<tr><td nowrap="nowrap">{MOD.COLUMN_TITLE_DEFAULT_VALUE}:</td><td><input type="text" name="default_value" value="{default_value}" /></td></tr>

6.    /modules/EditCustomFields/EditView.php

$xtpl->assign('NOEDIT', 'disabled');
    $xtpl->assign('custom_field_id', $focus->id);
    $xtpl->assign('name', $focus->name);
    $xtpl->assign('label', $focus->label);
    $xtpl->assign('custom_module', $focus->custom_module);
    
   $data_type_options_html = get_select_options_with_id($data_type_array,
        $focus->data_type);
    
    $xtpl->assign('data_type_options', $data_type_options_html);
    $xtpl->assign('max_size', $focus->max_size);
    //Hack:Allow for changing the individual textboxes html size setting
    $xtpl->assign('size', $focus->size);
    //Hack:Allow for changing the individual textboxes html size setting
    $xtpl->assign('required_option', $focus->required_option);
    if($focus->required_option == 'required'){
        $xtpl->assign('REQUIRED_CHECKED', 'checked');
    }
    $xtpl->assign('default_value', $focus->default_value);
    
    $xtpl ->assign('ENUM_OPTIONS', get_select_options_with_id($enum_keys, $focus->ext1));
    $xtpl->assign('ext1', $focus->ext1);
    $xtpl->assign('ext2', $focus->ext2);
    $xtpl->assign('ext3', $focus->ext3);

7.    /modules/EditCustomFields/Forms.html

{mod.COLUMN_TITLE_DATA_TYPE}<br />
<select name="data_type">{data_type_options}</select><br />
{mod.COLUMN_TITLE_MAX_SIZE}<br />
<input type="text" name="max_size" value="" /><br />
<!-- Hack: Allow for changing the individual textboxes html size setting -->
{mod.COLUMN_TITLE_SIZE}<br />
<input type="text" name="size" value="" /><br />
<!-- Hack: Allow for changing the individual textboxes html size setting -->
{mod.COLUMN_TITLE_REQUIRED_OPTION}<br />
<input type="checkbox" name="required_option" value="1" /><br />
{mod.COLUMN_TITLE_DEFAULT_VALUE}
<input type="text" name="default_value" value="" /><br />

8.    /modules/EditCustomFields/ListView.html

<td scope="col" ><a href="{ORDER_BY}data_type" class="listViewThLinkS1"
    >{MOD.COLUMN_TITLE_DATA_TYPE}{arrow_start}{data_type_arrow}{arrow_end}</a></td>
<td scope="col" ><a href="{ORDER_BY}max_size" class="listViewThLinkS1"
    >{MOD.COLUMN_TITLE_MAX_SIZE}{arrow_start}{max_size_arrow}{arrow_end}</a></td>
<!-- Hack: Allow for changing the individual textboxes html size setting -->
<td scope="col" class="listViewThS1"><a href="{ORDER_BY}size" class="listViewThLinkS1">{MOD.COLUMN_TITLE_SIZE}{arrow_start}{size_arrow}{arrow_end}</a></td>    
<!-- Hack: Allow for changing the individual textboxes html size setting -->    
<td scope="col" ><a href="{ORDER_BY}required_option" class="listViewThLinkS1"
    >{MOD.COLUMN_TITLE_REQUIRED_OPTION}{arrow_start}{required_option_arrow}{arrow_end}</a></td>
<td scope="col" ><a href="{ORDER_BY}default_value" class="listViewThLinkS1"
    >{MOD.COLUMN_TITLE_DEFAULT_VALUE}{arrow_start}{default_value_arrow}{arrow_end}</a></td>
<td scope="col" >&nbsp;</td>

9.    /modules/EditCustomFields/Popup.html

tr>
<td nowrap="nowrap">{mod.COLUMN_TITLE_DATA_TYPE}</td>
<td><select name="data_type">{data_type_options}</select></td>
</tr>

<tr>
<td nowrap="nowrap">{mod.COLUMN_TITLE_MAX_SIZE}</td>
<td><input type="text" name="max_size" value="{max_size}" /></td>
</tr>
<!-- Hack: Allow for changing the individual textboxes html size setting -->
<tr>
<td nowrap="nowrap">{mod.COLUMN_TITLE_SIZE}</td>
<td><input type="text" name="size" value="{size}" /></td>
</tr>
<!-- Hack: Allow for changing the individual textboxes html size setting -->

<tr>
<td nowrap="nowrap">{mod.COLUMN_TITLE_REQUIRED_OPTION}</td>
<td><input type="checkbox" name="required_option" value="{required_option}" /></td>
</tr>

10.    /modules/EditCustomFields/Save.php

if(isset($_REQUEST['ext2'])){        
    $ext2 = $_REQUEST['ext2'];
}
$ext3 = '';
if(isset($_REQUEST['ext3'])){        
    $ext3 = $_REQUEST['ext3'];
}
$max_size = '255';
if(isset($_REQUEST['max_size'])){        
    $max_size = $_REQUEST['max_size'];
}
//Hack:Allow for changing the individual textboxes html size setting
if(isset($_REQUEST['size'])){        
    $size = $_REQUEST['size'];
}
//Hack:Allow for changing the individual textboxes html size setting
$required_opt = 'optional';
if(isset($_REQUEST['required_option'])){
    $required_opt = 'required';
}
$default_value = '';
if(isset($_REQUEST['default_value'])){
    $default_value = $_REQUEST['default_value'];
}

11.    /modules/EditCustomFields/vardefs.php

'fields' => array (
        'id'=>array('name' =>'id', 'type' =>'varchar', 'len'=>'255', 'reportable'=>false),
        'name'=>array('name' =>'name', 'vname'=>'COLUMN_TITLE_NAME', 'type' =>'varchar', 'len'=>'255'),
        'vname'=>array('name' =>'vname' ,'type' =>'varchar','vname'=>'COLUMN_TITLE_LABEL',  'len'=>'255'),
        'comments'=>array('name' =>'comments' ,'type' =>'varchar','vname'=>'COLUMN_TITLE_LABEL',  'len'=>'255'),
        'help'=>array('name' =>'help' ,'type' =>'varchar','vname'=>'COLUMN_TITLE_LABEL',  'len'=>'255'),
        'custom_module'=>array('name' =>'custom_module',  'type' =>'varchar', 'len'=>'255', ),
        'type'=>array('name' =>'type', 'vname'=>'COLUMN_TITLE_DATA_TYPE',  'type' =>'varchar', 'len'=>'255'),
        'len'=>array('name' =>'len','vname'=>'COLUMN_TITLE_MAX_SIZE', 'type' =>'int', 'len'=>'11', 'required'=>false, 'validation' => array('type' => 'range', 'min' => 1, 'max' => 255),),
        // Hack: Allow for changing the individual textboxes html size setting
        'size'=>array('name' =>'size' ,'type' =>'varchar','vname'=>'COLUMN_TITLE_SIZE',  'len'=>'255'),
        // Hack: Allow for changing the individual textboxes html size setting
        'required'=>array('name' =>'required', 'type' =>'bool', 'default'=>'0'),
        'default_value'=>array('name' =>'default_value', 'type' =>'varchar', 'len'=>'255', ),
        'date_modified'=>array('name' =>'date_modified', 'type' =>'datetime', 'len'=>'255',),        
        'deleted'=>array('name' =>'deleted', 'type' =>'bool', 'default'=>'0', 'reportable'=>false),
        'audited'=>array('name' =>'audited', 'type' =>'bool', 'default'=>'0'),        
        'massupdate'=>array('name' =>'massupdate', 'type' =>'bool', 'default'=>'0'),    
        'duplicate_merge'=>array('name' =>'duplicate_merge', 'type' =>'short', 'default'=>'0'),  
        'reportable' => array('name'=>'reportable', 'type'=>'bool', 'default'=>'1'),

12.    /modules/EditCustomFields/language/en_us.lang.php

'LBL_REPORTABLE'=>'Reportable',
    'ERR_RESERVED_FIELD_NAME' => "Reserved Keyword",
    'ERR_SELECT_FIELD_TYPE' => 'Please Select a Field Type',
    'LBL_BTN_ADD' => 'Add',
    'LBL_BTN_EDIT' => 'Edit',
    'LBL_GENERATE_URL' => 'Generate URL',
    'LBL_DEPENDENT_CHECKBOX'=>'Dependent',
    'LBL_DEPENDENT_TRIGGER'=>'Trigger',
    'LBL_BTN_EDIT_VISIBILITY'=>'Edit Visibility',
    // Hack: Allow for changing the individual textboxes html size setting
    'COLUMN_TITLE_SIZE' => "Size",
    // Hack: Allow for changing the individual textboxes html size setting
);
?>

13.    /modules/ModuleBuilder/MB/MBField.php

class MBField{
    var $type = 'varchar';
    var $name = false;
    var $label = false;
    var $vname = false;
    //Hack:Allow for changing the individual textboxes html size setting
    var $size = false;
    //Hack:Allow for changing the individual textboxes html size setting
    var $options = false;
    var $length = false;
    var $error = '';
    var $required = false;
    var $reportable = true;
    var $default = 'MSI1';

function getFieldVardef(){
        if(empty($this->name)){
            $this->error = 'A name is required to create a field';
            return false;
        }        
        if(empty($this->label))$this->label = $this->name;
        $this->name = strtolower($this->getDBName($this->name));
        $vardef = array();
        $vardef['name']=$this->name;
        if(empty($this->vname))$this->vname = 'LBL_' . strtoupper($this->name);
        $vardef['vname'] = $this->addLabel();
        if(!empty($this->required))$vardef['required'] = $this->required;
        if(empty($this->reportable))$vardef['reportable'] = false;
        if(!empty($this->comment))$vardef['comment'] = $this->comment;
        //Hack:Allow for changing the individual textboxes html size setting
        if(!empty($this->size))$vardef['size'] = $this->size;
        //Hack:Allow for changing the individual textboxes html size setting
        if($this->default !== 'MSI1')$vardef['default'] = $this->default;
        switch($this->type){
            case 'date':
            case 'datetime':

14.    /modules/ModuleBuilder/MB/MBPackage.php

$result=$db->query("SELECT *  FROM fields_meta_data where custom_module='$value'");
                    while($row = $db->fetchByAssoc($result)){
                        $name = $row['id'];
                        foreach($row as $col=>$res){
                            switch ($col) {
                                case 'custom_module':
                                    $installdefs['custom_fields'][$name]['module'] = $res;
                                    break;
                                case 'required':
                                    $installdefs['custom_fields'][$name]['require_option'] = $res;
                                    break;
                                case 'vname':
                                    $installdefs['custom_fields'][$name]['label'] = $res;
                                    break;
                            //Hack:Allow for changing the individual textboxes html size setting
                                case 'size':
                                    $installdefs['custom_fields'][$name]['size'] = $res;
                                    break;                                    
                            //Hack:Allow for changing the individual textboxes html size setting                        
                                case 'required':
                                    $installdefs['custom_fields'][$name]['require_option'] = $res;
                                    break;
                                case 'massupdate':
                                    $installdefs['custom_fields'][$name]['mass_update'] = $res;
                                    break;

15.    /modules/ModuleBuilder/views/view.modulefield.php

if(empty($vardef['name'])){
                if(!empty($_REQUEST['type']))$vardef['type'] = $_REQUEST['type'];
                    $fv->ss->assign('hideLevel', 0);
            }else{
                if(!empty($module->mbvardefs->vardef['fields'][$vardef['name']])){
                    $fv->ss->assign('hideLevel', 1);
                }elseif(isset($vardef['custom_module'])){
                    $fv->ss->assign('hideLevel', 2);
                }else{
                    //Hack:Allow for changing the individual textboxes html size setting 
                    if($vardef['name'] == 'name'){
                        $action = 'saveField';
                         
                    } else {
                        $action = 'saveLabel';
                    }
                    //Hack:Allow for changing the individual textboxes html size setting 
                    $fv->ss->assign('hideLevel', 10); // tyoung bug 17350 - effectively mark template derived fields as readonly
                }
            }

16.    /modules/ModuleBuilder/views/view.modulefields.php

} else {
            require_once('modules/ModuleBuilder/MB/ModuleBuilder.php');
            $mb = new ModuleBuilder();
            $mb->getPackage($_REQUEST['view_package']);
            $package = $mb->packages[$_REQUEST['view_package']];

            $package->getModule($module_name);
            $this->module = $package->modules[$module_name];
            $this->loadPackageHelp($module_name);
            $this->module->getVardefs(true);
            $this->module->mbvardefs->vardefs['fields'] = array_reverse($this->module->mbvardefs->vardefs['fields'], true);
            foreach($this->module->mbvardefs->vardefs['fields'] as $k=>$v){
                if($k != $module_name)
                    $titleLBL[$k]=translate("LBL_".strtoupper($k),'ModuleBuilder');
                else{
                    $titleLBL[$k]=$k;
                }
            }
            
            //Hack:Allow for changing the individual textboxes html size setting 
            foreach($this->module->mbvardefs->vardefs['fields'][$module_name] as $k=>$v){
                foreach($titleLBL as $template){
                    if($template != $module_name){
                        $template = strtolower($template);
                        
                        //Ketty: Upgrade sugarbase to SugarCRM 5.5
                        $template = str_replace(' ', '_', $template);
                        //Ketty: Upgrade sugarbase to SugarCRM 5.5
                        
                        foreach($this->module->mbvardefs->vardefs['fields'][$template] as $key => $value){
                            if($k == $key && $key == 'name'){
                                unset($this->module->mbvardefs->vardefs['fields'][$template][$key] );
                            }
                        }
                    }                
                }                
            }
            //Hack:Allow for changing the individual textboxes html size setting 
            $this->module->mbvardefs->vardefs['fields'][$module_name] = $this->cullFields($this->module->mbvardefs->vardefs['fields'][$module_name]);
            if(file_exists($this->module->path. '/language/'.$GLOBALS['current_language'].'.lang.php')){
                include($this->module->path .'/language/'. $GLOBALS['current_language'].'.lang.php');
                $this->module->setModStrings($GLOBALS['current_language'],$mod_strings);
            }
            elseif(file_exists($this->module->path. '/language/en_us.lang.php')){
                include($this->module->path .'/language/en_us.lang.php');
                $this->module->setModStrings('en_us',$mod_strings);
            }
            $smarty->assign('title', $titleLBL);
            $smarty->assign('package', $package);
            $smarty->assign('module', $this->module);
            $smarty->assign('editLabelsMb','1'); //need to merge MB labels and studio labels. quick fix for now.

17.    /include/SugarFields/Fields/Base/EditView.tpl

{if strlen({{sugarvar key='value' string=true}}) <= 0}
{assign var="value" value={{sugarvar key='default_value' string=true}} }
{else}
{assign var="value" value={{sugarvar key='value' string=true}} }
{/if}
{* Hack:Allow for changing the individual textboxes html size setting *}  
<input type='text' name='{{sugarvar key='name'}}' id='{{sugarvar key='name'}}' 
{{if isset($displayParams.maxlength)}}maxlength='{{$displayParams.maxlength}}'
{{elseif isset($vardef.len)}}maxlength='{{$vardef.len}}'{{/if}} 
{{if !empty($displayParams.size)}}size='{{$displayParams.size}}'
{{elseif !empty($vardef.size)}}size='{{$vardef.size}}'{{/if}} 
value='{$value}' title='{{$vardef.help}}' tabindex='{{$tabindex}}' {{$displayParams.field}}>



Additional InfoYou need to execute sql statement to add column “size” in "fields_meta_data" table.
ALTER TABLE fields_meta_data  add column size varchar (255) NULL ;