Commit | Line | Data |
---|---|---|
11ade432 AE |
1 | <?php |
2 | namespace wcf\data; | |
11ade432 AE |
3 | use wcf\system\event\EventHandler; |
4 | use wcf\system\exception\PermissionDeniedException; | |
5 | use wcf\system\exception\ValidateActionException; | |
6 | use wcf\system\WCF; | |
7 | use wcf\util\ClassUtil; | |
8 | use 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 | 20 | abstract 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 | } |