ILIAS  release_5-3 Revision v5.3.23-19-g915713cf615
BasicPersistence.php
Go to the documentation of this file.
1 <?php
2 
4 
14 
15 class BasicPersistence implements Persistence
16 {
17 
21  protected static $instance;
25  protected static $buckets = [];
41  protected static $tasks = [];
45  protected $connector = null;
46 
47 
48  public static function instance()
49  {
50  if (!self::$instance) {
51  self::$instance = new BasicPersistence();
52  }
53 
54  return self::$instance;
55  }
56 
57 
63  {
64  $this->connector = $connector;
65  }
66 
67 
73  public function saveBucketAndItsTasks(Bucket $bucket)
74  {
75  $bucket->checkIntegrity();
76 
77  $this->saveObserver($bucket);
78  }
79 
80 
86  public function updateBucket(Bucket $bucket)
87  {
88  $bucketContainer = new BucketContainer($this->getBucketContainerId($bucket), $this->connector);
89 
90  // The basic information about the task.
91  $bucketContainer->setUserId($bucket->getUserId());
92  $bucketContainer->setState($bucket->getState());
93  $bucketContainer->setTotalNumberoftasks(count($bucket->getTask()->unfoldTask()));
94  $bucketContainer->setPercentage($bucket->getOverallPercentage());
95  $bucketContainer->setTitle($bucket->getTitle());
96  $bucketContainer->setLastHeartbeat($bucket->getLastHeartbeat());
97  $bucketContainer->setDescription($bucket->getDescription());
98  $bucketContainer->setCurrentTaskid($this->getTaskContainerId($bucket->getCurrentTask()));
99  $bucketContainer->setRootTaskid($this->getTaskContainerId($bucket->getTask()));
100 
101  // Save and store the container to bucket instance.
102  $bucketContainer->update();
103  }
104 
105 
109  public function getBucketIdsOfUser($user_id, $order_by = "id", $order_direction = "ASC")
110  {
111  return BucketContainer::where(['user_id' => $user_id])
112  ->orderBy($order_by, $order_direction)
113  ->getArray(null, 'id');
114  }
115 
116 
122  public function getBucketMetaOfUser($user_id)
123  {
124  $buckets = BucketContainer::where([ 'user_id' => $user_id ])->get();
125  $bucketMetas = array_map(function (BucketContainer $bucketContainer) {
126  $bucketMeta = new BasicBucketMeta();
127 
128  $bucketMeta->setUserId($bucketContainer->getUserId());
129  $bucketMeta->setState($bucketContainer->getState());
130  $bucketMeta->setTitle($bucketContainer->getTitle());
131  $bucketMeta->setDescription($bucketContainer->getDescription());
132  $bucketMeta->setOverallPercentage($bucketContainer->getPercentage());
133 
134  return $bucketMeta;
135  }, $buckets);
136 
137  return $bucketMetas;
138  }
139 
140 
144  public function getBucketIdsByState($state)
145  {
146  $buckets = BucketContainer::where([ 'state' => $state ])->get();
147  $ids = array_map(function (BucketContainer $bucket_container) {
148  return $bucket_container->getId();
149  }, $buckets);
150 
151  return $ids;
152  }
153 
154 
161  protected function saveObserver(Bucket $bucket)
162  {
163  // If the instance has a known container we use it, otherwise we create a new container.
164  if (isset($this->bucketHashToObserverContainerId[spl_object_hash($bucket)])) {
165  $bucketContainer = new BucketContainer($this->bucketHashToObserverContainerId[spl_object_hash($bucket)], $this->connector);
166  } else {
167  $bucketContainer = new BucketContainer(0, $this->connector);
168  }
169 
170  // The basic information about the task.
171  $bucketContainer->setUserId($bucket->getUserId());
172  $bucketContainer->setState($bucket->getState());
173  $bucketContainer->setTitle($bucket->getTitle());
174  $bucketContainer->setDescription($bucket->getDescription());
175  $bucketContainer->setTotalNumberoftasks(count($bucket->getTask()->unfoldTask()));
176  $bucketContainer->setPercentage($bucket->getOverallPercentage());
177 
178  // We want to store the bucket ID in every sub task and value. Thus we need to create an id if not available yet.
179  if (!$bucketContainer->getId()) {
180  $bucketContainer->create();
181  }
182 
183  // The recursive part.
184  $this->saveTask($bucket->getTask(), $bucketContainer->getId());
185  if (!$bucket->getCurrentTask()) {
186  $bucket->setCurrentTask($bucket->getTask());
187  }
188  $bucketContainer->setCurrentTaskid($this->getTaskContainerId($bucket->getCurrentTask()));
189  $bucketContainer->setRootTaskid($this->getTaskContainerId($bucket->getTask()));
190 
191  // Save and store the container to bucket instance.
192  $bucketContainer->save();
193  $this->bucketHashToObserverContainerId[spl_object_hash($bucket)] = $bucketContainer->getId();
194  }
195 
196 
204  protected function saveTask(Task $task, $bucketId)
205  {
206  // If the instance has a known container we use it, otherwise we create a new container.
207  if (isset($this->taskHashToTaskContainerId[spl_object_hash($task)])) {
208  $taskContainer = new TaskContainer($this->taskHashToTaskContainerId[spl_object_hash($task)], $this->connector);
209  } else {
210  $taskContainer = new TaskContainer(0, $this->connector);
211  }
212 
213  // The basic information about the task.
214  $taskContainer->setType($task->getType());
215  $taskContainer->setBucketId($bucketId);
216  $reflection = new \ReflectionClass(get_class($task));
217  $taskContainer->setClassName(get_class($task));
218  $taskContainer->setClassPath($reflection->getFileName());
219 
220  // Recursivly save the inputs and link them to this task.
221  foreach ($task->getInput() as $input) {
222  $this->saveValue($input, $bucketId);
223  }
224  $this->saveValueToTask($task, $taskContainer, $bucketId);
225 
226  // Save and store the container to the task instance.
227  $taskContainer->save();
228  $this->taskHashToTaskContainerId[spl_object_hash($task)] = $taskContainer->getId();
229  }
230 
231 
240  protected function saveValueToTask(Task $task, TaskContainer $taskContainer, $bucketId)
241  {
242  // If we have previous values to task associations we delete them.
243  if ($taskContainer->getId()) {
245  $olds = ValueToTaskContainer::where([ 'task_id' => $taskContainer->getId() ])->get();
246  foreach ($olds as $old) {
247  $old->delete();
248  }
249  } else {
250  // We need a valid ID to link the inputs
251  $taskContainer->save();
252  }
253 
254  // We create the new 1 to n relation.
255  foreach ($task->getInput() as $inputValue) {
256  $v = new ValueToTaskContainer(0, $this->connector);
257  $v->setTaskId($taskContainer->getId());
258  $v->setBucketId($bucketId);
259  $v->setValueId($this->getValueContainerId($inputValue));
260  $v->save();
261  }
262  }
263 
264 
272  protected function saveValue(Value $value, $bucketId)
273  {
274  // If we have previous values to task associations we delete them.
275  if (isset($this->valueHashToValueContainerId[spl_object_hash($value)])) {
276  $valueContainer = new ValueContainer($this->valueHashToValueContainerId[spl_object_hash($value)], $this->connector);
277  } else {
278  $valueContainer = new ValueContainer(0, $this->connector);
279  }
280 
281  // Save information about the value
282  $reflection = new \ReflectionClass(get_class($value));
283  $valueContainer->setClassName(get_class($value));
284  $valueContainer->setClassPath($reflection->getFileName());
285  $valueContainer->setType($value->getType());
286  $valueContainer->setHasParenttask($value->hasParentTask());
287  $valueContainer->setBucketId($bucketId);
288  $valueContainer->setHash($value->getHash());
289  $valueContainer->setSerialized($value->serialize());
290 
291  // If the value is a thunk value we also store its parent.
292  if ($value->hasParentTask()) {
293  $this->saveTask($value->getParentTask(), $bucketId);
294  $valueContainer->setParentTaskid($this->getTaskContainerId($value->getParentTask()));
295  }
296 
297  // We save the container and store the instance to container association.
298  $valueContainer->save();
299  $this->valueHashToValueContainerId[spl_object_hash($value)] = $valueContainer->getId();
300  }
301 
302 
309  public function getBucketContainerId(Bucket $bucket)
310  {
311  if (!isset($this->bucketHashToObserverContainerId[spl_object_hash($bucket)])) {
312  throw new SerializationException("Could not resolve container id of task: "
313  . print_r($bucket, true));
314  }
315 
316  return $this->bucketHashToObserverContainerId[spl_object_hash($bucket)];
317  }
318 
319 
326  protected function getTaskContainerId(Task $task)
327  {
328  if (!isset($this->taskHashToTaskContainerId[spl_object_hash($task)])) {
329  throw new SerializationException("Could not resolve container id of task: "
330  . print_r($task, true));
331  }
332 
333  return $this->taskHashToTaskContainerId[spl_object_hash($task)];
334  }
335 
336 
343  protected function getValueContainerId($value)
344  {
345  if (!isset($this->valueHashToValueContainerId[spl_object_hash($value)])) {
346  throw new SerializationException("Could not resolve container id of value: "
347  . print_r($value, true));
348  }
349 
350  return $this->valueHashToValueContainerId[spl_object_hash($value)];
351  }
352 
353 
360  public function loadBucket($bucket_id)
361  {
362  if (isset(self::$buckets[$bucket_id])) {
363  return self::$buckets[$bucket_id];
364  }
366  $bucketContainer = BucketContainer::find($bucket_id);
367  if (!$bucketContainer) {
368  throw new BucketNotFoundException("The requested bucket with container id $bucket_id could not be found in the database.");
369  }
370  $bucket = new BasicBucket();
371 
372  $bucket->setUserId($bucketContainer->getUserId());
373  $bucket->setState($bucketContainer->getState());
374  $bucket->setTitle($bucketContainer->getTitle());
375  $bucket->setDescription($bucketContainer->getDescription());
376  $bucket->setOverallPercentage($bucketContainer->getPercentage());
377  $bucket->setLastHeartbeat($bucketContainer->getLastHeartbeat());
378  $bucket->setTask($this->loadTask($bucketContainer->getRootTaskid(), $bucket, $bucketContainer));
379 
380  $this->bucketHashToObserverContainerId[spl_object_hash($bucket)] = $bucket_id;
381 
382  return $bucket;
383  }
384 
385 
397  private function loadTask($taskContainerId, Bucket $bucket, BucketContainer $bucketContainer)
398  {
399  global $DIC;
400  $factory = $DIC->backgroundTasks()->taskFactory();
402  $taskContainer = TaskContainer::find($taskContainerId);
404  require_once($taskContainer->getClassPath());
406  $task = $factory->createTask($taskContainer->getClassName());
407 
408  // Bugfix 0023775
409  // Added additional orderBy for the id to ensure that the items are returned in the right order.
411  $valueToTasks = ValueToTaskContainer::where([ 'task_id' => $taskContainerId ])->orderBy('task_id')->orderBy('id')->get();
412  $inputs = [];
413  foreach ($valueToTasks as $valueToTask) {
414  $inputs[] = $this->loadValue($valueToTask->getValueId(), $bucket, $bucketContainer);
415  }
416  $task->setInput($inputs);
417 
418  if ($taskContainerId == $bucketContainer->getCurrentTaskid()) {
419  $bucket->setCurrentTask($task);
420  }
421 
422  $this->taskHashToTaskContainerId[spl_object_hash($task)] = $taskContainerId;
423 
424  return $task;
425  }
426 
427 
428  private function loadValue($valueContainerId, Bucket $bucket, BucketContainer $bucketContainer)
429  {
430  global $DIC;
431  $factory = $DIC->backgroundTasks()->injector();
432 
434  $valueContainer = ValueContainer::find($valueContainerId);
436  require_once($valueContainer->getClassPath());
438  $value = $factory->createInstance($valueContainer->getClassName());
439 
440  $value->unserialize($valueContainer->getSerialized());
441  if ($valueContainer->getHasParenttask()) {
442  $value->setParentTask($this->loadTask($valueContainer->getParentTaskid(), $bucket, $bucketContainer));
443  }
444 
445  $this->valueHashToValueContainerId[spl_object_hash($value)] = $valueContainerId;
446 
447  return $value;
448  }
449 
450 
451  public function deleteBucketById($bucket_id)
452  {
454  $buckets = BucketContainer::where([ 'id' => $bucket_id ])->get();
455  array_map(function (\ActiveRecord $item) {
456  $item->delete();
457  }, $buckets);
458 
460  $tasks = TaskContainer::where([ 'bucket_id' => $bucket_id ])->get();
461  array_map(function (\ActiveRecord $item) {
462  $item->delete();
463  }, $tasks);
464 
466  $values = ValueContainer::where([ 'bucket_id' => $bucket_id ])->get();
467  array_map(function (\ActiveRecord $item) {
468  $item->delete();
469  }, $values);
470 
472  $valueToTasks = ValueToTaskContainer::where([ 'bucket_id' => $bucket_id ])->get();
473  array_map(function (\ActiveRecord $item) {
474  $item->delete();
475  }, $valueToTasks);
476  }
477 
478 
482  public function deleteBucket($bucket)
483  {
484  $id = $this->getBucketContainerId($bucket);
485  $this->deleteBucketById($id);
486  unset($this->bucketHashToObserverContainerId[spl_object_hash($bucket)]);
487  }
488 
489 
495  public function loadBuckets($bucket_container_id)
496  {
497  $buckets = [];
498  foreach ($bucket_container_id as $bucket_id) {
499  $buckets[] = $this->loadBucket($bucket_id);
500  }
501 
502  return $buckets;
503  }
504 }
setConnector(\arConnector $connector)
Currently for testing only.
Class ActiveRecord.
global $DIC
Definition: saml.php:7
deleteBucket($bucket)
Delete the bucket and all its stuff.Bucketvoid
$factory
Definition: metadata.php:47
if(!array_key_exists('StateId', $_REQUEST)) $id
Class arConnector.
static where($where, $operator=null)
if(!array_key_exists('stateid', $_REQUEST)) $state
Handle linkback() response from LinkedIn.
Definition: linkback.php:10
updateBucket(Bucket $bucket)
Updates only the bucket! Use this if e.g.
getLastHeartbeat()
When was the last time that something happened on this bucket?
saveBucketAndItsTasks(Bucket $bucket)
Fully updates or creates an Observer and all its tasks into the database.
$old
getBucketIdsByState($state)
intint[] Returns a list of bucket ids for the given Observer State
deleteBucketById($bucket_id)
Deletes the Observer AND all its tasks and values.
getBucketIdsOfUser($user_id, $order_by="id", $order_direction="ASC")
[] Returns an array of bucket ids for the given user Id.
loadBucket($bucket_container_id)