Skip to content

Commit

Permalink
fixup! feat: OCC and OCS Calendar Import/Export
Browse files Browse the repository at this point in the history
Signed-off-by: SebastianKrupinski <[email protected]>
  • Loading branch information
SebastianKrupinski committed Jan 26, 2025
1 parent c7abca8 commit c8dc1be
Show file tree
Hide file tree
Showing 6 changed files with 442 additions and 260 deletions.
95 changes: 7 additions & 88 deletions lib/Command/Export.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
*/
namespace OCA\Calendar\Command;

use InvalidArgumentException;
use OCA\Calendar\Service\Export\ExportService;
use OCP\Calendar\ICalendarExport;
use OCP\Calendar\IManager;
Expand Down Expand Up @@ -40,114 +41,32 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$location = $input->getArgument('location');

if (!$this->userManager->userExists($userId)) {
throw new \InvalidArgumentException("User <$userId> not found.");
throw new InvalidArgumentException("User <$userId> not found.");
}
// retrieve calendar and evaluate if export is supported
$calendars = $this->calendarManager->getCalendarsForPrincipal('principals/users/' . $userId, [$calendarId]);
if ($calendars === []) {
throw new \InvalidArgumentException("Calendar <$calendarId> not found.");
throw new InvalidArgumentException("Calendar <$calendarId> not found.");
}
$calendar = $calendars[0];
/*
if ($calendar instanceof ICalendarExport) {
throw new \InvalidArgumentException("Calendar <$calendarId> dose support this function");
if (!$calendar instanceof ICalendarExport) {
throw new InvalidArgumentException("Calendar <$calendarId> dose support this function");
}
*/
// evaluate if requested format is supported
if ($format !== null && !in_array($format, $this->exportService::FORMATS)) {
throw new \InvalidArgumentException("Format <$format> is not valid.");
throw new InvalidArgumentException("Format <$format> is not valid.");
} elseif ($format === null) {
$format = 'ical';
}
// evaluate is a valid location was given and is usable otherwise output to stdout
if ($location !== null) {
$handle = fopen($location, "w");
if ($handle === false) {
throw new \InvalidArgumentException("Location <$location> is not valid. Can not open location for write operation.");
throw new InvalidArgumentException("Location <$location> is not valid. Can not open location for write operation.");
} else {

fwrite($handle, "BEGIN:VCALENDAR\nVERSION:2.0\nPRODID:-//IDN nextcloud.com//Calendar App//EN\n");


for ($i=0; $i < 16384; $i++) {

$id = uniqid();
fwrite(
$handle,
'BEGIN:VEVENT
CREATED:20240910T123608Z
LAST-MODIFIED:20240916T075225Z
DTSTAMP:20240916T075225Z
UID:' . $id . PHP_EOL .
'SUMMARY:Brainstorming workshop- Collectives - Room A
STATUS:CONFIRMED
ORGANIZER;CN=Irina Mikhaylina;SCHEDULE-STATUS=1.1:mailto:irina.mikhaylina@n
extcloud.com
ATTENDEE;RSVP=TRUE;CN=Jonas Meurer;PARTSTAT=NEEDS-ACTION;CUTYPE=INDIVIDUAL;
ROLE=REQ-PARTICIPANT;LANGUAGE=en;SCHEDULE-STATUS=1.1:mailto:jonas.meurer@n
extcloud.com
ATTENDEE;RSVP=TRUE;CN=Simon Lindner;PARTSTAT=NEEDS-ACTION;CUTYPE=INDIVIDUAL
;ROLE=REQ-PARTICIPANT;LANGUAGE=en;SCHEDULE-STATUS=1.1:mailto:simon.lindner
@nextcloud.com
ATTENDEE;RSVP=TRUE;CN=Louis Chemineau;PARTSTAT=NEEDS-ACTION;CUTYPE=INDIVIDU
AL;ROLE=REQ-PARTICIPANT;LANGUAGE=en;SCHEDULE-STATUS=1.1:mailto:louis.chemi
[email protected]
ATTENDEE;RSVP=TRUE;CN=Jenna Stocks;PARTSTAT=NEEDS-ACTION;CUTYPE=INDIVIDUAL;
ROLE=REQ-PARTICIPANT;LANGUAGE=en_GB;SCHEDULE-STATUS=1.1:mailto:jenna.stock
[email protected]
ATTENDEE;RSVP=TRUE;CN=Marcel Hibbe;PARTSTAT=NEEDS-ACTION;CUTYPE=INDIVIDUAL;
ROLE=REQ-PARTICIPANT;LANGUAGE=en;SCHEDULE-STATUS=1.1:mailto:marcel.hibbe@n
extcloud.com
ATTENDEE;RSVP=TRUE;CN=Peter Mocanu;PARTSTAT=NEEDS-ACTION;CUTYPE=INDIVIDUAL;
ROLE=REQ-PARTICIPANT;LANGUAGE=en;SCHEDULE-STATUS=1.1:mailto:peter.mocanu@n
extcloud.com
ATTENDEE;RSVP=TRUE;CN=Cyprien Edouard;PARTSTAT=NEEDS-ACTION;CUTYPE=INDIVIDU
AL;ROLE=REQ-PARTICIPANT;LANGUAGE=en;SCHEDULE-STATUS=1.1:mailto:cyprien.edo
[email protected]
ATTENDEE;RSVP=TRUE;CN=Kim Pohlmann;PARTSTAT=NEEDS-ACTION;CUTYPE=INDIVIDUAL;
ROLE=REQ-PARTICIPANT;LANGUAGE=de;SCHEDULE-STATUS=1.1:mailto:kim.pohlmann@n
extcloud.com
ATTENDEE;RSVP=TRUE;CN=Tobias Kaminsky;PARTSTAT=ACCEPTED;CUTYPE=INDIVIDUAL;R
OLE=REQ-PARTICIPANT;LANGUAGE=en;SCHEDULE-STATUS=1.1:mailto:tobias.kaminsky
@nextcloud.com
DTSTART;TZID=Europe/Berlin:20240919T100000
DTEND;TZID=Europe/Berlin:20240919T110000
SEQUENCE:4
LOCATION:Room A (ground floor)
DESCRIPTION:Hello dear team\, \n \nwe would like to invite you to join ou
r upcoming Product Brainstorming Session\, where we will come together in
a group of 10 people to spark creativity and collaborate on potential new
features for Nextcloud apps 💥 Here is the structure of the session:\n\
n1. Introduction (5 minutes): We\'ll start with a brief introduction from t
he design team\, followed by participants introducing themselves. To make
things fun and relaxed\, we\'ll choose a moderator from the group. We’ll
just ask for volunteers on the spot\, so no one feels pressured or assigne
d without their agreement.\n\n2. App Demo (10 minutes): Next\, the develop
er of each team will share their screen and give a short demo of the app\,
walking everyone through its current features and explaining what it does
.\n\n3. Idea Generation (10 minutes): After the demo\, it\'s time for every
one to jot down ideas for new features or improvements they\'d like to see.
You can come up with up to 5 ideas and stick them on a whiteboard for us
all to review.\n\n4. Discussion (25 minutes): The moderator will then go t
hrough each idea on the board. The person who wrote it will explain their
thought process\, and then we’ll open the floor for feedback. Everyone c
an share whether they agree\, disagree\, or offer praise and suggestions.\
n\n5. Prioritization (10 minutes): We’ll pick the most important ideas b
ased on our discussion.\n\nThroughout the session\, the moderator will kee
p track of time and ensure we don’t spend too long on any one idea 🤓
\n\nIf you have any questions\, feel free to reach out with me!\n\nKind re
gards\nIrina
X-MOZ-GENERATION:1
END:VEVENT
'
);
}
fwrite($handle, "END:VCALENDAR\n");
/*
foreach ($this->exportService->export($calendar, $format) as $chunk) {
fwrite($handle, $chunk);
}
*/
fclose($handle);
}
} else {
Expand Down
21 changes: 11 additions & 10 deletions lib/Command/Import.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
*/
namespace OCA\Calendar\Command;

use InvalidArgumentException;
use OCA\Calendar\Service\Import\ImportService;
use OCP\Calendar\CalendarImportSettings;
use OCP\Calendar\ICalendarImport;
Expand Down Expand Up @@ -41,30 +42,30 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$location = $input->getArgument('location');

if (!$this->userManager->userExists($userId)) {
throw new \InvalidArgumentException("User <$userId> not found.");
throw new InvalidArgumentException("User <$userId> not found.");
}
// retrieve calendar and evaluate if import is supported and writeable
$calendars = $this->calendarManager->getCalendarsForPrincipal('principals/users/' . $userId, [$calendarId]);
if ($calendars === []) {
throw new \InvalidArgumentException("Calendar <$calendarId> not found.");
throw new InvalidArgumentException("Calendar <$calendarId> not found.");
}
$calendar = $calendars[0];
if ($calendar instanceof ICalendarImport) {
//throw new \InvalidArgumentException("Calendar <$calendarId> dose support this function");
if (!$calendar instanceof ICalendarImport) {
throw new InvalidArgumentException("Calendar <$calendarId> dose support this function");
}
if (!$calendar->isWritable()) {
throw new \InvalidArgumentException("Calendar <$calendarId> is not writeable");
throw new InvalidArgumentException("Calendar <$calendarId> is not writeable");
}
if ($calendar->isDeleted()) {
throw new \InvalidArgumentException("Calendar <$calendarId> is deleted");
throw new InvalidArgumentException("Calendar <$calendarId> is deleted");
}
// construct settings object
$settings = new CalendarImportSettings();
// evaluate if provided format is supported
if ($format !== null && !in_array($format, $this->importService::FORMATS)) {
throw new \InvalidArgumentException("Format <$format> is not valid.");
} elseif ($format === null) {
$settings->format = 'ical';
} else {
$settings->format = $format ?? 'ical';
}
// evaluate if a valid location was given and is usable otherwise default to stdin
if ($location !== null) {
Expand All @@ -73,7 +74,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
throw new \InvalidArgumentException("Location <$location> is not valid. Can not open location for read operation.");
} else {
try {
$this->importService->import($input, $calendar, $settings);
$outcome = $this->importService->import($input, $calendar, $settings);
} finally {
fclose($input);
}
Expand All @@ -89,7 +90,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
fwrite($temp, fread($input, 8192));
}
fseek($temp, 0);
$this->importService->import($temp, $calendar, $settings);
$outcome = $this->importService->import($temp, $calendar, $settings);
} finally {
fclose($input);
fclose($temp);
Expand Down
11 changes: 5 additions & 6 deletions lib/Service/Export/ExportService.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,19 @@ public function export(ICalendar&ICalendarExport $calendar, string $format, ?Cal
yield $this->exportStart($format);

// iterate through each returned vCalendar entry
// extract each vObject type, convert to appropriate format and output
// extract any vTimezones objects and save them but do not output
// extract each component except timezones, convert to appropriate format and output
// extract any timezones and save them but do not output
$timezones = [];
foreach ($calendar->export($range) as $entry) {
$consecutive = false;
foreach ($entry->getComponents() as $vComponent) {
if ($vComponent->name !== 'VTIMEZONE') {
yield $this->exportObject($vComponent, $format, $consecutive);
$consecutive = true;
}
if ($vComponent->name === 'VTIMEZONE') {
if (isset($vComponent->TZID) && !isset($timezones[$vComponent->TZID->getValue()])) {
$timezones[$vComponent->TZID->getValue()] = clone $vComponent;
}
} else {
yield $this->exportObject($vComponent, $format, $consecutive);
$consecutive = true;
}
}
}
Expand Down
Loading

0 comments on commit c8dc1be

Please sign in to comment.