I apologize for this being a bit lengthy but I waned to go through as much as I could to try and figure out what the problem was and ended up writing this out with no success and decided to post it here to see if someone else could see what I am doing wrong.
Several people have used this site ( Convert the Country Text to a Dropdown ) to set the Country field to a drop down. I am using SuiteCRM 7.12.7 and trying to modify the Accounts module country field.
At the bottom of the above linked site it states
The address country field exists on Accounts, Contacts, Leads and Targets by default. But in accounts for example it is billing_address_country and shipping_address_country you will just have to check the field names before makeing the changes.
Describe my Setup:
My table has billing_address_country instead of primary_address_country so I am using billing_address_country.
In the file custom/Extention/modules/Accounts/Ext/Language/Vardefs/_override_sugarfield_billing_address_country.php I have
$dictionary['Account']['fields']['billing_address_country']['required']=true;
$dictionary['Account']['fields']['billing_address_country']['inline_edit']=true;
$dictionary['Account']['fields']['billing_address_country']['comments']='The country used for the billing address';
$dictionary['Account']['fields']['billing_address_country']['merge_filter']='disabled';
$dictionary['Account']['fields']['billing_address_country']['type'] = 'enum';
$dictionary['Account']['fields']['billing_address_country']['options'] = 'countries_dom';
$dictionary['Account']['fields']['billing_address_country']['group'] = 'billing_address';
Several sites I found stated you must use the file en_us.EditView.tpl instead of the file EditView.tpl from the include/SugarFields/Fields/Address folder. This is true for my case since my $current_language is set to “en_us ”.
In custom/modules/Accounts/metadata/edtiviewdefs.php I have:
array (
0 =>
array (
'name' => 'billing_address_street',
'hideLabel' => true,
'type' => 'CustomAddress',
'displayParams' =>
array (
'key' => 'billing',
'rows' => 2,
'cols' => 30,
'maxlength' => 150,
),
'label' => 'LBL_BILLING_ADDRESS_STREET',
),
Details:
I am trying to get this to work but not having any luck. For clarification, can anyone tell me if the two labels used in this post CUSTOM_FIELD_TYPE_NAME and CUSTOM_TYPE_NAME are supposed to be the same text? If they are supposed to be the same text then does it matter what text I use? If so I can’t get it to work meaning there is no drop down because the custom template is not used.
The only way I get the drop down to show is if I
- Place a folder in the path custom/include/SugarFields/Fields/ named Address
- Place a customized en_us.EditView.tpl file in this folder.
- In the file custom/modules/Accounts/metadata/editviewdefs.php, set the value for ‘type’ => ‘address’,. However, the dropdown is empty.
Questions:
- Does anyone know why my drop down is empty?
- Has anyone used a custom template name other than “address”? (later on got this to work see below)
- This appears to a global configuration. By that I mean anywhere use the “address” this template is used. Is this Global? (I think so if using Address as a field type)
Digging into base Code:
I did some searching and found where I believe this template is selected. I only found one place in the code that searches for .tpl files in the include/SugarFields/Fields folder. In the file include/SugarFields/Fields/Base/SugarFieldBase.php around line 100 you will find this method:
/**
* @param string $view Eg EditView
* @return string
*/
public function findTemplate($view)
{
static $tplCache = array();
if (isset($tplCache[$this->type][$view])) {
return $tplCache[$this->type][$view];
}
$lastClass = get_class($this);
$classList = array($this->type, str_replace('SugarField', '', $lastClass));
while ($lastClass = get_parent_class($lastClass)) {
$classList[] = str_replace('SugarField', '', $lastClass);
}
$tplName = '';
foreach ($classList as $className) {
global $current_language;
if (isset($current_language)) {
$tplName = 'include/SugarFields/Fields/' . $className . '/' . $current_language . '.' . $view . '.tpl';
if (file_exists('custom/' . $tplName)) {
$tplName = 'custom/' . $tplName;
break;
}
if (file_exists($tplName)) {
break;
}
}
$tplName = 'include/SugarFields/Fields/' . $className . '/' . $view . '.tpl';
if (file_exists('custom/' . $tplName)) {
$tplName = 'custom/' . $tplName;
break;
}
if (file_exists($tplName)) {
break;
}
}
$tplCache[$this->type][$view] = $tplName;
return $tplName;
}
Looking at this code in my case the variable $current_language is set to “en_us”. Dumping the $classList only contains this:
ClassName: Enum
ClassName: Base
ClassName: Name
ClassName: Base
ClassName: Base
ClassName: Phone
ClassName: Address
ClassName: Float
ClassName: Datetime
ClassName: Int
As you can see ClassNames are what is used to search for field types. So I wonder, how would one add a custom CUSTOM_FIELD_TYPE_NAME? more to come…
So I did some more digging and found that in the file include/SugarFields/SugarFieldHander.php is where CUSTOM_FIELD_TYPE_NAME search is found in method getSugarField around line 88.
/**
* return the singleton of the SugarField
* @param $field
* @param bool $returnNullIfBase
* @return mixed
*/
public static function getSugarField($field, $returnNullIfBase=false)
{
static $sugarFieldObjects = array();
$field = self::fixupFieldType($field);
$field = ucfirst($field);
if (!isset($sugarFieldObjects[$field])) {
//check custom directory
if (file_exists('custom/include/SugarFields/Fields/' . $field . '/SugarField' . $field. '.php')) {
$file = 'custom/include/SugarFields/Fields/' . $field . '/SugarField' . $field. '.php';
$type = $field;
error_log("file:{$file}");
error_log("Type: {$type}");
//else check the fields directory
} elseif (file_exists('include/SugarFields/Fields/' . $field . '/SugarField' . $field. '.php')) {
$file = 'include/SugarFields/Fields/' . $field . '/SugarField' . $field. '.php';
$type = $field;
} else {
// No direct class, check the directories to see if they are defined
if ($returnNullIfBase &&
!is_dir('custom/include/SugarFields/Fields/'.$field) &&
!is_dir('include/SugarFields/Fields/'.$field)) {
return null;
}
$file = get_custom_file_if_exists('include/SugarFields/Fields/Base/SugarFieldBase.php');
$type = 'Base';
}
require_once($file);
$class = 'SugarField' . $type;
//could be a custom class check it
$customClass = 'Custom' . $class;
if (class_exists($customClass)) {
$sugarFieldObjects[$field] = new $customClass($field);
} else {
$sugarFieldObjects[$field] = new $class($field);
}
}
return $sugarFieldObjects[$field];
}
As you can see that the code is looking for a php file in custom/includeSugarFields/Fields/XXX folder where XXX is going to be one of the class names found in the findTemplate() method.
So more digging I found that this .php file when found needs to be a class file with a name SugarField that extends the SugarFieldBase class. So I added a file named SugarFieldCustomAddress.php in the custom/includes/SugarFields/Fields folder. This file looks like this:
<?php
require_once('include/SugarFields/Fields/Base/SugarFieldBase.php');
class SugarFieldCustomAddress extends SugarFieldBase
{
public function getEditViewSmarty($parentFieldArray, $vardef, $displayParams, $tabindex)
{
$this->setup($parentFieldArray, $vardef, $displayParams, $tabindex);
global $app_strings;
if (!isset($displayParams['key'])) {
$GLOBALS['log']->debug($app_strings['ERR_ADDRESS_KEY_NOT_SPECIFIED']);
$this->ss->trigger_error($app_strings['ERR_ADDRESS_KEY_NOT_SPECIFIED']);
return;
}
//Allow for overrides. You can specify a Smarty template file location in the language file.
if (isset($app_strings['SMARTY_ADDRESS_EDITVIEW'])) {
$tplCode = $app_strings['SMARTY_ADDRESS_EDITVIEW'];
return $this->fetch($tplCode);
}
return $this->fetch("custom/include/SugarFields/Fields/Account/CustomAddress/en_us.EditView.tpl");
}
}
This is copy of the base file with the return value changed to point to my
This does return my custom en_us.EditView.tpl template. However, like the first method I used, the Dropdown is still empty.
I don’t know what why the drop down is empty in both methods.
Here is part of my counries_dom find in the include/en_us.lang.php file:
$app_list_strings['countries_dom'] = array(
'' => '',
'ABU DHABI' => 'ABU DHABI',
'ADEN' => 'ADEN',
'AFGHANISTAN' => 'AFGHANISTAN',
'ALBANIA' => 'ALBANIA',
'ALGERIA' => 'ALGERIA',
'UNITED ARAB EMIRATES' => 'UNITED ARAB EMIRATES',
.....
'UNITED KINGDOM' => 'UNITED KINGDOM',
'URUGUAY' => 'URUGUAY',
'US PACIFIC ISLAND' => 'US PACIFIC ISLAND',
'US VIRGIN ISLANDS' => 'US VIRGIN ISLANDS',
'USA' => 'USA',
'ZAMBIA' => 'ZAMBIA',
'ZIMBABWE' => 'ZIMBABWE',
);
Here is my customized en_us.EditView.tpl file in the custom/include/SugarFields/Fields/CustomAddress folder:
<script src='{sugar_getjspath file="include/SugarFields/Fields/Address/SugarFieldAddress.js"}'></script>
{{assign var="key" value=$displayParams.key|upper}}
{{assign var="street" value=$displayParams.key|cat:'_address_street'}}
{{assign var="city" value=$displayParams.key|cat:'_address_city'}}
{{assign var="state" value=$displayParams.key|cat:'_address_state'}}
{{assign var="country" value=$displayParams.key|cat:'_address_country'}}
{{assign var="postalcode" value=$displayParams.key|cat:'_address_postalcode'}}
<fieldset id='{{$key}}_address_fieldset'>
<legend>*** NEW TEMPLATE ***{sugar_translate label='LBL_{{$key}}_ADDRESS' module='{{$module}}'}</legend>
<table border="0" cellspacing="1" cellpadding="0" class="edit" width="100%">
<tr>
<td valign="top" id="{{$street}}_label" width='25%' scope='row'>
<label for="{{$street}}">{sugar_translate label='LBL_{{$key}}_STREET' module='{{$module}}'}:</label>
{if $fields.{{$street}}.required || {{if $street|lower|in_array:$displayParams.required}}true{{else}}false{{/if}}}
<span class="required">{$APP.LBL_REQUIRED_SYMBOL}</span>
{/if}
</td>
<td width="*">
{{if $displayParams.maxlength}}
<textarea id="{{$street}}" name="{{$street}}" title='{{$vardef.help}}' maxlength="{{$displayParams.maxlength}}"
rows="{{$displayParams.rows|default:4}}" cols="{{$displayParams.cols|default:60}}"
tabindex="{{$tabindex}}">{$fields.{{$street}}.value}</textarea>
{{else}}
<textarea id="{{$street}}" name="{{$street}}" title='{{$vardef.help}}' rows="{{$displayParams.rows|default:4}}"
cols="{{$displayParams.cols|default:60}}"
tabindex="{{$tabindex}}">{$fields.{{$street}}.value}</textarea>
{{/if}}
</td>
</tr>
<tr>
<td id="{{$city}}_label" width='{{$def.templateMeta.widths[$smarty.foreach.colIteration.index].label}}%'
scope='row'>
<label for="{{$city}}">{sugar_translate label='LBL_CITY' module='{{$module}}'}:
{if $fields.{{$city}}.required || {{if $city|lower|in_array:$displayParams.required}}true{{else}}false{{/if}}}
<span class="required">{$APP.LBL_REQUIRED_SYMBOL}</span>
{/if}
</td>
<td>
<input type="text" name="{{$city}}" id="{{$city}}" title='{$fields.{{$city}}.help}' size="{{$displayParams.size|default:30}}"
{{if !empty($vardef.len)}}maxlength='{{$vardef.len}}'{{/if}} value='{$fields.{{$city}}.value}'
tabindex="{{$tabindex}}">
</td>
</tr>
<tr>
<td id="{{$state}}_label" width='{{$def.templateMeta.widths[$smarty.foreach.colIteration.index].label}}%'
scope='row'>
<label for="{{$state}}">{sugar_translate label='LBL_STATE' module='{{$module}}'}:</label>
{if $fields.{{$state}}.required || {{if $state|lower|in_array:$displayParams.required}}true{{else}}false{{/if}}}
<span class="required">{$APP.LBL_REQUIRED_SYMBOL}</span>
{/if}
</td>
<td>
<input type="text" name="{{$state}}" id="{{$state}}" title='{$fields.{{$state}}.help}' size="{{$displayParams.size|default:30}}"
{{if !empty($vardef.len)}}maxlength='{{$vardef.len}}'{{/if}} value='{$fields.{{$state}}.value}'
tabindex="{{$tabindex}}">
</td>
</tr>
<tr>
<td id="{{$postalcode}}_label"
width='{{$def.templateMeta.widths[$smarty.foreach.colIteration.index].label}}%' scope='row'>
<label for="{{$postalcode}}">{sugar_translate label='LBL_POSTAL_CODE' module='{{$module}}'}:</label>
{if $fields.{{$postalcode}}.required || {{if $postalcode|lower|in_array:$displayParams.required}}true{{else}}false{{/if}}}
<span class="required">{$APP.LBL_REQUIRED_SYMBOL}</span>
{/if}
</td>
<td>
<input type="text" name="{{$postalcode}}" id="{{$postalcode}}" title='{$fields.{{$postalcode}}.help}' size="{{$displayParams.size|default:30}}"
{{if !empty($vardef.len)}}maxlength='{{$vardef.len}}'{{/if}}
value='{$fields.{{$postalcode}}.value}' tabindex="{{$tabindex}}">
</td>
</tr>
<tr>
<td id="{{$country}}_label" width='{{$def.templateMeta.widths[$smarty.foreach.colIteration.index].label}}%'
scope='row'>
<label for="{{$country}}">{sugar_translate label='LBL_COUNTRY' module='{{$module}}'}:</label>
{if $fields.{{$country}}.required || {{if $country|lower|in_array:$displayParams.required}}true{{else}}false{{/if}}}
<span class="required">{$APP.LBL_REQUIRED_SYMBOL}</span>
{/if}
</td>
<td>
<select name="{{$country}}" width="{{$displayParams.size|default:30}}" id="{{$country}}" title="{{$vardef.help}}"
{{if !empty($tabindex)}} tabindex="{{$tabindex}}" {{/if}}
{{if isset($displayParams.script)}}{{$displayParams.script}}{{/if}}>
<option value='testing'>Test Option</option>
{if isset($fields.{{$country}}.value) && $fields.{{$country}}.value != ''}
{html_options options=$fields.{{$country}}.options selected=$fields.{{$country}}.value}
{else}
{html_options options=$fields.{{$country}}.options selected=$fields.{{$country}}.default_value}
{/if}
</select>
</td>
</tr>
{{if $displayParams.copy}}
<tr>
<td scope='row' NOWRAP>
{sugar_translate label='LBL_COPY_ADDRESS_FROM_LEFT' module=''}:
</td>
<td>
<input id="{{$displayParams.key}}_checkbox" name="{{$displayParams.key}}_checkbox" type="checkbox"
onclick="{{$displayParams.key}}_address.syncFields();">
</td>
</tr>
{{else}}
<tr>
<td colspan='2' NOWRAP> </td>
</tr>
{{/if}}
</table>
</fieldset>
<script type="text/javascript">
SUGAR.util.doWhen("typeof(SUGAR.AddressField) != 'undefined'", function () {ldelim}
{{$displayParams.key}}_address = new SUGAR.AddressField("{{$displayParams.key}}_checkbox", '{{$displayParams.copy}}', '{{$displayParams.key}}');
{rdelim});
</script>
I have done a Quick Repair & Rebuild multiple times during this process.
Looking for Ideas.
Thank,
Tony