summaryrefslogtreecommitdiff
path: root/vendor/eluceo/ical/src/Eluceo/iCal/Component.php
blob: 76c9b2d946b75728f7de579b731743068961774d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
<?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 = array();

    /**
     * The order in which the components will be rendered during build.
     *
     * Not defined components will be appended at the end.
     *
     * @var array
     */
    private $componentsBuildOrder = array('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(Component $component, $key = null)
    {
        if (null == $key) {
            $this->components[] = $component;
        } else {
            $this->components[$key] = $component;
        }
    }

    /**
     * Renders an array containing the lines of the iCal file.
     *
     * @return array
     */
    public function build()
    {
        $lines = array();

        $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 = array();

        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 = array();

        /** @var $component Component */
        foreach ($this->components as $component) {
            $type = $component->getType();
            if (!isset($componentsByType[$type])) {
                $componentsByType[$type] = array();
            }
            $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 array     $lines
     * @param Component $component
     */
    private function addComponentLines(array &$lines, Component $component)
    {
        foreach ($component->build() as $l) {
            $lines[] = $l;
        }
    }
}