Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 107 additions & 11 deletions components/ILIAS/ResourceStorage/classes/CollectionDBRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ class CollectionDBRepository implements CollectionRepository
public const R_IDENTIFICATION = 'rid';
public const C_IDENTIFICATION = 'rcid';

/** @var array<string, string[]> */
private array $resource_ids_cache = [];

public function __construct(protected \ilDBInterface $db)
{
}
Expand All @@ -55,11 +58,18 @@ public function blank(
?int $owner_id = null,
?string $title = null
): ResourceCollection {
return new ResourceCollection(
$collection = new ResourceCollection(
$identification,
$owner_id ?? ResourceCollection::NO_SPECIFIC_OWNER,
$title ?? ''
);

$rcid = $identification->serialize();
if (!isset($this->resource_ids_cache[$rcid])) {
$this->resource_ids_cache[$rcid] = [];
}

return $collection;
}

public function existing(ResourceCollectionIdentification $identification): ResourceCollection
Expand Down Expand Up @@ -91,17 +101,24 @@ public function has(ResourceCollectionIdentification $identification): bool
*/
public function getResourceIdStrings(ResourceCollectionIdentification $identification): \Generator
{
$q = "SELECT " . self::R_IDENTIFICATION . " FROM " . self::COLLECTION_ASSIGNMENT_TABLE_NAME . " WHERE " . self::C_IDENTIFICATION . " = %s ORDER BY position ASC";
$r = $this->db->queryF($q, ['text'], [$identification->serialize()]);
while ($d = $this->db->fetchAssoc($r)) {
yield (string) $d[self::R_IDENTIFICATION];
$rcid = $identification->serialize();

if (!isset($this->resource_ids_cache[$rcid])) {
$this->preload([$rcid]);
}

foreach ($this->resource_ids_cache[$rcid] ?? [] as $rid) {
yield $rid;
}
}

public function clear(ResourceCollectionIdentification $identification): void
{
$rcid = $identification->serialize();
$q = "DELETE FROM " . self::COLLECTION_ASSIGNMENT_TABLE_NAME . " WHERE " . self::C_IDENTIFICATION . " = %s";
$r = $this->db->manipulateF($q, ['text'], [$identification->serialize()]);
$this->db->manipulateF($q, ['text'], [$rcid]);

$this->resource_ids_cache[$rcid] = [];
}

public function update(ResourceCollection $collection, DataContainer $event_data_container): void
Expand Down Expand Up @@ -148,6 +165,8 @@ public function update(ResourceCollection $collection, DataContainer $event_data
]
);
}

