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