1<?php
2
3#################################################################
4#  Copyright notice
5#
6#  (c) 2013 Jérôme Schneider <mail@jeromeschneider.fr>
7#  All rights reserved
8#
9#  http://sabre.io/baikal
10#
11#  This script is part of the Baïkal Server project. The Baïkal
12#  Server project is free software; you can redistribute it
13#  and/or modify it under the terms of the GNU General Public
14#  License as published by the Free Software Foundation; either
15#  version 2 of the License, or (at your option) any later version.
16#
17#  The GNU General Public License can be found at
18#  http://www.gnu.org/copyleft/gpl.html.
19#
20#  This script is distributed in the hope that it will be useful,
21#  but WITHOUT ANY WARRANTY; without even the implied warranty of
22#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23#  GNU General Public License for more details.
24#
25#  This copyright notice MUST APPEAR in all copies of the script!
26#################################################################
27
28namespace Baikal\Model;
29
30use Symfony\Component\Yaml\Yaml;
31
32class Calendar extends \Flake\Core\Model\Db {
33    const DATATABLE = "calendarinstances";
34    const PRIMARYKEY = "id";
35    const LABELFIELD = "displayname";
36
37    protected $aData = [
38        "principaluri"  => "",
39        "displayname"   => "",
40        "uri"           => "",
41        "description"   => "",
42        "calendarorder" => 0,
43        "calendarcolor" => "",
44        "timezone"      => null,
45        "calendarid"    => 0
46    ];
47    protected $oCalendar; # Baikal\Model\Calendar\Calendar
48
49    function __construct($sPrimary = false) {
50        parent::__construct($sPrimary);
51        try {
52            $config = Yaml::parseFile(PROJECT_PATH_CONFIG . "baikal.yaml");
53            $this->set("timezone", $config['system']["timezone"]);
54        } catch (\Exception $e) {
55            error_log('Error reading baikal.yaml file : ' . $e->getMessage());
56        }
57    }
58
59    protected function initFloating() {
60        parent::initFloating();
61        $this->oCalendar = new Calendar\Calendar();
62    }
63
64    protected function initByPrimary($sPrimary) {
65        parent::initByPrimary($sPrimary);
66        $this->oCalendar = new Calendar\Calendar($this->get("calendarid"));
67    }
68
69    function persist() {
70        $this->oCalendar->persist();
71        $this->aData["calendarid"] = $this->oCalendar->get("id");
72        parent::persist();
73    }
74
75    static function icon() {
76        return "icon-calendar";
77    }
78
79    static function mediumicon() {
80        return "glyph-calendar";
81    }
82
83    static function bigicon() {
84        return "glyph2x-calendar";
85    }
86
87    function getEventsBaseRequester() {
88        $oBaseRequester = \Baikal\Model\Calendar\Event::getBaseRequester();
89        $oBaseRequester->addClauseEquals(
90            "calendarid",
91            $this->get("calendarid")
92        );
93
94        return $oBaseRequester;
95    }
96
97    function get($sPropName) {
98        if ($sPropName === "components") {
99            return $this->oCalendar->get($sPropName);
100        }
101
102        if ($sPropName === "todos") {
103            # TRUE if components contains VTODO, FALSE otherwise
104            if (($sComponents = $this->get("components")) !== "") {
105                $aComponents = explode(",", $sComponents);
106            } else {
107                $aComponents = [];
108            }
109
110            return in_array("VTODO", $aComponents);
111        }
112
113        if ($sPropName === "notes") {
114            # TRUE if components contains VJOURNAL, FALSE otherwise
115            if (($sComponents = $this->get("components")) !== "") {
116                $aComponents = explode(",", $sComponents);
117            } else {
118                $aComponents = [];
119            }
120
121            return in_array("VJOURNAL", $aComponents);
122        }
123
124        return parent::get($sPropName);
125    }
126
127    function set($sPropName, $sValue) {
128        if ($sPropName === "components") {
129            return $this->oCalendar->set($sPropName, $sValue);
130        }
131
132        if ($sPropName === "todos") {
133            if (($sComponents = $this->get("components")) !== "") {
134                $aComponents = explode(",", $sComponents);
135            } else {
136                $aComponents = [];
137            }
138
139            if ($sValue === true) {
140                if (!in_array("VTODO", $aComponents)) {
141                    $aComponents[] = "VTODO";
142                }
143            } else {
144                if (in_array("VTODO", $aComponents)) {
145                    unset($aComponents[array_search("VTODO", $aComponents)]);
146                }
147            }
148
149            return $this->set("components", implode(",", $aComponents));
150        }
151
152        if ($sPropName === "notes") {
153            if (($sComponents = $this->get("components")) !== "") {
154                $aComponents = explode(",", $sComponents);
155            } else {
156                $aComponents = [];
157            }
158
159            if ($sValue === true) {
160                if (!in_array("VJOURNAL", $aComponents)) {
161                    $aComponents[] = "VJOURNAL";
162                }
163            } else {
164                if (in_array("VJOURNAL", $aComponents)) {
165                    unset($aComponents[array_search("VJOURNAL", $aComponents)]);
166                }
167            }
168
169            return $this->set("components", implode(",", $aComponents));
170        }
171
172        return parent::set($sPropName, $sValue);
173    }
174
175    function formMorphologyForThisModelInstance() {
176        $oMorpho = new \Formal\Form\Morphology();
177
178        $oMorpho->add(new \Formal\Element\Text([
179            "prop"       => "uri",
180            "label"      => "Calendar token ID",
181            "validation" => "required,tokenid",
182            "popover"    => [
183                "title"   => "Calendar token ID",
184                "content" => "The unique identifier for this calendar.",
185            ]
186        ]));
187
188        $oMorpho->add(new \Formal\Element\Text([
189            "prop"       => "displayname",
190            "label"      => "Display name",
191            "validation" => "required",
192            "popover"    => [
193                "title"   => "Display name",
194                "content" => "This is the name that will be displayed in your CalDAV client.",
195            ]
196        ]));
197
198        $oMorpho->add(new \Formal\Element\Text([
199            "prop"       => "calendarcolor",
200            "label"      => "Calendar color",
201            "validation" => "color",
202            "popover"    => [
203                    "title"   => "Calendar color",
204                    "content" => "This is the color that will be displayed in your CalDAV client.<br/>" .
205                    "Must be supplied in format '#RRGGBBAA' (alpha channel optional) with hexadecimal values.<br/>" .
206                    "This value is optional.",
207            ]
208        ]));
209
210        $oMorpho->add(new \Formal\Element\Text([
211            "prop"  => "description",
212            "label" => "Description"
213        ]));
214
215        $oMorpho->add(new \Formal\Element\Checkbox([
216            "prop"  => "todos",
217            "label" => "Todos",
218            "help"  => "If checked, todos will be enabled on this calendar.",
219        ]));
220
221        $oMorpho->add(new \Formal\Element\Checkbox([
222            "prop"  => "notes",
223            "label" => "Notes",
224            "help"  => "If checked, notes will be enabled on this calendar.",
225        ]));
226
227        if ($this->floating()) {
228            $oMorpho->element("uri")->setOption(
229                "help",
230                "Allowed characters are digits, lowercase letters and the dash symbol '-'."
231            );
232        } else {
233            $oMorpho->element("uri")->setOption("readonly", true);
234        }
235
236        return $oMorpho;
237    }
238
239    function isDefault() {
240        return $this->get("uri") === "default";
241    }
242
243    function hasInstances() {
244        $rSql = $GLOBALS["DB"]->exec_SELECTquery(
245            "count(*)",
246            "calendarinstances",
247            "calendarid" . "='" . $this->aData["calendarid"] . "'"
248        );
249
250        if (($aRs = $rSql->fetch()) === false) {
251            return false;
252        } else {
253            reset($aRs);
254
255            return $aRs["count(*)"] > 1;
256        }
257    }
258
259    function destroy() {
260        $hasInstances = $this->hasInstances();
261        if (!$hasInstances) {
262            $oEvents = $this->getEventsBaseRequester()->execute();
263            foreach ($oEvents as $event) {
264                $event->destroy();
265            }
266        }
267
268        parent::destroy();
269        if (!$hasInstances) {
270            $this->oCalendar->destroy();
271        }
272    }
273}
274