feat: add calendar name to search entries

Signed-off-by: SebastianKrupinski <krupinskis05@gmail.com>
This commit is contained in:
SebastianKrupinski 2026-03-03 11:14:12 -05:00
parent f6c79c0d33
commit 277a35ee23
5 changed files with 60 additions and 49 deletions

View file

@ -150,13 +150,13 @@ class EventsSearchProvider extends ACalendarSearchProvider implements IFiltering
$formattedResults = \array_map(function (array $eventRow) use ($calendarsById, $subscriptionsById): SearchResultEntry {
$component = $this->getPrimaryComponent($eventRow['calendardata'], self::$componentType);
$title = (string)($component->SUMMARY ?? $this->l10n->t('Untitled event'));
$subline = $this->generateSubline($component);
if ($eventRow['calendartype'] === CalDavBackend::CALENDAR_TYPE_CALENDAR) {
$calendar = $calendarsById[$eventRow['calendarid']];
} else {
$calendar = $subscriptionsById[$eventRow['calendarid']];
}
$subline = $this->generateSubline($component, $calendar);
$resourceUrl = $this->getDeepLinkToCalendarApp($calendar['principaluri'], $calendar['uri'], $eventRow['uri']);
$result = new SearchResultEntry('', $title, $subline, $resourceUrl, 'icon-calendar-dark', false);
@ -204,7 +204,7 @@ class EventsSearchProvider extends ACalendarSearchProvider implements IFiltering
. $calendarObjectUri;
}
protected function generateSubline(Component $eventComponent): string {
protected function generateSubline(Component $eventComponent, array $calendarInfo): string {
$dtStart = $eventComponent->DTSTART;
$dtEnd = $this->getDTEndForEvent($eventComponent);
$isAllDayEvent = $dtStart instanceof Property\ICalendar\Date;
@ -214,24 +214,31 @@ class EventsSearchProvider extends ACalendarSearchProvider implements IFiltering
if ($isAllDayEvent) {
$endDateTime->modify('-1 day');
if ($this->isDayEqual($startDateTime, $endDateTime)) {
return $this->l10n->l('date', $startDateTime, ['width' => 'medium']);
$formattedSubline = $this->l10n->l('date', $startDateTime, ['width' => 'medium']);
} else {
$formattedStart = $this->l10n->l('date', $startDateTime, ['width' => 'medium']);
$formattedEnd = $this->l10n->l('date', $endDateTime, ['width' => 'medium']);
$formattedSubline = "$formattedStart - $formattedEnd";
}
} else {
$formattedStartDate = $this->l10n->l('date', $startDateTime, ['width' => 'medium']);
$formattedEndDate = $this->l10n->l('date', $endDateTime, ['width' => 'medium']);
$formattedStartTime = $this->l10n->l('time', $startDateTime, ['width' => 'short']);
$formattedEndTime = $this->l10n->l('time', $endDateTime, ['width' => 'short']);
$formattedStart = $this->l10n->l('date', $startDateTime, ['width' => 'medium']);
$formattedEnd = $this->l10n->l('date', $endDateTime, ['width' => 'medium']);
return "$formattedStart - $formattedEnd";
if ($this->isDayEqual($startDateTime, $endDateTime)) {
$formattedSubline = "$formattedStartDate $formattedStartTime - $formattedEndTime";
} else {
$formattedSubline = "$formattedStartDate $formattedStartTime - $formattedEndDate $formattedEndTime";
}
}
$formattedStartDate = $this->l10n->l('date', $startDateTime, ['width' => 'medium']);
$formattedEndDate = $this->l10n->l('date', $endDateTime, ['width' => 'medium']);
$formattedStartTime = $this->l10n->l('time', $startDateTime, ['width' => 'short']);
$formattedEndTime = $this->l10n->l('time', $endDateTime, ['width' => 'short']);
if ($this->isDayEqual($startDateTime, $endDateTime)) {
return "$formattedStartDate $formattedStartTime - $formattedEndTime";
if (isset($calendarInfo['{DAV:}displayname']) && !empty($calendarInfo['{DAV:}displayname'])) {
$formattedSubline = $formattedSubline . " ({$calendarInfo['{DAV:}displayname']})";
}
return "$formattedStartDate $formattedStartTime - $formattedEndDate $formattedEndTime";
// string cast is just to make psalm happy
return (string)$formattedSubline;
}
protected function getDTEndForEvent(Component $eventComponent):Property {

View file

@ -96,13 +96,13 @@ class TasksSearchProvider extends ACalendarSearchProvider {
$formattedResults = \array_map(function (array $taskRow) use ($calendarsById, $subscriptionsById):SearchResultEntry {
$component = $this->getPrimaryComponent($taskRow['calendardata'], self::$componentType);
$title = (string)($component->SUMMARY ?? $this->l10n->t('Untitled task'));
$subline = $this->generateSubline($component);
if ($taskRow['calendartype'] === CalDavBackend::CALENDAR_TYPE_CALENDAR) {
$calendar = $calendarsById[$taskRow['calendarid']];
} else {
$calendar = $subscriptionsById[$taskRow['calendarid']];
}
$subline = $this->generateSubline($component, $calendar);
$resourceUrl = $this->getDeepLinkToTasksApp($calendar['uri'], $taskRow['uri']);
return new SearchResultEntry('', $title, $subline, $resourceUrl, 'icon-checkmark', false);
@ -128,25 +128,29 @@ class TasksSearchProvider extends ACalendarSearchProvider {
);
}
protected function generateSubline(Component $taskComponent): string {
protected function generateSubline(Component $taskComponent, array $calendarInfo): string {
if ($taskComponent->COMPLETED) {
$completedDateTime = new \DateTime($taskComponent->COMPLETED->getDateTime()->format(\DateTimeInterface::ATOM));
$formattedDate = $this->l10n->l('date', $completedDateTime, ['width' => 'medium']);
return $this->l10n->t('Completed on %s', [$formattedDate]);
}
if ($taskComponent->DUE) {
$formattedSubline = $this->l10n->t('Completed on %s', [$formattedDate]);
} elseif ($taskComponent->DUE) {
$dueDateTime = new \DateTime($taskComponent->DUE->getDateTime()->format(\DateTimeInterface::ATOM));
$formattedDate = $this->l10n->l('date', $dueDateTime, ['width' => 'medium']);
if ($taskComponent->DUE->hasTime()) {
$formattedTime = $this->l10n->l('time', $dueDateTime, ['width' => 'short']);
return $this->l10n->t('Due on %s by %s', [$formattedDate, $formattedTime]);
$formattedSubline = $this->l10n->t('Due on %s by %s', [$formattedDate, $formattedTime]);
} else {
$formattedSubline = $this->l10n->t('Due on %s', [$formattedDate]);
}
return $this->l10n->t('Due on %s', [$formattedDate]);
} else {
$formattedSubline = '';
}
return '';
if (isset($calendarInfo['{DAV:}displayname']) && !empty($calendarInfo['{DAV:}displayname'])) {
$formattedSubline = $formattedSubline . (!empty($formattedSubline) ? ' ' : '') . "({$calendarInfo['{DAV:}displayname']})";
}
return $formattedSubline;
}
}

View file

@ -436,7 +436,7 @@ class EventsSearchProviderTest extends TestCase {
}
#[\PHPUnit\Framework\Attributes\DataProvider(methodName: 'generateSublineDataProvider')]
public function testGenerateSubline(string $ics, string $expectedSubline): void {
public function testGenerateSubline(string $ics, string $expectedSubline, array $calendarInfo = []): void {
$vCalendar = Reader::read($ics, Reader::OPTION_FORGIVING);
$eventComponent = $vCalendar->VEVENT;
@ -449,19 +449,23 @@ class EventsSearchProviderTest extends TestCase {
return $date->format('m-d');
});
$actual = self::invokePrivate($this->provider, 'generateSubline', [$eventComponent]);
$actual = self::invokePrivate($this->provider, 'generateSubline', [$eventComponent, $calendarInfo]);
$this->assertEquals($expectedSubline, $actual);
}
public static function generateSublineDataProvider(): array {
return [
[self::$vEvent1, '08-16 09:00 - 10:00'],
[self::$vEvent2, '08-16 09:00 - 08-17 10:00'],
[self::$vEvent3, '10-05'],
[self::$vEvent4, '10-05 - 10-07'],
[self::$vEvent5, '10-05 - 10-09'],
[self::$vEvent6, '10-05'],
[self::$vEvent7, '08-16 09:00 - 09:00'],
[self::$vEvent1, '08-16 09:00 - 10:00', []],
[self::$vEvent2, '08-16 09:00 - 08-17 10:00', []],
[self::$vEvent3, '10-05', []],
[self::$vEvent4, '10-05 - 10-07', []],
[self::$vEvent5, '10-05 - 10-09', []],
[self::$vEvent6, '10-05', []],
[self::$vEvent7, '08-16 09:00 - 09:00', []],
[self::$vEvent1, '08-16 09:00 - 10:00 (My Calendar)', ['{DAV:}displayname' => 'My Calendar']],
[self::$vEvent3, '10-05 (My Calendar)', ['{DAV:}displayname' => 'My Calendar']],
[self::$vEvent2, '08-16 09:00 - 08-17 10:00 (My Calendar)', ['{DAV:}displayname' => 'My Calendar']],
[self::$vEvent1, '08-16 09:00 - 10:00', ['{DAV:}displayname' => '']],
];
}
}

View file

@ -290,24 +290,29 @@ class TasksSearchProviderTest extends TestCase {
}
#[\PHPUnit\Framework\Attributes\DataProvider(methodName: 'generateSublineDataProvider')]
public function testGenerateSubline(string $ics, string $expectedSubline): void {
public function testGenerateSubline(string $ics, string $expectedSubline, array $calendarInfo = []): void {
$vCalendar = Reader::read($ics, Reader::OPTION_FORGIVING);
$taskComponent = $vCalendar->VTODO;
$this->l10n->method('t')->willReturnArgument(0);
$this->l10n->method('l')->willReturnArgument(0);
$actual = self::invokePrivate($this->provider, 'generateSubline', [$taskComponent]);
$actual = self::invokePrivate($this->provider, 'generateSubline', [$taskComponent, $calendarInfo]);
$this->assertEquals($expectedSubline, $actual);
}
public static function generateSublineDataProvider(): array {
return [
[self::$vTodo0, ''],
[self::$vTodo1, 'Completed on %s'],
[self::$vTodo2, 'Completed on %s'],
[self::$vTodo3, 'Due on %s'],
[self::$vTodo4, 'Due on %s by %s'],
[self::$vTodo0, '', []],
[self::$vTodo1, 'Completed on %s', []],
[self::$vTodo2, 'Completed on %s', []],
[self::$vTodo3, 'Due on %s', []],
[self::$vTodo4, 'Due on %s by %s', []],
[self::$vTodo0, '(My Tasks)', ['{DAV:}displayname' => 'My Tasks']],
[self::$vTodo1, 'Completed on %s (My Tasks)', ['{DAV:}displayname' => 'My Tasks']],
[self::$vTodo3, 'Due on %s (My Tasks)', ['{DAV:}displayname' => 'My Tasks']],
[self::$vTodo4, 'Due on %s by %s (My Tasks)', ['{DAV:}displayname' => 'My Tasks']],
[self::$vTodo1, 'Completed on %s', ['{DAV:}displayname' => '']],
];
}
}

View file

@ -839,9 +839,6 @@
</InvalidOperand>
</file>
<file src="apps/dav/lib/Search/EventsSearchProvider.php">
<FalsableReturnStatement>
<code><![CDATA[$this->l10n->l('date', $startDateTime, ['width' => 'medium'])]]></code>
</FalsableReturnStatement>
<InvalidOperand>
<code><![CDATA[$query->getCursor()]]></code>
</InvalidOperand>
@ -851,12 +848,6 @@
'ORGANIZER' => ['CN'],
]]]></code>
</InvalidPropertyAssignmentValue>
<InvalidReturnStatement>
<code><![CDATA[$this->l10n->l('date', $startDateTime, ['width' => 'medium'])]]></code>
</InvalidReturnStatement>
<InvalidReturnType>
<code><![CDATA[string]]></code>
</InvalidReturnType>
<UndefinedMethod>
<code><![CDATA[getDateTime]]></code>
<code><![CDATA[getDateTime]]></code>