Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added calendar name and description #394

Open
wants to merge 1 commit into
base: 2.x
Choose a base branch
from

Conversation

chrismeijer
Copy link

Added X-WR-CALNAME and X-WR-CALDESC fields to calendar factory for viewing the name and description when user is subscribed to the iCal-feed URL.

@vince83110
Copy link

What about this PR ? any news ? why isn't it a main feature of this plugin ?

@SimonIT
Copy link

SimonIT commented Jul 13, 2023

@markuspoerschke

@jamesmacwhite
Copy link

jamesmacwhite commented Dec 24, 2023

This seems like a nice addition, not sure why it's been left unmerged, given the projects active status. Possibly because the properties are technically not standard I guess?

Being able to provide a default name and description seems logical for calendars which are subscribed to on a front end, or having the ability to control the default value, most iCal formats would do it.

Because of the use of factories, you might be able to use custom properties like this: https://ical.poerschke.nrw/docs/custom-properties

It seems a bit over-engineered and more suitable being directly built into the library, but it's possible due to the RFC compliance side of things, that this is not standard and not been included.

@jamesmacwhite
Copy link

jamesmacwhite commented Dec 24, 2023

Here's how you can implement it without the PR being merged using extending. You need to extend both the Calendar Entity and Factory, to implement the additional logic required, but you can do it without merging this PR.

Hope this is useful.

CustomCalendar.php (Calendar Entity)

Set default values as null rather than an empty string, so we can simplify the check for a value.

<?php

namespace example\namespace\change\this;

use Eluceo\iCal\Domain\Entity\Calendar;

class CustomCalendar extends Calendar
{
	private ?string $calendarName = null;
	private ?string $calendarDescription = null;

	public function getCalendarName(): string
	{
		return $this->calendarName;
	}

	public function setCalendarName(string $calendarName): self
	{
		$this->calendarName = $calendarName;

		return $this;
	}

	public function getCalendarDescription(): string
	{
		return $this->calendarDescription;
	}

	public function setCalendarDescription(string $calendarDescription): self
	{
		$this->calendarDescription = $calendarDescription;

		return $this;
	}
}

CustomCalendarFactory.php (Calendar Factory)

Declaring the two properties as string or null allows us to simplify the condition for checking if a Calendar name or description is set.

<?php

namespace example\namespace\change\this;

use Eluceo\iCal\Domain\Entity\Calendar;
use Eluceo\iCal\Presentation\Component\Property;
use Eluceo\iCal\Presentation\Component\Property\Value\TextValue;
use Eluceo\iCal\Presentation\Factory\CalendarFactory;
use Generator;

class CustomCalendarFactory extends CalendarFactory
{
	protected function getProperties(Calendar $calendar): Generator
	{

                /* @see https://www.ietf.org/rfc/rfc5545.html#section-3.7.3 */
		yield new Property('PRODID', new TextValue($calendar->getProductIdentifier()));
		/* @see https://www.ietf.org/rfc/rfc5545.html#section-3.7.4 */
		yield new Property('VERSION', new TextValue('2.0'));
		/* @see https://www.ietf.org/rfc/rfc5545.html#section-3.7.1 */
		yield new Property('CALSCALE', new TextValue('GREGORIAN'));

                $publishedTTL = $calendar->getPublishedTTL();
		$calenderName = $calendar->getCalendarName();
		$calendarDescription = $calendar->getCalendarDescription();

		if ($publishedTTL) {
			/* @see http://msdn.microsoft.com/en-us/library/ee178699(v=exchg.80).aspx */
			yield new Property('X-PUBLISHED-TTL', new DurationValue($publishedTTL));
		}

		if ($calenderName) {
			/* @see https://learn.microsoft.com/en-us/openspecs/exchange_server_protocols/ms-oxcical/1da58449-b97e-46bd-b018-a1ce576f3e6d */
			yield new Property('X-WR-CALNAME', new TextValue($calenderName));
		}

		if ($calendarDescription) {
			/* @see https://learn.microsoft.com/en-us/openspecs/exchange_server_protocols/ms-oxcical/9194db93-6de2-41b3-bebe-fc76a11e31e9 */
			yield new Property('X-WR-CALDESC', new TextValue($calendarDescription));
		}
	}
}

In your code, when you call the usual Calendar Factory and Entity, you can alias your custom extended versions, so it's less work, to modify code samples from this project.

Code example with added properties

<?php
use example\namespace\changethis\CustomCalendar as Calendar;
use example\namespace\changethis\CustomCalendarFactory as CalendarFactory;
use Eluceo\iCal\Domain\ValueObject\Date;
use Eluceo\iCal\Domain\Entity\Event;
use Eluceo\iCal\Domain\ValueObject\SingleDay;

....

// 1. Create Event domain entity
$event = new Event();
$event
    ->setSummary('Christmas Eve')
    ->setOccurrence(
        new SingleDay(
            new Date(DateTimeImmutable::createFromFormat('Y-m-d', '2030-12-24'))
        )
    );

// 2. Create Calendar domain entity
$calendar = new Calendar([$event]);
$calendar->setCalendarName('Calendar Title');
$calendar->setCalendarDescription('Calendar Description');

// 3. Transform domain entity into an iCalendar component
$componentFactory = new CalendarFactory();
$calendarComponent = $componentFactory->createCalendar($calendar);

// 4. Set HTTP headers
header('Content-Type: text/calendar; charset=utf-8');
header('Content-Disposition: attachment; filename="cal.ics"');

// 5. Output
echo $calendarComponent;

The output should provide the additional X-WR-CALNAME and X-WR-CALDESC properties in the ical file before the first BEGIN:VEVENT.

X-WR-CALNAME:Calendar Title
X-WR-CALDESC:Calendar Description

@GenieTim
Copy link

Another property that would make sense: the Refresh interval; see also https://stackoverflow.com/a/17187346/3909202

@jamesmacwhite
Copy link

@GenieTim Probably worth adding into a new pull request, given this one has been open for sometime.

The good news with the extending example, you can implement it yourself with an extended class without having to wait or fork the library. If it was implemented upstream, you can then either revert to the main class or remove any duplicated logic which was since added.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants