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