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