0008006: token mode removes contact image
[tine20] / tine20 / Addressbook / Frontend / Json.php
1 <?php
2 /**
3  * Tine 2.0
4  *
5  * @package     Addressbook
6  * @subpackage  Frontend
7  * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
8  * @author      Lars Kneschke <l.kneschke@metaways.de>
9  * @copyright   Copyright (c) 2007-2012 Metaways Infosystems GmbH (http://www.metaways.de)
10  */
11
12 /**
13  * Addressbook_Frontend_Json
14  *
15  * This class handles all Json requests for the addressbook application
16  *
17  * @package     Addressbook
18  * @subpackage  Frontend
19  */
20 class Addressbook_Frontend_Json extends Tinebase_Frontend_Json_Abstract
21 {
22     /**
23      * app name
24      * 
25      * @var string
26      */
27     protected $_applicationName = 'Addressbook';
28     
29     /**
30      * resolve images
31      * @param Tinebase_Record_RecordSet $_records
32      */
33     public static function resolveImages(Tinebase_Record_RecordSet $_records)
34     {
35         foreach($_records as &$record) {
36             if($record['jpegphoto'] == '1') {
37                 $record['jpegphoto'] = Tinebase_Model_Image::getImageUrl('Addressbook', $record->__get('id'), '');
38             }
39         }
40     }
41
42     /**
43      * get one contact identified by $id
44      *
45      * @param string $id
46      * @return array
47      */
48     public function getContact($id)
49     {
50         return $this->_get($id, Addressbook_Controller_Contact::getInstance());
51     }
52     
53     /**
54      * Search for contacts matching given arguments
55      *
56      * @param  array $filter
57      * @param  array $paging
58      * @return array
59      */
60     public function searchContacts($filter, $paging)
61     {
62         return $this->_search($filter, $paging, Addressbook_Controller_Contact::getInstance(), 'Addressbook_Model_ContactFilter');
63     }    
64     
65     /**
66      * return autocomplete suggestions for a given property and value
67      * 
68      * @todo have spechial controller/backend fns for this
69      * @todo move to abstract json class and have tests
70      *
71      * @param  string   $property
72      * @param  string   $startswith
73      * @return array
74      */
75     public function autoCompleteContactProperty($property, $startswith)
76     {
77         if (preg_match('/[^A-Za-z0-9_]/', $property)) {
78             // NOTE: it would be better to ask the model for property presece, but we can't atm.
79             throw new Tasks_Exception_UnexpectedValue('bad property name');
80         }
81         
82         $filter = new Addressbook_Model_ContactFilter(array(
83             array('field' => $property, 'operator' => 'startswith', 'value' => $startswith),
84         ));
85         
86         $paging = new Tinebase_Model_Pagination(array('sort' => $property));
87         
88         $values = array_unique(Addressbook_Controller_Contact::getInstance()->search($filter, $paging)->{$property});
89         
90         $result = array(
91             'results'   => array(),
92             'totalcount' => count($values)
93         );
94         
95         foreach($values as $value) {
96             $result['results'][] = array($property => $value);
97         }
98         
99         return $result;
100     }
101     
102     /**
103      * Search for lists matching given arguments
104      *
105      * @param  array $filter
106      * @param  array $paging
107      * @return array
108      */
109     public function searchLists($filter, $paging)
110     {
111         return $this->_search($filter, $paging, Addressbook_Controller_List::getInstance(), 'Addressbook_Model_ListFilter');
112     }    
113
114     /**
115      * delete multiple contacts
116      *
117      * @param array $ids list of contactId's to delete
118      * @return array
119      */
120     public function deleteContacts($ids)
121     {
122         return $this->_delete($ids, Addressbook_Controller_Contact::getInstance());
123     }
124     
125     /**
126      * save one contact
127      *
128      * if $recordData['id'] is empty the contact gets added, otherwise it gets updated
129      *
130      * @param  array $recordData an array of contact properties
131      * @param  boolean $duplicateCheck
132      * @return array
133      */
134     public function saveContact($recordData, $duplicateCheck = TRUE)
135     {
136         return $this->_save($recordData, Addressbook_Controller_Contact::getInstance(), 'Contact', 'id', array($duplicateCheck));
137     }
138     
139     /**
140      * import contacts
141      * 
142      * @param string $tempFileId to import
143      * @param string $definitionId
144      * @param array $importOptions
145      * @param array $clientRecordData
146      * @return array
147      */
148     public function importContacts($tempFileId, $definitionId, $importOptions, $clientRecordData = array())
149     {
150         return $this->_import($tempFileId, $definitionId, $importOptions, $clientRecordData);
151     }
152     
153     /**
154     * get contact information from string by parsing it using predefined rules
155     *
156     * @param string $address
157     * @return array
158     */
159     public function parseAddressData($address)
160     {
161         $result = Addressbook_Controller_Contact::getInstance()->parseAddressData($address);
162         $contactData = $this->_recordToJson($result['contact']);
163         
164         unset($contactData['jpegphoto']);
165         unset($contactData['salutation']);
166         
167         return array(
168             'contact'             => $contactData,
169             'unrecognizedTokens'  => $result['unrecognizedTokens'],
170         );
171     }
172     
173     /**
174      * get default addressbook
175      * 
176      * @return array
177      */
178     public function getDefaultAddressbook()
179     {
180         $defaultAddressbook = Addressbook_Controller_Contact::getInstance()->getDefaultAddressbook();
181         $defaultAddressbookArray = $defaultAddressbook->toArray();
182         $defaultAddressbookArray['account_grants'] = Tinebase_Container::getInstance()->getGrantsOfAccount(Tinebase_Core::getUser(), $defaultAddressbook->getId())->toArray();
183         
184         return $defaultAddressbookArray;
185     }
186     
187     /**
188     * returns contact prepared for json transport
189     *
190     * @param Addressbook_Model_Contact $_contact
191     * @return array contact data
192     */
193     protected function _recordToJson($_contact)
194     {
195         $result = parent::_recordToJson($_contact);
196         $result['jpegphoto'] = $this->_getImageLink($result);
197     
198         return $result;
199     }
200     
201     /**
202      * returns multiple records prepared for json transport
203      *
204      * @param Tinebase_Record_RecordSet $_records Tinebase_Record_Abstract
205      * @param Tinebase_Model_Filter_FilterGroup
206      * @param Tinebase_Model_Pagination $_pagination
207      * @return array data
208      */
209     protected function _multipleRecordsToJson(Tinebase_Record_RecordSet $_records, $_filter = NULL, $_pagination = NULL)
210     {
211         $result = parent::_multipleRecordsToJson($_records, $_filter, $_pagination);
212         
213         foreach ($result as &$contact) {
214             $contact['jpegphoto'] = $this->_getImageLink($contact);
215         }
216         
217         return $result;
218     }
219
220     /**
221      * returns a image link
222      * 
223      * @param  array $contactArray
224      * @return string
225      */
226     protected function _getImageLink($contactArray)
227     {
228         $link = 'images/empty_photo_blank.png';
229         if (! empty($contactArray['jpegphoto'])) {
230             $link = Tinebase_Model_Image::getImageUrl('Addressbook', $contactArray['id'], '');
231         } else if (isset($contactArray['salutation']) && ! empty($contactArray['salutation'])) {
232             $salutations = Addressbook_Config::getInstance()->get(Addressbook_Config::CONTACT_SALUTATION, NULL);
233             if ($salutations && $salutations->records instanceof Tinebase_Record_RecordSet) {
234                 $salutationRecord = $salutations->records->getById($contactArray['salutation']);
235                 if ($salutationRecord && $salutationRecord->image) {
236                     $link = $salutationRecord->image;
237                 }
238             }
239         }
240         
241         return $link;
242     }
243
244     /**
245      * Returns registry data of addressbook.
246      * @see Tinebase_Application_Json_Abstract
247      * 
248      * @return mixed array 'variable name' => 'data'
249      */
250     public function getRegistryData()
251     {
252         $definitionConverter = new Tinebase_Convert_ImportExportDefinition_Json();
253         $importDefinitions = $this->_getImportDefinitions();
254         $defaultDefinition = $this->_getDefaultImportDefinition($importDefinitions);
255         
256         $registryData = array(
257             'defaultAddressbook'        => $this->getDefaultAddressbook(),
258             'defaultImportDefinition'   => $definitionConverter->fromTine20Model($defaultDefinition),
259             'importDefinitions'         => array(
260                 'results'               => $definitionConverter->fromTine20RecordSet($importDefinitions),
261                 'totalcount'            => count($importDefinitions),
262             ),
263         );
264         return $registryData;
265     }
266     
267     /**
268      * get addressbook import definitions
269      * 
270      * @return Tinebase_Record_RecordSet
271      * 
272      * @todo generalize this
273      */
274     protected function _getImportDefinitions()
275     {
276         $filter = new Tinebase_Model_ImportExportDefinitionFilter(array(
277             array('field' => 'application_id',  'operator' => 'equals', 'value' => Tinebase_Application::getInstance()->getApplicationByName('Addressbook')->getId()),
278             array('field' => 'type',            'operator' => 'equals', 'value' => 'import'),
279         ));
280         
281         $importDefinitions = Tinebase_ImportExportDefinition::getInstance()->search($filter);
282         
283         return $importDefinitions;
284     }
285     
286     /**
287      * get default definition
288      * 
289      * @param Tinebase_Record_RecordSet $_importDefinitions
290      * @return Tinebase_Model_ImportExportDefinition
291      * 
292      * @todo generalize this
293      */
294     protected function _getDefaultImportDefinition($_importDefinitions)
295     {
296         try {
297             $defaultDefinition = Tinebase_ImportExportDefinition::getInstance()->getByName('adb_tine_import_csv');
298         } catch (Tinebase_Exception_NotFound $tenf) {
299             if (count($_importDefinitions) > 0) {
300                 $defaultDefinition = $_importDefinitions->getFirstRecord();
301             } else {
302                 Tinebase_Core::getLogger()->warn(__METHOD__ . '::' . __LINE__ . ' No import definitions found for Addressbook');
303                 $defaultDefinition = NULL;
304             }
305         }
306         
307         return $defaultDefinition;
308     }
309 }