Component
6 months ago
ITip
6 months ago
Parser
6 months ago
Property
6 months ago
Recur
6 months ago
Splitter
6 months ago
TimezoneGuesser
6 months ago
timezonedata
1 year ago
BirthdayCalendarGenerator.php
6 months ago
Cli.php
6 months ago
Component.php
6 months ago
DateTimeParser.php
6 months ago
Document.php
6 months ago
ElementList.php
6 months ago
EofException.php
6 months ago
FreeBusyData.php
6 months ago
FreeBusyGenerator.php
6 months ago
InvalidDataException.php
6 months ago
Node.php
6 months ago
PHPUnitAssertions.php
6 months ago
Parameter.php
6 months ago
ParseException.php
6 months ago
Property.php
6 months ago
Reader.php
6 months ago
Settings.php
6 months ago
StringUtil.php
6 months ago
TimeZoneUtil.php
6 months ago
UUIDUtil.php
6 months ago
VCardConverter.php
6 months ago
Version.php
6 months ago
Writer.php
6 months ago
Parameter.php
369 lines
| 1 | <?php |
| 2 | |
| 3 | namespace AmeliaVendor\Sabre\VObject; |
| 4 | |
| 5 | use ArrayIterator; |
| 6 | use AmeliaVendor\Sabre\Xml; |
| 7 | |
| 8 | /** |
| 9 | * VObject Parameter. |
| 10 | * |
| 11 | * This class represents a parameter. A parameter is always tied to a property. |
| 12 | * In the case of: |
| 13 | * DTSTART;VALUE=DATE:20101108 |
| 14 | * VALUE=DATE would be the parameter name and value. |
| 15 | * |
| 16 | * @copyright Copyright (C) fruux GmbH (https://fruux.com/) |
| 17 | * @author Evert Pot (http://evertpot.com/) |
| 18 | * @license http://sabre.io/license/ Modified BSD License |
| 19 | */ |
| 20 | class Parameter extends Node |
| 21 | { |
| 22 | /** |
| 23 | * Parameter name. |
| 24 | * |
| 25 | * @var string |
| 26 | */ |
| 27 | public $name; |
| 28 | |
| 29 | /** |
| 30 | * vCard 2.1 allows parameters to be encoded without a name. |
| 31 | * |
| 32 | * We can deduce the parameter name based on its value. |
| 33 | * |
| 34 | * @var bool |
| 35 | */ |
| 36 | public $noName = false; |
| 37 | |
| 38 | /** |
| 39 | * Parameter value. |
| 40 | * |
| 41 | * @var string |
| 42 | */ |
| 43 | protected $value; |
| 44 | |
| 45 | /** |
| 46 | * Sets up the object. |
| 47 | * |
| 48 | * It's recommended to use the create:: factory method instead. |
| 49 | * |
| 50 | * @param string $name |
| 51 | * @param string $value |
| 52 | */ |
| 53 | public function __construct(Document $root, $name, $value = null) |
| 54 | { |
| 55 | $this->root = $root; |
| 56 | if (is_null($name)) { |
| 57 | $this->noName = true; |
| 58 | $this->name = static::guessParameterNameByValue($value); |
| 59 | } else { |
| 60 | $this->name = strtoupper($name); |
| 61 | } |
| 62 | |
| 63 | // If guessParameterNameByValue() returns an empty string |
| 64 | // above, we're actually dealing with a parameter that has no value. |
| 65 | // In that case we have to move the value to the name. |
| 66 | if ('' === $this->name) { |
| 67 | $this->noName = false; |
| 68 | $this->name = strtoupper($value); |
| 69 | } else { |
| 70 | $this->setValue($value); |
| 71 | } |
| 72 | } |
| 73 | |
| 74 | /** |
| 75 | * Try to guess property name by value, can be used for vCard 2.1 nameless parameters. |
| 76 | * |
| 77 | * Figuring out what the name should have been. Note that a ton of |
| 78 | * these are rather silly in 2014 and would probably rarely be |
| 79 | * used, but we like to be complete. |
| 80 | * |
| 81 | * @param string $value |
| 82 | * |
| 83 | * @return string |
| 84 | */ |
| 85 | public static function guessParameterNameByValue($value) |
| 86 | { |
| 87 | switch (strtoupper($value)) { |
| 88 | // Encodings |
| 89 | case '7-BIT': |
| 90 | case 'QUOTED-PRINTABLE': |
| 91 | case 'BASE64': |
| 92 | $name = 'ENCODING'; |
| 93 | break; |
| 94 | |
| 95 | // Common types |
| 96 | case 'WORK': |
| 97 | case 'HOME': |
| 98 | case 'PREF': |
| 99 | // Delivery Label Type |
| 100 | case 'DOM': |
| 101 | case 'INTL': |
| 102 | case 'POSTAL': |
| 103 | case 'PARCEL': |
| 104 | // Telephone types |
| 105 | case 'VOICE': |
| 106 | case 'FAX': |
| 107 | case 'MSG': |
| 108 | case 'CELL': |
| 109 | case 'PAGER': |
| 110 | case 'BBS': |
| 111 | case 'MODEM': |
| 112 | case 'CAR': |
| 113 | case 'ISDN': |
| 114 | case 'VIDEO': |
| 115 | // EMAIL types (lol) |
| 116 | case 'AOL': |
| 117 | case 'APPLELINK': |
| 118 | case 'ATTMAIL': |
| 119 | case 'CIS': |
| 120 | case 'EWORLD': |
| 121 | case 'INTERNET': |
| 122 | case 'IBMMAIL': |
| 123 | case 'MCIMAIL': |
| 124 | case 'POWERSHARE': |
| 125 | case 'PRODIGY': |
| 126 | case 'TLX': |
| 127 | case 'X400': |
| 128 | // Photo / Logo format types |
| 129 | case 'GIF': |
| 130 | case 'CGM': |
| 131 | case 'WMF': |
| 132 | case 'BMP': |
| 133 | case 'DIB': |
| 134 | case 'PICT': |
| 135 | case 'TIFF': |
| 136 | case 'PDF': |
| 137 | case 'PS': |
| 138 | case 'JPEG': |
| 139 | case 'MPEG': |
| 140 | case 'MPEG2': |
| 141 | case 'AVI': |
| 142 | case 'QTIME': |
| 143 | // Sound Digital Audio Type |
| 144 | case 'WAVE': |
| 145 | case 'PCM': |
| 146 | case 'AIFF': |
| 147 | // Key types |
| 148 | case 'X509': |
| 149 | case 'PGP': |
| 150 | $name = 'TYPE'; |
| 151 | break; |
| 152 | |
| 153 | // Value types |
| 154 | case 'INLINE': |
| 155 | case 'URL': |
| 156 | case 'CONTENT-ID': |
| 157 | case 'CID': |
| 158 | $name = 'VALUE'; |
| 159 | break; |
| 160 | |
| 161 | default: |
| 162 | $name = ''; |
| 163 | } |
| 164 | |
| 165 | return $name; |
| 166 | } |
| 167 | |
| 168 | /** |
| 169 | * Updates the current value. |
| 170 | * |
| 171 | * This may be either a single, or multiple strings in an array. |
| 172 | * |
| 173 | * @param string|array $value |
| 174 | */ |
| 175 | public function setValue($value) |
| 176 | { |
| 177 | $this->value = $value; |
| 178 | } |
| 179 | |
| 180 | /** |
| 181 | * Returns the current value. |
| 182 | * |
| 183 | * This method will always return a string, or null. If there were multiple |
| 184 | * values, it will automatically concatenate them (separated by comma). |
| 185 | * |
| 186 | * @return string|null |
| 187 | */ |
| 188 | public function getValue() |
| 189 | { |
| 190 | if (is_array($this->value)) { |
| 191 | return implode(',', $this->value); |
| 192 | } else { |
| 193 | return $this->value; |
| 194 | } |
| 195 | } |
| 196 | |
| 197 | /** |
| 198 | * Sets multiple values for this parameter. |
| 199 | */ |
| 200 | public function setParts(array $value) |
| 201 | { |
| 202 | $this->value = $value; |
| 203 | } |
| 204 | |
| 205 | /** |
| 206 | * Returns all values for this parameter. |
| 207 | * |
| 208 | * If there were no values, an empty array will be returned. |
| 209 | * |
| 210 | * @return array |
| 211 | */ |
| 212 | public function getParts() |
| 213 | { |
| 214 | if (is_array($this->value)) { |
| 215 | return $this->value; |
| 216 | } elseif (is_null($this->value)) { |
| 217 | return []; |
| 218 | } else { |
| 219 | return [$this->value]; |
| 220 | } |
| 221 | } |
| 222 | |
| 223 | /** |
| 224 | * Adds a value to this parameter. |
| 225 | * |
| 226 | * If the argument is specified as an array, all items will be added to the |
| 227 | * parameter value list. |
| 228 | * |
| 229 | * @param string|array $part |
| 230 | */ |
| 231 | public function addValue($part) |
| 232 | { |
| 233 | if (is_null($this->value)) { |
| 234 | $this->value = $part; |
| 235 | } else { |
| 236 | $this->value = array_merge((array) $this->value, (array) $part); |
| 237 | } |
| 238 | } |
| 239 | |
| 240 | /** |
| 241 | * Checks if this parameter contains the specified value. |
| 242 | * |
| 243 | * This is a case-insensitive match. It makes sense to call this for for |
| 244 | * instance the TYPE parameter, to see if it contains a keyword such as |
| 245 | * 'WORK' or 'FAX'. |
| 246 | * |
| 247 | * @param string $value |
| 248 | * |
| 249 | * @return bool |
| 250 | */ |
| 251 | public function has($value) |
| 252 | { |
| 253 | return in_array( |
| 254 | strtolower($value), |
| 255 | array_map('strtolower', (array) $this->value) |
| 256 | ); |
| 257 | } |
| 258 | |
| 259 | /** |
| 260 | * Turns the object back into a serialized blob. |
| 261 | * |
| 262 | * @return string |
| 263 | */ |
| 264 | public function serialize() |
| 265 | { |
| 266 | $value = $this->getParts(); |
| 267 | |
| 268 | if (0 === count($value)) { |
| 269 | return $this->name.'='; |
| 270 | } |
| 271 | |
| 272 | if (Document::VCARD21 === $this->root->getDocumentType() && $this->noName) { |
| 273 | return implode(';', $value); |
| 274 | } |
| 275 | |
| 276 | return $this->name.'='.array_reduce( |
| 277 | $value, |
| 278 | function ($out, $item) { |
| 279 | if (!is_null($out)) { |
| 280 | $out .= ','; |
| 281 | } |
| 282 | |
| 283 | // If there's no special characters in the string, we'll use the simple |
| 284 | // format. |
| 285 | // |
| 286 | // The list of special characters is defined as: |
| 287 | // |
| 288 | // Any character except CONTROL, DQUOTE, ";", ":", "," |
| 289 | // |
| 290 | // by the iCalendar spec: |
| 291 | // https://tools.ietf.org/html/rfc5545#section-3.1 |
| 292 | // |
| 293 | // And we add ^ to that because of: |
| 294 | // https://tools.ietf.org/html/rfc6868 |
| 295 | // |
| 296 | // But we've found that iCal (7.0, shipped with OSX 10.9) |
| 297 | // severely trips on + characters not being quoted, so we |
| 298 | // added + as well. |
| 299 | if (!preg_match('#(?: [\n":;\^,\+] )#x', $item)) { |
| 300 | return $out.$item; |
| 301 | } else { |
| 302 | // Enclosing in double-quotes, and using RFC6868 for encoding any |
| 303 | // special characters |
| 304 | $out .= '"'.strtr( |
| 305 | $item, |
| 306 | [ |
| 307 | '^' => '^^', |
| 308 | "\n" => '^n', |
| 309 | '"' => '^\'', |
| 310 | ] |
| 311 | ).'"'; |
| 312 | |
| 313 | return $out; |
| 314 | } |
| 315 | } |
| 316 | ); |
| 317 | } |
| 318 | |
| 319 | /** |
| 320 | * This method returns an array, with the representation as it should be |
| 321 | * encoded in JSON. This is used to create jCard or jCal documents. |
| 322 | * |
| 323 | * @return array |
| 324 | */ |
| 325 | #[\ReturnTypeWillChange] |
| 326 | public function jsonSerialize() |
| 327 | { |
| 328 | return $this->value; |
| 329 | } |
| 330 | |
| 331 | /** |
| 332 | * This method serializes the data into XML. This is used to create xCard or |
| 333 | * xCal documents. |
| 334 | * |
| 335 | * @param Xml\Writer $writer XML writer |
| 336 | */ |
| 337 | public function xmlSerialize(Xml\Writer $writer): void |
| 338 | { |
| 339 | foreach (explode(',', $this->value) as $value) { |
| 340 | $writer->writeElement('text', $value); |
| 341 | } |
| 342 | } |
| 343 | |
| 344 | /** |
| 345 | * Called when this object is being cast to a string. |
| 346 | * |
| 347 | * @return string |
| 348 | */ |
| 349 | public function __toString() |
| 350 | { |
| 351 | return (string) $this->getValue(); |
| 352 | } |
| 353 | |
| 354 | /** |
| 355 | * Returns the iterator for this object. |
| 356 | * |
| 357 | * @return ElementList |
| 358 | */ |
| 359 | #[\ReturnTypeWillChange] |
| 360 | public function getIterator() |
| 361 | { |
| 362 | if (!is_null($this->iterator)) { |
| 363 | return $this->iterator; |
| 364 | } |
| 365 | |
| 366 | return $this->iterator = new ArrayIterator((array) $this->value); |
| 367 | } |
| 368 | } |
| 369 |