1<?php 2/* 3 * Gallery - a web based photo album viewer and editor 4 * Copyright (C) 2000-2008 Bharat Mediratta 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or (at 9 * your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, but 12 * WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. 19 */ 20 21/** 22 * This controller will handle the addition of new items in the gallery 23 * @package GalleryCore 24 * @subpackage UserInterface 25 * @author Bharat Mediratta <bharat@menalto.com> 26 * @version $Revision: 17589 $ 27 */ 28class ItemAddController extends GalleryController { 29 /** 30 * ItemAddOption instances to use when handling this request. Only used by test code. 31 * 32 * @var array (optionId => ItemAddOption) $_optionInstances 33 * @access private 34 */ 35 var $_optionInstances; 36 37 /** 38 * Tests can use this method to hardwire a specific set of option instances to use. 39 * This avoids situations where some of the option instances will do unpredictable 40 * things and derail the tests. 41 * 42 * @param array $optionInstances (optionId => ItemAddOption, ...) 43 */ 44 function setOptionInstances($optionInstances) { 45 $this->_optionInstances = $optionInstances; 46 } 47 48 /** 49 * @see GalleryController::handleRequest 50 */ 51 function handleRequest($form) { 52 global $gallery; 53 $templateAdapter =& $gallery->getTemplateAdapter(); 54 55 $addPluginId = GalleryUtilities::getRequestVariables('addPlugin'); 56 57 /** 58 * Special case for backwards-compatibility with the webdav module 59 * @todo Remove on next major API change 60 */ 61 if ($addPluginId == 'ItemAddWebDav') { 62 /* WebDAV used to do a static ::handleRequest() call. We need an instance. */ 63 $controller = new ItemAddController(); 64 } else { 65 $controller = $this; 66 } 67 68 list ($ret, $item) = $controller->getItem(); 69 if ($ret) { 70 return array($ret, null); 71 } 72 $itemId = $item->getId(); 73 74 /* Make sure we have permission to add to this item */ 75 $ret = GalleryCoreApi::assertHasItemPermission($itemId, 'core.addDataItem'); 76 if ($ret) { 77 return array($ret, null); 78 } 79 80 if (!$item->getCanContainChildren()) { 81 return array(GalleryCoreApi::error(ERROR_BAD_PARAMETER), null); 82 } 83 84 /* Load the correct add plugin */ 85 list ($ret, $addPlugin) = 86 GalleryCoreApi::newFactoryInstanceById('ItemAddPlugin', $addPluginId); 87 if ($ret) { 88 return array($ret, null); 89 } 90 91 if (!isset($addPlugin)) { 92 return array(GalleryCoreApi::error(ERROR_BAD_PARAMETER), null); 93 } 94 95 /** 96 * Special case for backwards-compatibility with the webdav module 97 * @todo Remove on next major API change 98 */ 99 if ($addPluginId == 'ItemAddWebDav') { 100 /* Don't output any HTML (progress-bar) */ 101 ob_start(); 102 $ret = $controller->handleRequestWithProgressBar($form, $item, $addPlugin); 103 ob_end_clean(); 104 if ($ret) { 105 return array($ret, null); 106 } 107 108 $session =& $gallery->getSession(); 109 $results['status'] = $session->getStatus(); 110 $results['redirect'] = array('view' => 'core.ItemAdmin', 111 'subView' => 'core.ItemAddConfirmation', 112 'itemId' => $item->getId()); 113 $results['error'] = array(); 114 return array(null, $results); 115 } 116 117 /* Do the actual work in callback of a progress-bar view */ 118 $templateAdapter->registerTrailerCallback( 119 array($this, 'handleRequestWithProgressBar'), 120 array($form, $item, $addPlugin)); 121 122 return array(null, array('delegate' => array('view' => 'core.ProgressBar'), 123 'status' => array(), 'error' => array())); 124 } 125 126 /** 127 * Handles the add item request and is expected to be called as a progress-bar callback. 128 * @param array $form 129 * @param GalleryItem $item The container to which we're adding child-items 130 * @param ItemAddPlugin $addPlugin The plugin that handles this add item request 131 * @return GalleryStatus 132 */ 133 function handleRequestWithProgressBar($form, $item, $addPlugin) { 134 global $gallery; 135 $templateAdapter =& $gallery->getTemplateAdapter(); 136 $urlGenerator =& $gallery->getUrlGenerator(); 137 $phpVm = $gallery->getPhpVm(); 138 $session =& $gallery->getSession(); 139 140 $startTime = $phpVm->time(); 141 /* Auto-redirect if we complete the request within this period. Else show the continueURL */ 142 $autoRedirectSeconds = 15; 143 144 list ($ret, $this->_coreModule) = GalleryCoreApi::loadPlugin('module', 'core'); 145 if ($ret) { 146 return $ret; 147 } 148 $templateAdapter->updateProgressBar($this->_coreModule->translate('Adding items'), '', 0); 149 150 $error = array(); 151 $addPluginId = GalleryUtilities::getRequestVariables('addPlugin'); 152 153 list ($ret, $lockId) = GalleryCoreApi::acquireReadLock($item->getId()); 154 if ($ret) { 155 return $ret; 156 } 157 158 /* Start the add process */ 159 list ($ret, $error, $status) = $addPlugin->handleRequest($form, $item, $this); 160 if ($ret) { 161 GalleryCoreApi::releaseLocks($lockId); 162 return $ret; 163 } 164 165 if (empty($error)) { 166 list ($ret, $error) = $this->postprocessItems($form, $status); 167 if ($ret) { 168 GalleryCoreApi::releaseLocks($lockId); 169 return $ret; 170 } 171 } 172 173 $ret = GalleryCoreApi::releaseLocks($lockId); 174 if ($ret) { 175 return $ret; 176 } 177 178 if (!empty($error)) { 179 /** @todo Should we remove all added items in case of a late form validation error? */ 180 if (!empty($status['addedFiles'])) { 181 $error[] = 'form[error][itemsAddedDespiteFormErrors]'; 182 } 183 $session->put('itemAdd.error', $error); 184 185 $doRedirect = true; 186 $continueUrl = $urlGenerator->generateUrl( 187 array('view' => 'core.ItemAdmin', 'subView' => 'core.ItemAdd', 188 'addPlugin' => $addPluginId, 'itemId' => $item->getId()), 189 array('forceFullUrl' => true)); 190 } else { 191 $session->putStatus($status); 192 $doRedirect = ($phpVm->time() - $startTime) <= $autoRedirectSeconds; 193 194 if (empty($status['addedFiles'])) { 195 /* 196 * Append all form parameters for the next view request. Some plugins submit a 197 * first form to the controller only to forward the request to the view which might 198 * depend on the same form parameters. 199 */ 200 $continueUrl = $urlGenerator->generateUrl( 201 array('view' => 'core.ItemAdmin', 'subView' => 'core.ItemAdd', 202 'addPlugin' => $addPluginId, 'itemId' => $item->getId(), 'form' => $form), 203 array('forceFullUrl' => true)); 204 $templateAdapter->updateProgressBar( 205 $this->_coreModule->translate('Adding items'), '', 1); 206 } else { 207 $continueUrl = $urlGenerator->generateUrl( 208 array('view' => 'core.ItemAdmin', 'subView' => 'core.ItemAddConfirmation', 209 'itemId' => $item->getId()), array('forceFullUrl' => true)); 210 } 211 } 212 213 $templateAdapter->completeProgressBar($continueUrl, $doRedirect); 214 215 return null; 216 } 217 218 /** 219 * Do post-processing which includes extracting archive-items and letting all ItemAddOption 220 * instances handle the added items. 221 * 222 * If called from an ItemAddPlugin, the plugin should stop adding items if $error is non-empty. 223 * 224 * @param array $form 225 * @param array $status An array including the list of all added items 226 * @see ItemAddPlugin::handleRequest() for the structure of the $status array 227 * @return array GalleryStatus 228 * array $error request parameter errors 229 */ 230 function postprocessItems($form, &$status) { 231 global $gallery; 232 $this->_templateAdapter =& $gallery->getTemplateAdapter(); 233 $this->_storage =& $gallery->getStorage(); 234 235 if (!isset($this->_coreModule)) { 236 list ($ret, $this->_coreModule) = GalleryCoreApi::loadPlugin('module', 'core'); 237 if ($ret) { 238 return array($ret, null); 239 } 240 } 241 242 $this->_processingItemsMessage = $this->_coreModule->translate('Processing items'); 243 244 if (!isset($this->_optionInstances)) { 245 list ($ret, $this->_optionInstances) = ItemAddOption::getAllAddOptions(); 246 if ($ret) { 247 return array($ret, null); 248 } 249 } 250 251 if (!isset($this->_extractionToolkitMap)) { 252 list ($ret, $extractToolkits) = 253 GalleryCoreApi::getToolkitOperationMimeTypes('extract'); 254 if ($ret) { 255 return array($ret, null); 256 } 257 $this->_extractionToolkitMap = array(); 258 foreach ($extractToolkits as $mimeType => $toolkitList) { 259 if (!empty($toolkitList)) { 260 list ($ret, $this->_extractionToolkitMap[$mimeType]) = 261 GalleryCoreApi::getToolkitByOperation($mimeType, 'extract'); 262 if ($ret) { 263 return array($ret, null); 264 } 265 } 266 } 267 } 268 269 if (empty($status['addedFiles']) 270 || empty($this->_extractionToolkitMap) && empty($this->_optionInstances)) { 271 /* Nothing to do */ 272 return array(null, array()); 273 } 274 275 $this->_templateAdapter->updateProgressBar($this->_processingItemsMessage, '', 0); 276 277 $ret = $this->_storage->checkPoint(); 278 if ($ret) { 279 return array($ret, null); 280 } 281 $gallery->guaranteeTimeLimit(60); 282 283 if (!isset($this->_processedItems)) { 284 $this->_processedItems = array(); 285 } 286 $errors = array(); 287 288 /* The number of items a ItemAddOption should be able to process in less than 30 seconds */ 289 $batchSize = 20; 290 291 /* Extract all archive-type items and call the ItemAddOption instances for postprocessing */ 292 $itemsToProcess = $itemsToProcessKeyMap = array(); 293 $i = 0; 294 do { 295 $file =& $status['addedFiles'][$i]; 296 if (empty($file['id']) || isset($this->_processedItems[$i])) { 297 /* We couldn't add this file for whatever reason or it has been processed already */ 298 continue; 299 } 300 list ($ret, $addedItem) = GalleryCoreApi::loadEntitiesById($file['id'], 'GalleryItem'); 301 if ($ret) { 302 return array($ret, null); 303 } 304 305 /* Check if we should extract individual files out of an archive */ 306 if (GalleryUtilities::isA($addedItem, 'GalleryDataItem') 307 && isset($this->_extractionToolkitMap[$addedItem->getMimeType()])) { 308 list ($ret, $extractedItems) = $this->_extractAndAddFiles( 309 $addedItem, $this->_extractionToolkitMap[$addedItem->getMimeType()]); 310 if ($ret) { 311 return array($ret, null); 312 } 313 $ret = GalleryCoreApi::deleteEntityById($addedItem->getId(), 'GalleryItem'); 314 if ($ret) { 315 return array($ret, null); 316 } 317 /* 318 * Remove this element from the status and use array_merge to append the extracted 319 * items and to reindex the whole array to fill the gap we just created. 320 */ 321 unset($status['addedFiles'][$i--]); 322 $status['addedFiles'] = array_merge($status['addedFiles'], $extractedItems); 323 324 $gallery->guaranteeTimeLimit(30); 325 $ret = $this->_storage->checkPoint(); 326 if ($ret) { 327 return array($ret, null); 328 } 329 } else { 330 /* This is not an archive, add it to our array of item objects */ 331 $itemsToProcess[] = $addedItem; 332 /* 333 * We can't index $itemsToProcess directly by $i because some options expect it to 334 * be indexed from 0..n without holes. 335 */ 336 $itemsToProcessKeyMap[] = $i; 337 } 338 339 if (count($itemsToProcess) % $batchSize == 0 340 || !isset($status['addedFiles'][$i+1]) && count($itemsToProcess)) { 341 /* Allow ItemAddOptions to process added item(s) */ 342 $optionNumber = 0; 343 foreach ($this->_optionInstances as $option) { 344 $this->_templateAdapter->updateProgressBar( 345 $this->_processingItemsMessage, '', 346 $optionNumber++ / count($this->_optionInstances)); 347 $gallery->guaranteeTimeLimit(60); 348 349 list ($ret, $optionErrors, $optionWarnings) = 350 $option->handleRequestAfterAdd($form, $itemsToProcess); 351 if ($ret) { 352 return array($ret, null); 353 } 354 355 $errors = array_merge($errors, $optionErrors); 356 /* For each item, put the items warnings into our status array */ 357 foreach ($optionWarnings as $j => $messages) { 358 $key = $itemsToProcessKeyMap[$j]; 359 if (!isset($status['addedFiles'][$key]['warnings'])) { 360 $status['addedFiles'][$key]['warnings'] = array(); 361 } 362 $status['addedFiles'][$key]['warnings'] = 363 array_merge($status['addedFiles'][$key]['warnings'], $messages); 364 } 365 366 $ret = $this->_storage->checkPoint(); 367 if ($ret) { 368 return array($ret, null); 369 } 370 } 371 372 foreach ($itemsToProcessKeyMap as $j) { 373 $this->_processedItems[$j] = 1; 374 } 375 $itemsToProcess = $itemsToProcessKeyMap = array(); 376 $gallery->guaranteeTimeLimit(60); 377 $this->_templateAdapter->updateProgressBar($this->_processingItemsMessage, '', 1); 378 } 379 } while (isset($status['addedFiles'][++$i])); 380 381 $this->_templateAdapter->updateProgressBar($this->_processingItemsMessage, '', 1); 382 383 return array(null, $errors); 384 } 385 386 /** 387 * Extract files from an archive item and add new items to the same album. 388 * @param GalleryDataItem $archiveItem archive 389 * @param GalleryToolkit $toolkit toolkit that supports extract operation 390 * @return array GalleryStatus a status code 391 * array of array('fileName' => '..', 'id' => ##, 'warnings' => array of string) 392 * @access private 393 */ 394 function _extractAndAddFiles($archiveItem, $toolkit) { 395 global $gallery; 396 $this->_platform =& $gallery->getPlatform(); 397 398 $this->_extractingArchiveMessage = $this->_coreModule->translate('Extracting archive'); 399 $this->_templateAdapter->updateProgressBar($this->_extractingArchiveMessage, '', 0); 400 $gallery->guaranteeTimeLimit(120); 401 402 $parentId = $archiveItem->getParentId(); 403 list ($ret, $hasAddAlbumPermission) = 404 GalleryCoreApi::hasItemPermission($parentId, 'core.addAlbumItem'); 405 if ($ret) { 406 return array($ret, null); 407 } 408 409 list ($ret, $file) = $archiveItem->fetchPath(); 410 if ($ret) { 411 return array($ret, null); 412 } 413 414 $base = $this->_platform->tempnam($gallery->getConfig('data.gallery.tmp'), 'tmp_'); 415 $tmpDir = $base . '.dir'; 416 if (!$this->_platform->mkdir($tmpDir)) { 417 return array(GalleryCoreApi::error(ERROR_PLATFORM_FAILURE), null); 418 } 419 420 list ($ret) = $toolkit->performOperation($archiveItem->getMimeType(), 'extract', 421 $file, $tmpDir, array()); 422 if ($ret) { 423 @$this->_platform->recursiveRmdir($tmpDir); 424 @$this->_platform->unlink($base); 425 return array($ret, null); 426 } 427 428 /* 429 * If archive title matches the filename or base filename then name new items 430 * with the same strategy; otherwise just use the archive title. 431 */ 432 $archiveTitle = $archiveItem->getTitle(); 433 $archiveName = $archiveItem->getPathComponent(); 434 list ($archiveBase) = GalleryUtilities::getFileNameComponents($archiveName); 435 if ($archiveTitle == $archiveName) { 436 $titleMode = 'file'; 437 } else if ($archiveTitle == $archiveBase) { 438 $titleMode = 'base'; 439 } else { 440 $titleMode = 'archive'; 441 } 442 443 $this->_templateAdapter->updateProgressBar($this->_extractingArchiveMessage, '', 0.1); 444 $gallery->guaranteeTimeLimit(30); 445 446 $addedFiles = array(); 447 $ret = $this->_recursiveAddDir( 448 $tmpDir, $parentId, $addedFiles, $archiveItem, $titleMode, $hasAddAlbumPermission); 449 @$this->_platform->recursiveRmdir($tmpDir); 450 @$this->_platform->unlink($base); 451 if ($ret) { 452 return array($ret, null); 453 } 454 455 $this->_templateAdapter->updateProgressBar($this->_extractingArchiveMessage, '', 1); 456 457 return array(null, $addedFiles); 458 } 459 460 /** 461 * Recursively add files from extracted archive. 462 * @return GalleryStatus a status code 463 * @access private 464 */ 465 function _recursiveAddDir($dir, $parentId, &$addedFiles, &$archiveItem, $titleMode, 466 $canAddAlbums) { 467 global $gallery; 468 469 $list = array(); 470 $dh = $this->_platform->opendir($dir); 471 while (($file = $this->_platform->readdir($dh)) !== false) { 472 if ($file != '.' && $file != '..') { 473 $list[] = $file; 474 } 475 } 476 $this->_platform->closedir($dh); 477 478 foreach ($list as $filename) { 479 $path = "$dir/$filename"; 480 if ($this->_platform->is_dir($path)) { 481 if ($canAddAlbums) { 482 $title = $filename; 483 GalleryUtilities::sanitizeInputValues($title); 484 list ($ret, $album) = GalleryCoreApi::createAlbum( 485 $parentId, $filename, $title, '', '', ''); 486 if ($ret) { 487 return $ret; 488 } 489 list ($ret, $lockId) = GalleryCoreApi::acquireReadLock($album->getId()); 490 if ($ret) { 491 return $ret; 492 } 493 $ret = $this->_recursiveAddDir($path, $album->getId(), $addedFiles, 494 $archiveItem, $titleMode, $canAddAlbums); 495 if ($ret) { 496 GalleryCoreApi::releaseLocks($lockId); 497 return $ret; 498 } 499 $ret = GalleryCoreApi::releaseLocks($lockId); 500 if ($ret) { 501 return $ret; 502 } 503 $newItem =& $album; 504 } else { 505 /* 506 * Flattening folder structure since we're not allowed to create albums. 507 * Adding files but ignoring directories. 508 */ 509 $ret = $this->_recursiveAddDir( 510 $path, $parentId, $addedFiles, $archiveItem, $titleMode, $canAddAlbums); 511 if ($ret) { 512 return $ret; 513 } 514 $newItem = null; 515 } 516 } else { 517 list ($ret, $mimeType) = GalleryCoreApi::getMimeType($filename); 518 if ($ret) { 519 return $ret; 520 } 521 if ($titleMode == 'file') { 522 $title = $filename; 523 GalleryUtilities::sanitizeInputValues($title); 524 } else if ($titleMode == 'base') { 525 list ($title) = GalleryUtilities::getFileNameComponents($filename); 526 GalleryUtilities::sanitizeInputValues($title); 527 } else { 528 $title = $archiveItem->getTitle(); 529 } 530 list ($ret, $newItem) = GalleryCoreApi::addItemToAlbum( 531 $path, $filename, $title, $archiveItem->getSummary(), 532 $archiveItem->getDescription(), $mimeType, $parentId); 533 if ($ret) { 534 return $ret; 535 } 536 } 537 538 if ($newItem) { 539 $sanitizedFilename = $filename; 540 GalleryUtilities::sanitizeInputValues($sanitizedFilename); 541 $addedFiles[] = array('fileName' => $sanitizedFilename, 'id' => $newItem->getId(), 542 'warnings' => array()); 543 } 544 if (count($addedFiles) % 10 == 0) { 545 /* The percentage isn't accurate at all, we just keep the visual feedback going */ 546 $this->_templateAdapter->updateProgressBar($this->_extractingArchiveMessage, '', 547 0.1 + 0.9 * count($addedFiles) / (count($list) + count($addedFiles))); 548 $gallery->guaranteeTimeLimit(30); 549 $ret = $this->_storage->checkPoint(); 550 if ($ret) { 551 return $ret; 552 } 553 } 554 } 555 556 return null; 557 } 558} 559 560/** 561 * This view will show the selected plugin for adding items to the gallery 562 */ 563class ItemAddView extends GalleryView { 564 565 /** 566 * @see GalleryView::loadTemplate 567 */ 568 function loadTemplate(&$template, &$form) { 569 global $gallery; 570 $session =& $gallery->getSession(); 571 572 $addPlugin = GalleryUtilities::getRequestVariables('addPlugin'); 573 574 list ($ret, $item) = $this->getItem(); 575 if ($ret) { 576 return array($ret, null); 577 } 578 $itemId = $item->getId(); 579 580 /* Make sure we have permission to add to this item */ 581 $ret = GalleryCoreApi::assertHasItemPermission($itemId, 'core.addDataItem'); 582 if ($ret) { 583 return array($ret, null); 584 } 585 586 list ($ret, $isAdmin) = GalleryCoreApi::isUserInSiteAdminGroup(); 587 if ($ret) { 588 return array($ret, null); 589 } 590 591 /* Get all the add plugins */ 592 list ($ret, $allPluginIds) = 593 GalleryCoreApi::getAllFactoryImplementationIds('ItemAddPlugin'); 594 if ($ret) { 595 return array($ret, null); 596 } 597 598 $pluginInstances = array(); 599 foreach (array_keys($allPluginIds) as $pluginId) { 600 list ($ret, $plugin) = 601 GalleryCoreApi::newFactoryInstanceById('ItemAddPlugin', $pluginId); 602 if ($ret) { 603 return array($ret, null); 604 } 605 606 list ($ret, $isAppropriate) = $plugin->isAppropriate(); 607 if ($ret) { 608 return array($ret, null); 609 } 610 611 if ($isAppropriate) { 612 $pluginInstances[$pluginId] = $plugin; 613 } 614 } 615 616 /* Get all the add options */ 617 list ($ret, $optionInstances) = ItemAddOption::getAllAddOptions(); 618 if ($ret) { 619 return array($ret, null); 620 } 621 622 /* 623 * If the plugin is empty get it from the session. If it's empty there, 624 * default to the first plugin we find. Either way, save the user's 625 * preference in the session. 626 */ 627 $addPluginSessionKey = 'core.view.ItemAdd.addPlugin.' . get_class($item); 628 if (empty($addPlugin) || !isset($pluginInstances[$addPlugin])) { 629 $addPlugin = $session->get($addPluginSessionKey); 630 if (empty($addPlugin) || !isset($pluginInstances[$addPlugin])) { 631 $ids = array_keys($pluginInstances); 632 $addPlugin = $ids[0]; 633 } 634 } 635 $session->put($addPluginSessionKey, $addPlugin); 636 637 $errors = $session->get('itemAdd.error'); 638 if (!empty($errors)) { 639 $session->remove('itemAdd.error'); 640 /* Same logic as in main.php */ 641 foreach ($errors as $error) { 642 GalleryUtilities::putRequestVariable($error, 1); 643 } 644 } 645 646 /* Get display data for all plugins */ 647 $plugins = array(); 648 foreach ($pluginInstances as $pluginId => $plugin) { 649 list ($ret, $title) = $plugin->getTitle(); 650 if ($ret) { 651 return array($ret, null); 652 } 653 $plugins[] = array('title' => $title, 654 'id' => $pluginId, 655 'isSelected' => ($pluginId == $addPlugin)); 656 } 657 658 $ItemAdd = array(); 659 $ItemAdd['addPlugin'] = $addPlugin; 660 $ItemAdd['plugins'] = $plugins; 661 $ItemAdd['isAdmin'] = $isAdmin; 662 663 /* Let the plugin load its template data */ 664 list ($ret, $ItemAdd['pluginFile'], $ItemAdd['pluginL10Domain']) = 665 $pluginInstances[$addPlugin]->loadTemplate($template, $form, $item); 666 if ($ret) { 667 return array($ret, null); 668 } 669 670 /* Now let all options load their template data */ 671 $ItemAdd['options'] = array(); 672 foreach ($optionInstances as $option) { 673 list ($ret, $entry['file'], $entry['l10Domain']) = 674 $option->loadTemplate($template, $form, $item); 675 if ($ret) { 676 return array($ret, null); 677 } 678 if (!empty($entry['file'])) { 679 $ItemAdd['options'][] = $entry; 680 } 681 } 682 683 /* Make sure that we've got some toolkits */ 684 list ($ret, $operations) = GalleryCoreApi::getToolkitOperations('image/jpeg'); 685 if ($ret) { 686 return array($ret, null); 687 } 688 689 $ItemAdd['hasToolkit'] = false; 690 for ($i = 0; $i < sizeof($operations); $i++) { 691 if ($operations[$i]['name'] == 'thumbnail') { 692 $ItemAdd['hasToolkit'] = true; 693 break; 694 } 695 } 696 697 $template->setVariable('ItemAdd', $ItemAdd); 698 $template->setVariable('controller', 'core.ItemAdd'); 699 return array(null, 700 array('body' => 'modules/core/templates/ItemAdd.tpl')); 701 } 702 703 /** 704 * @see GalleryView::getViewDescription 705 */ 706 function getViewDescription() { 707 list ($ret, $core) = GalleryCoreApi::loadPlugin('module', 'core'); 708 if ($ret) { 709 return array($ret, null); 710 } 711 return array(null, $core->translate('add items')); 712 } 713} 714 715 716/** 717 * Interface for plugins to the ItemAdd view and controller. 718 * Plugins provide alternate ways to add items into Gallery. 719 * @abstract 720 */ 721class ItemAddPlugin { 722 723 /** 724 * Load the template with data from this plugin 725 * @see GalleryView::loadTemplate 726 * 727 * @param GalleryTemplate $template 728 * @param array $form the form values 729 * @param GalleryItem $item 730 * @return array GalleryStatus a status code 731 * string the path to a template file to include 732 * string localization domain for the template file 733 */ 734 function loadTemplate(&$template, &$form, $item) { 735 return array(GalleryCoreApi::error(ERROR_UNIMPLEMENTED), null, null); 736 } 737 738 /** 739 * Let the plugin handle the incoming request 740 * @see GalleryController::handleRequest 741 * 742 * @param array $form the form values 743 * @param GalleryItem $item 744 * @param GalleryItemAddController $addController A reference to the ItemAddController 745 * to be used for the post-processing calls. 746 * @return array GalleryStatus a status code 747 * array error messages (request parameter errors). Stop processing on errors. 748 * array status data, 'addedFiles' entry should contain: 749 * array(array('fileName' => '...', 'id' => ##, 750 * 'warnings' => array of strings), ...) 751 */ 752 function handleRequest($form, &$item, &$addController) { 753 return array(GalleryCoreApi::error(ERROR_UNIMPLEMENTED), null, null); 754 } 755 756 /** 757 * Return a localized title for this plugin, suitable for display to the user 758 * 759 * @return array GalleryStatus a status code 760 * return-array (same as GalleryController::handleRequest) 761 */ 762 function getTitle() { 763 return array(GalleryCoreApi::error(ERROR_UNIMPLEMENTED), null); 764 } 765 766 /** 767 * Is this plugin appropriate at this time? Default is true. 768 * 769 * @return array GalleryStatus a status code 770 * boolean true or false 771 */ 772 function isAppropriate() { 773 return array(null, true); 774 } 775} 776 777/** 778 * Interface for options to the ItemAdd view and controller. 779 * Options allow us to provide extra UI in the views and extra processing in the controller so 780 * that we can add new functionality like watermarking, quotas, etc to every ItemAddPlugin 781 * @abstract 782 */ 783class ItemAddOption { 784 785 /** 786 * Return all the available option plugins 787 * 788 * @return array GalleryStatus a status code 789 * array ItemAddOption instances 790 * @static 791 */ 792 function getAllAddOptions() { 793 /* Get all the option plugins */ 794 list ($ret, $allOptionIds) = 795 GalleryCoreApi::getAllFactoryImplementationIds('ItemAddOption'); 796 if ($ret) { 797 return array($ret, null); 798 } 799 800 $optionInstances = array(); 801 foreach (array_keys($allOptionIds) as $optionId) { 802 list ($ret, $option) = 803 GalleryCoreApi::newFactoryInstanceById('ItemAddOption', $optionId); 804 if ($ret) { 805 return array($ret, null); 806 } 807 808 list ($ret, $isAppropriate) = $option->isAppropriate(); 809 if ($ret) { 810 return array($ret, null); 811 } 812 813 if ($isAppropriate) { 814 $optionInstances[$optionId] = $option; 815 } 816 } 817 818 return array(null, $optionInstances); 819 } 820 821 /** 822 * Load the template with data from this plugin 823 * @see GalleryView::loadTemplate 824 * 825 * @param GalleryTemplate $template 826 * @param array $form the form values 827 * @param GalleryItem $item 828 * @return array GalleryStatus a status code 829 * string the path to a template file to include 830 * string localization domain for the template file 831 */ 832 function loadTemplate(&$template, &$form, $item) { 833 return array(null, null, null); 834 } 835 836 /** 837 * Let the plugin handle the incoming request. We expect the $items to be locked. 838 * @see GalleryController::handleRequest 839 * 840 * @param array $form the form values 841 * @param array $items GalleryDataItems 842 * @return array GalleryStatus a status code 843 * array localized error messages. Attempt to continue processing on errors since 844 * the items have already been added and post-processing will continue. 845 * array localized warning messages 846 */ 847 function handleRequestAfterAdd($form, $items) { 848 return array(GalleryCoreApi::error(ERROR_UNIMPLEMENTED), null, null); 849 } 850 851 /** 852 * Is this option appropriate at this time? 853 * 854 * @return array GalleryStatus a status code 855 * boolean true or false 856 */ 857 function isAppropriate() { 858 return array(null, false); 859 } 860} 861?> 862