From 900fc840f2113cb8f07168dd86c0f6064cf092fb Mon Sep 17 00:00:00 2001
From: nathangray
Date: Wed, 13 Sep 2017 10:21:50 -0600
Subject: [PATCH] Infolog - Simplify UI by allowing free text in Contact field,
and removing custom contact / phone from details tab. Anything in address
field is concatenated into contact.
---
infolog/inc/class.infolog_bo.inc.php | 24 ++-
infolog/inc/class.infolog_so.inc.php | 2 +-
infolog/inc/class.infolog_tracking.inc.php | 3 -
infolog/inc/class.infolog_ui.inc.php | 24 +--
infolog/inc/class.infolog_widget.inc.php | 1 -
infolog/setup/importexport_default.xml | 2 -
infolog/setup/setup.inc.php | 2 +-
infolog/setup/tables_current.inc.php | 1 -
infolog/setup/tables_update.inc.php | 56 +++++++
infolog/templates/default/delete.xet | 4 +-
infolog/templates/default/edit.print.xet | 2 -
infolog/templates/default/edit.xet | 12 +-
infolog/templates/default/home.link.xet | 2 +-
infolog/templates/default/home.xet | 1 -
infolog/templates/default/index.rows.xet | 1 -
infolog/templates/default/index.xet | 1 -
infolog/templates/mobile/edit.xet | 6 -
infolog/templates/mobile/index.xet | 5 -
infolog/templates/mobile/view.xet | 6 -
infolog/templates/pixelegg/app.css | 4 +-
infolog/templates/pixelegg/app.less | 7 -
infolog/test/ContactTest.php | 181 +++++++++++++++++++++
22 files changed, 268 insertions(+), 79 deletions(-)
create mode 100644 infolog/test/ContactTest.php
diff --git a/infolog/inc/class.infolog_bo.inc.php b/infolog/inc/class.infolog_bo.inc.php
index 2ca7f70548..6766b1c6dc 100644
--- a/infolog/inc/class.infolog_bo.inc.php
+++ b/infolog/inc/class.infolog_bo.inc.php
@@ -460,17 +460,16 @@ class infolog_bo
{
$info['old_pm_id'] = $info['pm_id'] = $id;
}
- $info['info_link'] = array(
+ $info['info_link'] = $info['info_contact'] = array(
'app' => $app,
'id' => $id,
'title' => (!empty($info['info_from']) ? $info['info_from'] : $title),
);
- $info['info_contact'] = $app.':'.$id;
//echo " title='$title'
\n";
return $info['blur_title'] = $title;
}
- $info['info_link'] = array('title' => $info['info_from']);
+ $info['info_link'] = $info['info_contact'] = array('id' => 'none', 'title' => $info['info_from']);
$info['info_link_id'] = 0; // link might have been deleted
$info['info_custom_from'] = (int)!!$info['info_from'];
@@ -959,13 +958,14 @@ class infolog_bo
Link::link('infolog',$info_id,$to_write['link_to']['to_id']);
$values['link_to']['to_id'] = $info_id;
}
- $this->write_check_links($to_write);
+ $this->write_check_links($to_write);
if(!$values['info_link_id'] || $values['info_link_id'] != $to_write['info_link_id'])
{
// Just got a link ID, need to save it
$this->so->write($to_write);
$values['info_link_id'] = $to_write['info_link_id'];
$values['info_contact'] = $to_write['info_contact'];
+ $values['info_from'] = $to_write['info_from'];
$this->link_id2from($values);
}
@@ -1057,7 +1057,8 @@ class infolog_bo
{
// eTemplate2 returns the array all ready
$app = $values['info_contact']['app'];
- $id = $values['info_contact']['id'];
+ $id = (int)$values['info_contact']['id'];
+ $from = $values['info_contact']['search'];
}
else if ($values['info_contact'])
{
@@ -1068,7 +1069,7 @@ class infolog_bo
{
unset($values['info_link_id'], $id, $values['info_contact']);
}
- elseif ($app && $id)
+ else if ($app && $id)
{
if(!is_array($values['link_to']))
{
@@ -1079,10 +1080,16 @@ class infolog_bo
$values['info_id'],
$app,$id
));
+ $values['info_from'] = Link::title($app, $id);
+ }
+ else if ($from)
+ {
+ $values['info_from'] = $from;
}
else
{
unset($values['info_link_id']);
+ $values['info_from'] = null;
}
}
else if ($values['pm_id'] && $values['info_id'] && !$values['old_pm_id'])
@@ -1269,8 +1276,7 @@ class infolog_bo
$info = array(
'info_id' => 0,
'info_type' => $type,
- 'info_from' => implode(', ',$names),
- 'info_addr' => implode(', ',$emails),
+ 'info_from' => implode(', ',$names) . implode(', ', $emails),
'info_subject' => $_subject,
'info_des' => $_message,
'info_startdate' => Api\DateTime::server2user($_date),
@@ -1297,7 +1303,7 @@ class infolog_bo
}
if (!$contacts || !is_array($contacts) || !is_array($contacts[0]))
{
- $info['msg'] = lang('Attention: No Contact with address %1 found.',$info['info_addr']);
+ $info['msg'] = lang('Attention: No Contact with address %1 found.',$info['info_from']);
$info['info_custom_from'] = true; // show the info_from line and NOT only the link
}
else
diff --git a/infolog/inc/class.infolog_so.inc.php b/infolog/inc/class.infolog_so.inc.php
index 488be33649..6537b0a198 100644
--- a/infolog/inc/class.infolog_so.inc.php
+++ b/infolog/inc/class.infolog_so.inc.php
@@ -884,7 +884,7 @@ class infolog_so
if ($query['query']) $query['search'] = $query['query']; // allow both names
if ($query['search']) // we search in _from, _subject, _des and _extra_value for $query
{
- $columns = array('info_from','info_addr','info_location','info_subject','info_extra_value');
+ $columns = array('info_from','info_location','info_subject','info_extra_value');
// at the moment MaxDB 7.5 cant cast nor search text columns, it's suppost to change in 7.6
if ($this->db->capabilities['like_on_text']) $columns[] = 'info_des';
diff --git a/infolog/inc/class.infolog_tracking.inc.php b/infolog/inc/class.infolog_tracking.inc.php
index bc9202e505..fe5be3e5e0 100644
--- a/infolog/inc/class.infolog_tracking.inc.php
+++ b/infolog/inc/class.infolog_tracking.inc.php
@@ -50,7 +50,6 @@ class infolog_tracking extends Api\Storage\Tracking
var $field2history = array(
'info_type' => 'Ty',
'info_from' => 'Fr',
- 'info_addr' => 'Ad',
'info_link_id' => 'Li',
'info_id_parent' => 'parent',
'info_cat' => 'Ca',
@@ -88,7 +87,6 @@ class infolog_tracking extends Api\Storage\Tracking
'info_from' => 'Contact',
'info_subject' => 'Subject',
'info_des' => 'Description',
- 'info_addr' => 'Phone/Email',
'info_link_id' => 'primary link',
'info_id_parent' => 'Parent',
'info_cat' => 'Category',
@@ -218,7 +216,6 @@ class infolog_tracking extends Api\Storage\Tracking
foreach(array(
'info_type' => lang($this->infolog->enums['type'][$data['info_type']]).$id,
'info_from' => $data['info_from'],
- 'info_addr' => $data['info_addr'],
'info_cat' => $data['info_cat'] ? $GLOBALS['egw']->categories->id2name($data['info_cat']) : '',
'info_priority' => lang($this->infolog->enums['priority'][$data['info_priority']]),
'info_owner' => Api\Accounts::username($data['info_owner']),
diff --git a/infolog/inc/class.infolog_ui.inc.php b/infolog/inc/class.infolog_ui.inc.php
index 3cb32ee403..e7b81ac3a0 100644
--- a/infolog/inc/class.infolog_ui.inc.php
+++ b/infolog/inc/class.infolog_ui.inc.php
@@ -480,7 +480,6 @@ class infolog_ui
// Check to see if we need to remove description
foreach($infos as $id => $info)
{
- if (!(strpos($info['info_addr'],',')===false) && strpos($info['info_addr'],', ')===false) $info['info_addr'] = str_replace(',',', ',$info['info_addr']);
if (!$query['csv_export'] || !is_array($query['csv_export']))
{
$info['links'] =& $links[$id];
@@ -1765,14 +1764,6 @@ class infolog_ui
{
$content['info_link_id'] = 0; // as field has to be int
}
- if (is_array($content['info_contact']) && $content['info_contact']['id'])
- {
- $content['info_contact'] = $content['info_contact']['app'] . ':' . $content['info_contact']['id'];
- }
- else
- {
- $content['info_contact'] = false;
- }
$active_tab = $content['tabs'];
if (!($info_id = $this->bo->write($content, true, true, true, $content['no_notifications'])))
{
@@ -1921,7 +1912,6 @@ class infolog_ui
{
Framework::window_close(lang('Permission denied!'));
}
- if (!(strpos($content['info_addr'],',')===false) && strpos($content['info_addr'],', ')===false) $content['info_addr'] = str_replace(',',', ',$content['info_addr']);
foreach(array('info_subject', 'info_des') as $key)
{
if(!isset($content[$key]) || strlen($content[$key]) < 75)
@@ -2041,7 +2031,7 @@ class infolog_ui
$action_ids = explode(',',$action_id);
if(count($action_ids) == 1)
{
- $content['info_contact'] = $action.':'.$action_id;
+ $content['info_contact'] = array('app' => $action, 'id' => $action_id);
}
foreach ($action_ids as $n => $id)
{
@@ -2357,8 +2347,13 @@ class infolog_ui
if (!isset($content['info_contact']) || empty($content['info_contact']) || $content['info_contact'] === 'copy:')
{
$linkinfos = Link::get_link($info_link_id);
- $content['info_contact'] = $linkinfos['link_app1']=='infolog'? $linkinfos['link_app2'].':'.$linkinfos['link_id2']:$linkinfos['link_app1'].':'.$linkinfos['link_id1'];
- if (stripos($content['info_contact'],'projectmanager')!==false) $content['pm_id'] = $linkinfos['link_app1']=='projectmanager'? $linkinfos['link_id1']:$linkinfos['link_id2'];
+ $content['info_contact'] = $linkinfos['link_app1']=='infolog'?
+ array('app' => $linkinfos['link_app2'], 'id' => $linkinfos['link_id2']):
+ array('app' => $linkinfos['link_app1'], 'id' => $linkinfos['link_id1']);
+ if ($content['info_contact']['app'] == 'projectmanager')
+ {
+ $content['pm_id'] = $linkinfos['link_app1']=='projectmanager'? $linkinfos['link_id1']:$linkinfos['link_id2'];
+ }
}
unset($content['info_link_id']);
}
@@ -2412,7 +2407,6 @@ class infolog_ui
$fields = array(
'info_cat' => 'Category',
'info_from' => 'Contact',
- 'info_addr' => 'Phone/Email',
'info_subject' => 'Subject',
'info_des' => 'Description',
'link_to' => 'Links',
@@ -2424,7 +2418,6 @@ class infolog_ui
$excludefields = array(
'info_cat' => 'Category',
'info_from' => 'Contact',
- 'info_addr' => 'Phone/Email',
'info_subject' => 'Subject',
'info_des' => 'Description',
'link_to' => 'Links',
@@ -2633,7 +2626,6 @@ class infolog_ui
$fields = array(
'info_type' => lang('Type'),
'info_from' => lang('Contact'),
- 'info_addr' => lang('Phone/Email'),
// 'info_link_id' => lang('primary link'),
'info_cat' => array('label' => lang('Category'),'type' => 'select-cat'),
'info_priority' => lang('Priority'),
diff --git a/infolog/inc/class.infolog_widget.inc.php b/infolog/inc/class.infolog_widget.inc.php
index 39a647058e..4b6c2d94ca 100644
--- a/infolog/inc/class.infolog_widget.inc.php
+++ b/infolog/inc/class.infolog_widget.inc.php
@@ -109,7 +109,6 @@ class infolog_widget extends Etemplate\Widget\Entry
'info_des' => lang('Description'),
'info_cat' => lang('Category'),
'info_from' => lang('Contact'),
- 'info_addr' => lang('Phone/Email'),
'info_responsible' => lang('Responsible'),
'info_startdate' => lang('Startdate'),
'info_enddate' => lang('Enddate'),
diff --git a/infolog/setup/importexport_default.xml b/infolog/setup/importexport_default.xml
index b5656a2846..e5be91b8e9 100644
--- a/infolog/setup/importexport_default.xml
+++ b/infolog/setup/importexport_default.xml
@@ -21,7 +21,6 @@
Contact
Subject
Description
- Phone/Email
primary link
Category
Priority
@@ -95,7 +94,6 @@
info_from
info_subject
info_des
- info_addr
info_link_id
info_cat
info_priority
diff --git a/infolog/setup/setup.inc.php b/infolog/setup/setup.inc.php
index 8a86dd1a64..ddb37a8618 100644
--- a/infolog/setup/setup.inc.php
+++ b/infolog/setup/setup.inc.php
@@ -12,7 +12,7 @@
*/
$setup_info['infolog']['name'] = 'infolog';
-$setup_info['infolog']['version'] = '16.1.003';
+$setup_info['infolog']['version'] = '16.1.004';
$setup_info['infolog']['app_order'] = 5;
$setup_info['infolog']['tables'] = array('egw_infolog','egw_infolog_extra','egw_infolog_users');
$setup_info['infolog']['enable'] = 1;
diff --git a/infolog/setup/tables_current.inc.php b/infolog/setup/tables_current.inc.php
index 77f7461713..6b0254abe9 100644
--- a/infolog/setup/tables_current.inc.php
+++ b/infolog/setup/tables_current.inc.php
@@ -17,7 +17,6 @@ $phpgw_baseline = array(
'info_id' => array('type' => 'auto','nullable' => False,'comment' => 'id of the infolog-entry'),
'info_type' => array('type' => 'varchar','precision' => '40','nullable' => False,'default' => 'task','comment' => 'infolog-type e.g. task, phone, email or note'),
'info_from' => array('type' => 'varchar','precision' => '255','comment' => 'text of the primary link'),
- 'info_addr' => array('type' => 'varchar','precision' => '255','comment' => 'textfield for phone-number or email of the primary contact'),
'info_subject' => array('type' => 'varchar','precision' => '255','comment' => 'title of the infolog-entry'),
'info_des' => array('type' => 'longtext','comment' => 'desciption of the infolog-entry'),
'info_owner' => array('type' => 'int','meta' => 'account','precision' => '4','nullable' => False,'comment' => 'owner of the entry, can be account or group'),
diff --git a/infolog/setup/tables_update.inc.php b/infolog/setup/tables_update.inc.php
index ce0a4a5c7a..66b578e55c 100644
--- a/infolog/setup/tables_update.inc.php
+++ b/infolog/setup/tables_update.inc.php
@@ -932,3 +932,59 @@ function infolog_upgrade16_1_002()
return $GLOBALS['setup_info']['infolog']['currentver'] = '16.1.003';
}
+/**
+ * Copy info_addr contents into info_from, contatinating if there is anything there
+ * already, then drop the info_addr column.
+ * @return string
+ */
+function infolog_upgrade16_1_003()
+{
+ $GLOBALS['egw_setup']->db->query("UPDATE egw_infolog SET info_from = CONCAT(info_from, ', ', info_addr)".
+ " WHERE info_from IS NOT NULL AND info_addr IS NOT NULL", __LINE__, __FILE__);
+
+ $GLOBALS['egw_setup']->db->query("UPDATE egw_infolog SET info_from = info_addr".
+ " WHERE info_from IS NULL AND info_addr IS NOT NULL", __LINE__, __FILE__);
+
+ $GLOBALS['egw_setup']->oProc->DropColumn('egw_infolog',array(
+ 'fd' => array(
+ 'info_id' => array('type' => 'auto','nullable' => False,'comment' => 'id of the infolog-entry'),
+ 'info_type' => array('type' => 'varchar','precision' => '40','nullable' => False,'default' => 'task','comment' => 'infolog-type e.g. task, phone, email or note'),
+ 'info_from' => array('type' => 'varchar','precision' => '255','comment' => 'text of the primary link'),
+ 'info_subject' => array('type' => 'varchar','precision' => '255','comment' => 'title of the infolog-entry'),
+ 'info_des' => array('type' => 'longtext','comment' => 'desciption of the infolog-entry'),
+ 'info_owner' => array('type' => 'int','meta' => 'account','precision' => '4','nullable' => False,'comment' => 'owner of the entry, can be account or group'),
+ 'info_access' => array('type' => 'ascii','precision' => '10','default' => 'public','comment' => 'public or privat'),
+ 'info_cat' => array('type' => 'int','meta' => 'category','precision' => '4','nullable' => False,'default' => '0','comment' => 'category id'),
+ 'info_datemodified' => array('type' => 'int','meta' => 'timestamp','precision' => '8','nullable' => False,'comment' => 'timestamp of the last mofification'),
+ 'info_startdate' => array('type' => 'int','meta' => 'timestamp','precision' => '8','nullable' => False,'default' => '0','comment' => 'timestamp of the startdate'),
+ 'info_enddate' => array('type' => 'int','meta' => 'timestamp','precision' => '8','nullable' => False,'default' => '0','comment' => 'timestamp of the enddate'),
+ 'info_id_parent' => array('type' => 'int','precision' => '4','nullable' => False,'default' => '0','comment' => 'id of the parent infolog'),
+ 'info_planned_time' => array('type' => 'int','precision' => '4','nullable' => False,'default' => '0','comment' => 'pm-field: planned time'),
+ 'info_replanned_time' => array('type' => 'int','precision' => '4','nullable' => False,'default' => '0','comment' => 'pm-field: replanned time'),
+ 'info_used_time' => array('type' => 'int','precision' => '4','nullable' => False,'default' => '0','comment' => 'pm-field: used time'),
+ 'info_status' => array('type' => 'varchar','precision' => '40','default' => 'done','comment' => 'status e.g. ongoing, done ...'),
+ 'info_confirm' => array('type' => 'ascii','precision' => '10','default' => 'not'),
+ 'info_modifier' => array('type' => 'int','meta' => 'user','precision' => '4','nullable' => False,'default' => '0','comment' => 'account id of the last modifier'),
+ 'info_link_id' => array('type' => 'int','precision' => '4','nullable' => False,'default' => '0','comment' => 'id of the primary link'),
+ 'info_priority' => array('type' => 'int','precision' => '2','default' => '1','comment' => '0=Low, 1=Normal, 2=High, 3=Urgent'),
+ 'pl_id' => array('type' => 'int','precision' => '4','comment' => 'pm-field: id of the pricelist'),
+ 'info_price' => array('type' => 'float','precision' => '8','comment' => 'pm-field: price-field'),
+ 'info_percent' => array('type' => 'int','meta' => 'percent','precision' => '2','default' => '0','comment' => 'percentage of completion'),
+ 'info_datecompleted' => array('type' => 'int','meta' => 'timestamp','precision' => '8','comment' => 'timestamp of completion'),
+ 'info_location' => array('type' => 'varchar','precision' => '255','comment' => 'textfield location'),
+ 'info_custom_from' => array('type' => 'int','precision' => '1','comment' => 'tick-box to show infolog_from'),
+ 'info_uid' => array('type' => 'ascii','precision' => '128','comment' => 'unique id of the infolog-entry'),
+ 'info_cc' => array('type' => 'varchar','precision' => '255','comment' => 'textfield for email-adress to be notified via email of changes'),
+ 'caldav_name' => array('type' => 'ascii','precision' => '128','comment' => 'name part of CalDAV URL, if specified by client'),
+ 'info_etag' => array('type' => 'int','precision' => '4','default' => '0','comment' => 'etag, not yet used'),
+ 'info_created' => array('type' => 'int','meta' => 'timestamp','precision' => '8','comment' => 'timestamp of the creation date'),
+ 'info_creator' => array('type' => 'int','meta' => 'user','precision' => '4','comment' => 'account id of the creator')
+ ),
+ 'pk' => array('info_id'),
+ 'fk' => array(),
+ 'ix' => array('caldav_name','info_owner','info_datemodified','info_id_parent'),
+ 'uc' => array()
+ ),'info_addr');
+
+ return $GLOBALS['setup_info']['infolog']['currentver'] = '16.1.004';
+}
\ No newline at end of file
diff --git a/infolog/templates/default/delete.xet b/infolog/templates/default/delete.xet
index 86ccd8e8aa..a6df8d1f79 100644
--- a/infolog/templates/default/delete.xet
+++ b/infolog/templates/default/delete.xet
@@ -65,7 +65,7 @@
-
+
@@ -190,7 +190,7 @@
-
+
diff --git a/infolog/templates/default/edit.print.xet b/infolog/templates/default/edit.print.xet
index d725db10bb..f2b58754c8 100644
--- a/infolog/templates/default/edit.print.xet
+++ b/infolog/templates/default/edit.print.xet
@@ -136,8 +136,6 @@
-
-
diff --git a/infolog/templates/default/edit.xet b/infolog/templates/default/edit.xet
index 53ab7d777d..4e12ca2f40 100644
--- a/infolog/templates/default/edit.xet
+++ b/infolog/templates/default/edit.xet
@@ -141,16 +141,6 @@
-
-
-
-
-
-
-
-
-
-
@@ -190,7 +180,7 @@
diff --git a/infolog/templates/mobile/view.xet b/infolog/templates/mobile/view.xet
index 1dcfa0f302..c37dee50de 100644
--- a/infolog/templates/mobile/view.xet
+++ b/infolog/templates/mobile/view.xet
@@ -113,12 +113,6 @@
-
-
-
-
-
-
diff --git a/infolog/templates/pixelegg/app.css b/infolog/templates/pixelegg/app.css
index 3d6eb20589..fc63496b71 100755
--- a/infolog/templates/pixelegg/app.css
+++ b/infolog/templates/pixelegg/app.css
@@ -39,7 +39,7 @@
}
.normal,
.normal_done {
- color: black;
+ color: #000000;
}
.high {
color: #cc0000;
@@ -198,7 +198,7 @@ div#infolog-edit_infolog-edit-description {
height: auto;
}
div#infolog-edit_info_contact input.ui-autocomplete-input span.ui-icon-close {
- background-color: #FFFFFF;
+ background-color: #ffffff;
background-size: contain;
background-position: 5px 5px;
top: 9px !important;
diff --git a/infolog/templates/pixelegg/app.less b/infolog/templates/pixelegg/app.less
index 6cb965878f..f5dba5f27b 100755
--- a/infolog/templates/pixelegg/app.less
+++ b/infolog/templates/pixelegg/app.less
@@ -92,13 +92,6 @@ div.et2_box_widget {}
//
input.infolog-edit_info_custom_from {}
-
-// Phone + Email
-td.inputFullWidth{
- input#infolog-edit_info_addr{}
-}
-
-
// Kategorie
diff --git a/infolog/test/ContactTest.php b/infolog/test/ContactTest.php
new file mode 100644
index 0000000000..63cce28230
--- /dev/null
+++ b/infolog/test/ContactTest.php
@@ -0,0 +1,181 @@
+ui = new \infolog_ui();
+
+ $this->ui->tmpl = $this->getMockBuilder('\\Egroupware\\Api\\Etemplate')
+ ->disableOriginalConstructor()
+ ->setMethods(array('exec', 'read'))
+ ->getMock($this->ui);
+ $this->bo = $this->ui->bo;
+
+ $this->mockTracking($this->bo, 'infolog_tracking');
+ }
+
+ public function tearDown()
+ {
+ // Double delete to make sure it's gone, not preserved due to history setting
+ $this->bo->delete($this->info_id);
+ $this->bo->delete($this->info_id);
+
+ $this->bo = null;
+ }
+
+ /**
+ * Test that free text in the info_contact field winds up in info_from, and
+ * when loaded again it is put into the search of info_contact for display.
+ */
+ public function testFreeText()
+ {
+ $content = array(
+ 'contact' => array(
+ 'app' => 'addressbook',
+ 'id' => Null,
+ 'search'=> 'Free text'
+ )
+ );
+
+ $info = $this->getTestInfolog($content);
+
+ // Skipping notifications - save initial state
+ $this->info_id = $this->bo->write($info, true, true, true, true);
+
+ // Read it back to check
+ $saved = $this->bo->read($this->info_id);
+
+ $this->assertEquals($content['contact']['search'], $saved['info_from']);
+ $this->assertEquals(0, $saved['info_link_id']);
+
+ // Mock the etemplate call to check the results
+ $this->ui->tmpl->expects($this->once())
+ ->method('exec')
+ ->will(
+ $this->returnCallback(function($method, $info) {
+ $this->assertNotNull($info['info_id']);
+ $this->assertEquals('Free text', $info['info_contact']['title']);
+ return true;
+ })
+ );
+
+ // Make a call to edit, looks like initial load
+ $_REQUEST['info_id'] = $this->info_id;
+ $this->ui->edit();
+
+ // Change it
+ $saved['info_contact']['search'] = 'Totally different';
+
+ // Skipping notifications - save initial state
+ $this->bo->write($saved, true, true, true, true);
+
+ // Read it back to check
+ $resaved = $this->bo->read($this->info_id);
+ $this->assertEquals('Totally different', $resaved['info_from'], 'Did not change free text');
+ $this->assertEquals(0, $resaved['info_link_id']);
+
+ // Now clear it
+ $saved = $resaved;
+ $saved['info_contact']['search'] = '';
+
+ // Skipping notifications - save initial state
+ $this->bo->write($saved, false, false);
+
+ // Read it back to check
+ $resaved = $this->bo->read($this->info_id);
+ $this->assertEquals('', $resaved['info_from'], 'Did not clear free text');
+ $this->assertEquals(0, $resaved['info_link_id']);
+ }
+
+ /**
+ * Test that a selected entry is put into info_link_id, and its link title
+ * is put into info_from (not the search text)
+ */
+ public function testLinkedEntry()
+ {
+ $content = array(
+ 'contact' => array(
+ 'app' => 'addressbook',
+ // Linking to current user's contact
+ 'id' => $GLOBALS['egw_info']['user']['person_id'],
+ 'search'=> 'Free text'
+ )
+ );
+ $link_title = $GLOBALS['egw']->contacts->link_title($content['contact']['id']);
+ $info = $this->getTestInfolog($content);
+
+ // Skipping notifications - save initial state
+ $this->info_id = $this->bo->write($info, true, true, true, true);
+
+ // Read it back to check
+ $saved = $this->bo->read($this->info_id);
+
+ $this->assertEquals($link_title, $saved['info_contact']['title'], 'Link title was missing');
+ $this->assertNotEquals(0, $saved['info_link_id']);
+
+ // Mock the etemplate call to check the results
+ $this->ui->tmpl->expects($this->once())
+ ->method('exec')
+ ->will(
+ $this->returnCallback(function($method, $info) use($link_title) {
+ $this->assertNotNull($info['info_id']);
+ $this->assertEquals('', $info['contact']['search']);
+ $this->assertEquals($GLOBALS['egw_info']['user']['person_id'], $info['info_contact']['id']);
+ $this->assertEquals($link_title, $info['info_contact']['title']);
+ })
+ );
+
+ // Make a call to edit, looks like initial load
+ $_REQUEST['info_id'] = $this->info_id;
+ $this->ui->edit();
+ }
+
+ /**
+ * Set up a basic infolog entry for testing with the specified fields
+ * set.
+ *
+ * @param Array $fields Fields to be set for initial conditions
+ * @return Array
+ */
+ protected function getTestInfolog($fields)
+ {
+ $info = array(
+ 'info_subject' => 'Test Infolog Entry for ' . $this->getName()
+ );
+
+ foreach($fields as $field => $value)
+ {
+ $info["info_{$field}"] = $value;
+ }
+
+ return $info;
+ }
+
+}