From 52830ea6056dc85d8ffcb0cfb7ead7d70624e109 Mon Sep 17 00:00:00 2001 From: Thomas Bruederli Date: Tue, 10 Sep 2013 23:37:10 +0200 Subject: Improve handling of date strings and DateTime values in contacts --- program/lib/Roundcube/rcube_addressbook.php | 6 ++--- program/lib/Roundcube/rcube_contacts.php | 4 +++ program/lib/Roundcube/rcube_utils.php | 38 +++++++++++++++++++++++++++++ program/lib/Roundcube/rcube_vcard.php | 4 +-- program/steps/addressbook/save.inc | 10 ++++++++ 5 files changed, 57 insertions(+), 5 deletions(-) diff --git a/program/lib/Roundcube/rcube_addressbook.php b/program/lib/Roundcube/rcube_addressbook.php index c8cf2d290..9301211ff 100644 --- a/program/lib/Roundcube/rcube_addressbook.php +++ b/program/lib/Roundcube/rcube_addressbook.php @@ -563,9 +563,9 @@ abstract class rcube_addressbook // use only strict comparison (mode = 1) // @TODO: partial search, e.g. match only day and month if (in_array($colname, $this->date_cols)) { - return (($value = rcube_utils::strtotime($value)) - && ($search = rcube_utils::strtotime($search)) - && date('Ymd', $value) == date('Ymd', $search)); + return (($value = rcube_utils::anytodatetime($value)) + && ($search = rcube_utils::anytodatetime($search)) + && $value->format('Ymd') == $search->format('Ymd')); } // composite field, e.g. address diff --git a/program/lib/Roundcube/rcube_contacts.php b/program/lib/Roundcube/rcube_contacts.php index 3919cdc6e..6d01368a1 100644 --- a/program/lib/Roundcube/rcube_contacts.php +++ b/program/lib/Roundcube/rcube_contacts.php @@ -718,6 +718,10 @@ class rcube_contacts extends rcube_addressbook foreach ($save_data as $key => $values) { list($field, $section) = explode(':', $key); $fulltext = in_array($field, $this->fulltext_cols); + // avoid casting DateTime objects to array + if (is_object($values) && is_a($values, 'DateTime')) { + $values = array(0 => $values); + } foreach ((array)$values as $value) { if (isset($value)) $vcard->set($field, $value, $section); diff --git a/program/lib/Roundcube/rcube_utils.php b/program/lib/Roundcube/rcube_utils.php index 2540f779d..1d76ae508 100644 --- a/program/lib/Roundcube/rcube_utils.php +++ b/program/lib/Roundcube/rcube_utils.php @@ -787,6 +787,44 @@ class rcube_utils return (int) $ts; } + /** + * Date parsing function that turns the given value into a DateTime object + * + * @param string $date Date string + * + * @return object DateTime instance or false on failure + */ + public static function anytodatetime($date) + { + if (is_object($date) && is_a($date, 'DateTime')) { + return $date; + } + + $dt = false; + $date = trim($date); + + // try to parse string with DateTime first + if (!empty($date)) { + try { + $dt = new DateTime($date); + } + catch (Exception $e) { + // ignore + } + } + + // try our advanced strtotime() method + if (!$dt && ($timestamp = self::strtotime($date))) { + try { + $dt = new DateTime("@".$timestamp); + } + catch (Exception $e) { + // ignore + } + } + + return $dt; + } /* * Idn_to_ascii wrapper. diff --git a/program/lib/Roundcube/rcube_vcard.php b/program/lib/Roundcube/rcube_vcard.php index a85eb8873..d54dc56ad 100644 --- a/program/lib/Roundcube/rcube_vcard.php +++ b/program/lib/Roundcube/rcube_vcard.php @@ -358,8 +358,8 @@ class rcube_vcard case 'birthday': case 'anniversary': - if (($val = rcube_utils::strtotime($value)) && ($fn = self::$fieldmap[$field])) { - $this->raw[$fn][] = array(0 => date('Y-m-d', $val), 'value' => array('date')); + if (($val = rcube_utils::anytodatetime($value)) && ($fn = self::$fieldmap[$field])) { + $this->raw[$fn][] = array(0 => $val->format('Y-m-d'), 'value' => array('date')); } break; diff --git a/program/steps/addressbook/save.inc b/program/steps/addressbook/save.inc index 1628f5b0f..2adc53bcf 100644 --- a/program/steps/addressbook/save.inc +++ b/program/steps/addressbook/save.inc @@ -77,6 +77,16 @@ foreach ($GLOBALS['CONTACT_COLTYPES'] as $col => $colprop) { } else if (isset($_POST[$fname])) { $a_record[$col] = get_input_value($fname, RCUBE_INPUT_POST, true); + + // normalize the submitted date strings + if ($colprop['type'] == 'date') { + if ($timestamp = rcube_utils::strtotime($a_record[$col])) { + $a_record[$col] = date('Y-m-d', $timestamp); + } + else { + unset($a_record[$col]); + } + } } } -- cgit v1.2.3