1<?php 2 3namespace Sabre\CardDAV; 4 5use Sabre\DAV; 6use Sabre\DAVACL; 7 8/** 9 * The Card object represents a single Card from an addressbook 10 * 11 * @copyright Copyright (C) fruux GmbH (https://fruux.com/) 12 * @author Evert Pot (http://evertpot.com/) 13 * @license http://sabre.io/license/ Modified BSD License 14 */ 15class Card extends DAV\File implements ICard, DAVACL\IACL { 16 17 use DAVACL\ACLTrait; 18 19 /** 20 * CardDAV backend 21 * 22 * @var Backend\BackendInterface 23 */ 24 protected $carddavBackend; 25 26 /** 27 * Array with information about this Card 28 * 29 * @var array 30 */ 31 protected $cardData; 32 33 /** 34 * Array with information about the containing addressbook 35 * 36 * @var array 37 */ 38 protected $addressBookInfo; 39 40 /** 41 * Constructor 42 * 43 * @param Backend\BackendInterface $carddavBackend 44 * @param array $addressBookInfo 45 * @param array $cardData 46 */ 47 function __construct(Backend\BackendInterface $carddavBackend, array $addressBookInfo, array $cardData) { 48 49 $this->carddavBackend = $carddavBackend; 50 $this->addressBookInfo = $addressBookInfo; 51 $this->cardData = $cardData; 52 53 } 54 55 /** 56 * Returns the uri for this object 57 * 58 * @return string 59 */ 60 function getName() { 61 62 return $this->cardData['uri']; 63 64 } 65 66 /** 67 * Returns the VCard-formatted object 68 * 69 * @return string 70 */ 71 function get() { 72 73 // Pre-populating 'carddata' is optional. If we don't yet have it 74 // already, we fetch it from the backend. 75 if (!isset($this->cardData['carddata'])) { 76 $this->cardData = $this->carddavBackend->getCard($this->addressBookInfo['id'], $this->cardData['uri']); 77 } 78 return $this->cardData['carddata']; 79 80 } 81 82 /** 83 * Updates the VCard-formatted object 84 * 85 * @param string $cardData 86 * @return string|null 87 */ 88 function put($cardData) { 89 90 if (is_resource($cardData)) 91 $cardData = stream_get_contents($cardData); 92 93 // Converting to UTF-8, if needed 94 $cardData = DAV\StringUtil::ensureUTF8($cardData); 95 96 $etag = $this->carddavBackend->updateCard($this->addressBookInfo['id'], $this->cardData['uri'], $cardData); 97 $this->cardData['carddata'] = $cardData; 98 $this->cardData['etag'] = $etag; 99 100 return $etag; 101 102 } 103 104 /** 105 * Deletes the card 106 * 107 * @return void 108 */ 109 function delete() { 110 111 $this->carddavBackend->deleteCard($this->addressBookInfo['id'], $this->cardData['uri']); 112 113 } 114 115 /** 116 * Returns the mime content-type 117 * 118 * @return string 119 */ 120 function getContentType() { 121 122 return 'text/vcard; charset=utf-8'; 123 124 } 125 126 /** 127 * Returns an ETag for this object 128 * 129 * @return string 130 */ 131 function getETag() { 132 133 if (isset($this->cardData['etag'])) { 134 return $this->cardData['etag']; 135 } else { 136 $data = $this->get(); 137 if (is_string($data)) { 138 return '"' . md5($data) . '"'; 139 } else { 140 // We refuse to calculate the md5 if it's a stream. 141 return null; 142 } 143 } 144 145 } 146 147 /** 148 * Returns the last modification date as a unix timestamp 149 * 150 * @return int 151 */ 152 function getLastModified() { 153 154 return isset($this->cardData['lastmodified']) ? $this->cardData['lastmodified'] : null; 155 156 } 157 158 /** 159 * Returns the size of this object in bytes 160 * 161 * @return int 162 */ 163 function getSize() { 164 165 if (array_key_exists('size', $this->cardData)) { 166 return $this->cardData['size']; 167 } else { 168 return strlen($this->get()); 169 } 170 171 } 172 173 /** 174 * Returns the owner principal 175 * 176 * This must be a url to a principal, or null if there's no owner 177 * 178 * @return string|null 179 */ 180 function getOwner() { 181 182 return $this->addressBookInfo['principaluri']; 183 184 } 185 186 187 /** 188 * Returns a list of ACE's for this node. 189 * 190 * Each ACE has the following properties: 191 * * 'privilege', a string such as {DAV:}read or {DAV:}write. These are 192 * currently the only supported privileges 193 * * 'principal', a url to the principal who owns the node 194 * * 'protected' (optional), indicating that this ACE is not allowed to 195 * be updated. 196 * 197 * @return array 198 */ 199 function getACL() { 200 201 // An alternative acl may be specified through the cardData array. 202 if (isset($this->cardData['acl'])) { 203 return $this->cardData['acl']; 204 } 205 206 return [ 207 [ 208 'privilege' => '{DAV:}all', 209 'principal' => $this->addressBookInfo['principaluri'], 210 'protected' => true, 211 ], 212 ]; 213 214 } 215 216} 217