From: Michael J. Rubinsky Date: Tue, 13 Apr 2010 14:31:22 +0000 (-0400) Subject: Move responsibility for translating contact messages into the client code. X-Git-Url: https://git.internetallee.de/?a=commitdiff_plain;h=02f1d5881741fd7cd94c1782c18824ffaff97e1c;p=horde.git Move responsibility for translating contact messages into the client code. Clean up the rest of the message objects, standardize on getter/setters, remove dead code and obsolete tests. --- diff --git a/framework/ActiveSync/lib/Horde/ActiveSync/Driver/Horde.php b/framework/ActiveSync/lib/Horde/ActiveSync/Driver/Horde.php index edcd8be2d..efc045a0e 100644 --- a/framework/ActiveSync/lib/Horde/ActiveSync/Driver/Horde.php +++ b/framework/ActiveSync/lib/Horde/ActiveSync/Driver/Horde.php @@ -216,8 +216,7 @@ class Horde_ActiveSync_Driver_Horde extends Horde_ActiveSync_Driver_Base $events = $this->_connector->calendar_listEvents($startstamp, $endstamp, null); } catch (Horde_Exception $e) { $this->_logger->err($e->GetMessage()); - - return false; + return array(); } foreach ($events as $day) { foreach($day as $e) { @@ -231,8 +230,7 @@ class Horde_ActiveSync_Driver_Horde extends Horde_ActiveSync_Driver_Base $contacts = $this->_connector->contacts_list(); } catch (Horde_Exception $e) { $this->_logger->err($e->GetMessage()); - - return false; + return array(); } foreach ($contacts as $contact) { @@ -249,7 +247,7 @@ class Horde_ActiveSync_Driver_Horde extends Horde_ActiveSync_Driver_Base break; default: - return false; + return array(); } return $messages; @@ -300,13 +298,12 @@ class Horde_ActiveSync_Driver_Horde extends Horde_ActiveSync_Driver_Base case self::CONTACTS_FOLDER: try { - $contact = $this->_connector->contacts_export($id); + return $this->_connector->contacts_export($id); } catch (Horde_Exception $e) { $this->_logger->err($e->GetMessage()); return false; } - return self::_fromHash($contact); break; case self::TASKS_FOLDER: @@ -415,10 +412,9 @@ class Horde_ActiveSync_Driver_Horde extends Horde_ActiveSync_Driver_Base break; case self::CONTACTS_FOLDER: - $content = self::_toHash($message); if (!$id) { try { - $id = $this->_connector->contacts_import($content); + $id = $this->_connector->contacts_import($message); } catch (Horde_Exception $e) { $this->_logger->err($e->getMessage()); return false; @@ -553,229 +549,4 @@ class Horde_ActiveSync_Driver_Horde extends Horde_ActiveSync_Driver_Base return $message; } - /** - * Create a hash suitable for importing into contacts/import or - * contacts/replace from a Horde_ActiveSync_Message_Base object. - * - * @param Horde_ActiveSync_Message_Contact $message - * - * @return array - */ - private static function _toHash(Horde_ActiveSync_Message_Contact $message) - { - $charset = Horde_Nls::getCharset(); - $formattedname = false; - - /* Name */ - $hash['name'] = Horde_String::convertCharset($message->fileas, 'utf-8', $charset); - $hash['lastname'] = Horde_String::convertCharset($message->lastname, 'utf-8', $charset); - $hash['firstname'] = Horde_String::convertCharset($message->firstname, 'utf-8', $charset); - $hash['middlenames'] = Horde_String::convertCharset($message->middlename, 'utf-8', $charset); - $hash['namePrefix'] = Horde_String::convertCharset($message->title, 'utf-8', $charset); - $hash['nameSuffix'] = Horde_String::convertCharset($message->suffix, 'utf-8', $charset); - - - // picture ($message->picture *should* already be base64 encdoed) - $hash['photo'] = base64_decode($message->picture); - - /* Home */ - $hash['homeStreet'] = Horde_String::convertCharset($message->homestreet, 'utf-8', $charset); - $hash['homeCity'] = Horde_String::convertCharset($message->homecity, 'utf-8', $charset); - $hash['homeProvince'] = Horde_String::convertCharset($message->homestate, 'utf-8', $charset); - $hash['homePostalCode'] = $message->homepostalcode; - $hash['homeCountry'] = Horde_String::convertCharset($message->homecountry, 'utf-8', $charset); - - /* Business */ - $hash['workStreet'] = Horde_String::convertCharset($message->businessstreet, 'utf-8', $charset); - $hash['workCity'] = Horde_String::convertCharset($message->businesscity, 'utf-8', $charset); - $hash['workProvince'] = Horde_String::convertCharset($message->businessstate, 'utf-8', $charset); - $hash['workPostalCode'] = $message->businesspostalcode; - $hash['workCountry'] = Horde_String::convertCharset($message->businesscountry, 'utf-8', $charset); - - $hash['homePhone'] = $message->homephonenumber; - $hash['workPhone'] = $message->businessphonenumber; - $hash['fax'] = $message->businessfaxnumber; - $hash['pager'] = $message->pagernumber; - $hash['cellPhone'] = $message->mobilephonenumber; - - /* Email addresses */ - $hash['email'] = Horde_iCalendar_vcard::getBareEmail($message->email1address); - - /* Job title */ - $hash['title'] = Horde_String::convertCharset($message->jobtitle, 'utf-8', $charset); - - $hash['company'] = Horde_String::convertCharset($message->companyname, 'utf-8', $charset); - $hash['department'] = Horde_String::convertCharset($message->department, 'utf-8', $charset); - - /* Categories */ - if (count($message->categories)) { - $hash['category']['value'] = Horde_String::convertCharset(implode(';', $message->categories), 'utf-8', $charset); - $hash['category']['new'] = true; - } - - /* Children */ - // @TODO - - /* Spouse */ - $hash['spouse'] = Horde_String::convertCharset($message->spouse, 'utf-8', $charset); - - /* Notes */ - $hash['notes'] = Horde_String::convertCharset($message->body, 'utf-8', $charset); - - /* webpage */ - $hash['website'] = Horde_String::convertCharset($message->webpage, 'utf-8', $charset); - - /* Birthday and Anniversary */ - if (!empty($message->birthday)) { - $bday = new Horde_Date($message->birthday); - $hash['birthday'] = $bday->format('Y-m-d'); - } else { - $hash['birthday'] = null; - } - if (!empty($message->anniversary)) { - $anniversary = new Horde_Date($message->anniversary); - $hash['anniversary'] = $anniversary->format('Y-m-d'); - } else { - $hash['anniversary'] = null; - } - - /* Assistant */ - $hash['assistant'] = Horde_String::convertCharset($message->assistantname, 'utf-8', $charset); - - return $hash; - } - - /** - * Import data from Horde's contacts API - * - * @param array $hash A hash as returned from contacts/export - * - * @return Horde_ActiveSync_Message_Base object - */ - private static function _fromHash($hash) - { - $message = new Horde_ActiveSync_Message_Contact(); - - $charset = Horde_Nls::getCharset(); - - foreach ($hash as $field => $value) { - switch ($field) { - case 'name': - $message->fileas = Horde_String::convertCharset($value, $charset, 'utf-8'); - break; - case 'lastname': - $message->lastname = Horde_String::convertCharset($value, $charset, 'utf-8'); - break; - case 'firstname': - $message->firstname = Horde_String::convertCharset($value, $charset, 'utf-8'); - break; - case 'middlenames': - $message->middlename = Horde_String::convertCharset($value, $charset, 'utf-8'); - break; - case 'namePrefix': - $message->title = Horde_String::convertCharset($value, $charset, 'utf-8'); - break; - case 'nameSuffix': - $message->suffix = Horde_String::convertCharset($value, $charset, 'utf-8'); - break; - - case 'photo': - $message->picture = base64_encode($value['load']['data']); - break; - - /* Address (TODO: check for a single home/workAddress field instead) */ - case 'homeStreet': - $message->homestreet = Horde_String::convertCharset($hash['homeStreet'], $charset, 'utf-8'); - break; - case 'homeCity': - $message->homecity = Horde_String::convertCharset($hash['homeCity'], $charset, 'utf-8'); - break; - case 'homeProvince': - $message->homestate = Horde_String::convertCharset($hash['homeProvince'], $charset, 'utf-8'); - break; - case 'homePostalCode': - $message->homepostalcode = Horde_String::convertCharset($hash['homePostalCode'], $charset, 'utf-8'); - break; - case 'homeCountry': - $message->homecountry = Horde_String::convertCharset($hash['homeCountry'], $charset, 'utf-8'); - break; - case 'workStreet': - $message->businessstreet = Horde_String::convertCharset($hash['workStreet'], $charset, 'utf-8'); - break; - case 'workCity': - $message->businesscity = Horde_String::convertCharset($hash['workCity'], $charset, 'utf-8'); - break; - case 'workProvince': - $message->businessstate = Horde_String::convertCharset($hash['workProvince'], $charset, 'utf-8'); - break; - case 'workPostalCode': - $message->businesspostalcode = Horde_String::convertCharset($hash['workPostalCode'], $charset, 'utf-8'); - break; - case 'workCountry': - $message->businesscountry = Horde_String::convertCharset($hash['workCountry'], $charset, 'utf-8'); - break; - case 'homePhone': - /* Phone */ - $message->homephonenumber = $hash['homePhone']; - break; - case 'cellPhone': - $message->mobilephonenumber = $hash['cellPhone']; - break; - case 'fax': - $message->businessfaxnumber = $hash['fax']; - break; - case 'workPhone': - $message->businessphonenumber = $hash['workPhone']; - break; - case 'pager': - $message->pagernumber = $hash['pager']; - break; - - case 'email': - $message->email1address = Horde_iCalendar_vcard::getBareEmail($value); - break; - - case 'title': - $message->jobtitle = Horde_String::convertCharset($value, $charset, 'utf-8'); - break; - - case 'company': - $message->companyname = Horde_String::convertCharset($value, $charset, 'utf-8'); - break; - case 'departnemt': - $message->department = Horde_String::convertCharset($value, $charset, 'utf-8'); - break; - - case 'category': - // Categories FROM horde are a simple string value, going BACK to horde are an array with 'value' and 'new' keys - $message->categories = explode(';', Horde_String::convertCharset($value, $charset, 'utf-8')); - break; - - case 'spouse': - $message->spouse = Horde_String::convertCharset($value, $charset, 'utf-8'); - break; - case 'notes': - $message->body = Horde_String::convertCharset($value, $charset, 'utf-8'); - $message->bodysize = strlen($message->body); - $message->bodytruncated = false; - break; - case 'website': - $message->webpage = $value; - break; - - case 'birthday': - case 'anniversary': - if (!empty($value)) { - $date = new Horde_Date($value); - $message->{$field} = $date; - } else { - $message->$field = null; - } - break; - } - } - - return $message; - } - } diff --git a/framework/ActiveSync/lib/Horde/ActiveSync/Driver/Horde/Connector/Registry.php b/framework/ActiveSync/lib/Horde/ActiveSync/Driver/Horde/Connector/Registry.php index 3cae54396..acf4062e2 100644 --- a/framework/ActiveSync/lib/Horde/ActiveSync/Driver/Horde/Connector/Registry.php +++ b/framework/ActiveSync/lib/Horde/ActiveSync/Driver/Horde/Connector/Registry.php @@ -151,7 +151,7 @@ class Horde_ActiveSync_Driver_Horde_Connector_Registry */ public function contacts_export($uid) { - return $this->_registry->contacts->export($uid, 'array'); + return $this->_registry->contacts->export($uid, 'activesync'); } /** diff --git a/framework/ActiveSync/lib/Horde/ActiveSync/Message/Appointment.php b/framework/ActiveSync/lib/Horde/ActiveSync/Message/Appointment.php index bc4d34b98..101ca7a59 100644 --- a/framework/ActiveSync/lib/Horde/ActiveSync/Message/Appointment.php +++ b/framework/ActiveSync/lib/Horde/ActiveSync/Message/Appointment.php @@ -97,7 +97,7 @@ class Horde_ActiveSync_Message_Appointment extends Horde_ActiveSync_Message_Base * @return Horde_ActiveSync_Message_Appointment */ public function __construct($params = array()) { - $mapping = array( + $this->_mapping = array( self::POOMCAL_TIMEZONE => array (self::KEY_ATTRIBUTE => 'timezone'), self::POOMCAL_DTSTAMP => array (self::KEY_ATTRIBUTE => 'dtstamp', self::KEY_TYPE => self::TYPE_DATE), self::POOMCAL_STARTTIME => array (self::KEY_ATTRIBUTE => 'starttime', self::KEY_TYPE => self::TYPE_DATE), @@ -122,7 +122,28 @@ class Horde_ActiveSync_Message_Appointment extends Horde_ActiveSync_Message_Base //self::POOMCAL_RESPONSETYPE => array(self::KEY_ATTRIBUTE => 'responsetype'), ); - parent::__construct($mapping, $params); + $this->_properties = array( + 'timezone' => false, + 'dtstamp' => false, + 'starttime' => false, + 'subject' => false, + 'uid' => false, + 'organizername' => false, + 'organizeremail' => false, + 'location' => false, + 'endtime' => false, + 'recurrence' => false, + 'sensitivity' => false, + 'busystatus' => false, + 'alldayevent' => false, + 'reminder' => false, + 'rtf' => false, + 'meetingstatus' => false, + 'body' => false, + 'bodytruncated' => false, + ); + + parent::__construct($params); } /** diff --git a/framework/ActiveSync/lib/Horde/ActiveSync/Message/Attendee.php b/framework/ActiveSync/lib/Horde/ActiveSync/Message/Attendee.php index f54252a8f..9ef2cf67f 100644 --- a/framework/ActiveSync/lib/Horde/ActiveSync/Message/Attendee.php +++ b/framework/ActiveSync/lib/Horde/ActiveSync/Message/Attendee.php @@ -28,14 +28,19 @@ class Horde_ActiveSync_Message_Attendee extends Horde_ActiveSync_Message_Base * @param array $params */ function __construct($params = array()) { - $mapping = array( + $this->_mapping = array( Horde_ActiveSync_Message_Appointment::POOMCAL_EMAIL => array (self::KEY_ATTRIBUTE => 'email'), Horde_ActiveSync_Message_Appointment::POOMCAL_NAME => array (self::KEY_ATTRIBUTE => 'name'), //SYNC_POOMCAL_ATTENDEETYPE => array(self::KEY_ATTRIBUTE => 'type'), //SYNC_POOMCAL_ATTENDEESTATUS => array(self::KEY_ATTRIBUTE => 'status') ); - parent::__construct($mapping, $params); + $this->_properties = array( + 'email' => false, + 'name' => false, + ); + + parent::__construct($params); } } \ No newline at end of file diff --git a/framework/ActiveSync/lib/Horde/ActiveSync/Message/Base.php b/framework/ActiveSync/lib/Horde/ActiveSync/Message/Base.php index 81127f953..9ca0af0ab 100644 --- a/framework/ActiveSync/lib/Horde/ActiveSync/Message/Base.php +++ b/framework/ActiveSync/lib/Horde/ActiveSync/Message/Base.php @@ -60,7 +60,7 @@ class Horde_ActiveSync_Message_Base * //FIXME: use accessor methods, make this protected * @var Horde_ActiveSync_FLAG_* constant */ - public $flags; + public $flags = false; /** * Logger @@ -77,17 +77,22 @@ class Horde_ActiveSync_Message_Base * * @return Horde_ActiveSync_Message_Base */ - public function __construct($mapping, $options) + public function __construct($options) { - $this->_mapping = $mapping; - $this->flags = false; if (!empty($options['logger'])) { $this->_logger = $options['logger']; + } else { + $this->_logger = new Horde_Support_Stub(); } } public function __get($property) { + if (!array_key_exists($property, $this->_properties)) { + $this->_logger->err('Unknown property: ' . $property); + throw new InvalidArgumentException('Unknown property: ' . $property); + } + if (!empty($this->_properties[$property])) { return $this->_properties[$property]; } else { @@ -97,9 +102,28 @@ class Horde_ActiveSync_Message_Base public function __set($property, $value) { + if (!array_key_exists($property, $this->_properties)) { + $this->_logger->err('Unknown property: ' . $property); + throw new InvalidArgumentException('Unknown property: ' . $property); + } $this->_properties[$property] = $value; } + public function __call($method, $arg) + { + /* Support calling set{Property}() */ + if (strpos($method, 'set') === 0) { + $property = Horde_String::lower(substr($method, 3)); + $this->_properties[$property] = $arg; + } elseif (strpos($method, 'get') === 0) { + return $this->_getAttribute(Horde_String::lower(substr($method, 3))); + } + + throw new BadMethodCallException('Unknown method: ' . $method . ' in class: ' . __CLASS__); + } + + + public function __isset($property) { return !empty($this->_properties[$property]); @@ -329,6 +353,14 @@ class Horde_ActiveSync_Message_Base } } + /** + * Helper method to allow default values for unset properties. + * + * @param string $name The property name + * @param stting $default The default value to return if $property is empty + * + * @return mixed + */ protected function _getAttribute($name, $default = null) { if (!empty($this->_properties[$name])) { diff --git a/framework/ActiveSync/lib/Horde/ActiveSync/Message/Contact.php b/framework/ActiveSync/lib/Horde/ActiveSync/Message/Contact.php index 2179a911f..4476dbca4 100644 --- a/framework/ActiveSync/lib/Horde/ActiveSync/Message/Contact.php +++ b/framework/ActiveSync/lib/Horde/ActiveSync/Message/Contact.php @@ -10,10 +10,10 @@ */ class Horde_ActiveSync_Message_Contact extends Horde_ActiveSync_Message_Base { + /* Workaround for issues with arrays from __get() */ public $categories = array(); public $children = array(); - /* POOMCONTACTS */ const ANNIVERSARY = "POOMCONTACTS:Anniversary"; const ASSISTANTNAME = "POOMCONTACTS:AssistantName"; @@ -93,7 +93,8 @@ class Horde_ActiveSync_Message_Contact extends Horde_ActiveSync_Message_Base */ public function __construct($params = array()) { - $mapping = array ( + /* Mappings for the encoder */ + $this->_mapping = array ( self::ANNIVERSARY => array (self::KEY_ATTRIBUTE => 'anniversary', self::KEY_TYPE => self::TYPE_DATE_DASHES), self::ASSISTANTNAME => array (self::KEY_ATTRIBUTE => 'assistantname'), self::ASSISTNAMEPHONENUMBER => array (self::KEY_ATTRIBUTE => 'assistnamephonenumber'), @@ -150,9 +151,67 @@ class Horde_ActiveSync_Message_Contact extends Horde_ActiveSync_Message_Base self::CATEGORIES => array (self::KEY_ATTRIBUTE => 'categories', self::KEY_VALUES => self::CATEGORY), ); + /* Accepted property values */ + $this->_properties = array( + 'anniversary' => false, + 'assistantname' => false, + 'assistnamephonenumber' => false, + 'birthday' => false, + 'body' => false, + 'bodysize' => false, + 'bodytruncated' => false, + 'business2phonenumber' => false, + 'businesscity' => false, + 'businesscountry' => false, + 'businesspostalcode' => false, + 'businessstate' => false, + 'businessstreet' => false, + 'businessfaxnumber' => false, + 'businessphonenumber' => false, + 'carphonenumber' => false, + 'children' => false, + 'companyname' => false, + 'department' => false, + 'email1address' => false, + 'email2address' => false, + 'email3address' => false, + 'fileas' => false, + 'firstname' => false, + 'home2phonenumber' => false, + 'homecity' => false, + 'homecountry' => false, + 'homepostalcode' => false, + 'homestate' => false, + 'homestreet' => false, + 'homefaxnumber' => false, + 'homephonenumber' => false, + 'jobtitle' => false, + 'lastname' => false, + 'middlename' => false, + 'mobilephonenumber' => false, + 'officelocation' => false, + 'othercity' => false, + 'othercountry' => false, + 'otherpostalcode' => false, + 'otherstate' => false, + 'otherstreet' => false, + 'pagernumber' => false, + 'radiophonenumber' => false, + 'spouse' => false, + 'suffix' => false, + 'title' => false, + 'webpage' => false, + 'yomicompanyname' => false, + 'yomifirstname' => false, + 'yomilastname' => false, + 'rtf' => false, + 'picture' => false, + 'categories' => false, + ); + /* Additional mappings for AS versions >= 2.5 */ if (isset($params['protocolversion']) && $params['protocolversion'] >= 2.5) { - $mapping += array( + $this->_mapping += array( self::CUSTOMERID => array (self::KEY_ATTRIBUTE => 'customerid'), self::GOVERNMENTID => array (self::KEY_ATTRIBUTE => 'governmentid'), self::IMADDRESS => array (self::KEY_ATTRIBUTE => 'imaddress'), @@ -164,9 +223,22 @@ class Horde_ActiveSync_Message_Contact extends Horde_ActiveSync_Message_Base self::NICKNAME => array (self::KEY_ATTRIBUTE => 'nickname'), self::MMS => array (self::KEY_ATTRIBUTE => 'mms'), ); + + $this->_properties += array( + 'customerid' => false, + 'governmentid' => false, + 'imaddress' => false, + 'imaddress2' => false, + 'imaddress3' => false, + 'managername' => false, + 'companymainphone' => false, + 'accountname' => false, + 'nickname' => false, + 'mms' => false, + ); } - parent::__construct($mapping, $params); + parent::__construct($params); } public function getClass() diff --git a/framework/ActiveSync/lib/Horde/ActiveSync/Message/Exception.php b/framework/ActiveSync/lib/Horde/ActiveSync/Message/Exception.php index afa72faf0..09db9dfbe 100644 --- a/framework/ActiveSync/lib/Horde/ActiveSync/Message/Exception.php +++ b/framework/ActiveSync/lib/Horde/ActiveSync/Message/Exception.php @@ -2,7 +2,7 @@ /** * Horde_ActiveSync_Message_Exception class represents a single exception to a * recurring event. This is basically a Appointment object with some tweaks. - * + * * @copyright 2010 The Horde Project (http://www.horde.org) * * @author Michael J. Rubinsky @@ -18,7 +18,7 @@ class Horde_ActiveSync_Message_Exception extends Horde_ActiveSync_Message_Appoin * @return Horde_ActiveSync_Message_Appointment */ public function __construct($params = array()) - { + { parent::__construct($params); /* Some additional properties for Exceptions */ @@ -27,6 +27,11 @@ class Horde_ActiveSync_Message_Exception extends Horde_ActiveSync_Message_Appoin self::KEY_TYPE => self::TYPE_DATE); $this->_mapping[Horde_ActiveSync_Message_Appointment::POOMCAL_DELETED] = array(self::KEY_ATTRIBUTE => 'deleted'); + + $this->_properties += array( + 'exceptionstarttime' => false, + 'deleted' => false, + ); } /** diff --git a/framework/ActiveSync/lib/Horde/ActiveSync/Message/Folder.php b/framework/ActiveSync/lib/Horde/ActiveSync/Message/Folder.php index b147558c3..83682f033 100644 --- a/framework/ActiveSync/lib/Horde/ActiveSync/Message/Folder.php +++ b/framework/ActiveSync/lib/Horde/ActiveSync/Message/Folder.php @@ -17,14 +17,21 @@ class Horde_ActiveSync_Message_Folder extends Horde_ActiveSync_Message_Base public function __construct($params = array()) { - $mapping = array ( + $this->_mapping = array ( Horde_ActiveSync::FOLDERHIERARCHY_SERVERENTRYID => array (self::KEY_ATTRIBUTE => 'serverid'), Horde_ActiveSync::FOLDERHIERARCHY_PARENTID => array (self::KEY_ATTRIBUTE => 'parentid'), Horde_ActiveSync::FOLDERHIERARCHY_DISPLAYNAME => array (self::KEY_ATTRIBUTE => 'displayname'), Horde_ActiveSync::FOLDERHIERARCHY_TYPE => array (self::KEY_ATTRIBUTE => 'type') ); - parent::__construct($mapping, $params); + $this->_properties = array( + 'serverid' => false, + 'parentid' => false, + 'displayname' => false, + 'type' => false, + ); + + parent::__construct($params); } public function getClass() diff --git a/framework/ActiveSync/lib/Horde/ActiveSync/Message/Recurrence.php b/framework/ActiveSync/lib/Horde/ActiveSync/Message/Recurrence.php index 40840cc45..34ee0032b 100644 --- a/framework/ActiveSync/lib/Horde/ActiveSync/Message/Recurrence.php +++ b/framework/ActiveSync/lib/Horde/ActiveSync/Message/Recurrence.php @@ -20,7 +20,7 @@ class Horde_ActiveSync_Message_Recurrence extends Horde_ActiveSync_Message_Base function __construct($params = array()) { - $mapping = array ( + $this->_mapping = array ( Horde_ActiveSync_Message_Appointment::POOMCAL_TYPE => array (self::KEY_ATTRIBUTE => 'type'), Horde_ActiveSync_Message_Appointment::POOMCAL_UNTIL => array (self::KEY_ATTRIBUTE => 'until', self::KEY_TYPE => self::TYPE_DATE), Horde_ActiveSync_Message_Appointment::POOMCAL_OCCURRENCES => array (self::KEY_ATTRIBUTE => 'occurrences'), @@ -31,7 +31,18 @@ class Horde_ActiveSync_Message_Recurrence extends Horde_ActiveSync_Message_Base Horde_ActiveSync_Message_Appointment::POOMCAL_MONTHOFYEAR => array (self::KEY_ATTRIBUTE => 'monthofyear') ); - parent::__construct($mapping, $params); + $this->_properties = array( + 'type' => false, + 'until' => false, + 'occurrences' => false, + 'interval' => false, + 'dayofweek' => false, + 'dayofmonth' => false, + 'weekofmonth' => false, + 'monthofyear' => false, + ); + + parent::__construct($params); } } \ No newline at end of file diff --git a/framework/ActiveSync/lib/Horde/ActiveSync/Message/Task.php b/framework/ActiveSync/lib/Horde/ActiveSync/Message/Task.php index acee8a1bb..4ec04e125 100644 --- a/framework/ActiveSync/lib/Horde/ActiveSync/Message/Task.php +++ b/framework/ActiveSync/lib/Horde/ActiveSync/Message/Task.php @@ -58,7 +58,7 @@ class Horde_ActiveSync_Message_Task extends Horde_ActiveSync_Message_Base * @param array $params */ function __construct($params = array()) { - $mapping = array ( + $this->_mapping = array ( self::POOMTASKS_BODY => array (self::KEY_ATTRIBUTE => 'body'), self::POOMTASKS_COMPLETE => array (self::KEY_ATTRIBUTE => 'complete'), self::POOMTASKS_DATECOMPLETED => array (self::KEY_ATTRIBUTE => 'datecompleted', self::KEY_TYPE => self::TYPE_DATE_DASHES), @@ -78,7 +78,27 @@ class Horde_ActiveSync_Message_Task extends Horde_ActiveSync_Message_Base self::POOMTASKS_CATEGORIES => array (self::KEY_ATTRIBUTE => 'categories', self::KEY_VALUES => self::POOMTASKS_CATEGORY), ); - parent::__construct($mapping, $params); + $this->_properties = array( + 'body' => false, + 'complete' => false, + 'datecompleted' => false, + 'duedate' => false, + 'utcduedate' => false, + 'importance' => false, + 'recurrence' => false, + 'regenerate' => false, + 'deadoccur' => false, + 'reminderset' => false, + 'remindertime' => false, + 'sensitiviy' => false, + 'startdate' => false, + 'utcstartdate' => false, + 'subject' => false, + 'rtf' => false, + 'categories' => false, + ); + + parent::__construct($params); } /** diff --git a/framework/ActiveSync/test/Horde/ActiveSync/HordeDriverTest.php b/framework/ActiveSync/test/Horde/ActiveSync/HordeDriverTest.php index ed9431fd4..52ca48b88 100644 --- a/framework/ActiveSync/test/Horde/ActiveSync/HordeDriverTest.php +++ b/framework/ActiveSync/test/Horde/ActiveSync/HordeDriverTest.php @@ -75,152 +75,72 @@ class Horde_ActiveSync_HordeDriverTest extends Horde_Test_Case } /** - * Test retrieving a message from storage. - * Mocks the registry response. - * - * @TODO: Calendar data, more complete test of vCard attribtues. - * + * Tests that getMessage() requests the correct object type based on + * the folder class we are requesting. */ public function testGetMessage() { require_once 'Horde/ActiveSync.php'; - $contact = array( - '__key' => '9b07c14b086932e69cc7eb1baed0cc87', - '__owner' => 'mike', - '__type' => 'Object', - '__members' => '', - '__uid' => '20100205111228.89913meqtp5u09rg@localhost', - 'firstname' => 'Michael', - 'lastname' => 'Rubinsky', - 'middlenames' => 'Joseph', - 'namePrefix' => 'Dr', - 'nameSuffix' => 'PharmD', - 'name' => 'Michael Joseph Rubinsky', - 'alias' => 'Me', - 'birthday' => '1970-03-20', - 'homeStreet' => '123 Main St.', - 'homePOBox' => '', - 'homeCity' => 'Anywhere', - 'homeProvince' => 'NJ', - 'homePostalCode' => '08080', - 'homeCountry' => 'US', - 'workStreet' => 'Kings Hwy', - 'workPOBox' => '', - 'workCity' => 'Somewhere', - 'workProvince' => 'NJ', - 'workPostalCode' => '08052', - 'workCountry' => 'US', - 'timezone' => 'America/New_York', - 'email' => 'mrubinsk@horde.org', - 'homePhone' => '(856)555-1234', - 'workPhone' => '(856)555-5678', - 'cellPhone' => '(609)555-9876', - 'fax' => '', - 'pager' => '', - 'title' => '', - 'role' => '', - 'company' => '', - 'category' => '', - 'notes' => '', - 'website' => '', - 'freebusyUrl' => '', - 'pgpPublicKey' => '', - 'smimePublicKey' => '', - ); + $contact = new Horde_ActiveSync_Message_Contact(); + $event = new Horde_ActiveSync_Message_Appointment(); + $task = new Horde_ActiveSync_Message_Task(); if (version_compare(PHP_VERSION, '5.3.0', '>=')) { error_reporting(E_ALL & ~E_DEPRECATED); } - /* This test REQUIRES that the NLS system be initialized, so skip this - * if we don't have a configured horde - */ - if (!file_exists(dirname(__FILE__) . '/../../../../../horde/config/conf.php')) { - $this->markTestIncomplete('Test requires the NLS system'); - return; - } - require_once dirname(__FILE__) . '/../../../../../horde/lib/core.php'; - Horde_Nls::setLanguage(); - $fixture = array('contacts_export' => $contact); + /* Mock the registry connector */ + $fixture = array( + 'contacts_export' => $contact, + 'calendar_export' => $event, + 'tasks_export' => $task + ); $connector = new Horde_ActiveSync_MockConnector(array('fixture' => $fixture)); + + /* We don't need to remember any state for this test, mock it */ $state = $this->getMockSkipConstructor('Horde_ActiveSync_State_File'); + + /* Get the driver, and test it */ $driver = new Horde_ActiveSync_Driver_Horde(array('connector' => $connector, 'state_basic' => $state)); - $results = $driver->getMessage(Horde_ActiveSync_Driver_Horde::CONTACTS_FOLDER, - '20070112030603.249j42k3k068@test.theupstairsroom.com', - 0); + $results = $driver->getMessage(Horde_ActiveSync_Driver_Horde::CONTACTS_FOLDER, 'xxx', 0); $this->assertType('Horde_ActiveSync_Message_Contact', $results); - $this->assertEquals('Dr', $results->title); - $this->assertEquals('PharmD', $results->suffix); - $this->assertEquals('Michael Joseph Rubinsky', $results->fileas); - $this->assertEquals('mrubinsk@horde.org', $results->email1address); - $this->assertEquals('1970-03-20', $results->birthday->format('Y-m-d')); - $this->assertEquals('(856)555-1234', $results->homephonenumber); - $this->assertEquals('(856)555-5678', $results->businessphonenumber); - $this->assertEquals('(609)555-9876', $results->mobilephonenumber); - $this->assertEquals('123 Main St.', $results->homestreet); - $this->assertEquals('Anywhere', $results->homecity); - $this->assertEquals('NJ', $results->homestate); - $this->assertEquals('08080', $results->homepostalcode); - $this->assertEquals('US', $results->homecountry); - $this->assertEquals('Kings Hwy', $results->businessstreet); - $this->assertEquals('Somewhere', $results->businesscity); - $this->assertEquals('NJ', $results->businessstate); - $this->assertEquals('08052', $results->businesspostalcode); - $this->assertEquals('US', $results->businesscountry); + + $results = $driver->getMessage(Horde_ActiveSync_Driver_Horde::APPOINTMENTS_FOLDER, 'xxx', 0); + $this->assertType('Horde_ActiveSync_Message_Appointment', $results); + + $results = $driver->getMessage(Horde_ActiveSync_Driver_Horde::TASKS_FOLDER, 'xxx', 0); + $this->assertType('Horde_ActiveSync_Message_Task', $results); } /** - * Test that the values present in the contact message are always utf-8. + * Test ChangeMessage: Only thing to really test for the changeMessage + * method is that it calls the correct API method, with the correct object + * type. No data conversion is done in the driver, it's the responsiblity of + * the client code. */ - public function testStreamerUTF8() + public function testChangeMessage() { - if (version_compare(PHP_VERSION, '5.3.0', '>=')) { - error_reporting(E_ALL & ~E_DEPRECATED); - } + $this->markTestIncomplete('Test still being written'); + /* Setup mock connector method return values for adding a new contact */ + $connector = $this->getMockSkipConstructor('Horde_ActiveSync_Driver_Horde_Connector_Registry'); + $connector->expects($this->once())->method('contacts_import')->will($this->returnValue(1)); + $connector->expects($this->at(1))->method('contacts_getActionTimestamp')->will($this->returnValue(array('todo'))); - /* This test REQUIRES that the NLS system be initialized, so skip this - * if we don't have a configured horde - */ - if (!file_exists(dirname(__FILE__) . '/../../../../../horde/config/conf.php')) { - $this->markTestIncomplete('Test requires the NLS system'); - return; - } - require_once dirname(__FILE__) . '/../../../../../horde/lib/core.php'; - Horde_Nls::setLanguage(); + /* Setup mock connector return for modifying an existing contact */ + $connector->expects($this->once())->method('contacts_replace')->will($this->returnValue(2)); + $connector->expects($this->at(1))->method('contacts_getActionTimestamp')->will($this->returnValue(array('todo'))); - $contact = array( - '__uid' => '20100205111228.89913meqtp5u09rg@localhost', - 'firstname' => Horde_String::convertCharset('Grüb', Horde_Nls::getCharset(), 'iso-8859-1') - ); + /* TODO: appointments and todos */ - $fixture = array('contacts_export' => $contact); - $connector = new Horde_ActiveSync_MockConnector(array('fixture' => $fixture)); + /* We don't need to remember any state for this test, mock it */ $state = $this->getMockSkipConstructor('Horde_ActiveSync_State_File'); + + /* Get the driver, and test it */ $driver = new Horde_ActiveSync_Driver_Horde(array('connector' => $connector, 'state_basic' => $state)); - - $results = $driver->getMessage(Horde_ActiveSync_Driver_Horde::CONTACTS_FOLDER, - '20070112030603.249j42k3k068@test.theupstairsroom.com', - 0); - - $this->assertEquals(Horde_String::convertCharset('Grüb', Horde_Nls::getCharset(), 'utf-8'), $results->firstname); - } - - /** - * Test ChangeMessage: - * - * This tests converting the contact streamer object to a hash suitable for - * passing to the contacts/import method. Because it only returns the UID - * for the newly added/edited entry, we can't check the results here. The - * check is done in the MockConnector object, throwing an exception if it - * fails. - * - */ - public function testChangeMessage() - { // fixtures $message = new Horde_ActiveSync_Message_Contact(); $message->fileas = 'Michael Joseph Rubinsky'; @@ -242,14 +162,8 @@ class Horde_ActiveSync_HordeDriverTest extends Horde_Test_Case error_reporting(E_ALL & ~E_DEPRECATED); } - $connector = new Horde_ActiveSync_MockConnector(array('fixture' => array())); - $state = $this->getMockSkipConstructor('Horde_ActiveSync_State_File'); - $driver = new Horde_ActiveSync_Driver_Horde(array('connector' => $connector, - 'state_basic' => $state)); - try { - $results = $driver->ChangeMessage(Horde_ActiveSync_Driver_Horde::CONTACTS_FOLDER, - 0, $message); + $results = $driver->ChangeMessage(Horde_ActiveSync_Driver_Horde::CONTACTS_FOLDER, 0, $message); } catch (Horde_ActiveSync_Exception $e) { $this->fail($e->getMessage()); } diff --git a/turba/lib/Api.php b/turba/lib/Api.php index c99002747..d66d3bd73 100644 --- a/turba/lib/Api.php +++ b/turba/lib/Api.php @@ -596,8 +596,8 @@ class Turba_Api extends Horde_Registry_Api * * @param string $content The content of the contact. * @param string $contentType What format is the data in? Currently - * supports array, text/directory, text/vcard - * and text/x-vcard. + * supports array, text/directory, text/vcard, + * text/x-vcard, and activesync. * @param string $source The source into which the contact will be * imported. * @@ -684,6 +684,10 @@ class Turba_Api extends Horde_Registry_Api } break; + case 'activesync': + $hash = $driver->fromASContact($content); + break; + default: throw new Horde_Exception(sprintf(_("Unsupported Content-Type: %s"), $contentType)); } @@ -809,6 +813,13 @@ class Turba_Api extends Horde_Registry_Api } return $attributes; + + case 'activesync': + foreach ($result->objects as $object) { + $return = $object; + } + + return $driver->toASContact($return); } throw new Horde_Exception(sprintf(_("Unsupported Content-Type: %s"), $contentType)); @@ -979,7 +990,7 @@ class Turba_Api extends Horde_Registry_Api * @param string $content The content of the contact. * @param string $contentType What format is the data in? Currently * supports array, text/directory, - * text/vcard and text/x-vcard. + * text/vcard, text/x-vcard and activesync. * @param string|array $sources The source(s) where the contact will be * replaced. * @@ -1056,6 +1067,9 @@ class Turba_Api extends Horde_Registry_Api throw new Horde_Exception(_("Only one vcard supported.")); } break; + case 'activesync': + $content = $driver->fromASContact($content); + break; default: throw new Horde_Exception(sprintf(_("Unsupported Content-Type: %s"), $contentType)); diff --git a/turba/lib/Driver.php b/turba/lib/Driver.php index 854e9057d..18443e000 100644 --- a/turba/lib/Driver.php +++ b/turba/lib/Driver.php @@ -2290,6 +2290,231 @@ class Turba_Driver } /** + * Convert the contact to an ActiveSync contact message + * + * @param Turba_Object $object The turba object to convert + * + * @return Horde_ActiveSync_Message_Contact + */ + public function toASContact(Turba_Object $object) + { + $message = new Horde_ActiveSync_Message_Contact(array('logger' => $GLOBALS['injector']->getInstance('Horde_Log_Logger'))); + $charset = Horde_Nls::getCharset(); + $hash = $object->getAttributes(); + //var_dump($hash); + foreach ($hash as $field => $value) { + switch ($field) { + case 'name': + $message->fileas = Horde_String::convertCharset($value, $charset, 'utf-8'); + break; + case 'lastname': + $message->lastname = Horde_String::convertCharset($value, $charset, 'utf-8'); + break; + case 'firstname': + $message->firstname = Horde_String::convertCharset($value, $charset, 'utf-8'); + break; + case 'middlenames': + $message->middlename = Horde_String::convertCharset($value, $charset, 'utf-8'); + break; + case 'namePrefix': + $message->title = Horde_String::convertCharset($value, $charset, 'utf-8'); + break; + case 'nameSuffix': + $message->suffix = Horde_String::convertCharset($value, $charset, 'utf-8'); + break; + + case 'photo': + $message->picture = base64_encode($value); + break; + + /* Address (TODO: check for a single home/workAddress field instead) */ + case 'homeStreet': + $message->homestreet = Horde_String::convertCharset($hash['homeStreet'], $charset, 'utf-8'); + break; + case 'homeCity': + $message->homecity = Horde_String::convertCharset($hash['homeCity'], $charset, 'utf-8'); + break; + case 'homeProvince': + $message->homestate = Horde_String::convertCharset($hash['homeProvince'], $charset, 'utf-8'); + break; + case 'homePostalCode': + $message->homepostalcode = Horde_String::convertCharset($hash['homePostalCode'], $charset, 'utf-8'); + break; + case 'homeCountry': + $message->homecountry = Horde_String::convertCharset($hash['homeCountry'], $charset, 'utf-8'); + break; + case 'workStreet': + $message->businessstreet = Horde_String::convertCharset($hash['workStreet'], $charset, 'utf-8'); + break; + case 'workCity': + $message->businesscity = Horde_String::convertCharset($hash['workCity'], $charset, 'utf-8'); + break; + case 'workProvince': + $message->businessstate = Horde_String::convertCharset($hash['workProvince'], $charset, 'utf-8'); + break; + case 'workPostalCode': + $message->businesspostalcode = Horde_String::convertCharset($hash['workPostalCode'], $charset, 'utf-8'); + break; + case 'workCountry': + $message->businesscountry = Horde_String::convertCharset($hash['workCountry'], $charset, 'utf-8'); + break; + case 'homePhone': + /* Phone */ + $message->homephonenumber = $hash['homePhone']; + break; + case 'cellPhone': + $message->mobilephonenumber = $hash['cellPhone']; + break; + case 'fax': + $message->businessfaxnumber = $hash['fax']; + break; + case 'workPhone': + $message->businessphonenumber = $hash['workPhone']; + break; + case 'pager': + $message->pagernumber = $hash['pager']; + break; + + case 'email': + $message->email1address = Horde_iCalendar_vcard::getBareEmail($value); + break; + + case 'title': + $message->jobtitle = Horde_String::convertCharset($value, $charset, 'utf-8'); + break; + + case 'company': + $message->companyname = Horde_String::convertCharset($value, $charset, 'utf-8'); + break; + case 'departnemt': + $message->department = Horde_String::convertCharset($value, $charset, 'utf-8'); + break; + + case 'category': + // Categories FROM horde are a simple string value, going BACK to horde are an array with 'value' and 'new' keys + $message->categories = explode(';', Horde_String::convertCharset($value, $charset, 'utf-8')); + break; + + case 'spouse': + $message->spouse = Horde_String::convertCharset($value, $charset, 'utf-8'); + break; + case 'notes': + $message->body = Horde_String::convertCharset($value, $charset, 'utf-8'); + $message->bodysize = strlen($message->body); + $message->bodytruncated = false; + break; + case 'website': + $message->webpage = $value; + break; + + case 'birthday': + case 'anniversary': + if (!empty($value)) { + $date = new Horde_Date($value); + $message->{$field} = $date; + } else { + $message->$field = null; + } + break; + } + } + + return $message; + } + + /** + * Convert an ActiveSync contact message into a hash suitable for importing + * via add. + * + * @param Horde_ActiveSync_Message_Contact $message The contact message object + * + * @return array A contact hash + */ + public function fromASContact($message) + { + $hash = array(); + $charset = Horde_Nls::getCharset(); + $formattedname = false; + + /* Name */ + $hash['name'] = Horde_String::convertCharset($message->fileas, 'utf-8', $charset); + $hash['lastname'] = Horde_String::convertCharset($message->lastname, 'utf-8', $charset); + $hash['firstname'] = Horde_String::convertCharset($message->firstname, 'utf-8', $charset); + $hash['middlenames'] = Horde_String::convertCharset($message->middlename, 'utf-8', $charset); + $hash['namePrefix'] = Horde_String::convertCharset($message->title, 'utf-8', $charset); + $hash['nameSuffix'] = Horde_String::convertCharset($message->suffix, 'utf-8', $charset); + + // picture ($message->picture *should* already be base64 encdoed) + $hash['photo'] = base64_decode($message->picture); + + /* Home */ + $hash['homeStreet'] = Horde_String::convertCharset($message->homestreet, 'utf-8', $charset); + $hash['homeCity'] = Horde_String::convertCharset($message->homecity, 'utf-8', $charset); + $hash['homeProvince'] = Horde_String::convertCharset($message->homestate, 'utf-8', $charset); + $hash['homePostalCode'] = $message->homepostalcode; + $hash['homeCountry'] = Horde_String::convertCharset($message->homecountry, 'utf-8', $charset); + + /* Business */ + $hash['workStreet'] = Horde_String::convertCharset($message->businessstreet, 'utf-8', $charset); + $hash['workCity'] = Horde_String::convertCharset($message->businesscity, 'utf-8', $charset); + $hash['workProvince'] = Horde_String::convertCharset($message->businessstate, 'utf-8', $charset); + $hash['workPostalCode'] = $message->businesspostalcode; + $hash['workCountry'] = Horde_String::convertCharset($message->businesscountry, 'utf-8', $charset); + + $hash['homePhone'] = $message->homephonenumber; + $hash['workPhone'] = $message->businessphonenumber; + $hash['fax'] = $message->businessfaxnumber; + $hash['pager'] = $message->pagernumber; + $hash['cellPhone'] = $message->mobilephonenumber; + + /* Email addresses */ + $hash['email'] = Horde_iCalendar_vcard::getBareEmail($message->email1address); + + /* Job title */ + $hash['title'] = Horde_String::convertCharset($message->jobtitle, 'utf-8', $charset); + + $hash['company'] = Horde_String::convertCharset($message->companyname, 'utf-8', $charset); + $hash['department'] = Horde_String::convertCharset($message->department, 'utf-8', $charset); + + /* Categories */ + if (count($message->categories)) { + $hash['category']['value'] = Horde_String::convertCharset(implode(';', $message->categories), 'utf-8', $charset); + $hash['category']['new'] = true; + } + + /* Children */ + // @TODO + + /* Spouse */ + $hash['spouse'] = Horde_String::convertCharset($message->spouse, 'utf-8', $charset); + + /* Notes */ + $hash['notes'] = Horde_String::convertCharset($message->body, 'utf-8', $charset); + + /* webpage */ + $hash['website'] = Horde_String::convertCharset($message->webpage, 'utf-8', $charset); + + /* Birthday and Anniversary */ + if (!empty($message->birthday)) { + $bday = new Horde_Date($message->birthday); + $hash['birthday'] = $bday->format('Y-m-d'); + } else { + $hash['birthday'] = null; + } + if (!empty($message->anniversary)) { + $anniversary = new Horde_Date($message->anniversary); + $hash['anniversary'] = $anniversary->format('Y-m-d'); + } else { + $hash['anniversary'] = null; + } + + /* Assistant */ + $hash['assistant'] = Horde_String::convertCharset($message->assistantname, 'utf-8', $charset); + + return $hash; + } + + /** * Checks if the current user has the requested permissions on this * address book. * diff --git a/turba/lib/tests/ApiTest.php b/turba/lib/tests/ApiTest.php index fecb4cfe7..e08026184 100644 --- a/turba/lib/tests/ApiTest.php +++ b/turba/lib/tests/ApiTest.php @@ -15,7 +15,10 @@ class Turba_ApiTest extends Turba_TestBase { require_once TURBA_BASE . '/lib/api.php'; $this->setUpDatabase(); } - + function testSomething() + { + echo 'fail'; + } function test_search_api_should_return_results() { global $registry;