185 lines
4.1 KiB
PHP
185 lines
4.1 KiB
PHP
<?php
|
|
|
|
/*
|
|
* This file is part of the eluceo/iCal package.
|
|
*
|
|
* (c) Markus Poerschke <markus@eluceo.de>
|
|
*
|
|
* This source file is subject to the MIT license that is bundled
|
|
* with this source code in the file LICENSE.
|
|
*/
|
|
|
|
namespace Eluceo\iCal;
|
|
|
|
use Eluceo\iCal\Util\ComponentUtil;
|
|
|
|
/**
|
|
* Abstract Calender Component.
|
|
*/
|
|
abstract class Component
|
|
{
|
|
/**
|
|
* Array of Components.
|
|
*
|
|
* @var Component[]
|
|
*/
|
|
protected $components = [];
|
|
|
|
/**
|
|
* The order in which the components will be rendered during build.
|
|
*
|
|
* Not defined components will be appended at the end.
|
|
*
|
|
* @var array
|
|
*/
|
|
private $componentsBuildOrder = ['VTIMEZONE', 'DAYLIGHT', 'STANDARD'];
|
|
|
|
/**
|
|
* The type of the concrete Component.
|
|
*
|
|
* @abstract
|
|
*
|
|
* @return string
|
|
*/
|
|
abstract public function getType();
|
|
|
|
/**
|
|
* Building the PropertyBag.
|
|
*
|
|
* @abstract
|
|
*
|
|
* @return PropertyBag
|
|
*/
|
|
abstract public function buildPropertyBag();
|
|
|
|
/**
|
|
* Adds a Component.
|
|
*
|
|
* If $key is given, the component at $key will be replaced else the component will be append.
|
|
*
|
|
* @param Component $component The Component that will be added
|
|
* @param null $key The key of the Component
|
|
*/
|
|
public function addComponent(self $component, $key = null)
|
|
{
|
|
if (null == $key) {
|
|
$this->components[] = $component;
|
|
} else {
|
|
$this->components[$key] = $component;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set all Components.
|
|
*
|
|
* @param Component[] $components The array of Component that will be set
|
|
* @param null $key The key of the Component
|
|
*/
|
|
public function setComponents(array $components)
|
|
{
|
|
$this->components = $components;
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Renders an array containing the lines of the iCal file.
|
|
*
|
|
* @return array
|
|
*/
|
|
public function build()
|
|
{
|
|
$lines = [];
|
|
|
|
$lines[] = sprintf('BEGIN:%s', $this->getType());
|
|
|
|
/** @var $property Property */
|
|
foreach ($this->buildPropertyBag() as $property) {
|
|
foreach ($property->toLines() as $l) {
|
|
$lines[] = $l;
|
|
}
|
|
}
|
|
|
|
$this->buildComponents($lines);
|
|
|
|
$lines[] = sprintf('END:%s', $this->getType());
|
|
|
|
$ret = [];
|
|
|
|
foreach ($lines as $line) {
|
|
foreach (ComponentUtil::fold($line) as $l) {
|
|
$ret[] = $l;
|
|
}
|
|
}
|
|
|
|
return $ret;
|
|
}
|
|
|
|
/**
|
|
* Renders the output.
|
|
*
|
|
* @return string
|
|
*/
|
|
public function render()
|
|
{
|
|
return implode("\r\n", $this->build());
|
|
}
|
|
|
|
/**
|
|
* Renders the output when treating the class as a string.
|
|
*
|
|
* @return string
|
|
*/
|
|
public function __toString()
|
|
{
|
|
return $this->render();
|
|
}
|
|
|
|
/**
|
|
* @param $lines
|
|
*
|
|
* @return array
|
|
*/
|
|
private function buildComponents(array &$lines)
|
|
{
|
|
$componentsByType = [];
|
|
|
|
/** @var $component Component */
|
|
foreach ($this->components as $component) {
|
|
$type = $component->getType();
|
|
if (!isset($componentsByType[$type])) {
|
|
$componentsByType[$type] = [];
|
|
}
|
|
$componentsByType[$type][] = $component;
|
|
}
|
|
|
|
// render ordered components
|
|
foreach ($this->componentsBuildOrder as $type) {
|
|
if (!isset($componentsByType[$type])) {
|
|
continue;
|
|
}
|
|
foreach ($componentsByType[$type] as $component) {
|
|
$this->addComponentLines($lines, $component);
|
|
}
|
|
unset($componentsByType[$type]);
|
|
}
|
|
|
|
// render all other
|
|
foreach ($componentsByType as $components) {
|
|
foreach ($components as $component) {
|
|
$this->addComponentLines($lines, $component);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param Component $component
|
|
*/
|
|
private function addComponentLines(array &$lines, self $component)
|
|
{
|
|
foreach ($component->build() as $l) {
|
|
$lines[] = $l;
|
|
}
|
|
}
|
|
}
|