1<?php
2
3namespace Sabre\VObject\Property\ICalendar;
4
5use
6    Sabre\VObject\Property,
7    Sabre\VObject\Parser\MimeDir;
8
9/**
10 * Recur property
11 *
12 * This object represents RECUR properties.
13 * These values are just used for RRULE and the now deprecated EXRULE.
14 *
15 * The RRULE property may look something like this:
16 *
17 * RRULE:FREQ=MONTHLY;BYDAY=1,2,3;BYHOUR=5.
18 *
19 * This property exposes this as a key=>value array that is accessible using
20 * getParts, and may be set using setParts.
21 *
22 * @copyright Copyright (C) fruux GmbH (https://fruux.com/)
23 * @author Evert Pot (http://evertpot.com/)
24 * @license http://sabre.io/license/ Modified BSD License
25 */
26class Recur extends Property {
27
28    /**
29     * Updates the current value.
30     *
31     * This may be either a single, or multiple strings in an array.
32     *
33     * @param string|array $value
34     * @return void
35     */
36    public function setValue($value) {
37
38        // If we're getting the data from json, we'll be receiving an object
39        if ($value instanceof \StdClass) {
40            $value = (array)$value;
41        }
42
43        if (is_array($value)) {
44            $newVal = array();
45            foreach($value as $k=>$v) {
46
47                if (is_string($v)) {
48                    $v = strtoupper($v);
49
50                    // The value had multiple sub-values
51                    if (strpos($v,',')!==false) {
52                        $v = explode(',', $v);
53                    }
54                } else {
55                    $v = array_map('strtoupper', $v);
56                }
57
58                $newVal[strtoupper($k)] = $v;
59            }
60            $this->value = $newVal;
61        } elseif (is_string($value)) {
62            $this->value = self::stringToArray($value);
63        } else {
64            throw new \InvalidArgumentException('You must either pass a string, or a key=>value array');
65        }
66
67    }
68
69    /**
70     * Returns the current value.
71     *
72     * This method will always return a singular value. If this was a
73     * multi-value object, some decision will be made first on how to represent
74     * it as a string.
75     *
76     * To get the correct multi-value version, use getParts.
77     *
78     * @return string
79     */
80    public function getValue() {
81
82        $out = array();
83        foreach($this->value as $key=>$value) {
84            $out[] = $key . '=' . (is_array($value)?implode(',', $value):$value);
85        }
86        return strtoupper(implode(';',$out));
87
88    }
89
90    /**
91     * Sets a multi-valued property.
92     *
93     * @param array $parts
94     * @return void
95     */
96    public function setParts(array $parts) {
97
98        $this->setValue($parts);
99
100    }
101
102    /**
103     * Returns a multi-valued property.
104     *
105     * This method always returns an array, if there was only a single value,
106     * it will still be wrapped in an array.
107     *
108     * @return array
109     */
110    public function getParts() {
111
112        return $this->value;
113
114    }
115
116    /**
117     * Sets a raw value coming from a mimedir (iCalendar/vCard) file.
118     *
119     * This has been 'unfolded', so only 1 line will be passed. Unescaping is
120     * not yet done, but parameters are not included.
121     *
122     * @param string $val
123     * @return void
124     */
125    public function setRawMimeDirValue($val) {
126
127        $this->setValue($val);
128
129    }
130
131    /**
132     * Returns a raw mime-dir representation of the value.
133     *
134     * @return string
135     */
136    public function getRawMimeDirValue() {
137
138        return $this->getValue();
139
140    }
141
142    /**
143     * Returns the type of value.
144     *
145     * This corresponds to the VALUE= parameter. Every property also has a
146     * 'default' valueType.
147     *
148     * @return string
149     */
150    public function getValueType() {
151
152        return "RECUR";
153
154    }
155
156    /**
157     * Returns the value, in the format it should be encoded for json.
158     *
159     * This method must always return an array.
160     *
161     * @return array
162     */
163    public function getJsonValue() {
164
165        $values = array();
166        foreach($this->getParts() as $k=>$v) {
167            $values[strtolower($k)] = $v;
168        }
169        return array($values);
170
171    }
172
173    /**
174     * Parses an RRULE value string, and turns it into a struct-ish array.
175     *
176     * @param string $value
177     * @return array
178     */
179    static function stringToArray($value) {
180
181        $value = strtoupper($value);
182        $newValue = array();
183        foreach(explode(';', $value) as $part) {
184
185            // Skipping empty parts.
186            if (empty($part)) {
187                continue;
188            }
189            list($partName, $partValue) = explode('=', $part);
190
191            // The value itself had multiple values..
192            if (strpos($partValue,',')!==false) {
193                $partValue=explode(',', $partValue);
194            }
195            $newValue[$partName] = $partValue;
196
197        }
198
199        return $newValue;
200
201    }
202
203}
204