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 * Plugin for editing data common to all items
23 * @package GalleryCore
24 * @subpackage UserInterface
25 * @author Bharat Mediratta <bharat@menalto.com>
26 * @version $Revision: 17580 $
27 */
28class ItemEditItem extends ItemEditPlugin {
29
30    /**
31     * @see ItemEditPlugin::handleRequest
32     */
33    function handleRequest($form, &$item, &$preferred) {
34	global $gallery;
35
36	$status = null;
37	$error = array();
38	if (isset($form['action']['undo'])) {
39	    /*
40	     * Take no action and we'll be redirected back to the same page which will
41	     * reset the form.
42	     */
43	} else if (isset($form['action']['save'])) {
44	    list ($ret, $rootAlbumId) =
45		GalleryCoreApi::getPluginParameter('module', 'core', 'id.rootAlbum');
46	    if ($ret) {
47		return array($ret, null, null, null);
48	    }
49
50	    $isRootAlbum = $item->getId() == $rootAlbumId;
51
52	    /* Validate the input data. */
53	    $platform =& $gallery->getPlatform();
54
55	    foreach (array('title', 'summary', 'keywords', 'description') as $key) {
56		if (!empty($form[$key]) && is_string($form[$key])) {
57		    $form[$key] = trim($form[$key]);
58		} else {
59		    $form[$key] = null;
60		}
61	    }
62
63	    if (!$isRootAlbum) {
64		if (empty($form['pathComponent']) || !is_string($form['pathComponent'])) {
65		    $error[] = 'form[error][pathComponent][missing]';
66		    $form['pathComponent'] = '';
67		} else if (!$platform->isLegalPathComponent($form['pathComponent'])) {
68		    $error[] = 'form[error][pathComponent][invalid]';
69		}
70	    }
71
72	    if ($isRootAlbum) {
73		if (empty($form['title'])) {
74		    $error[] = 'form[error][title][missingRootTitle]';
75		}
76	    }
77
78	    if (!empty($form['originationTimestampSplit'])) {
79		$newOriginationTimestamp = mktime($form['originationTimestampSplit']['Time_Hour'],
80						  $form['originationTimestampSplit']['Time_Minute'],
81						  $form['originationTimestampSplit']['Time_Second'],
82						  $form['originationTimestampSplit']['Date_Month'],
83						  $form['originationTimestampSplit']['Date_Day'],
84						  $form['originationTimestampSplit']['Date_Year']);
85		GalleryUtilities::putRequestVariable(
86		    'form[originationTimestamp]', $newOriginationTimestamp);
87	    }
88
89	    if (!empty($form['thumbnail']['size']) &&
90		    (!is_numeric($form['thumbnail']['size']) || $form['thumbnail']['size'] < 0)) {
91		$error[] = 'form[error][thumbnail][size][invalid]';
92	    }
93
94	    if (empty($error) && isset($form['thumbnail']['size'])) {
95		/* Load the thumbnail */
96		list ($ret, $thumbnail) =
97		    GalleryCoreApi::fetchThumbnailsByItemIds(array($item->getId()));
98		if ($ret) {
99		    return array($ret, null, null, null);
100		}
101		$thumbnail = empty($thumbnail) ? null : $thumbnail[$item->getId()];
102
103		if (!isset($thumbnail) && $form['thumbnail']['size'] > 0) {
104		    if (GalleryUtilities::isA($item, 'GalleryAlbumItem')) {
105			/* Create album highlight (with default thumbnail size) */
106			list ($ret) = GalleryCoreApi::guaranteeAlbumHasThumbnail($item->getId());
107			if ($ret) {
108			    return array($ret, null, null, null);
109			}
110			list ($ret, $thumbnail) =
111			    GalleryCoreApi::fetchThumbnailsByItemIds(array($item->getId()));
112			if ($ret) {
113			    return array($ret, null, null, null);
114			}
115			if (empty($thumbnail)) {
116			    $error[] = 'form[error][thumbnail][create][forAlbum]';
117			    $thumbnail = null;
118			} else {
119			    $thumbnail = $thumbnail[$item->getId()];
120			}
121		    } else {
122			/* Prepare new thumbnail source and toolkit operations */
123			list ($ret, $source) = GalleryCoreApi::fetchPreferredSource($item);
124			if ($ret) {
125			    return array($ret, null, null, null);
126			}
127			if (isset($source)) {
128			    list ($ret, $operations, $outputMimeType) =
129				GalleryCoreApi::makeSupportedViewableOperationSequence(
130					$source->getMimeType(),
131					'thumbnail|' . $form['thumbnail']['size']);
132			    if ($ret) {
133				return array($ret, null, null, null);
134			    }
135			}
136			if (!isset($operations)) {
137			    $error[] = 'form[error][thumbnail][create][forItem]';
138			}
139		    }
140		}
141
142		if (isset($thumbnail) && $form['thumbnail']['size'] > 0) {
143		    /* Change the thumbnail */
144		    $thumbnail->setDerivativeOperations(
145			preg_replace('/((^|;)thumbnail)\|\d+/', '$1|' .
146				     $form['thumbnail']['size'],
147				     $thumbnail->getDerivativeOperations()));
148
149		    if ($thumbnail->isModified()) {
150			list ($ret, $lockId) =
151			    GalleryCoreApi::acquireWriteLock($thumbnail->getId());
152			if ($ret) {
153			    return array($ret, null, null, null);
154			}
155			$ret = $thumbnail->save();
156			if ($ret) {
157			    return array($ret, null, null, null);
158			}
159			$ret = GalleryCoreApi::releaseLocks(array($lockId));
160			if ($ret) {
161			    return array($ret, null, null, null);
162			}
163		    }
164		} else if (isset($thumbnail) && empty($form['thumbnail']['size'])) {
165		    /* Delete the thumbnail */
166		    $ret = GalleryCoreApi::deleteEntityById($thumbnail->getId(),
167							    'GalleryDerivative');
168		    if ($ret) {
169			return array($ret, null, null, null);
170		    }
171		} else if ($form['thumbnail']['size'] > 0 && empty($error)) {
172		    /* Create the thumbnail */
173		    list ($ret, $thumbnail) =
174			GalleryCoreApi::newFactoryInstanceByHint('GalleryDerivative',
175								 $source->getEntityType());
176		    if ($ret) {
177			return array($ret, null, null, null);
178		    }
179		    if (!isset($thumbnail)) {
180			return array(GalleryCoreApi::error(ERROR_MISSING_OBJECT),
181				     null, null, null);
182		    }
183
184		    $ret = $thumbnail->create($item->getId(), DERIVATIVE_TYPE_IMAGE_THUMBNAIL);
185		    if ($ret) {
186			return array($ret, null, null, null);
187		    }
188
189		    $thumbnail->setMimeType($outputMimeType);
190		    $thumbnail->setDerivativeSourceId($source->getId());
191		    $thumbnail->setDerivativeOperations($operations);
192
193		    $ret = $thumbnail->save();
194		    if ($ret) {
195			return array($ret, null, null, null);
196		    }
197		}
198	    }
199
200	    if (empty($error)) {
201		list ($ret, $lockId) = GalleryCoreApi::acquireWriteLock($item->getId());
202		if ($ret) {
203		    return array($ret, null, null, null);
204		}
205
206		/*
207		 * It's possible to get a collision when we rename, so try that
208		 * first.  If there's no collision then make the rest of the changes.
209		 */
210		$originalPathComponent = $item->getPathComponent();
211		if (isset($form['pathComponent']) &&
212			$item->getPathComponent() != $form['pathComponent']) {
213		    if ($isRootAlbum) {
214			GalleryCoreApi::releaseLocks($lockId);
215			return array(GalleryCoreApi::error(ERROR_BAD_PARAMETER),
216				     null, null, null);
217		    } else {
218			$ret = $item->rename($form['pathComponent']);
219			if ($ret && !($ret->getErrorCode() & ERROR_COLLISION)) {
220			    GalleryCoreApi::releaseLocks($lockId);
221			    return array($ret, null, null, null);
222			}
223		    }
224		}
225
226		if ($ret && $ret->getErrorCode() & ERROR_COLLISION) {
227		    $error[] = 'form[error][pathComponent][collision]';
228		} else {
229		    list ($ret, $markup) =
230			GalleryCoreApi::getPluginParameter('module', 'core', 'misc.markup');
231		    if ($ret) {
232			return array($ret, null, null, null);
233		    }
234		    if ($markup == 'html') {
235			/* Strip malicious content if html markup allowed */
236			$form['title'] = GalleryUtilities::htmlSafe($form['title'], true);
237			$form['summary'] = GalleryUtilities::htmlSafe($form['summary'], true);
238			$form['description'] =
239			    GalleryUtilities::htmlSafe($form['description'], true);
240		    }
241
242		    $item->setTitle($form['title']);
243		    $item->setSummary($form['summary']);
244		    $item->setKeywords($form['keywords']);
245		    $item->setDescription($form['description']);
246		    $item->setSerialNumber($form['serialNumber']);
247
248		    /* Change the originationTimestamp */
249		    if (!empty($newOriginationTimestamp)) {
250			$item->setOriginationTimestamp($newOriginationTimestamp);
251		    }
252
253		    $ret = $item->save();
254		    if ($ret) {
255			if (isset($form['pathComponent']) &&
256				$originalPathComponent != $form['pathComponent']) {
257			    /*
258			     * Move the file back and hope that this succeeds
259			     * since we're already in an error state
260			     */
261			    $item->rename($originalPathComponent);
262			}
263
264			GalleryCoreApi::releaseLocks($lockId);
265			return array($ret, null, null, null);
266		    }
267
268		    /* Prepare our status message */
269		    list ($ret, $module) = GalleryCoreApi::loadPlugin('module', 'core');
270		    if ($ret) {
271			return array($ret, null, null, null);
272		    }
273
274		    $status = $module->translate('Changes saved successfully');
275		}
276
277		$ret = GalleryCoreApi::releaseLocks($lockId);
278		if ($ret) {
279		    return array($ret, null, null, null);
280		}
281	    }
282	}
283
284	return array(null, $error, $status, false);
285    }
286
287    /**
288     * @see ItemEditPlugin::loadTemplate
289     */
290    function loadTemplate(&$template, &$form, $item, $thumbnail) {
291	global $gallery;
292	$platform =& $gallery->getPlatform();
293
294	if ($form['formName'] != 'ItemEditItem') {
295	    /* First time around, load the form with item data */
296	    $form['formName'] = 'ItemEditItem';
297
298	    $form['title'] = $item->getTitle();
299	    $form['summary'] = $item->getSummary();
300	    $form['keywords'] = $item->getKeywords();
301	    $form['description'] = $item->getDescription();
302	    $form['pathComponent'] = $item->getPathComponent();
303	    $form['originationTimestamp'] = $item->getOriginationTimestamp();
304
305	    $form['thumbnail']['size'] = null;
306	    if (!empty($thumbnail) && preg_match('/thumbnail\|(\d+)/',
307						 $thumbnail->getDerivativeOperations(),
308						 $matches)) {
309		$form['thumbnail']['size'] = $matches[1];
310	    }
311	}
312
313	foreach (array('title', 'description', 'summary', 'pathComponent') as $key) {
314	    if (!empty($form[$key]) && !is_string($form[$key])) {
315		$form[$key] = '';
316	    }
317	}
318
319	list ($ret, $rootAlbumId) =
320	    GalleryCoreApi::getPluginParameter('module', 'core', 'id.rootAlbum');
321	if ($ret) {
322	    return array($ret, null, null);
323	}
324
325	$can = array('createThumbnail' => false);
326	$can['changePathComponent'] = $can['editThumbnail'] = ($item->getId() != $rootAlbumId);
327
328	if (GalleryUtilities::isA($item, 'GalleryAlbumItem')) {
329	    $can['createThumbnail'] = true;
330	    if (!isset($thumbnail)) {
331		list ($ret, $childIds) = GalleryCoreApi::fetchChildItemIds($item, 0, 1);
332		if ($ret) {
333		    return array($ret, null, null);
334		}
335		if (empty($childIds)) {
336		    $can['editThumbnail'] = false;
337		}
338	    }
339	} else if (isset($thumbnail) && $thumbnail->getDerivativeSourceId() != $item->getId()) {
340	    list ($ret, $source) = GalleryCoreApi::loadEntitiesById(
341		$thumbnail->getDerivativeSourceId(),
342		array('GalleryFileSystemEntity', 'GalleryDerivative'));
343	    if ($ret) {
344		return array($ret, null, null);
345	    }
346	    list ($ret, $can['createThumbnail']) = GalleryCoreApi::isSupportedOperationSequence(
347		    $source->getMimeType(), $thumbnail->getDerivativeOperations());
348	    if ($ret) {
349		return array($ret, null, null);
350	    }
351	} else if (method_exists($item, 'getMimeType')) {
352	    list ($ret, $operations) = GalleryCoreApi::makeSupportedViewableOperationSequence(
353						       $item->getMimeType(), 'thumbnail|150');
354	    if ($ret) {
355		return array($ret, null, null);
356	    }
357	    $can['createThumbnail'] = isset($operations);
358	}
359
360	$ItemEditItem = array('can' => $can,
361		'typeName' => array_merge($item->itemTypeName(), $item->itemTypeName(false)));
362
363	/* The originateTimestamp that we can get from our toolkits */
364	list ($ret, $originationTimestamp) = GalleryCoreApi::fetchOriginationTimestamp($item);
365	if ($ret) {
366	    return array($ret, null, null);
367	}
368	if ($originationTimestamp > 0) {
369	    $ItemEditItem['originationTimestamp'] = array(
370		'timestamp' => $originationTimestamp,
371		'Time_Hour' => $platform->strftime('%H', $originationTimestamp),
372		'Time_Minute' => $platform->strftime('%M', $originationTimestamp),
373		'Time_Second' => $platform->strftime('%S', $originationTimestamp),
374		'Date_Day' => ltrim($platform->strftime('%d', $originationTimestamp), '0'),
375		'Date_Month' => $platform->strftime('%m', $originationTimestamp),
376		'Date_Year' => $platform->strftime('%Y', $originationTimestamp),
377	    );
378	}
379
380	/* The template needs to differentiate some important itemTypes */
381	if (GalleryUtilities::isA($item, 'GalleryPhotoItem')) {
382	    $ItemEditItem['isItemPhoto'] = true;
383	} else if (GalleryUtilities::isA($item, 'GalleryUnknownItem')) {
384	    $ItemEditItem['isItemUnknown'] = true;
385	}
386
387	/* Render the HTML body */
388	$template->setVariable('ItemEditItem', $ItemEditItem);
389	$template->setVariable('controller', 'core.ItemEditItem');
390
391	return array(null,
392		     'modules/core/templates/ItemEditItem.tpl', 'modules_core');
393    }
394
395    /**
396     * @see ItemEditPlugin::isSupported
397     */
398    function isSupported($item, $thumbnail) {
399	return (GalleryUtilities::isA($item, 'GalleryItem'));
400    }
401
402    /**
403     * @see ItemEditPlugin::getTitle
404     */
405    function getTitle() {
406	list ($ret, $module) = GalleryCoreApi::loadPlugin('module', 'core');
407	if ($ret) {
408	    return array($ret, null);
409	}
410
411	return array(null, $module->translate('General'));
412    }
413}
414?>
415