| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368 |
- <?php
- namespace Sabre\VObject;
- use ArrayIterator;
- use Sabre\Xml;
- /**
- * VObject Parameter.
- *
- * This class represents a parameter. A parameter is always tied to a property.
- * In the case of:
- * DTSTART;VALUE=DATE:20101108
- * VALUE=DATE would be the parameter name and value.
- *
- * @copyright Copyright (C) fruux GmbH (https://fruux.com/)
- * @author Evert Pot (http://evertpot.com/)
- * @license http://sabre.io/license/ Modified BSD License
- */
- class Parameter extends Node
- {
- /**
- * Parameter name.
- *
- * @var string
- */
- public $name;
- /**
- * vCard 2.1 allows parameters to be encoded without a name.
- *
- * We can deduce the parameter name based on its value.
- *
- * @var bool
- */
- public $noName = false;
- /**
- * Parameter value.
- *
- * @var string
- */
- protected $value;
- /**
- * Sets up the object.
- *
- * It's recommended to use the create:: factory method instead.
- *
- * @param string $name
- * @param string $value
- */
- public function __construct(Document $root, $name, $value = null)
- {
- $this->root = $root;
- if (is_null($name)) {
- $this->noName = true;
- $this->name = static::guessParameterNameByValue($value);
- } else {
- $this->name = strtoupper($name);
- }
- // If guessParameterNameByValue() returns an empty string
- // above, we're actually dealing with a parameter that has no value.
- // In that case we have to move the value to the name.
- if ('' === $this->name) {
- $this->noName = false;
- $this->name = strtoupper($value);
- } else {
- $this->setValue($value);
- }
- }
- /**
- * Try to guess property name by value, can be used for vCard 2.1 nameless parameters.
- *
- * Figuring out what the name should have been. Note that a ton of
- * these are rather silly in 2014 and would probably rarely be
- * used, but we like to be complete.
- *
- * @param string $value
- *
- * @return string
- */
- public static function guessParameterNameByValue($value)
- {
- switch (strtoupper($value)) {
- // Encodings
- case '7-BIT':
- case 'QUOTED-PRINTABLE':
- case 'BASE64':
- $name = 'ENCODING';
- break;
- // Common types
- case 'WORK':
- case 'HOME':
- case 'PREF':
- // Delivery Label Type
- case 'DOM':
- case 'INTL':
- case 'POSTAL':
- case 'PARCEL':
- // Telephone types
- case 'VOICE':
- case 'FAX':
- case 'MSG':
- case 'CELL':
- case 'PAGER':
- case 'BBS':
- case 'MODEM':
- case 'CAR':
- case 'ISDN':
- case 'VIDEO':
- // EMAIL types (lol)
- case 'AOL':
- case 'APPLELINK':
- case 'ATTMAIL':
- case 'CIS':
- case 'EWORLD':
- case 'INTERNET':
- case 'IBMMAIL':
- case 'MCIMAIL':
- case 'POWERSHARE':
- case 'PRODIGY':
- case 'TLX':
- case 'X400':
- // Photo / Logo format types
- case 'GIF':
- case 'CGM':
- case 'WMF':
- case 'BMP':
- case 'DIB':
- case 'PICT':
- case 'TIFF':
- case 'PDF':
- case 'PS':
- case 'JPEG':
- case 'MPEG':
- case 'MPEG2':
- case 'AVI':
- case 'QTIME':
- // Sound Digital Audio Type
- case 'WAVE':
- case 'PCM':
- case 'AIFF':
- // Key types
- case 'X509':
- case 'PGP':
- $name = 'TYPE';
- break;
- // Value types
- case 'INLINE':
- case 'URL':
- case 'CONTENT-ID':
- case 'CID':
- $name = 'VALUE';
- break;
- default:
- $name = '';
- }
- return $name;
- }
- /**
- * Updates the current value.
- *
- * This may be either a single, or multiple strings in an array.
- *
- * @param string|array $value
- */
- public function setValue($value)
- {
- $this->value = $value;
- }
- /**
- * Returns the current value.
- *
- * This method will always return a string, or null. If there were multiple
- * values, it will automatically concatenate them (separated by comma).
- *
- * @return string|null
- */
- public function getValue()
- {
- if (is_array($this->value)) {
- return implode(',', $this->value);
- } else {
- return $this->value;
- }
- }
- /**
- * Sets multiple values for this parameter.
- */
- public function setParts(array $value)
- {
- $this->value = $value;
- }
- /**
- * Returns all values for this parameter.
- *
- * If there were no values, an empty array will be returned.
- *
- * @return array
- */
- public function getParts()
- {
- if (is_array($this->value)) {
- return $this->value;
- } elseif (is_null($this->value)) {
- return [];
- } else {
- return [$this->value];
- }
- }
- /**
- * Adds a value to this parameter.
- *
- * If the argument is specified as an array, all items will be added to the
- * parameter value list.
- *
- * @param string|array $part
- */
- public function addValue($part)
- {
- if (is_null($this->value)) {
- $this->value = $part;
- } else {
- $this->value = array_merge((array) $this->value, (array) $part);
- }
- }
- /**
- * Checks if this parameter contains the specified value.
- *
- * This is a case-insensitive match. It makes sense to call this for for
- * instance the TYPE parameter, to see if it contains a keyword such as
- * 'WORK' or 'FAX'.
- *
- * @param string $value
- *
- * @return bool
- */
- public function has($value)
- {
- return in_array(
- strtolower($value),
- array_map('strtolower', (array) $this->value)
- );
- }
- /**
- * Turns the object back into a serialized blob.
- *
- * @return string
- */
- public function serialize()
- {
- $value = $this->getParts();
- if (0 === count($value)) {
- return $this->name.'=';
- }
- if (Document::VCARD21 === $this->root->getDocumentType() && $this->noName) {
- return implode(';', $value);
- }
- return $this->name.'='.array_reduce(
- $value,
- function ($out, $item) {
- if (!is_null($out)) {
- $out .= ',';
- }
- // If there's no special characters in the string, we'll use the simple
- // format.
- //
- // The list of special characters is defined as:
- //
- // Any character except CONTROL, DQUOTE, ";", ":", ","
- //
- // by the iCalendar spec:
- // https://tools.ietf.org/html/rfc5545#section-3.1
- //
- // And we add ^ to that because of:
- // https://tools.ietf.org/html/rfc6868
- //
- // But we've found that iCal (7.0, shipped with OSX 10.9)
- // severely trips on + characters not being quoted, so we
- // added + as well.
- if (!preg_match('#(?: [\n":;\^,\+] )#x', $item)) {
- return $out.$item;
- } else {
- // Enclosing in double-quotes, and using RFC6868 for encoding any
- // special characters
- $out .= '"'.strtr(
- $item,
- [
- '^' => '^^',
- "\n" => '^n',
- '"' => '^\'',
- ]
- ).'"';
- return $out;
- }
- }
- );
- }
- /**
- * This method returns an array, with the representation as it should be
- * encoded in JSON. This is used to create jCard or jCal documents.
- *
- * @return array
- */
- #[\ReturnTypeWillChange]
- public function jsonSerialize()
- {
- return $this->value;
- }
- /**
- * This method serializes the data into XML. This is used to create xCard or
- * xCal documents.
- *
- * @param Xml\Writer $writer XML writer
- */
- public function xmlSerialize(Xml\Writer $writer): void
- {
- foreach (explode(',', $this->value) as $value) {
- $writer->writeElement('text', $value);
- }
- }
- /**
- * Called when this object is being cast to a string.
- *
- * @return string
- */
- public function __toString()
- {
- return (string) $this->getValue();
- }
- /**
- * Returns the iterator for this object.
- *
- * @return ElementList
- */
- #[\ReturnTypeWillChange]
- public function getIterator()
- {
- if (!is_null($this->iterator)) {
- return $this->iterator;
- }
- return $this->iterator = new ArrayIterator((array) $this->value);
- }
- }
|