ILIAS  release_8 Revision v8.24
class.ilECSEventQueueReader.php
Go to the documentation of this file.
1<?php
2
18declare(strict_types=1);
19
26{
27 public const TYPE_EXPORTED = 'exported';
28 public const TYPE_DIRECTORY_TREES = 'directory_trees';
29 public const TYPE_CMS_COURSES = 'courses';
30 public const TYPE_CMS_COURSE_MEMBERS = 'course_members';
31 public const TYPE_REMOTE_COURSE = 'rcrs';
32 public const TYPE_REMOTE_CATEGORY = 'rcat';
33 public const TYPE_REMOTE_FILE = 'rfil';
34 public const TYPE_REMOTE_GLOSSARY = 'rglo';
35 public const TYPE_REMOTE_GROUP = 'rgrp';
36 public const TYPE_REMOTE_LEARNING_MODULE = 'rlm';
37 public const TYPE_REMOTE_WIKI = 'rwik';
38 public const TYPE_REMOTE_TEST = 'rtst';
39 public const TYPE_COURSE_URLS = 'course_urls';
40 public const TYPE_ENROLMENT_STATUS = 'member_status';
41
44
45 protected array $events = array();
46 protected array $econtent_ids = array();
48
55 {
56 global $DIC;
57
58 $this->logger = $DIC->logger()->wsrv();
59 $this->db = $DIC->database();
60
61 $this->settings = $settings;
62 $this->read();
63 }
64
68 protected static function getEventTypeFromObjectType(string $a_obj_type): string
69 {
70 // currently they are the same for all resource types
71 return $a_obj_type;
72 }
73
77 public static function getAllEContentTypes(): array
78 {
79 return array(self::TYPE_REMOTE_COURSE, self::TYPE_REMOTE_CATEGORY,
80 self::TYPE_REMOTE_FILE, self::TYPE_REMOTE_GLOSSARY, self::TYPE_REMOTE_GROUP,
81 self::TYPE_REMOTE_LEARNING_MODULE, self::TYPE_REMOTE_WIKI, self::TYPE_REMOTE_TEST);
82 }
83
92 protected static function getAllResourceIds(ilECSSetting $server, array $a_types, bool $a_sender_only = false): array
93 {
94 $list = array();
95 foreach ($a_types as $type) {
97 if ($robj) {
98 $list[$type] = $robj->getAllResourceIds($server, $a_sender_only);
99 }
100 }
101
102 return $list;
103 }
104
110 public function handleImportReset(): bool
111 {
112 try {
113 $types = self::getAllEContentTypes();
114
115 $this->deleteAllEContentEvents($types);
116
117 $list = self::getAllResourceIds($this->settings, $types);
118 $imported = ilECSImportManager::getInstance()->getAllImportedRemoteObjects($this->settings->getServerId());
119
120 $this->logger->info(__METHOD__ . ': Imported = ' . print_r($imported, true));
121 $this->logger->info(__METHOD__ . ': List = ' . print_r($list, true));
122
123 foreach ($list as $resource_type => $link_ids) {
124 if (!in_array($resource_type, ilECSUtils::getPossibleRemoteTypes(), true)) {
125 $this->logger->info(__METHOD__ . ': Ignoring resource type ' . $resource_type);
126 continue;
127 }
128
129
130 foreach ((array) $link_ids as $link_id) {
131 if (!isset($imported[$link_id])) {
132 // Add create event for not imported econtent
133 $this->add(
134 $resource_type,
135 $link_id,
137 );
138 } else {
139 // Add update event for already existing events
140 $this->add(
141 $resource_type,
142 $link_id,
144 );
145 }
146
147 if (isset($imported[$link_id])) {
148 unset($imported[$link_id]);
149 }
150 }
151 }
152
153 if (is_array($imported)) {
154 // Delete event for deprecated econtent
155 foreach ($imported as $econtent_id => $obj_id) {
157 if ($type) {
158 $this->add(
159 $type,
160 $econtent_id,
162 );
163 }
164 }
165 }
166 } catch (ilECSConnectorException $e1) {
167 $this->logger->info('Cannot connect to ECS server: ' . $e1->getMessage());
168 throw $e1;
169 } catch (ilException $e2) {
170 $this->logger->info('Update failed: ' . $e2->getMessage());
171 throw $e2;
172 }
173 return true;
174 }
175
182 public function handleExportReset(): bool
183 {
184 // Delete all export events
185
187
188 // Read all local export info
189 $exportManager = ilECSExportManager::getInstance();
190 $local_econtent_ids = $exportManager->_getAllEContentIds($this->settings->getServerId());
191
192 $types = self::getAllEContentTypes();
193 $list = self::getAllResourceIds($this->settings, $types, true);
194
195
196 // merge in one array
197 $all_remote_ids = [];
198 foreach ($list as $resource_type => $remote_ids) {
199 $all_remote_ids += (array) $remote_ids;
200 }
201 $all_remote_ids = array_unique($all_remote_ids);
202
203 $this->logger->info(__METHOD__ . ': Resources = ' . print_r($all_remote_ids, true));
204 $this->logger->info(__METHOD__ . ': Local = ' . print_r($local_econtent_ids, true));
205 foreach ($local_econtent_ids as $local_econtent_id => $local_obj_id) {
206 if (!in_array($local_econtent_id, $all_remote_ids, true)) {
207 // Delete this deprecated info
208 $this->logger->info(__METHOD__ . ': Deleting deprecated econtent id ' . $local_econtent_id);
209 $exportManager->_deleteEContentIds($this->settings->getServerId(), array($local_econtent_id));
210 }
211 }
212 return true;
213 }
214
215
219 public function getServer(): \ilECSSetting
220 {
221 return $this->settings;
222 }
223
224
228 public function getEvents(): array
229 {
230 return $this->events ?: array();
231 }
232
236 public function deleteAll(): bool
237 {
238 $query = "DELETE FROM ecs_events " .
239 'WHERE server_id = ' . $this->db->quote($this->settings->getServerId(), 'integer');
240 $this->db->manipulate($query);
241 return true;
242 }
243
247 public function deleteAllEContentEvents(array $a_types): bool
248 {
249 $query = "DELETE FROM ecs_events " .
250 "WHERE " . $this->db->in("type", $a_types, false, "text") . ' ' .
251 'AND server_id = ' . $this->db->quote($this->getServer()->getServerId(), 'integer');
252 $this->db->manipulate($query);
253 return true;
254 }
255
259 protected function deleteAllExportedEvents(): bool
260 {
261 $query = "DELETE FROM ecs_events " .
262 "WHERE type = " . $this->db->quote(self::TYPE_EXPORTED, 'text') . ' ' .
263 'AND server_id = ' . $this->db->quote($this->getServer()->getServerId(), 'integer');
264 $this->db->manipulate($query);
265 return true;
266 }
267
273 public function refresh(): void
274 {
275 try {
276 $connector = new ilECSConnector($this->getServer());
277 while (true) {
278 $res = $connector->readEventFifo(false);
279
280 if (!count($res->getResult())) {
281 return;
282 }
283
284 foreach ($res->getResult() as $result) {
285 $event = new ilECSEvent($result);
286
287 $this->logger->info(__METHOD__ . ' ---------------------------- Handling new event ');
288 $this->logger->info(__METHOD__ . print_r($event, true));
289 $this->logger->info(__METHOD__ . ' ---------------------------- Done! ');
290
291 // Fill command queue
292 $this->writeEventToDB($event);
293 }
294 // Delete from fifo
295 $connector->readEventFifo(true);
296 }
297 } catch (ilECSConnectorException $e) {
298 $this->logger->error(__METHOD__ . ': Cannot read event fifo. Aborting');
299 }
300 }
301
305 public function delete(): void
306 {
307 $query = 'DELETE FROM ecs_events ' .
308 'WHERE server_id = ' . $this->db->quote($this->getServer()->getServerId(), 'integer');
309 $this->db->manipulate($query);
310 }
311
315 private function writeEventToDB(ilECSEvent $ev): void
316 {
317 // this should probably be moved elsewhere
318 switch ($ev->getRessourceType()) {
319 case 'directory_trees':
321 break;
322
323 case 'course_members':
325 break;
326
327 case 'courses':
329 break;
330
331 case 'courselinks':
333 break;
334
335 case 'categories':
337 break;
338
339 case 'files':
341 break;
342
343 case 'glossaries':
345 break;
346
347 case 'groups':
349 break;
350
351 case 'learningmodules':
353 break;
354
355 case 'wikis':
357 break;
358
359 case 'tests':
361 break;
362
363 case 'course_urls':
365 break;
366
367 case 'member_status':
369 break;
370
371 default:
372 // write custom event type
373 $type = $ev->getRessourceType();
374 break;
375 }
376
377 $query = "SELECT * FROM ecs_events " .
378 "WHERE type = " . $this->db->quote($type, 'text') . " " .
379 "AND id = " . $this->db->quote($ev->getRessourceId(), 'integer') . " " .
380 'AND server_id = ' . $this->db->quote($this->getServer()->getServerId(), 'integer');
381 $res = $this->db->query($query);
382
383 $event_id = 0;
384 while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
385 $event_id = $row->event_id;
386 }
387
388 if (!$event_id) {
389 // No previous entry exists => perform insert
390 $query = "INSERT ecs_events (event_id,type,id,op,server_id) " .
391 "VALUES( " .
392 $this->db->quote($this->db->nextId('ecs_events'), 'integer') . ',' .
393 $this->db->quote($type, 'text') . ', ' .
394 $this->db->quote($ev->getRessourceId(), 'integer') . ', ' .
395 $this->db->quote($ev->getStatus(), 'text') . ', ' .
396 $this->db->quote($this->getServer()->getServerId(), 'integer') . ' ' .
397 ')';
398 $this->db->manipulate($query);
399 return;
400 }
401 // Do update
402 $do_update = false;
403 switch ($ev->getStatus()) {
405 // Do update, although impossible
406 $do_update = true;
407 break;
408
410 $do_update = true;
411 break;
412
414 // Do nothing. Old status is ok.
415 break;
416 }
417
418 if (!$do_update) {
419 return;
420 }
421 $query = "UPDATE ecs_events " .
422 "SET op = " . $this->db->quote($ev->getStatus(), 'text') . " " .
423 "WHERE event_id = " . $this->db->quote($event_id, 'integer') . ' ' .
424 'AND type = ' . $this->db->quote($type, 'text') . ' ' .
425 'AND server_id = ' . $this->db->quote($this->getServer()->getServerId(), 'integer');
426 $this->db->manipulate($query);
427 }
428
434 public function shift(): array
435 {
436 $event = array_shift($this->events);
437 return $event ?? [];
438 }
439
440
444 public function add(string $a_type, int $a_id, string $a_op): bool
445 {
446 $next_id = $this->db->nextId('ecs_events');
447 $query = "INSERT INTO ecs_events (event_id,type,id,op,server_id) " .
448 "VALUES (" .
449 $this->db->quote($next_id, 'integer') . ", " .
450 $this->db->quote($a_type, 'text') . ", " .
451 $this->db->quote($a_id, 'integer') . ", " .
452 $this->db->quote($a_op, 'text') . ", " .
453 $this->db->quote($this->getServer()->getServerId(), 'integer') . ' ' .
454 ")";
455 $this->db->manipulate($query);
456
457 $new_event['event_id'] = $next_id;
458 $new_event['type'] = $a_type;
459 $new_event['id'] = $a_id;
460 $new_event['op'] = $a_op;
461
462 $this->events[] = $new_event;
463 $this->econtent_ids[$a_id] = $a_id;
464 return true;
465 }
466
470 private function update(string $a_type, int $a_id, string $a_operation): void
471 {
472 $query = "UPDATE ecs_events " .
473 "SET op = " . $this->db->quote($a_operation, 'text') . " " .
474 "WHERE type = " . $this->db->quote($a_type, 'text') . " " .
475 "AND id = " . $this->db->quote($a_id, 'integer') . " " .
476 'AND server_id = ' . $this->db->quote($this->settings->getServerId(), 'integer');
477 $this->db->manipulate($query);
478 }
479
483 public function deleteEvent(int $a_event_id): bool
484 {
485 $query = "DELETE FROM ecs_events " .
486 "WHERE event_id = " . $this->db->quote($a_event_id, 'integer') . " " .
487 'AND server_id = ' . $this->db->quote($this->getServer()->getServerId(), 'integer');
488 $this->db->manipulate($query);
489 unset($this->econtent_ids[$a_event_id]);
490 return true;
491 }
492
496 private function read(): bool
497 {
498 $query = "SELECT * FROM ecs_events " .
499 'WHERE server_id = ' . $this->db->quote($this->getServer()->getServerId(), 'integer') . ' ' .
500 'ORDER BY event_id';
501
502 $res = $this->db->query($query);
503 while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
504 $event = [];
505 $event['event_id'] = (int) $row->event_id;
506 $event['type'] = $row->type;
507 $event['id'] = (int) $row->id;
508 $event['op'] = $row->op;
509 $this->events[] = $event;
510
511 $this->econtent_ids[(int) $row->event_id] = (int) $row->event_id;
512 }
513 return true;
514 }
515
516 public static function deleteByServerId(int $a_server_id): bool
517 {
518 global $DIC;
519
520 $ilDB = $DIC['ilDB'];
521
522 $query = 'DELETE FROM ecs_events' .
523 ' WHERE server_id = ' . $ilDB->quote($a_server_id, 'integer');
524 $ilDB->manipulate($query);
525 return true;
526 }
527}
Reads ECS events and stores them in the database.
static getAllEContentTypes()
All available content types.
handleImportReset()
Reread all imported econtent.
handleExportReset()
Handle export reset.
deleteAllEContentEvents(array $a_types)
Delete all econtents.
add(string $a_type, int $a_id, string $a_op)
add
writeEventToDB(ilECSEvent $ev)
Write event to db.
refresh()
Fetch events from fifo Using fifo.
shift()
get and delete the first event entry
update(string $a_type, int $a_id, string $a_operation)
update one entry
deleteAllExportedEvents()
Delete all exported events.
static deleteByServerId(int $a_server_id)
__construct(ilECSSetting $settings)
Constructor.
static getEventTypeFromObjectType(string $a_obj_type)
Convert object type to event type.
deleteEvent(int $a_event_id)
delete
static getAllResourceIds(ilECSSetting $server, array $a_types, bool $a_sender_only=false)
Get all resource ids by resource type.
getRessourceType()
Get ressource type.
getStatus()
get title
getRessourceId()
Get ressource id.
static getInstance()
Get the singelton instance of this ilECSExportManager.
static getInstance()
Get the singleton instance of this ilECSImportManager.
static getPossibleRemoteTypes(bool $a_with_captions=false)
Get all possible remote object types.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Component logger with individual log levels by component id.
static _lookupType(int $id, bool $reference=false)
static getInstanceByEventType(string $a_type)
Get instance by ilECSEvent(QueueReader) type.
$server
global $DIC
Definition: feed.php:28
Interface ilDBInterface.
$res
Definition: ltiservices.php:69
$query
$type