1<?php
2/**
3 * The Turba_View_Browse class provides the logic for browsing lists
4 * of contacts.
5 *
6 * Copyright 2000-2017 Horde LLC (http://www.horde.org/)
7 *
8 * See the enclosed file LICENSE for license information (ASL).  If you did
9 * did not receive this file, see http://www.horde.org/licenses/apache.
10 *
11 * @author  Chuck Hagenbuch <chuck@horde.org>
12 * @package Turba
13 */
14class Turba_View_Browse
15{
16    /**
17     * @var array
18     */
19     protected $_params;
20
21    /**
22     * Constructor;
23     *
24     * @param array $params Stuff to import into the view's scope.
25     */
26    public function __construct(array $params)
27    {
28        $this->_params = $params;
29    }
30
31    public function updateSortOrderFromVars()
32    {
33        extract($this->_params, EXTR_REFS);
34        Turba::setPreferredSortOrder($vars, $source);
35    }
36
37    public function run()
38    {
39        extract($this->_params, EXTR_REFS);
40
41        $this->updateSortOrderFromVars();
42        $title = _("Address Book Listing");
43        if (!$browse_source_count && $vars->get('key') != '**search') {
44            $notification->push(_("There are no browseable address books."), 'horde.warning');
45        } else {
46            try {
47                $driver = $factory->create($source);
48            } catch (Turba_Exception $e) {
49                $notification->push($e, 'horde.error');
50                unset($driver);
51            }
52        }
53
54        if (isset($driver)) {
55            $actionID = $vars->get('actionID');
56            switch ($actionID) {
57            case 'delete':
58                $keys = $vars->get('objectkeys');
59                if (!is_array($keys)) {
60                    break;
61                }
62
63                $key = false;
64                if ($vars->exists('key')) {
65                    $key = $vars->get('key');
66                }
67                if ($key && $key != '**search') {
68                    // We are removing a contact from a list.
69                    $errorCount = 0;
70                    $list = $driver->getObject($key);
71                    foreach ($keys as $sourceKey) {
72                        list($objectSource, $objectKey) = explode(':', $sourceKey, 2);
73                        if (!$list->removeMember($objectKey, $objectSource)) {
74                            $errorCount++;
75                        }
76                    }
77                    if (!$errorCount) {
78                        $notification->push(
79                            sprintf(_("Successfully removed %d contact(s) from list."),
80                                count($keys)),
81                            'horde.success');
82                    } elseif (count($keys) == $errorCount) {
83                        $notification->push(
84                            sprintf(_("Error removing %d contact(s) from list."),
85                                 count($keys)),
86                            'horde.error');
87                    } else {
88                        $notification->push(
89                            sprintf(_("Error removing %d of %d requested contact(s) from list."),
90                                $errorCount,
91                                count($keys)),
92                            'horde.error');
93                    }
94                    $list->store();
95                } else {
96                    // We are deleting an object.
97                    $errorCount = 0;
98                    foreach ($keys as $sourceKey) {
99                        list($objectSource, $objectKey) = explode(':', $sourceKey, 2);
100                        try {
101                            $driver->delete($objectKey);
102                        } catch (Turba_Exception $e) {
103                            ++$errorCount;
104                        }
105                    }
106                    if (!$errorCount) {
107                        $notification->push(
108                            sprintf(ngettext("Successfully deleted %d contact.", "Successfully deleted %d contacts.", count($keys)),
109                                count($keys)),
110                            'horde.success');
111                    } elseif (count($keys) == $errorCount) {
112                        $notification->push(
113                            sprintf(ngettext("Error deleting %d contact.", "Error deleting %d contacts.", count($keys)),
114                                count($keys)),
115                            'horde.error');
116                    } else {
117                        $notification->push(
118                            sprintf(ngettext("Error deleting %d of %d requested contact.", "Error deleting %d of %d requested contacts.", count($keys)),
119                                $errorCount,
120                                count($keys)),
121                            'horde.error');
122                    }
123                }
124                break;
125
126            case 'move':
127            case 'copy':
128                $keys = $vars->get('objectkeys');
129                if (!(is_array($keys) && $keys)) {
130                    break;
131                }
132
133                // If we have data, try loading the target address book driver.
134                $targetSource = $vars->get('targetAddressbook');
135
136                try {
137                    $targetDriver = $factory->create($targetSource);
138                } catch (Turba_Exception $e) {
139                    $notification->push($e, 'horde.error');
140                    break;
141                }
142
143                $max_contacts = Turba::getExtendedPermission($targetDriver, 'max_contacts');
144                if ($max_contacts !== true &&
145                    $max_contacts <= count($targetDriver)) {
146                    Horde::permissionDeniedError(
147                        'turba',
148                        'max_contacts',
149                        sprintf(_("You are not allowed to create more than %d contacts in \"%s\"."), $max_contacts, $cfgSources[$targetSource]['title'])
150                    );
151                    break;
152                }
153
154                foreach ($keys as $sourceKey) {
155                    // Split up the key into source and object ids.
156                    list($objectSource, $objectKey) = explode(':', $sourceKey, 2);
157
158                    // Ignore this entry if the target is the same as the
159                    // source.
160                    if ($objectSource == $targetDriver->getName()) {
161                        continue;
162                    }
163
164                    // Try and load the driver for the source.
165                    try {
166                        $sourceDriver = $factory->create($objectSource);
167                    } catch (Turba_Exception $e) {
168                        $notification->push($e, 'horde.error');
169                        continue;
170                    }
171
172                    try {
173                        $object = $sourceDriver->getObject($objectKey);
174                    } catch (Horde_Exception_NotFound $e) {
175                        $notification->push(
176                            _("Failed to find object to be added"),
177                            'horde.error'
178                        );
179                        continue;
180                    }
181
182                    if ($object->isGroup()) {
183                        if ($actionID == 'move') {
184                            $notification->push(
185                                sprintf(_("\"%s\" was not moved because it is a list."),
186                                    $object->getValue('name')),
187                                'horde.warning');
188                        } else {
189                            $notification->push(
190                                sprintf(_("\"%s\" was not copied because it is a list."),
191                                    $object->getValue('name')),
192                                'horde.warning');
193                        }
194                        continue;
195                    }
196
197                    // Try adding to the target.
198                    $objAttributes = array();
199
200                    // Get the values through the Turba_Object class.
201                    foreach (array_keys($targetDriver->getCriteria()) as $info_key) {
202                        if (!is_array($targetDriver->map[$info_key]) ||
203                            isset($targetDriver->map[$info_key]['attribute'])) {
204                            $objectValue = $object->getValue($info_key);
205
206                            // Get 'data' value if object type is image, the
207                            // direct value in other case.
208                            $objAttributes[$info_key] =
209                                isset($attributes[$info_key]) &&
210                                    $attributes[$info_key]['type'] == 'image'
211                                    ? $objectValue['load']['data']
212                                    : $objectValue;
213                        }
214                    }
215                    unset($objAttributes['__owner']);
216                    if ($actionID == 'copy') {
217                        unset($objAttributes['__uid']);
218                    }
219                    // Try adding tags.
220                    $objAttributes['__tags'] = $object->getValue('__tags');
221
222                    try {
223                        $targetDriver->add($objAttributes);
224                    } catch (Turba_Exception $e) {
225                        $notification->push(
226                            sprintf(_("Failed to add %s to %s: %s"),
227                                $object->getValue('name'),
228                                $targetDriver->title,
229                                $e),
230                            'horde.error');
231                        break;
232                    }
233
234                    $notification->push(
235                        sprintf(_("Successfully added %s to %s"),
236                            $object->getValue('name'),
237                            $targetDriver->title),
238                        'horde.success');
239
240                    // If we're moving objects, and we succeeded,
241                    // delete them from the original source now.
242                    if ($actionID == 'move') {
243                        try {
244                            $sourceDriver->delete($objectKey, false);
245                        } catch (Turba_Exception $e) {
246                            $notification->push(
247                                sprintf(_("There was an error deleting \"%s\" from the source address book."),
248                                    $object->getValue('name')),
249                                'horde.error');
250                        }
251
252                        /* Log the adding of this item in the history again,
253                         * because otherwise the delete log would be after the
254                         * add log. */
255                        try {
256                            $history->log('turba:' . $targetDriver->getName() . ':' . $objAttributes['__uid'],
257                                      array('action' => 'add'),
258                                      true);
259                        } catch (Exception $e) {
260                            Horde::log($e, 'ERR');
261                        }
262                    }
263                }
264                break;
265
266            case 'add':
267                // Add a contact to a list.
268                $keys = $vars->get('objectkeys');
269                $targetKey = $vars->get('targetList');
270                if (empty($targetKey)) {
271                    break;
272                }
273
274                if (!$vars->exists('targetNew') || $vars->get('targetNew') == '') {
275                    list($targetSource, $targetKey) = explode(':', $targetKey, 2);
276                    if (!isset($cfgSources[$targetSource])) {
277                        break;
278                    }
279
280                    try {
281                        $targetDriver = $factory->create($targetSource);
282                    } catch (Turba_Exception $e) {
283                        $notification->push($e, 'horde.error');
284                        break;
285                    }
286
287                    try {
288                        $target = $targetDriver->getObject($targetKey);
289                    } catch (Horde_Exception $e) {
290                        $notification->push($e);
291                        break;
292                    }
293                } else {
294                    $targetSource = $vars->get('targetAddressbook');
295                    try {
296                        $targetDriver = $factory->create($targetSource);
297                    } catch (Turba_Exception $e) {
298                        $notification->push($e, 'horde.error');
299                        break;
300                    }
301                }
302                if (!empty($target) && $target->isGroup()) {
303                    // Adding contact to an existing list.
304                    if (is_array($keys)) {
305                        $errorCount = 0;
306                        foreach ($keys as $sourceKey) {
307                            list($objectSource, $objectKey) = explode(':', $sourceKey, 2);
308                            try {
309                                $target->addMember($objectKey, $objectSource);
310                            } catch (Turba_Exception $e) {
311                                $notification->push($e, 'horde.error');
312                                $errorCount++;
313                            }
314                        }
315                        if (!$errorCount) {
316                            $notification->push(
317                                sprintf(_("Successfully added %d contact(s) to list."),
318                                    count($keys)),
319                                'horde.success');
320                        } elseif ($errorCount == count($keys)) {
321                            $notification->push(
322                                sprintf(_("Error adding %d contact(s) to list."),
323                                    count($keys)),
324                                'horde.error');
325                        } else {
326                            $notification->push(
327                                sprintf(_("Error adding %d of %d requested contact(s) to list."),
328                                    $errorCount,
329                                    count($keys)),
330                                'horde.error');
331                        }
332                        $target->store();
333                    }
334                } else {
335                    // Check permissions.
336                    $max_contacts = Turba::getExtendedPermission($driver, 'max_contacts');
337                    if ($max_contacts !== true &&
338                        $max_contacts <= count($driver)) {
339                        Horde::permissionDeniedError(
340                            'turba',
341                            'max_contacts',
342                            sprintf(_("You are not allowed to create more than %d contacts in \"%s\"."),
343                                $max_contacts,
344                                $cfgSources[$source]['title'])
345                        );
346                        break;
347                    }
348
349                    // Adding contact to a new list.
350                    $newList = array(
351                        '__owner' => $targetDriver->getContactOwner(),
352                        '__type' => 'Group',
353                        'name' => $targetKey
354                    );
355
356                    try {
357                        $targetKey = $targetDriver->add($newList);
358                    } catch (Turba_Exception $e) {
359                        $notification->push(_("There was an error creating a new list."), 'horde.error');
360                        $targetKey = null;
361                    }
362
363                    if ($targetKey) {
364                        try {
365                            $target = $targetDriver->getObject($targetKey);
366                            if ($target->isGroup()) {
367                                $notification->push(
368                                    sprintf(_("Successfully created the contact list \"%s\"."),
369                                        $newList['name']),
370                                    'horde.success');
371                                if (is_array($keys)) {
372                                    $errorCount = 0;
373                                    foreach ($keys as $sourceKey) {
374                                        list($objectSource, $objectKey) = explode(':', $sourceKey, 2);
375                                        try {
376                                            $target->addMember($objectKey, $objectSource);
377                                        } catch (Turba_Exception $e) {
378                                            $notification->push($e, 'horde.error');
379                                            ++$errorCount;
380                                        }
381                                    }
382                                    if (!$errorCount) {
383                                        $notification->push(
384                                            sprintf(_("Successfully added %d contact(s) to list."),
385                                                count($keys)),
386                                            'horde.success');
387                                    } elseif ($errorCount == count($keys)) {
388                                        $notification->push(
389                                            sprintf(_("Error adding %d contact(s) to list."),
390                                                count($keys)),
391                                            'horde.error');
392                                    } else {
393                                        $notification->push(
394                                            sprintf(_("Error adding %d of %d requested contact(s) to list."),
395                                                $errorCount,
396                                                count($keys)),
397                                            'horde.error');
398                                    }
399                                    $target->store();
400                                }
401                            }
402                        } catch (Turba_Exception $e) {}
403                    }
404                }
405                break;
406            }
407
408            // We might get here from the search page but are not allowed to browse
409            // the current address book.
410            if ($actionID && empty($cfgSources[$source]['browse'])) {
411                Horde::url($prefs->getValue('initial_page'), true)
412                    ->redirect();
413            }
414        }
415
416        $templates = array();
417        if (isset($driver)) {
418            Turba::addBrowseJs();
419
420            // Read the columns to display from the preferences.
421            $sources = Turba::getColumns();
422            $columns = isset($sources[$source]) ? $sources[$source] : array();
423            $sortorder = Turba::getPreferredSortOrder();
424
425            if ($vars->get('key')) {
426                // We are displaying a list.
427                try {
428                    $list = $driver->getObject($vars->get('key'));
429                } catch (Horde_Exception $e) {
430                    $notification->push(_("There was an error displaying the list"), 'horde.error');
431                    $list = null;
432                }
433
434                if ($list && $list->isGroup()) {
435                    $title = sprintf(_("Contacts in list: %s"),
436                                     $list->getValue('name'));
437                    $templates[] = '/browse/header.inc';
438
439                    // Show List Members.
440                    try {
441                        $results = $list->listMembers($sortorder);
442                        if (count($results) != $list->count()) {
443                            $count = $list->count() - count($results);
444                            $notification->push(
445                                sprintf(ngettext("There is %d contact in this list that is not viewable to you",
446                                                 "There are %d contacts in this list that are not viewable to you", $count),
447                                $count),
448                            'horde.message');
449                        }
450                        $view = new Turba_View_List($results, null, $columns);
451                        $view->setType('list');
452                    } catch (Turba_Exception $e) {
453                        $notification->push(_("Failed to browse list"), 'horde.error');
454                    }
455                }
456            } else {
457                // We are displaying an address book.
458                $title = $cfgSources[$source]['title'];
459                $templates[] = '/browse/header.inc';
460                if (empty($cfgSources[$source]['browse'])) {
461                    $notification->push(_("Your default address book is not browseable."), 'horde.warning');
462                } else {
463                    $type_filter = array();
464                    switch ($vars->get('show')) {
465                    case 'contacts':
466                        $type_filter = array('__type' => 'Object');
467                        break;
468
469                    case 'lists':
470                        $type_filter = array('__type' => 'Group');
471                        break;
472                    }
473
474                    try {
475                        $results = $driver->search($type_filter, $sortorder, 'AND', array_merge(array('__uid'), $columns ? $columns : array('name')));
476                        $view = new Turba_View_List($results, null, $columns);
477                        $view->setType('directory');
478                    } catch (Turba_Exception $e) {
479                        $notification->push($e, 'horde.error');
480                    }
481                }
482            }
483        } else {
484            $templates[] = '/browse/header.inc';
485        }
486
487        $page_output->addScriptFile('quickfinder.js', 'horde');
488        $page_output->addScriptFile('scriptaculous/effects.js', 'horde');
489        $page_output->addScriptFile('redbox.js', 'horde');
490        $page_output->header(array(
491            'title' => $title
492        ));
493        $notification->notify(array('listeners' => 'status'));
494        foreach ($templates as $template) {
495            require TURBA_TEMPLATES . $template;
496        }
497
498        if (isset($view) && is_object($view)) {
499            $view->display();
500        }
501
502        $page_output->footer();
503    }
504
505}
506