Merge branch 'master' of github.com:WoltLab/WCF
[GitHub/WoltLab/WCF.git] / wcfsetup / install / files / lib / data / AbstractDatabaseObjectAction.class.php
CommitLineData
11ade432
AE
1<?php
2namespace wcf\data;
11ade432
AE
3use wcf\system\event\EventHandler;
4use wcf\system\exception\PermissionDeniedException;
5use wcf\system\exception\ValidateActionException;
6use wcf\system\WCF;
7use wcf\util\ClassUtil;
8use wcf\util\StringUtil;
9
10/**
11 * Default implementation for DatabaseObject-related actions.
12 *
13 * @author Alexander Ebert
14 * @copyright 2001-2011 WoltLab GmbH
15 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
16 * @package com.woltlab.wcf
17 * @subpackage data
18 * @category Community Framework
19 */
b522d4f1 20abstract class AbstractDatabaseObjectAction implements IDatabaseObjectAction {
11ade432
AE
21 /**
22 * pending action
11ade432
AE
23 * @var string
24 */
25 protected $action = '';
26
27 /**
28 * object editor class name
11ade432
AE
29 * @var string
30 */
31 protected $className = '';
32
33 /**
34 * list of object ids
11ade432
AE
35 * @var array<integer>
36 */
37 protected $objectIDs = array();
38
39 /**
832371b2 40 * list of object editors
a2554026 41 * @var array<wcf\data\DatabaseObjectEditor>
11ade432
AE
42 */
43 protected $objects = array();
44
45 /**
46 * multi-dimensional array of parameters required by an action
11ade432
AE
47 * @var array<array>
48 */
49 protected $parameters = array();
50
51 /**
52 * list of permissions required to create objects
832371b2 53 * @var array<string>
11ade432
AE
54 */
55 protected $permissionsCreate = array();
56
57 /**
58 * list of permissions required to delete objects
832371b2 59 * @var array<string>
11ade432
AE
60 */
61 protected $permissionsDelete = array();
62
63 /**
64 * list of permissions required to update objects
832371b2 65 * @var array<string>
11ade432
AE
66 */
67 protected $permissionsUpdate = array();
68
69 /**
70 * values returned by executed action
11ade432
AE
71 * @var mixed
72 */
73 protected $returnValues = null;
74
fca077a6 75 /**
878d0d80
AE
76 * allows guest access for all specified methods, by default
77 * guest access is completely disabled
78 * @var array<string>
fca077a6 79 */
878d0d80 80 protected $allowGuestAccess = array();
fca077a6 81
11ade432 82 /**
a90028e5 83 * Initialize a new DatabaseObject-related action.
11ade432
AE
84 *
85 * @param array $objectIDs
86 * @param string $action
87 * @param array $parameters
88 */
89 public function __construct(array $objectIDs, $action, array $parameters = array()) {
90 $this->objectIDs = $objectIDs;
91 $this->action = $action;
92 $this->parameters = $parameters;
93
94 // fire event action
95 EventHandler::getInstance()->fireAction($this, 'initializeAction');
96 }
97
98 /**
a2554026 99 * @see wcf\data\IDatabaseObjectAction::validateAction()
11ade432
AE
100 */
101 public function validateAction() {
fca077a6 102 // validate if user is logged in
878d0d80 103 if (!WCF::getUser()->userID && !in_array($this->getActionName(), $this->allowGuestAccess)) {
fca077a6
AE
104 throw new ValidateActionException("Please login before executing this action");
105 }
106
11ade432
AE
107 // validate action name
108 if (!method_exists($this, $this->getActionName())) {
109 throw new ValidateActionException("unknown action '".$this->getActionName()."'");
110 }
111
112 $actionName = 'validate'.StringUtil::firstCharToUpperCase($this->getActionName());
113 if (!method_exists($this, $actionName)) {
114 throw new ValidateActionException("validation of action '".$this->getActionName()."' failed");
115 }
116
117 // execute action
118 call_user_func_array(array($this, $actionName), $this->getParameters());
119 }
120
121 /**
a2554026 122 * @see wcf\data\IDatabaseObjectAction::executeAction()
11ade432
AE
123 */
124 public function executeAction() {
125 // execute action
126 if (method_exists($this, $this->getActionName())) {
127 $this->returnValues = call_user_func_array(array($this, $this->getActionName()), $this->getParameters());
128 }
129
130 // reset cache
b522d4f1 131 if (ClassUtil::isInstanceOf($this->className, 'wcf\data\IEditableCachedObject')) {
11ade432
AE
132 call_user_func(array($this->className, 'resetCache'));
133 }
134
135 // fire event action
136 EventHandler::getInstance()->fireAction($this, 'finalizeAction');
137
138 return $this->getReturnValues();
139 }
140
141 /**
b522d4f1 142 * @see wcf\data\IDatabaseObjectAction::getActionName()
11ade432
AE
143 */
144 public function getActionName() {
145 return $this->action;
146 }
147
148 /**
b522d4f1 149 * @see wcf\data\IDatabaseObjectAction::getObjectIDs()
11ade432
AE
150 */
151 public function getObjectIDs() {
152 return $this->objectIDs;
153 }
154
e9aeabca
MW
155 /**
156 * Sets the database objects.
157 *
158 * @param array<wcf\data\DatabaseObject> $objects
159 */
160 public function setObjects(array $objects) {
161 $this->objects = $objects;
162 }
163
11ade432 164 /**
b522d4f1 165 * @see wcf\data\IDatabaseObjectAction::getParameters()
11ade432
AE
166 */
167 public function getParameters() {
168 return $this->parameters;
169 }
170
171 /**
b522d4f1 172 * @see wcf\data\IDatabaseObjectAction::getReturnValues()
11ade432
AE
173 */
174 public function getReturnValues() {
175 return array(
176 'objectIDs' => $this->getObjectIDs(),
177 'returnValues' => $this->returnValues
178 );
179 }
180
181 /**
182 * Validates permissions and parameters.
183 */
184 public function validateCreate() {
185 // validate permissions
186 if (is_array($this->permissionsCreate) && count($this->permissionsCreate)) {
187 try {
7c720e36 188 WCF::getSession()->checkPermissions($this->permissionsCreate);
11ade432
AE
189 }
190 catch (PermissionDeniedException $e) {
191 throw new ValidateActionException('Insufficient permissions');
192 }
193 }
194 else {
195 throw new ValidateActionException('Insufficient permissions');
196 }
197 }
198
199 /**
200 * Validates permissions and parameters.
201 */
202 public function validateDelete() {
203 // validate permissions
204 if (is_array($this->permissionsDelete) && count($this->permissionsDelete)) {
205 try {
7c720e36 206 WCF::getSession()->checkPermissions($this->permissionsDelete);
11ade432
AE
207 }
208 catch (PermissionDeniedException $e) {
209 throw new ValidateActionException('Insufficient permissions');
210 }
211 }
212 else {
213 throw new ValidateActionException('Insufficient permissions');
214 }
215
046f3d7b 216 // read objects
e9aeabca
MW
217 if (!count($this->objects)) {
218 $this->readObjects();
219 }
11ade432
AE
220
221 if (!count($this->objects)) {
222 throw new ValidateActionException('Invalid object id');
223 }
224 }
225
226 /**
227 * Validates permissions and parameters.
228 */
229 public function validateUpdate() {
230 // validate permissions
231 if (is_array($this->permissionsUpdate) && count($this->permissionsUpdate)) {
232 try {
7c720e36 233 WCF::getSession()->checkPermissions($this->permissionsUpdate);
11ade432
AE
234 }
235 catch (PermissionDeniedException $e) {
236 throw new ValidateActionException('Insufficient permissions');
237 }
238 }
239 else {
240 throw new ValidateActionException('Insufficient permissions');
241 }
242
046f3d7b 243 // read objects
e9aeabca
MW
244 if (!count($this->objects)) {
245 $this->readObjects();
246 }
11ade432
AE
247
248 if (!count($this->objects)) {
249 throw new ValidateActionException('Invalid object id');
250 }
251 }
252
253 /**
832371b2 254 * Creates new database object.
11ade432 255 *
a2554026 256 * @return wcf\data\DatabaseObject
11ade432
AE
257 */
258 public function create() {
11ade432
AE
259 return call_user_func(array($this->className, 'create'), $this->parameters['data']);
260 }
261
262 /**
832371b2 263 * Deletes database object and returns the number of deleted objects.
11ade432
AE
264 *
265 * @return integer
266 */
267 public function delete() {
268 if (!count($this->objects)) {
269 $this->readObjects();
270 }
271
272 // get index name
273 $indexName = call_user_func(array($this->className, 'getDatabaseTableIndexName'));
274
275 // get ids
276 $objectIDs = array();
277 foreach ($this->objects as $object) {
278 $objectIDs[] = $object->__get($indexName);
279 }
280
281 // execute action
282 return call_user_func(array($this->className, 'deleteAll'), $objectIDs);
283 }
284
285 /**
286 * Updates data.
287 */
288 public function update() {
289 if (!count($this->objects)) {
290 $this->readObjects();
291 }
292
046f3d7b
MS
293 if (isset($this->parameters['data'])) {
294 foreach ($this->objects as $object) {
295 $object->update($this->parameters['data']);
296 }
11ade432
AE
297 }
298 }
299
300 /**
301 * Reads data by data id.
302 */
303 protected function readObjects() {
304 if (!count($this->objectIDs)) {
305 return;
306 }
307
308 // get base class
309 $baseClass = call_user_func(array($this->className, 'getBaseClass'));
310
311 // get db information
312 $tableName = call_user_func(array($this->className, 'getDatabaseTableName'));
313 $indexName = call_user_func(array($this->className, 'getDatabaseTableIndexName'));
314
315 // get objects
316 $sql = "SELECT *
317 FROM ".$tableName."
318 WHERE ".$indexName." IN (".str_repeat('?,', count($this->objectIDs) - 1)."?)";
319 $statement = WCF::getDB()->prepareStatement($sql);
320 $statement->execute($this->objectIDs);
321 while ($object = $statement->fetchObject($baseClass)) {
322 $this->objects[] = new $this->className($object);
323 }
324 }
325}