$this->resource_ids_cache[$identification->serialize()] = array_values($resource_identification_strings);
if ($this->has($identification)) {
$this->db->update(
self::COLLECTION_TABLE_NAME,
Expand All @@ -174,34 +193,111 @@ public function update(ResourceCollection $collection, DataContainer $event_data

public function removeResourceFromAllCollections(ResourceIdentification $resource_identification): void
{
$rid = $resource_identification->serialize();

$this->db->manipulateF(
"DELETE FROM " . self::COLLECTION_ASSIGNMENT_TABLE_NAME . " WHERE " . self::R_IDENTIFICATION . " = %s",
['text'],
[$resource_identification->serialize()]
[$rid]
);

foreach ($this->resource_ids_cache as $rcid => $rids) {
if (in_array($rid, $rids, true)) {
$this->resource_ids_cache[$rcid] = array_values(array_diff($rids, [$rid]));
}
}
}

public function delete(ResourceCollectionIdentification $identification): void
{
$rcid = $identification->serialize();

$this->db->manipulateF(
"DELETE FROM " . self::COLLECTION_ASSIGNMENT_TABLE_NAME . " WHERE " . self::C_IDENTIFICATION . " = %s",
['text'],
[$identification->serialize()]
[$rcid]
);
$this->db->manipulateF(
"DELETE FROM " . self::COLLECTION_TABLE_NAME . " WHERE " . self::C_IDENTIFICATION . " = %s",
['text'],
[$identification->serialize()]
[$rcid]
);

unset($this->resource_ids_cache[$rcid]);
}

public function preload(array $identification_strings): void
{
// TODO: Implement preload() method.
if ($identification_strings === []) {
return;
}

$identification_strings = array_values(array_unique($identification_strings));

$to_load = [];
foreach ($identification_strings as $rcid) {
if (!isset($this->resource_ids_cache[$rcid])) {
$this->resource_ids_cache[$rcid] = [];
$to_load[] = $rcid;
}
}

if ($to_load === []) {
return;
}

$q = "SELECT " . self::C_IDENTIFICATION . ", " . self::R_IDENTIFICATION .
" FROM " . self::COLLECTION_ASSIGNMENT_TABLE_NAME .
" WHERE " . $this->db->in(self::C_IDENTIFICATION, $to_load, false, 'text') .
" ORDER BY position ASC";

$res = $this->db->query($q);
while ($row = $this->db->fetchAssoc($res)) {
$rcid = (string) $row[self::C_IDENTIFICATION];
$rid = (string) $row[self::R_IDENTIFICATION];
$this->resource_ids_cache[$rcid][] = $rid;
}
}

/**
* @param string[] $collection_identifications
* @return ResourceIdentification[]
*/
public function getResourceIdsForCollections(array $collection_identifications): array
{
if ($collection_identifications === []) {
return [];
}

$collection_identifications = array_values(array_unique($collection_identifications));

$to_preload = [];
foreach ($collection_identifications as $rcid) {
if (!isset($this->resource_ids_cache[$rcid])) {
$to_preload[] = $rcid;
}
}
if ($to_preload !== []) {
$this->preload($to_preload);
}

$result_rids = [];
foreach ($collection_identifications as $rcid) {
foreach ($this->resource_ids_cache[$rcid] ?? [] as $rid) {
$result_rids[] = $rid;
}
}

$result_rids = array_values(array_unique($result_rids));

return array_map(
static fn(string $rid): ResourceIdentification => new ResourceIdentification($rid),
$result_rids
);
}

public function populateFromArray(array $data): void
{
// TODO: Implement populateFromArray() method.
// Nothing to do here
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,14 @@
use ILIAS\ResourceStorage\Identification\ResourceIdentification;
use ILIAS\ResourceStorage\Lock\LockingRepository;
use ILIAS\ResourceStorage\Events\DataContainer;
use ILIAS\ResourceStorage\Preloader\PreloadableRepository;

/**
* Interface CollectionRepository
*
* @author Fabian Schmid <fabian@sr.solutions>
*/
interface CollectionRepository extends LockingRepository
interface CollectionRepository extends LockingRepository, PreloadableRepository
{
public function has(ResourceCollectionIdentification $identification): bool;

Expand All @@ -46,6 +47,12 @@ public function clear(ResourceCollectionIdentification $identification): void;
*/
public function getResourceIdStrings(ResourceCollectionIdentification $identification): \Generator;

/**
* @param string[] $collection_identifications
* @return ResourceIdentification[]
*/
public function getResourceIdsForCollections(array $collection_identifications): array;

public function update(ResourceCollection $collection, DataContainer $event_data_container): void;

public function delete(ResourceCollectionIdentification $identification): void;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,12 @@
interface RepositoryPreloader
{
public function preload(array $identification_strings): void;

/**
* Preload collections (by their collection identifications) and all
* resources contained in those collections.
*
* @param string[] $collection_identification_strings
*/
public function preloadCollections(array $collection_identification_strings): void;
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
use ILIAS\ResourceStorage\Stakeholder\Repository\StakeholderRepository;
use ILIAS\ResourceStorage\Repositories;
use ILIAS\ResourceStorage\Resource\Repository\FlavourRepository;
use ILIAS\ResourceStorage\Collection\Repository\CollectionRepository;
use ILIAS\ResourceStorage\Identification\ResourceIdentification;

/**
* Class StandardRepositoryPreloader
Expand All @@ -38,6 +40,7 @@ class StandardRepositoryPreloader implements RepositoryPreloader
protected InformationRepository $information_repository;
protected StakeholderRepository $stakeholder_repository;
protected FlavourRepository $flavour_repository;
protected CollectionRepository $collection_repository;

public function __construct(Repositories $repositories)
{
Expand All @@ -46,6 +49,7 @@ public function __construct(Repositories $repositories)
$this->information_repository = $repositories->getInformationRepository();
$this->stakeholder_repository = $repositories->getStakeholderRepository();
$this->flavour_repository = $repositories->getFlavourRepository();
$this->collection_repository = $repositories->getCollectionRepository();
}

public function preload(array $identification_strings): void
Expand All @@ -56,4 +60,24 @@ public function preload(array $identification_strings): void
$this->stakeholder_repository->preload($identification_strings);
$this->flavour_repository->preload($identification_strings);
}

/**
* @param string[] $collection_identification_strings
*/
public function preloadCollections(array $collection_identification_strings): void
{
if ($collection_identification_strings === []) {
return;
}
$resource_ids = $this->collection_repository->getResourceIdsForCollections($collection_identification_strings);
$resource_ids = array_values(array_unique(
array_map(static fn(ResourceIdentification $id) => $id->serialize(), $resource_ids)
));

if ($resource_ids === []) {
return;
}

$this->preload($resource_ids);
}
}
8 changes: 8 additions & 0 deletions components/ILIAS/ResourceStorage/src/Services.php
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,14 @@ public function preload(array $identification_strings): void
$this->preloader->preload($identification_strings);
}

/**
* @param string[] $collection_identification_strings
*/
public function preloadCollections(array $collection_identification_strings): void
{
$this->preloader->preloadCollections($collection_identification_strings);
}

public function events(): Subject
{
return $this->events;
Expand Down