Parameter.php 8.9 KB

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