Import of W&K seminar exports with preview, booking form via form generator with event-dependent field rules, notification routing, inbox with folders and CSV export for W&K. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
111 lines
3.2 KiB
PHP
111 lines
3.2 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Mummert\ContaoWkSyncBundle\Import;
|
|
|
|
use Contao\StringUtil;
|
|
use Doctrine\DBAL\ArrayParameterType;
|
|
use Doctrine\DBAL\Connection;
|
|
|
|
/**
|
|
* Kursleiter und Referenten aus W&K als Mitglieder (tl_member) führen. Die Zuordnung erfolgt wie bisher
|
|
* über den Nachnamen; W&K liefert meist „Vorname Nachname“ in einem Feld.
|
|
*/
|
|
class MemberResolver
|
|
{
|
|
/** @var array<string, int|null> */
|
|
private array $lookup = [];
|
|
|
|
public function __construct(private readonly Connection $connection)
|
|
{
|
|
}
|
|
|
|
/**
|
|
* ID eines vorhandenen Mitglieds mit diesem Namen, ohne es anzulegen.
|
|
*/
|
|
public function findId(string $name): int|null
|
|
{
|
|
$name = trim($name);
|
|
|
|
if ('' === $name) {
|
|
return null;
|
|
}
|
|
|
|
$key = mb_strtolower($name);
|
|
|
|
if (!\array_key_exists($key, $this->lookup)) {
|
|
$id = $this->connection->fetchOne('SELECT id FROM tl_member WHERE lastname = ? ORDER BY id LIMIT 1', [$name]);
|
|
$this->lookup[$key] = false === $id ? null : (int) $id;
|
|
}
|
|
|
|
return $this->lookup[$key];
|
|
}
|
|
|
|
/**
|
|
* ID des Mitglieds; legt es bei Bedarf an und ergänzt die Mitgliedergruppe.
|
|
*
|
|
* @return array{0: int|null, 1: bool} ID und ob neu angelegt
|
|
*/
|
|
public function resolve(string $name, int $groupId): array
|
|
{
|
|
$name = trim($name);
|
|
|
|
if ('' === $name) {
|
|
return [null, false];
|
|
}
|
|
|
|
$id = $this->findId($name);
|
|
$created = false;
|
|
|
|
if (null === $id) {
|
|
$this->connection->insert('tl_member', [
|
|
'tstamp' => time(),
|
|
'dateAdded' => time(),
|
|
'firstname' => '',
|
|
'lastname' => $name,
|
|
'groups' => serialize($groupId > 0 ? [(string) $groupId] : []),
|
|
]);
|
|
|
|
$id = (int) $this->connection->lastInsertId();
|
|
$this->lookup[mb_strtolower($name)] = $id;
|
|
$created = true;
|
|
} elseif ($groupId > 0) {
|
|
$this->ensureGroup($id, $groupId);
|
|
}
|
|
|
|
return [$id, $created];
|
|
}
|
|
|
|
/**
|
|
* @param list<int> $ids
|
|
*
|
|
* @return array<int, string> ID => Name
|
|
*/
|
|
public function namesByIds(array $ids): array
|
|
{
|
|
$ids = array_values(array_filter(array_map(intval(...), $ids)));
|
|
|
|
if ([] === $ids) {
|
|
return [];
|
|
}
|
|
|
|
$rows = $this->connection->fetchAllKeyValue('SELECT id, TRIM(CONCAT(lastname, " ", firstname)) FROM tl_member WHERE id IN (?)', [$ids], [ArrayParameterType::INTEGER]);
|
|
|
|
return array_map(strval(...), array_combine(array_map(intval(...), array_keys($rows)), array_values($rows)));
|
|
}
|
|
|
|
private function ensureGroup(int $memberId, int $groupId): void
|
|
{
|
|
$groups = StringUtil::deserialize($this->connection->fetchOne('SELECT `groups` FROM tl_member WHERE id = ?', [$memberId]), true);
|
|
$groups = array_map(strval(...), $groups);
|
|
|
|
if (\in_array((string) $groupId, $groups, true)) {
|
|
return;
|
|
}
|
|
|
|
$groups[] = (string) $groupId;
|
|
$this->connection->update('tl_member', ['groups' => serialize(array_values($groups)), 'tstamp' => time()], ['id' => $memberId]);
|
|
}
|
|
}
|