This post will show you how to add multiple custom fields to Horde 5’s Address Book Application. Annoyingly the system only has an email field by default but there are several ways to easily enable a workEmail and HomeEmail field. There are many tutorials showing you how to do this but I couldn’t find an up to date tutorial on adding a custom field.
Any horde configuration file should not be edited! You should create a .local.php file instead and begin the file with <?php and then add any edits in there.
To enable the homeEmail and workEmail fields then create a new file called /var/www/turba/config/backends.local.php
Add the following (This is for SQL backend):
1 2 3 |
<?php $cfgSources['localsql']['map']['homeEmail']='object_homeemail'; $cfgSources['localsql']['map']['workEmail']='object_workemail'; |
I found it easier to just copy the backends.php file to the backends.local.php. Then I removed everything except for the following:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
<?php $cfgSources['localsql'] = array( // ENABLED by default 'disabled' => false, 'title' => _("Shared Address Books"), 'type' => 'sql', 'params' => array( // The default connection details are pulled from the Horde-wide SQL // connection configuration. // To use another DB connection, you must provide configuration // information here - for example, //'sql' => array( // 'persistent' => false, // 'username' => 'horde', // 'password' => 'secret', // 'socket' => '/var/run/mysqld/mysqld.sock', // 'protocol' => 'unix', // 'database' => 'horde', // 'charset' => 'utf-8', // 'ssl' => false, // 'splitread' => false, // 'phptype' => 'mysql' //), 'table' => 'turba_objects' ), 'map' => array( '__key' => 'object_id', '__owner' => 'owner_id', '__type' => 'object_type', '__members' => 'object_members', '__uid' => 'object_uid', 'firstname' => 'object_firstname', 'lastname' => 'object_lastname', 'middlenames' => 'object_middlenames', 'namePrefix' => 'object_nameprefix', 'nameSuffix' => 'object_namesuffix', 'name' => array('fields' => array('namePrefix', 'firstname', 'middlenames', 'lastname', 'nameSuffix'), 'format' => '%s %s %s %s %s', 'parse' => array( array('fields' => array('firstname', 'middlenames', 'lastname'), 'format' => '%s %s %s'), array('fields' => array('firstname', 'lastname'), 'format' => '%s %s'))), // This is a shorter version of a "name" composite field which only // consists of the first name and last name. // 'name' => array('fields' => array('firstname', 'lastname'), // 'format' => '%s %s'), 'alias' => 'object_alias', 'yomifirstname' => 'object_yomifirstname', 'yomilastname' => 'object_yomilastname', 'birthday' => 'object_bday', 'anniversary' => 'object_anniversary', 'spouse' => 'object_spouse', 'photo' => 'object_photo', 'phototype' => 'object_phototype', 'homeStreet' => 'object_homestreet', 'homePOBox' => 'object_homepob', 'homeCity' => 'object_homecity', 'homeProvince' => 'object_homeprovince', 'homePostalCode' => 'object_homepostalcode', 'homeCountry' => 'object_homecountry', 'homeAddress' => array('fields' => array('homeStreet', 'homeCity', 'homeProvince', 'homePostalCode'), 'format' => "%s \n %s, %s %s"), 'workStreet' => 'object_workstreet', 'workPOBox' => 'object_workpob', 'workCity' => 'object_workcity', 'workProvince' => 'object_workprovince', 'workPostalCode' => 'object_workpostalcode', 'workCountry' => 'object_workcountry', 'workAddress' => array('fields' => array('workStreet', 'workCity', 'workProvince', 'workPostalCode'), 'format' => "%s \n %s, %s %s"), 'otherStreet' => 'object_otherstreet', 'otherPOBox' => 'object_otherpob', 'otherCity' => 'object_othercity', 'otherProvince' => 'object_otherprovince', 'otherPostalCode' => 'object_otherpostalcode', 'otherCountry' => 'object_othercountry', 'otherAddress' => array('fields' => array('otherStreet', 'otherCity', 'otherProvince', 'otherPostalCode'), 'format' => "%s \n %s, %s %s"), 'department' => 'object_department', 'manager' => 'object_manager', 'assistant' => 'object_assistant', 'timezone' => 'object_tz', 'email' => 'object_email', 'homeEmail' => 'object_homeemail', 'workEmail' => 'object_workemail', 'otherEmail' => 'object_otheremail', 'other1Email' => 'object_other1email', 'other2Email' => 'object_other2email', 'other3Email' => 'object_other3email', 'homePhone' => 'object_homephone', 'homePhone2' => 'object_homephone2', 'homeFax' => 'object_homefax', 'workPhone' => 'object_workphone', 'workPhone2' => 'object_workphone2', 'cellPhone' => 'object_cellphone', 'carPhone' => 'object_carphone', 'radioPhone' => 'object_radiophone', 'companyPhone' => 'object_companyphone', 'assistPhone' => 'object_assistantphone', 'fax' => 'object_fax', 'pager' => 'object_pager', 'title' => 'object_title', 'role' => 'object_role', 'company' => 'object_company', 'logo' => 'object_logo', 'logotype' => 'object_logotype', 'category' => 'object_category', 'notes' => 'object_notes', 'website' => 'object_url', 'freebusyUrl' => 'object_freebusyurl', 'pgpPublicKey' => 'object_pgppublickey', 'smimePublicKey' => 'object_smimepublickey', 'imaddress' => 'object_imaddress', 'imaddress2' => 'object_imaddress2', 'imaddress3' => 'object_imaddress3' ), 'tabs' => array( _("Personal") => array('firstname', 'lastname', 'middlenames', 'namePrefix', 'nameSuffix', 'name', 'alias', 'birthday', 'spouse', 'anniversary', 'yomifirstname', 'yomilastname', 'photo'), _("Location") => array('homeStreet', 'homePOBox', 'homeCity', 'homeProvince', 'homePostalCode', 'homeCountry', 'homeAddress', 'workStreet', 'workPOBox', 'workCity', 'workProvince', 'workPostalCode', 'workCountry', 'workAddress', 'otherStreet', 'otherPOBox', 'otherCity', 'otherProvince', 'otherPostalCode', 'otherCountry', 'otherAddress','timezone'), _("Communications") => array('email', 'homeEmail', 'otherEmail', 'other1Email', 'other2Email', 'other3Email', 'workEmail', 'homePhone', 'homePhone2', 'workPhone', 'workPhone2', 'carPhone', 'radioPhone', 'companyPhone', 'assistPhone', 'homeFax', 'cellPhone', 'fax', 'pager', 'imaddress'), _("Organization") => array('title', 'role', 'company', 'department', 'logo', 'assistant', 'manager'), _("Other") => array('category', 'notes', 'website', 'freebusyUrl', 'pgpPublicKey', 'smimePublicKey'), ), 'search' => array( 'name', 'email' ), 'strict' => array( 'object_id', 'owner_id', 'object_type', 'object_uid' ), 'export' => true, 'browse' => true, 'use_shares' => true, 'list_name_field' => 'lastname', 'alternative_name' => 'company', ); |
The parts that I added were:
1 2 3 4 |
'otherEmail' => 'object_otheremail', 'other1Email' => 'object_other1email', 'other2Email' => 'object_other2email', 'other3Email' => 'object_other3email', |
These map the field names defined in the attributes file to the MySQL column names in the table.
I also added the fields to the communications section so they actually display in the web interface.
1 2 3 4 5 6 |
_("Communications") => array('email', 'homeEmail', 'otherEmail', 'other1Email', 'other2Email', 'other3Email', 'workEmail', 'homePhone', 'homePhone2', 'workPhone', 'workPhone2', 'carPhone', 'radioPhone', 'companyPhone', 'assistPhone', 'homeFax', 'cellPhone', 'fax', 'pager', 'imaddress'), |
The extra fields still do not display in the web interface as of yet. We still need to add the custom fields to the attributes file and then add the extra entries to the MySQL database.
Copy the attributes.php file to attributes.local.php and then open the file with nano. Once opened pressing Ctrl + W will open a search box, enter without quotes “homeEmail”. It should take you to a section with this:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
/* Additional attributes supported by some SyncML clients */ $attributes['workEmail'] = array( 'label' => _("Work Email"), 'type' => 'email', 'required' => false, 'params' => array('allow_multi' => false, 'strip_domain' => false, 'link_compose' => true, 'link_name' => null, 'delimiters' => ',', 'size' => null) ); $attributes['homeEmail'] = array( 'label' => _("Home Email"), 'type' => 'email', 'required' => false, 'params' => array('allow_multi' => false, 'strip_domain' => false, 'link_compose' => true, 'link_name' => null, 'delimiters' => ',', 'size' => null) ); |
Just duplicate the homeEmail section with the additional email address fields, in this case it would be the following:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
$attributes['otherEmail'] = array( 'label' => _("Other Email"), 'type' => 'email', 'required' => false, 'params' => array('allow_multi' => false, 'strip_domain' => false, 'link_compose' => true, 'link_name' => null, 'delimiters' => ',', 'size' => null) ); $attributes['other1Email'] = array( 'label' => _("Other Email 1"), 'type' => 'email', 'required' => false, 'params' => array('allow_multi' => false, 'strip_domain' => false, 'link_compose' => true, 'link_name' => null, 'delimiters' => ',', 'size' => null) ); $attributes['other2Email'] = array( 'label' => _("Other Email 2"), 'type' => 'email', 'required' => false, 'params' => array('allow_multi' => false, 'strip_domain' => false, 'link_compose' => true, 'link_name' => null, 'delimiters' => ',', 'size' => null) ); $attributes['other3Email'] = array( 'label' => _("Other Email 3"), 'type' => 'email', 'required' => false, 'params' => array('allow_multi' => false, 'strip_domain' => false, 'link_compose' => true, 'link_name' => null, 'delimiters' => ',', 'size' => null) ); |
Now we need to add the additional columns to the MySQL database. Open the database using:
1 |
mysql -u root -p |
In this case the database is “horde” and the table we need to modify is “turba_objects” so we enter the following commands:
1 2 3 4 5 |
mysql> use horde; Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Database changed |
The following will add an extra email column called object_other1email. Make sure the names match the names given in the backends.local.php file.
1 |
alter table turba_objects add `object_other1email` varchar(255) AFTER `object_otheremail`; |
The table should look like this now (I removed most of the columns to shorten the post).
1 2 3 4 5 6 7 8 9 10 11 12 13 |
mysql> describe turba_objects; +------------------------+--------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +------------------------+--------------+------+-----+---------+-------+ | object_workemail | varchar(255) | YES | | NULL | | | object_homeemail | varchar(255) | YES | | NULL | | | object_otheremail | varchar(255) | YES | | NULL | | | object_other1email | varchar(255) | YES | | NULL | | | object_other2email | varchar(255) | YES | | NULL | | | object_other3email | varchar(255) | YES | | NULL | | | object_other4email | varchar(255) | YES | | NULL | | +------------------------+--------------+------+-----+---------+-------+ 76 rows in set (0.01 sec) |
If all has gone well then it should all be working now as seen below: