760 lines
24 KiB
PHP
760 lines
24 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace MummertMedia\EventManagerBundle\Service;
|
|
|
|
use Doctrine\DBAL\Connection;
|
|
use Doctrine\DBAL\ParameterType;
|
|
|
|
class EventRepository
|
|
{
|
|
public function __construct(
|
|
private readonly Connection $connection,
|
|
) {
|
|
}
|
|
|
|
/**
|
|
* @return array<int, array<string, mixed>>
|
|
*/
|
|
public function findByMemberId(int $memberId): array
|
|
{
|
|
return $this->connection->createQueryBuilder()
|
|
->select('DISTINCT e.*')
|
|
->from('tl_calendar_events', 'e')
|
|
->innerJoin('e', 'tl_calendar_events_organization', 'ceo', 'ceo.event_id = e.id')
|
|
->innerJoin('ceo', 'tl_member_organization', 'mo', 'mo.organization_id = ceo.organization_id')
|
|
->where('mo.member_id = :memberId')
|
|
->setParameter('memberId', $memberId, ParameterType::INTEGER)
|
|
->orderBy('e.startDate', 'DESC')
|
|
->executeQuery()
|
|
->fetchAllAssociative();
|
|
}
|
|
|
|
public function memberHasEvent(int $memberId, int $eventId): bool
|
|
{
|
|
$exists = $this->connection->createQueryBuilder()
|
|
->select('1')
|
|
->from('tl_calendar_events', 'e')
|
|
->innerJoin('e', 'tl_calendar_events_organization', 'ceo', 'ceo.event_id = e.id')
|
|
->innerJoin('ceo', 'tl_member_organization', 'mo', 'mo.organization_id = ceo.organization_id')
|
|
->where('e.id = :eventId')
|
|
->andWhere('mo.member_id = :memberId')
|
|
->setParameter('eventId', $eventId, ParameterType::INTEGER)
|
|
->setParameter('memberId', $memberId, ParameterType::INTEGER)
|
|
->setMaxResults(1)
|
|
->executeQuery()
|
|
->fetchOne();
|
|
|
|
return false !== $exists;
|
|
}
|
|
|
|
public function togglePublished(int $eventId): void
|
|
{
|
|
$published = $this->connection->createQueryBuilder()
|
|
->select('published')
|
|
->from('tl_calendar_events')
|
|
->where('id = :id')
|
|
->setParameter('id', $eventId, ParameterType::INTEGER)
|
|
->setMaxResults(1)
|
|
->executeQuery()
|
|
->fetchOne();
|
|
|
|
$isPublished = '1' === (string) $published;
|
|
|
|
$this->connection->update(
|
|
'tl_calendar_events',
|
|
[
|
|
'published' => $isPublished ? 0 : 1,
|
|
'tstamp' => time(),
|
|
],
|
|
['id' => $eventId],
|
|
['id' => ParameterType::INTEGER],
|
|
);
|
|
}
|
|
|
|
public function duplicate(int $eventId): ?int
|
|
{
|
|
$row = $this->findById($eventId);
|
|
|
|
if (null === $row) {
|
|
return null;
|
|
}
|
|
|
|
unset($row['id']);
|
|
|
|
if (array_key_exists('title', $row)) {
|
|
$normalizedTitle = html_entity_decode((string) $row['title'], ENT_QUOTES | ENT_HTML5, 'UTF-8');
|
|
$row['title'] = trim($normalizedTitle.' (Kopie)');
|
|
}
|
|
|
|
if (array_key_exists('alias', $row)) {
|
|
$row['alias'] = '';
|
|
}
|
|
|
|
if (array_key_exists('published', $row)) {
|
|
$row['published'] = 0;
|
|
}
|
|
|
|
$now = time();
|
|
|
|
if (array_key_exists('dateAdded', $row)) {
|
|
$row['dateAdded'] = $now;
|
|
}
|
|
|
|
if (array_key_exists('tstamp', $row)) {
|
|
$row['tstamp'] = $now;
|
|
}
|
|
|
|
$this->connection->insert('tl_calendar_events', $row);
|
|
|
|
$newEventId = (int) $this->connection->lastInsertId();
|
|
|
|
$organizationIds = $this->connection->createQueryBuilder()
|
|
->select('organization_id')
|
|
->from('tl_calendar_events_organization')
|
|
->where('event_id = :eventId')
|
|
->setParameter('eventId', $eventId, ParameterType::INTEGER)
|
|
->executeQuery()
|
|
->fetchFirstColumn();
|
|
|
|
foreach ($organizationIds as $organizationId) {
|
|
$this->connection->insert(
|
|
'tl_calendar_events_organization',
|
|
[
|
|
'event_id' => $newEventId,
|
|
'organization_id' => (int) $organizationId,
|
|
],
|
|
[
|
|
'event_id' => ParameterType::INTEGER,
|
|
'organization_id' => ParameterType::INTEGER,
|
|
],
|
|
);
|
|
}
|
|
|
|
$tagIds = $this->getTagIdsForEvent($eventId);
|
|
|
|
if ([] !== $tagIds) {
|
|
$this->assignTagsToEvent($newEventId, $tagIds);
|
|
}
|
|
|
|
return $newEventId;
|
|
}
|
|
|
|
public function createDraftForMember(int $memberId, int $authorId, int $archiveId): ?int
|
|
{
|
|
$resolvedArchiveId = $this->resolveArchiveId($archiveId);
|
|
|
|
if ($resolvedArchiveId <= 0) {
|
|
return null;
|
|
}
|
|
|
|
$organizationId = $this->connection->createQueryBuilder()
|
|
->select('organization_id')
|
|
->from('tl_member_organization')
|
|
->where('member_id = :memberId')
|
|
->setParameter('memberId', $memberId, ParameterType::INTEGER)
|
|
->orderBy('organization_id', 'ASC')
|
|
->setMaxResults(1)
|
|
->executeQuery()
|
|
->fetchOne();
|
|
|
|
if (false === $organizationId) {
|
|
return null;
|
|
}
|
|
|
|
$now = time();
|
|
|
|
$this->connection->insert(
|
|
'tl_calendar_events',
|
|
[
|
|
'pid' => $resolvedArchiveId,
|
|
'author' => max(0, $authorId),
|
|
'title' => '',
|
|
'alias' => '',
|
|
'startDate' => 0,
|
|
'endDate' => null,
|
|
'published' => 0,
|
|
'tstamp' => $now,
|
|
],
|
|
[
|
|
'pid' => ParameterType::INTEGER,
|
|
'author' => ParameterType::INTEGER,
|
|
],
|
|
);
|
|
|
|
$eventId = (int) $this->connection->lastInsertId();
|
|
|
|
if ($eventId <= 0) {
|
|
return null;
|
|
}
|
|
|
|
$this->connection->insert(
|
|
'tl_calendar_events_organization',
|
|
[
|
|
'tstamp' => $now,
|
|
'event_id' => $eventId,
|
|
'organization_id' => (int) $organizationId,
|
|
],
|
|
[
|
|
'event_id' => ParameterType::INTEGER,
|
|
'organization_id' => ParameterType::INTEGER,
|
|
],
|
|
);
|
|
|
|
return $eventId;
|
|
}
|
|
|
|
/** @return array{authorId:int,archiveId:int} */
|
|
public function findCreationDefaultsByListPage(int $listPageId): array
|
|
{
|
|
if ($listPageId <= 0) {
|
|
return ['authorId' => 0, 'archiveId' => 0];
|
|
}
|
|
|
|
$row = $this->connection->createQueryBuilder()
|
|
->select('frontendAuthorId', 'frontendArchiveId')
|
|
->from('tl_module')
|
|
->where('type = :type')
|
|
->andWhere('listPage = :listPage')
|
|
->setParameter('type', 'event_edit')
|
|
->setParameter('listPage', $listPageId, ParameterType::INTEGER)
|
|
->orderBy('id', 'ASC')
|
|
->setMaxResults(1)
|
|
->executeQuery()
|
|
->fetchAssociative();
|
|
|
|
if (false === $row || null === $row) {
|
|
return ['authorId' => 0, 'archiveId' => 0];
|
|
}
|
|
|
|
return [
|
|
'authorId' => (int) ($row['frontendAuthorId'] ?? 0),
|
|
'archiveId' => (int) ($row['frontendArchiveId'] ?? 0),
|
|
];
|
|
}
|
|
|
|
private function resolveArchiveId(int $archiveId): int
|
|
{
|
|
if ($archiveId > 0) {
|
|
$exists = $this->connection->createQueryBuilder()
|
|
->select('id')
|
|
->from('tl_calendar')
|
|
->where('id = :id')
|
|
->setParameter('id', $archiveId, ParameterType::INTEGER)
|
|
->setMaxResults(1)
|
|
->executeQuery()
|
|
->fetchOne();
|
|
|
|
if (false !== $exists) {
|
|
return $archiveId;
|
|
}
|
|
}
|
|
|
|
$fallback = $this->connection->createQueryBuilder()
|
|
->select('id')
|
|
->from('tl_calendar')
|
|
->orderBy('id', 'ASC')
|
|
->setMaxResults(1)
|
|
->executeQuery()
|
|
->fetchOne();
|
|
|
|
return false !== $fallback ? (int) $fallback : 0;
|
|
}
|
|
|
|
public function delete(int $eventId): void
|
|
{
|
|
$this->connection->delete(
|
|
'tl_tags_rel',
|
|
['ptable' => 'tl_calendar_events', 'field' => 'tags', 'pid' => $eventId],
|
|
['pid' => ParameterType::INTEGER],
|
|
);
|
|
|
|
$this->connection->delete(
|
|
'tl_calendar_events_organization',
|
|
['event_id' => $eventId],
|
|
['event_id' => ParameterType::INTEGER],
|
|
);
|
|
|
|
$this->connection->delete(
|
|
'tl_calendar_events',
|
|
['id' => $eventId],
|
|
['id' => ParameterType::INTEGER],
|
|
);
|
|
}
|
|
|
|
/** @return array<string, mixed>|null */
|
|
public function findById(int $eventId): ?array
|
|
{
|
|
$row = $this->connection->createQueryBuilder()
|
|
->select('*')
|
|
->from('tl_calendar_events')
|
|
->where('id = :id')
|
|
->setParameter('id', $eventId, ParameterType::INTEGER)
|
|
->setMaxResults(1)
|
|
->executeQuery()
|
|
->fetchAssociative();
|
|
|
|
return false === $row ? null : $row;
|
|
}
|
|
|
|
/** @return array{id:int,title:string}|null */
|
|
public function findPrimaryOrganizationForEvent(int $eventId): ?array
|
|
{
|
|
$row = $this->connection->createQueryBuilder()
|
|
->select('o.id', 'o.title')
|
|
->from('tl_calendar_events_organization', 'ceo')
|
|
->innerJoin('ceo', 'tl_organization', 'o', 'o.id = ceo.organization_id')
|
|
->where('ceo.event_id = :eventId')
|
|
->setParameter('eventId', $eventId, ParameterType::INTEGER)
|
|
->orderBy('ceo.organization_id', 'ASC')
|
|
->setMaxResults(1)
|
|
->executeQuery()
|
|
->fetchAssociative();
|
|
|
|
if (false === $row || null === $row) {
|
|
return null;
|
|
}
|
|
|
|
return [
|
|
'id' => (int) $row['id'],
|
|
'title' => (string) ($row['title'] ?? ''),
|
|
];
|
|
}
|
|
|
|
/** @return array<int> */
|
|
public function getOrganizationIdsForEvent(int $eventId): array
|
|
{
|
|
$rows = $this->connection->createQueryBuilder()
|
|
->select('organization_id')
|
|
->from('tl_calendar_events_organization')
|
|
->where('event_id = :eventId')
|
|
->setParameter('eventId', $eventId, ParameterType::INTEGER)
|
|
->orderBy('organization_id', 'ASC')
|
|
->executeQuery()
|
|
->fetchFirstColumn();
|
|
|
|
return array_values(array_unique(array_map('intval', $rows)));
|
|
}
|
|
|
|
/**
|
|
* @return array<string, int>
|
|
*/
|
|
public function getTagChoicesForEventType(array $allowedTagIds = []): array
|
|
{
|
|
$rows = $this->connection->createQueryBuilder()
|
|
->select('DISTINCT t.id', 't.tag')
|
|
->from('tl_tags', 't')
|
|
->innerJoin('t', 'tl_tags_rel', 'r', 'r.tag_id = t.id')
|
|
->where('r.ptable = :ptable')
|
|
->andWhere('r.field = :field')
|
|
->setParameter('ptable', 'tl_calendar_events')
|
|
->setParameter('field', 'tags')
|
|
->orderBy('t.tag', 'ASC')
|
|
->executeQuery()
|
|
->fetchAllAssociative();
|
|
|
|
if ([] === $rows) {
|
|
$rows = $this->connection->createQueryBuilder()
|
|
->select('t.id', 't.tag')
|
|
->from('tl_tags', 't')
|
|
->orderBy('t.tag', 'ASC')
|
|
->executeQuery()
|
|
->fetchAllAssociative();
|
|
}
|
|
|
|
$choices = [];
|
|
|
|
foreach ($rows as $row) {
|
|
$choices[(string) ($row['tag'] ?? '')] = (int) $row['id'];
|
|
}
|
|
|
|
$allowedTagIds = array_values(array_unique(array_map('intval', $allowedTagIds)));
|
|
|
|
if ([] !== $allowedTagIds) {
|
|
$choices = array_filter(
|
|
$choices,
|
|
static fn (int $id): bool => in_array($id, $allowedTagIds, true),
|
|
);
|
|
}
|
|
|
|
return $choices;
|
|
}
|
|
|
|
/** @return array<int> */
|
|
public function getTagIdsForEvent(int $eventId): array
|
|
{
|
|
if ($eventId <= 0) {
|
|
return [];
|
|
}
|
|
|
|
$ids = $this->connection->createQueryBuilder()
|
|
->select('tag_id')
|
|
->from('tl_tags_rel')
|
|
->where('ptable = :ptable')
|
|
->andWhere('field = :field')
|
|
->andWhere('pid = :pid')
|
|
->setParameter('ptable', 'tl_calendar_events')
|
|
->setParameter('field', 'tags')
|
|
->setParameter('pid', $eventId, ParameterType::INTEGER)
|
|
->orderBy('tag_id', 'ASC')
|
|
->executeQuery()
|
|
->fetchFirstColumn();
|
|
|
|
return array_values(array_unique(array_map('intval', $ids)));
|
|
}
|
|
|
|
/**
|
|
* @return array<string, int>
|
|
*/
|
|
public function getLocationChoices(): array
|
|
{
|
|
$rows = $this->connection->createQueryBuilder()
|
|
->select('id', 'title')
|
|
->from('tl_location')
|
|
->where('published = :published')
|
|
->setParameter('published', '1')
|
|
->orderBy('title', 'ASC')
|
|
->executeQuery()
|
|
->fetchAllAssociative();
|
|
|
|
$choices = [];
|
|
|
|
foreach ($rows as $row) {
|
|
$choices[(string) $row['title']] = (int) $row['id'];
|
|
}
|
|
|
|
return $choices;
|
|
}
|
|
|
|
/**
|
|
* @return array<string, int>
|
|
*/
|
|
public function getOrganizationChoicesForMember(int $memberId): array
|
|
{
|
|
$rows = $this->connection->createQueryBuilder()
|
|
->select('o.id', 'o.title')
|
|
->from('tl_member_organization', 'mo')
|
|
->innerJoin('mo', 'tl_organization', 'o', 'o.id = mo.organization_id')
|
|
->where('mo.member_id = :memberId')
|
|
->setParameter('memberId', $memberId, ParameterType::INTEGER)
|
|
->orderBy('o.title', 'ASC')
|
|
->executeQuery()
|
|
->fetchAllAssociative();
|
|
|
|
$choices = [];
|
|
$seenLabels = [];
|
|
|
|
foreach ($rows as $row) {
|
|
$id = (int) $row['id'];
|
|
$label = trim((string) ($row['title'] ?? ''));
|
|
|
|
if ('' === $label) {
|
|
$label = 'Organisation '.$id;
|
|
}
|
|
|
|
if (isset($seenLabels[$label])) {
|
|
$label .= ' (#'.$id.')';
|
|
}
|
|
|
|
$seenLabels[$label] = true;
|
|
$choices[$label] = $id;
|
|
}
|
|
|
|
return $choices;
|
|
}
|
|
|
|
/** @return array<int> */
|
|
public function getOrganizationIdsForMember(int $memberId): array
|
|
{
|
|
$ids = $this->connection->createQueryBuilder()
|
|
->select('organization_id')
|
|
->from('tl_member_organization')
|
|
->where('member_id = :memberId')
|
|
->setParameter('memberId', $memberId, ParameterType::INTEGER)
|
|
->orderBy('organization_id', 'ASC')
|
|
->executeQuery()
|
|
->fetchFirstColumn();
|
|
|
|
return array_values(array_unique(array_map('intval', $ids)));
|
|
}
|
|
|
|
/** @param array<int> $organizationIds */
|
|
public function assignEventToOrganizations(int $eventId, array $organizationIds): void
|
|
{
|
|
$this->connection->delete(
|
|
'tl_calendar_events_organization',
|
|
['event_id' => $eventId],
|
|
['event_id' => ParameterType::INTEGER],
|
|
);
|
|
|
|
$organizationIds = array_values(array_unique(array_map('intval', $organizationIds)));
|
|
|
|
foreach ($organizationIds as $organizationId) {
|
|
if ($organizationId <= 0) {
|
|
continue;
|
|
}
|
|
|
|
$this->connection->insert(
|
|
'tl_calendar_events_organization',
|
|
[
|
|
'tstamp' => time(),
|
|
'event_id' => $eventId,
|
|
'organization_id' => $organizationId,
|
|
],
|
|
[
|
|
'event_id' => ParameterType::INTEGER,
|
|
'organization_id' => ParameterType::INTEGER,
|
|
],
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param array<string, mixed> $data
|
|
*/
|
|
public function update(int $eventId, array $data): void
|
|
{
|
|
$eventData = $this->buildEventData($data);
|
|
|
|
$this->connection->update(
|
|
'tl_calendar_events',
|
|
$eventData,
|
|
['id' => $eventId],
|
|
[
|
|
'id' => ParameterType::INTEGER,
|
|
],
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @param array<string, mixed> $data
|
|
* @param array<int> $organizationIds
|
|
*/
|
|
public function createForMember(int $memberId, int $authorId, int $archiveId, array $data, array $organizationIds): ?int
|
|
{
|
|
if ($memberId <= 0) {
|
|
return null;
|
|
}
|
|
|
|
$resolvedArchiveId = $this->resolveArchiveId($archiveId);
|
|
|
|
if ($resolvedArchiveId <= 0) {
|
|
return null;
|
|
}
|
|
|
|
$eventData = $this->buildEventData($data);
|
|
$eventData['pid'] = $resolvedArchiveId;
|
|
$eventData['author'] = max(0, $authorId);
|
|
|
|
$this->connection->insert(
|
|
'tl_calendar_events',
|
|
$eventData,
|
|
[
|
|
'pid' => ParameterType::INTEGER,
|
|
'author' => ParameterType::INTEGER,
|
|
],
|
|
);
|
|
|
|
$eventId = (int) $this->connection->lastInsertId();
|
|
|
|
if ($eventId <= 0) {
|
|
return null;
|
|
}
|
|
|
|
$memberOrganizationIds = $this->getOrganizationIdsForMember($memberId);
|
|
$allowedOrganizationIds = array_values(array_intersect(array_map('intval', $organizationIds), array_map('intval', $memberOrganizationIds)));
|
|
|
|
if ([] === $allowedOrganizationIds) {
|
|
$this->connection->delete('tl_calendar_events', ['id' => $eventId], ['id' => ParameterType::INTEGER]);
|
|
|
|
return null;
|
|
}
|
|
|
|
$this->assignEventToOrganizations($eventId, $allowedOrganizationIds);
|
|
|
|
return $eventId;
|
|
}
|
|
|
|
/** @param array<int|string> $tagIds */
|
|
public function assignTagsToEvent(int $eventId, array $tagIds): void
|
|
{
|
|
$this->connection->delete(
|
|
'tl_tags_rel',
|
|
['ptable' => 'tl_calendar_events', 'field' => 'tags', 'pid' => $eventId],
|
|
['pid' => ParameterType::INTEGER],
|
|
);
|
|
|
|
$tagIds = array_values(array_unique(array_map('intval', $tagIds)));
|
|
|
|
if ([] === $tagIds) {
|
|
return;
|
|
}
|
|
|
|
$allowedTagIds = $this->getAllowedTagIdsForEvents();
|
|
$tagIds = array_values(array_intersect($tagIds, $allowedTagIds));
|
|
|
|
foreach ($tagIds as $tagId) {
|
|
$this->connection->insert(
|
|
'tl_tags_rel',
|
|
[
|
|
'tag_id' => $tagId,
|
|
'pid' => $eventId,
|
|
'ptable' => 'tl_calendar_events',
|
|
'field' => 'tags',
|
|
],
|
|
[
|
|
'tag_id' => ParameterType::INTEGER,
|
|
'pid' => ParameterType::INTEGER,
|
|
],
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param array<string, mixed> $data
|
|
*
|
|
* @return array<string, mixed>
|
|
*/
|
|
private function buildEventData(array $data): array
|
|
{
|
|
$startDate = !empty($data['startDate']) ? strtotime((string) $data['startDate']) : false;
|
|
$endDate = !empty($data['endDate']) ? strtotime((string) $data['endDate']) : false;
|
|
$url = trim((string) ($data['url'] ?? ''));
|
|
$addTime = !empty($data['addTime']);
|
|
$alias = $this->buildAlias($startDate, (string) ($data['title'] ?? ''));
|
|
|
|
$startDateTimestamp = false !== $startDate ? (int) $startDate : 0;
|
|
$endDateTimestamp = false !== $endDate ? (int) $endDate : 0;
|
|
$timeBaseTimestamp = $endDateTimestamp > 0 ? $endDateTimestamp : $startDateTimestamp;
|
|
|
|
$startTimeTimestamp = $startDateTimestamp;
|
|
$endTimeTimestamp = $timeBaseTimestamp > 0 ? $timeBaseTimestamp + 86399 : 0;
|
|
|
|
if ($addTime) {
|
|
$startTimeCandidate = $this->combineDateAndTime($startDateTimestamp, (string) ($data['startTime'] ?? ''));
|
|
$startTimeTimestamp = null !== $startTimeCandidate ? $startTimeCandidate : $startDateTimestamp;
|
|
|
|
$endTimeCandidate = $this->combineDateAndTime($timeBaseTimestamp, (string) ($data['endTime'] ?? ''));
|
|
$endTimeTimestamp = null !== $endTimeCandidate ? $endTimeCandidate : $startTimeTimestamp;
|
|
}
|
|
|
|
return [
|
|
'title' => $data['title'] ?? '',
|
|
'alias' => $alias,
|
|
'startDate' => false !== $startDate ? $startDate : 0,
|
|
'endDate' => false !== $endDate ? $endDate : null,
|
|
'location_id' => (int) ($data['location_id'] ?? 0),
|
|
'addTime' => $addTime ? 1 : 0,
|
|
'startTime' => $startTimeTimestamp,
|
|
'endTime' => $endTimeTimestamp,
|
|
'teaser' => $data['teaser'] ?? null,
|
|
'description' => $data['description'] ?? null,
|
|
'url' => $url,
|
|
'source' => '' !== $url ? 'external' : 'default',
|
|
'photographer' => $data['photographer'] ?? '',
|
|
'addImage' => !empty($data['addImage']) ? 1 : 0,
|
|
'termsAccepted' => !empty($data['termsAccepted']) ? '1' : '',
|
|
'isSoldOut' => !empty($data['isSoldOut']) ? '1' : '',
|
|
'isCanceled' => !empty($data['isCanceled']) ? '1' : '',
|
|
'published' => !empty($data['published']) ? 1 : 0,
|
|
'tstamp' => time(),
|
|
];
|
|
}
|
|
|
|
private function buildAlias(false|int $startDate, string $title): string
|
|
{
|
|
if (false === $startDate || $startDate <= 0) {
|
|
return '';
|
|
}
|
|
|
|
$normalizedTitle = trim($title);
|
|
|
|
if ('' === $normalizedTitle) {
|
|
return '';
|
|
}
|
|
|
|
$normalizedTitle = strtolower($normalizedTitle);
|
|
$transliterated = iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $normalizedTitle);
|
|
|
|
if (false !== $transliterated) {
|
|
$normalizedTitle = strtolower($transliterated);
|
|
}
|
|
|
|
$normalizedTitle = preg_replace('/[^a-z0-9]+/', '', $normalizedTitle) ?? '';
|
|
$normalizedTitle = substr($normalizedTitle, 0, 20);
|
|
|
|
if ('' === $normalizedTitle) {
|
|
return '';
|
|
}
|
|
|
|
return date('Y-m-d', $startDate).'_'.$normalizedTitle;
|
|
}
|
|
|
|
private function combineDateAndTime(int $dateTimestamp, string $time): ?int
|
|
{
|
|
if ($dateTimestamp <= 0) {
|
|
return null;
|
|
}
|
|
|
|
$normalizedTime = trim($time);
|
|
|
|
if (!preg_match('/^([01]\d|2[0-3]):([0-5]\d)$/', $normalizedTime, $matches)) {
|
|
return null;
|
|
}
|
|
|
|
$hours = (int) $matches[1];
|
|
$minutes = (int) $matches[2];
|
|
|
|
return $dateTimestamp + ($hours * 3600) + ($minutes * 60);
|
|
}
|
|
|
|
public function updateImageFields(int $eventId, bool $addImage, ?string $singleSrcUuid): void
|
|
{
|
|
$types = [
|
|
'id' => ParameterType::INTEGER,
|
|
];
|
|
|
|
if (null !== $singleSrcUuid) {
|
|
$types['singleSRC'] = ParameterType::BINARY;
|
|
}
|
|
|
|
$this->connection->update(
|
|
'tl_calendar_events',
|
|
[
|
|
'addImage' => $addImage ? 1 : 0,
|
|
'singleSRC' => $singleSrcUuid,
|
|
'tstamp' => time(),
|
|
],
|
|
['id' => $eventId],
|
|
$types,
|
|
);
|
|
}
|
|
|
|
/** @return array<int> */
|
|
private function getAllowedTagIdsForEvents(): array
|
|
{
|
|
$ids = $this->connection->createQueryBuilder()
|
|
->select('DISTINCT r.tag_id')
|
|
->from('tl_tags_rel', 'r')
|
|
->where('r.ptable = :ptable')
|
|
->andWhere('r.field = :field')
|
|
->setParameter('ptable', 'tl_calendar_events')
|
|
->setParameter('field', 'tags')
|
|
->executeQuery()
|
|
->fetchFirstColumn();
|
|
|
|
$ids = array_values(array_unique(array_map('intval', $ids)));
|
|
|
|
if ([] !== $ids) {
|
|
return $ids;
|
|
}
|
|
|
|
return array_values(array_unique(array_map('intval', $this->connection->createQueryBuilder()
|
|
->select('id')
|
|
->from('tl_tags')
|
|
->executeQuery()
|
|
->fetchFirstColumn())));
|
|
}
|
|
}
|