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 changing the order of items in an album.
23 * @package GalleryCore
24 * @subpackage UserInterface
25 * @author Bharat Mediratta <bharat@menalto.com>
26 * @version $Revision: 17580 $
27 */
28class ItemReorderController extends GalleryController {
29
30    /**
31     * @see GalleryController::handleRequest
32     */
33    function handleRequest($form) {
34	global $gallery;
35
36	list ($ret, $item) = $this->getItem();
37	if ($ret) {
38	    return array($ret, null);
39	}
40	$itemId = $item->getId();
41
42	/* Check permissions */
43	$ret = GalleryCoreApi::assertHasItemPermission($itemId, 'core.edit');
44	if ($ret) {
45	    return array($ret, null);
46	}
47
48	$status = $error = array();
49	if (isset($form['action']['reorder'])) {
50
51	    /* Verify that we've got what we need */
52	    if (empty($form['selectedId'])) {
53		$error[] = 'form[error][selectedId][missing]';
54	    }
55
56	    if (empty($form['targetId'])) {
57		$error[] = 'form[error][targetId][missing]';
58	    }
59
60	    $before = 0;
61	    if (empty($form['placement']) || $form['placement'] == 'before') {
62		$before = 1;
63	    }
64
65	    /*
66	     * Make sure that the selectedId and targetId are children of the album
67	     */
68	    if (empty($error)) {
69		$selectedId = (int)$form['selectedId'];
70		$targetId = (int)$form['targetId'];
71		list ($ret, $entities) =
72		    GalleryCoreApi::loadEntitiesById(array($selectedId, $targetId), 'GalleryItem');
73		if ($ret) {
74		    return array($ret, null);
75		}
76
77		list ($ret, $permissions) =
78		    GalleryCoreApi::fetchPermissionsForItems(array($selectedId, $targetId));
79		if ($ret) {
80		    return array($ret, null);
81		}
82		if (!isset($permissions[$selectedId]['core.view'])
83			|| !isset($permissions[$selectedId]['core.view'])) {
84		    /* Avoid information disclosure, act as if the items didn't exist. */
85		    return array(GalleryCoreApi::error(ERROR_MISSING_OBJECT), null);
86		}
87
88		if ($entities[0]->getParentId() != $itemId ||
89		    $entities[1]->getParentId() != $itemId) {
90		    return array(GalleryCoreApi::error(ERROR_PERMISSION_DENIED), null);
91		}
92	    }
93
94	    if (empty($error)) {
95		$loopCount = 0;
96		while (true) {
97		    /*
98		     * Get the current and target order weights (have to do
99		     * this after every rebalance, too)
100		     */
101		    list ($ret, $orderWeights) =
102			GalleryCoreApi::fetchItemOrderWeights(array($selectedId, $targetId));
103		    if ($ret) {
104			return array($ret, null);
105		    }
106
107		    list ($ret, $next) = GalleryCoreApi::fetchNextItemWeight($targetId,
108			$before ? LOWER_WEIGHT : HIGHER_WEIGHT);
109		    if ($ret) {
110			return array($ret, null);
111		    }
112
113		    if (isset($next)) {
114			/* Floor rounds down, so separate the sign and the magnitude */
115			$delta = (int)(($next - $orderWeights[$targetId]) / 2);
116		    } else {
117			/*
118			 * We couldn't get a weight, which means that the
119			 * target is at the edge.  So go beyond the edge
120			 */
121			$delta = $before ? -1000 : 1000;
122		    }
123
124		    if (abs($delta) > 0) {
125			break;
126		    }
127
128		    if ($loopCount++ > 0) {
129			/*
130			 * If we have to rebalance more than once then something went wrong!
131			 */
132			return array(GalleryCoreApi::error(ERROR_UNKNOWN), null);
133		    }
134
135		    /* A delta of 0 means that we don't have room, so rebalance */
136		    $ret = GalleryCoreApi::rebalanceChildOrderWeights($itemId);
137		    if ($ret) {
138			return array($ret, null);
139		    }
140		}
141		$newWeight = $orderWeights[$targetId] + $delta;
142
143		$ret = GalleryCoreApi::setItemOrderWeight($selectedId, $newWeight);
144		if ($ret) {
145		    return array($ret, null);
146		}
147
148		$event = GalleryCoreApi::newEvent('Gallery::ItemOrder');
149		$event->setData($itemId);
150		list ($ret) = GalleryCoreApi::postEvent($event);
151		if ($ret) {
152		    return array($ret, null);
153		}
154
155		/* Redirect back to the same page so that we can do more reordering */
156		$redirect['view'] = 'core.ItemAdmin';
157		$redirect['subView'] = 'core.ItemReorder';
158		$redirect['itemId'] = $itemId;
159		$status['saved'] = 1;
160	    }
161	} else if (isset($form['action']['cancel'])) {
162	    $redirect['return'] = true;
163	}
164
165	if (!empty($redirect)) {
166	    $results['redirect'] = $redirect;
167	} else {
168	    $results['delegate']['view'] = 'core.ItemAdmin';
169	    $results['delegate']['subView'] = 'core.ItemReorder';
170	}
171	$results['status'] = $status;
172	$results['error'] = $error;
173
174	return array(null, $results);
175    }
176}
177
178/**
179 * This view will prompt for how to change the order of items in the album
180 */
181class ItemReorderView extends GalleryView {
182
183    /**
184     * @see GalleryView::loadTemplate
185     */
186    function loadTemplate(&$template, &$form) {
187	global $gallery;
188
189	/* itemId is the album where we want to move items from */
190	list ($ret, $item) = $this->getItem();
191	if ($ret) {
192	    return array($ret, null);
193	}
194	$itemId = $item->getId();
195
196	if ($form['formName'] == 'ItemReorder') {
197	    /* No validation at the moment */
198	} else {
199	    /* First time around, load the form with item data */
200	    $form['formName'] = 'ItemReorder';
201	}
202
203	$show = array();
204	$ItemReorder = array();
205	$orderBy = $item->getOrderBy();
206	if (empty($orderBy)) {
207	    list ($ret, $orderBy) =
208		GalleryCoreApi::getPluginParameter('module', 'core', 'default.orderBy');
209	    if ($ret) {
210		return array($ret, null);
211	    }
212	}
213	if ($orderBy != 'orderWeight') {
214	    $show['automaticOrderMessage'] = 1;
215	} else {
216
217	    /* Get all peers that we can see */
218	    list ($ret, $peerIds) = GalleryCoreApi::fetchChildItemIds($item);
219	    if ($ret) {
220		return array($ret, null);
221	    }
222
223	    /* Load all the peers */
224	    list ($ret, $peerItems) = GalleryCoreApi::loadEntitiesById($peerIds, 'GalleryItem');
225	    if ($ret) {
226		return array($ret, null);
227	    }
228
229	    /* Build our peers table */
230	    $peers = array();
231	    foreach ($peerItems as $peerItem) {
232		$peers[$peerItem->getId()] = (array)$peerItem;
233		if (GalleryUtilities::isA($peerItem, 'GalleryAlbumItem')) {
234		    $peerTypes['album'][$peerItem->getId()] = 1;
235		} else {
236		    $peerTypes['data'][$peerItem->getId()] = 1;
237		}
238		$peers[$peerItem->getId()]['selected'] =
239		    isset($form['selectedIds'][$peerItem->getId()]);
240	    }
241	    $ItemReorder['peers'] = $peers;
242	    $ItemReorder['peerTypes'] = $peerTypes;
243	}
244
245	$ItemReorder['show'] = $show;
246
247	$template->setVariable('ItemReorder', $ItemReorder);
248	$template->setVariable('controller', 'core.ItemReorder');
249	return array(null, array('body' => 'modules/core/templates/ItemReorder.tpl'));
250    }
251
252    /**
253     * @see GalleryView::getViewDescription
254     */
255    function getViewDescription() {
256	list ($ret, $core) = GalleryCoreApi::loadPlugin('module', 'core');
257	if ($ret) {
258	    return array($ret, null);
259	}
260
261	return array(null, $core->translate('reorder items'));
262    }
263}
264?>
265