ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
BasicPersistence.php
Go to the documentation of this file.
1<?php
2
4
14
16{
17
21 protected static $instance;
25 protected static $buckets = [];
41 protected static $tasks = [];
45 protected $connector = null;
46
50 protected function __construct()
51 {
52 $this->valueHashToValueContainerId = new \SplObjectStorage();
53 $this->bucketHashToObserverContainerId = new \SplObjectStorage();
54 $this->taskHashToTaskContainerId = new \SplObjectStorage();
55 }
56
57 public static function instance() : self
58 {
59 if (!self::$instance) {
60 self::$instance = new BasicPersistence();
61 }
62
63 return self::$instance;
64 }
65
66
67
68
75 {
76 $this->connector = $connector;
77 }
78
79
85 public function saveBucketAndItsTasks(Bucket $bucket)
86 {
87 $bucket->checkIntegrity();
88
89 $this->saveObserver($bucket);
90 }
91
92
98 public function updateBucket(Bucket $bucket)
99 {
100 $bucketContainer = new BucketContainer($this->getBucketContainerId($bucket), $this->connector);
101
102 // The basic information about the task.
103 $bucketContainer->setUserId($bucket->getUserId());
104 $bucketContainer->setState($bucket->getState());
105 $bucketContainer->setTotalNumberoftasks(count($bucket->getTask()->unfoldTask()));
106 $bucketContainer->setPercentage($bucket->getOverallPercentage());
107 $bucketContainer->setTitle($bucket->getTitle());
108 $bucketContainer->setLastHeartbeat($bucket->getLastHeartbeat());
109 $bucketContainer->setDescription($bucket->getDescription());
110 $bucketContainer->setCurrentTaskid($this->getTaskContainerId($bucket->getCurrentTask()));
111 $bucketContainer->setRootTaskid($this->getTaskContainerId($bucket->getTask()));
112
113 // Save and store the container to bucket instance.
114 $bucketContainer->update();
115 }
116
117
121 public function getBucketIdsOfUser($user_id, $order_by = "id", $order_direction = "ASC")
122 {
123 return BucketContainer::where(['user_id' => $user_id])
124 ->orderBy($order_by, $order_direction)
125 ->getArray(null, 'id');
126 }
127
128
134 public function getBucketMetaOfUser($user_id)
135 {
136 $buckets = BucketContainer::where(['user_id' => $user_id])->get();
137 $bucketMetas = array_map(function (BucketContainer $bucketContainer) {
138 $bucketMeta = new BasicBucketMeta();
139
140 $bucketMeta->setUserId($bucketContainer->getUserId());
141 $bucketMeta->setState($bucketContainer->getState());
142 $bucketMeta->setTitle($bucketContainer->getTitle());
143 $bucketMeta->setDescription($bucketContainer->getDescription());
144 $bucketMeta->setOverallPercentage($bucketContainer->getPercentage());
145
146 return $bucketMeta;
147 }, $buckets);
148
149 return $bucketMetas;
150 }
151
152
157 {
158 $buckets = BucketContainer::where(['state' => $state])->get();
159 $ids = array_map(function (BucketContainer $bucket_container) {
160 return $bucket_container->getId();
161 }, $buckets);
162
163 return $ids;
164 }
165
166
173 protected function saveObserver(Bucket $bucket)
174 {
175 // If the instance has a known container we use it, otherwise we create a new container.
176 if ($this->bucketHashToObserverContainerId->contains($bucket)) {
177 $bucketContainer = new BucketContainer($this->bucketHashToObserverContainerId[$bucket], $this->connector);
178 } else {
179 $bucketContainer = new BucketContainer(0, $this->connector);
180 }
181
182 // The basic information about the task.
183 $bucketContainer->setUserId($bucket->getUserId());
184 $bucketContainer->setState($bucket->getState());
185 $bucketContainer->setTitle($bucket->getTitle());
186 $bucketContainer->setDescription($bucket->getDescription());
187 $bucketContainer->setTotalNumberoftasks(count($bucket->getTask()->unfoldTask()));
188 $bucketContainer->setPercentage($bucket->getOverallPercentage());
189
190 // We want to store the bucket ID in every sub task and value. Thus we need to create an id if not available yet.
191 if (!$bucketContainer->getId()) {
192 $bucketContainer->create();
193 }
194
195 // The recursive part.
196 $this->saveTask($bucket->getTask(), $bucketContainer->getId());
197 if (!$bucket->getCurrentTask()) {
198 $bucket->setCurrentTask($bucket->getTask());
199 }
200 $bucketContainer->setCurrentTaskid($this->getTaskContainerId($bucket->getCurrentTask()));
201 $bucketContainer->setRootTaskid($this->getTaskContainerId($bucket->getTask()));
202
203 // Save and store the container to bucket instance.
204 $bucketContainer->save();
205 $this->bucketHashToObserverContainerId[$bucket] = $bucketContainer->getId();
206 }
207
208
216 protected function saveTask(Task $task, $bucketId)
217 {
218 // If the instance has a known container we use it, otherwise we create a new container.
219 if ($this->taskHashToTaskContainerId->contains($task)) {
220 $taskContainer = new TaskContainer($this->taskHashToTaskContainerId[$task], $this->connector);
221 } else {
222 $taskContainer = new TaskContainer(0, $this->connector);
223 }
224
225 // The basic information about the task.
226 $taskContainer->setType($task->getType());
227 $taskContainer->setBucketId($bucketId);
228 $reflection = new \ReflectionClass(get_class($task));
229 $taskContainer->setClassName(get_class($task));
230 // bugfix mantis 23503
231 $absolute_class_path = $reflection->getFileName();
232 // $relative_class_path = str_replace(ILIAS_ABSOLUTE_PATH,".",$absolute_class_path);
233 $taskContainer->setClassPath($reflection->getFileName());
234
235 // Recursivly save the inputs and link them to this task.
236 foreach ($task->getInput() as $k => $input) {
237 $this->saveValue($input, $bucketId, $k);
238 }
239 $this->saveValueToTask($task, $taskContainer, $bucketId);
240
241 // Save and store the container to the task instance.
242 $taskContainer->save();
243 $this->taskHashToTaskContainerId[$task] = $taskContainer->getId();
244 }
245
246
255 protected function saveValueToTask(Task $task, TaskContainer $taskContainer, $bucketId)
256 {
257 // If we have previous values to task associations we delete them.
258 if ($taskContainer->getId()) {
260 $olds = ValueToTaskContainer::where(['task_id' => $taskContainer->getId()])->get();
261 foreach ($olds as $old) {
262 $old->delete();
263 }
264 } else {
265 // We need a valid ID to link the inputs
266 $taskContainer->save();
267 }
268
269 // We create the new 1 to n relation.
270 foreach ($task->getInput() as $k => $inputValue) {
271 $v = new ValueToTaskContainer(0, $this->connector);
272 $v->setTaskId($taskContainer->getId());
273 $v->setPosition($k);
274 $v->setBucketId($bucketId);
275 $v->setValueId($this->getValueContainerId($inputValue));
276 $v->save();
277 }
278 }
279
280
288 protected function saveValue(Value $value, $bucketId, $position)
289 {
290 // If we have previous values to task associations we delete them.
291 if ($this->valueHashToValueContainerId->contains($value)) {
292 $valueContainer = new ValueContainer($this->valueHashToValueContainerId[$value], $this->connector);
293 } else {
294 $valueContainer = new ValueContainer(0, $this->connector);
295 }
296
297 // Save information about the value
298 $reflection = new \ReflectionClass(get_class($value));
299 $valueContainer->setClassName(get_class($value));
300 // bugfix mantis 23503
301 // $absolute_class_path = $reflection->getFileName();
302 // $relative_class_path = str_replace(ILIAS_ABSOLUTE_PATH,".",$absolute_class_path);
303 // $valueContainer->setClassPath($relative_class_path);
304 $valueContainer->setType($value->getType());
305 $valueContainer->setHasParenttask($value->hasParentTask());
306 $valueContainer->setBucketId($bucketId);
307 $valueContainer->setPosition($position);
308 $valueContainer->setHash($value->getHash());
309 $valueContainer->setSerialized($value->serialize());
310
311 // If the value is a thunk value we also store its parent.
312 if ($value->hasParentTask()) {
313 $this->saveTask($value->getParentTask(), $bucketId);
314 $valueContainer->setParentTaskid($this->getTaskContainerId($value->getParentTask()));
315 }
316
317 // We save the container and store the instance to container association.
318 $valueContainer->save();
319 $this->valueHashToValueContainerId->attach($value, $valueContainer->getId());
320 }
321
322
329 public function getBucketContainerId(Bucket $bucket)
330 {
331 if (!$this->bucketHashToObserverContainerId->contains(($bucket))) {
332 throw new SerializationException("Could not resolve container id of task: "
333 . print_r($bucket, true));
334 }
335
336 return $this->bucketHashToObserverContainerId[$bucket];
337 }
338
339
346 protected function getTaskContainerId(Task $task)
347 {
348 if (!$this->taskHashToTaskContainerId->contains($task)) {
349 throw new SerializationException("Could not resolve container id of task: "
350 . print_r($task, true));
351 }
352
353 return $this->taskHashToTaskContainerId[$task];
354 }
355
356
363 protected function getValueContainerId($value) : int
364 {
365 if (!$this->valueHashToValueContainerId->contains($value)) {
366 throw new SerializationException("Could not resolve container id of value: "
367 . print_r($value, true));
368 }
369
370 return (int) $this->valueHashToValueContainerId[$value];
371 }
372
373
380 public function loadBucket($bucket_id)
381 {
382 if (isset(self::$buckets[$bucket_id])) {
383 return self::$buckets[$bucket_id];
384 }
386 $bucketContainer = BucketContainer::find($bucket_id);
387 if (!$bucketContainer) {
388 throw new BucketNotFoundException("The requested bucket with container id $bucket_id could not be found in the database.");
389 }
390 $bucket = new BasicBucket();
391
392 $bucket->setUserId($bucketContainer->getUserId());
393 $bucket->setState($bucketContainer->getState());
394 $bucket->setTitle($bucketContainer->getTitle());
395 $bucket->setDescription($bucketContainer->getDescription());
396 $bucket->setOverallPercentage($bucketContainer->getPercentage());
397 $bucket->setLastHeartbeat($bucketContainer->getLastHeartbeat());
398 $bucket->setTask($this->loadTask($bucketContainer->getRootTaskid(), $bucket, $bucketContainer));
399
400 $this->bucketHashToObserverContainerId[$bucket] = $bucket_id;
401
402 return $bucket;
403 }
404
405
417 private function loadTask($taskContainerId, Bucket $bucket, BucketContainer $bucketContainer)
418 {
419 global $DIC;
420 $factory = $DIC->backgroundTasks()->taskFactory();
422 $taskContainer = TaskContainer::find($taskContainerId);
425 $task = $factory->createTask($taskContainer->getClassName());
426
427 // Bugfix 0023775
428 // Added additional orderBy for the id to ensure that the items are returned in the right order.
429
431 $valueToTasks = ValueToTaskContainer::where(['task_id' => $taskContainerId])
432 ->orderBy('task_id')
433 ->orderBy('position')
434 ->orderBy('id')
435 ->get();
436 $inputs = [];
437 foreach ($valueToTasks as $valueToTask) {
438 $inputs[] = $this->loadValue($valueToTask->getValueId(), $bucket, $bucketContainer);
439 }
440 $task->setInput($inputs);
441
442 if ($taskContainerId == $bucketContainer->getCurrentTaskid()) {
443 $bucket->setCurrentTask($task);
444 }
445
446 $this->taskHashToTaskContainerId[$task] = $taskContainerId;
447
448 return $task;
449 }
450
451
452 private function loadValue($valueContainerId, Bucket $bucket, BucketContainer $bucketContainer)
453 {
454 global $DIC;
455 $factory = $DIC->backgroundTasks()->injector();
456
458 $valueContainer = ValueContainer::find($valueContainerId);
462 $value = $factory->createInstance($valueContainer->getClassName());
463
464 $value->unserialize($valueContainer->getSerialized());
465 if ($valueContainer->getHasParenttask()) {
466 $value->setParentTask($this->loadTask($valueContainer->getParentTaskid(), $bucket, $bucketContainer));
467 }
468
469 $this->valueHashToValueContainerId[$value] = $valueContainerId;
470
471 return $value;
472 }
473
474
475 public function deleteBucketById($bucket_id)
476 {
477// return;
479 $buckets = BucketContainer::where(['id' => $bucket_id])->get();
480 array_map(function (\ActiveRecord $item) {
481 $item->delete();
482 }, $buckets);
483
485 $tasks = TaskContainer::where(['bucket_id' => $bucket_id])->get();
486 array_map(function (\ActiveRecord $item) {
487 $item->delete();
488 }, $tasks);
489
491 $values = ValueContainer::where(['bucket_id' => $bucket_id])->get();
492 array_map(function (\ActiveRecord $item) {
493 $item->delete();
494 }, $values);
495
497 $valueToTasks = ValueToTaskContainer::where(['bucket_id' => $bucket_id])->get();
498 array_map(function (\ActiveRecord $item) {
499 $item->delete();
500 }, $valueToTasks);
501 }
502
503
507 public function deleteBucket($bucket)
508 {
509 $id = $this->getBucketContainerId($bucket);
510 $this->deleteBucketById($id);
511 $this->bucketHashToObserverContainerId->detach($bucket);
512 }
513
514
520 public function loadBuckets($bucket_container_id)
521 {
522 $buckets = [];
523 foreach ($bucket_container_id as $bucket_id) {
524 try {
525 $buckets[] = $this->loadBucket($bucket_id);
526 } catch (\Throwable $t) {
527 $this->deleteBucketById($bucket_id);
528 }
529 }
530
531 return $buckets;
532 }
533}
$factory
Definition: metadata.php:43
if(!array_key_exists('stateid', $_REQUEST)) $state
Handle linkback() response from LinkedIn.
Definition: linkback.php:10
Class ActiveRecord.
static where($where, $operator=null)
An exception for terminatinating execution or to throw for unit testing.
saveBucketAndItsTasks(Bucket $bucket)
Fully updates or creates an Observer and all its tasks into the database.
updateBucket(Bucket $bucket)
Updates only the bucket! Use this if e.g.
getBucketIdsOfUser($user_id, $order_by="id", $order_direction="ASC")
\int[] Returns an array of bucket ids for the given user Id.
getBucketIdsByState($state)
int[] Returns a list of bucket ids for the given Observer State
deleteBucket($bucket)
Delete the bucket and all its stuff.void
setConnector(\arConnector $connector)
Currently for testing only.
Class arConnector.
if(!array_key_exists('StateId', $_REQUEST)) $id
getLastHeartbeat()
When was the last time that something happened on this bucket?
deleteBucketById($bucket_id)
Deletes the Observer AND all its tasks and values.
loadBucket($bucket_container_id)
global $DIC
Definition: saml.php:7
$values