[ Index ] |
PHP Cross Reference of Unnamed Project |
[Summary view] [Print] [Text view]
1 <?php 2 /** 3 * Copyright 2012-2014 Horde LLC (http://www.horde.org/) 4 * 5 * See the enclosed file COPYING for license information (BSD). If you 6 * did not receive this file, see http://www.horde.org/licenses/bsd. 7 * 8 * @category Horde 9 * @copyright 2012-2014 Horde LLC 10 * @license http://www.horde.org/licenses/bsd New BSD License 11 * @package Mail 12 */ 13 14 /** 15 * Container object for a collection of RFC 822 elements. 16 * 17 * @author Michael Slusarz <slusarz@horde.org> 18 * @category Horde 19 * @copyright 2012-2014 Horde LLC 20 * @license http://www.horde.org/licenses/bsd New BSD License 21 * @package Mail 22 * 23 * @property-read array $addresses The list of all addresses (address 24 * w/personal parts). 25 * @property-read array $bare_addresses The list of all addresses (mail@host). 26 * @property-read array $bare_addresses_idn The list of all addresses 27 * (mail@host; IDN encoded). 28 * (@since 2.1.0) 29 * @property-read array $base_addresses The list of ONLY base addresses 30 * (Address objects). 31 * @property-read array $raw_addresses The list of all addresses (Address 32 * objects). 33 */ 34 class Horde_Mail_Rfc822_List extends Horde_Mail_Rfc822_Object implements ArrayAccess, Countable, SeekableIterator, Serializable 35 { 36 /** Filter masks. */ 37 const HIDE_GROUPS = 1; 38 const BASE_ELEMENTS = 2; 39 40 /** 41 * List data. 42 * 43 * @var array 44 */ 45 protected $_data = array(); 46 47 /** 48 * Current Iterator filter. 49 * 50 * @var array 51 */ 52 protected $_filter = array(); 53 54 /** 55 * Current Iterator pointer. 56 * 57 * @var array 58 */ 59 protected $_ptr; 60 61 /** 62 * Constructor. 63 * 64 * @param mixed $obs Address data to store in this object. 65 */ 66 public function __construct($obs = null) 67 { 68 if (!is_null($obs)) { 69 $this->add($obs); 70 } 71 } 72 73 /** 74 */ 75 public function __get($name) 76 { 77 switch ($name) { 78 case 'addresses': 79 case 'bare_addresses': 80 case 'bare_addresses_idn': 81 case 'base_addresses': 82 case 'raw_addresses': 83 $old = $this->_filter; 84 $mask = ($name == 'base_addresses') 85 ? self::BASE_ELEMENTS 86 : self::HIDE_GROUPS; 87 $this->setIteratorFilter($mask, empty($old['filter']) ? null : $old['filter']); 88 89 $out = array(); 90 foreach ($this as $val) { 91 switch ($name) { 92 case 'addresses': 93 $out[] = strval($val); 94 break; 95 96 case 'bare_addresses': 97 $out[] = $val->bare_address; 98 break; 99 100 case 'bare_addresses_idn': 101 $out[] = $val->bare_address_idn; 102 break; 103 104 case 'base_addresses': 105 case 'raw_addresses': 106 $out[] = clone $val; 107 break; 108 } 109 } 110 111 $this->_filter = $old; 112 return $out; 113 } 114 } 115 116 /** 117 * Add objects to the container. 118 * 119 * @param mixed $obs Address data to store in this object. 120 */ 121 public function add($obs) 122 { 123 foreach ($this->_normalize($obs) as $val) { 124 $this->_data[] = $val; 125 } 126 } 127 128 /** 129 * Remove addresses from the container. This method ignores Group objects. 130 * 131 * @param mixed $obs Addresses to remove. 132 */ 133 public function remove($obs) 134 { 135 $old = $this->_filter; 136 $this->setIteratorFilter(self::HIDE_GROUPS | self::BASE_ELEMENTS); 137 138 foreach ($this->_normalize($obs) as $val) { 139 $remove = array(); 140 141 foreach ($this as $key => $val2) { 142 if ($val2->match($val)) { 143 $remove[] = $key; 144 } 145 } 146 147 foreach (array_reverse($remove) as $key) { 148 unset($this[$key]); 149 } 150 } 151 152 $this->_filter = $old; 153 } 154 155 /** 156 * Removes duplicate addresses from list. This method ignores Group 157 * objects. 158 */ 159 public function unique() 160 { 161 $exist = $remove = array(); 162 163 $old = $this->_filter; 164 $this->setIteratorFilter(self::HIDE_GROUPS | self::BASE_ELEMENTS); 165 166 // For duplicates, we use the first address that contains personal 167 // information. 168 foreach ($this as $key => $val) { 169 $bare = $val->bare_address; 170 if (isset($exist[$bare])) { 171 if (($exist[$bare] == -1) || is_null($val->personal)) { 172 $remove[] = $key; 173 } else { 174 $remove[] = $exist[$bare]; 175 $exist[$bare] = -1; 176 } 177 } else { 178 $exist[$bare] = is_null($val->personal) 179 ? $key 180 : -1; 181 } 182 } 183 184 foreach (array_reverse($remove) as $key) { 185 unset($this[$key]); 186 } 187 188 $this->_filter = $old; 189 } 190 191 /** 192 * Group count. 193 * 194 * @return integer The number of groups in the list. 195 */ 196 public function groupCount() 197 { 198 $ret = 0; 199 200 foreach ($this->_data as $val) { 201 if ($val instanceof Horde_Mail_Rfc822_Group) { 202 ++$ret; 203 } 204 } 205 206 return $ret; 207 } 208 209 /** 210 * Set the Iterator filter. 211 * 212 * @param integer $mask Filter masks. 213 * @param mixed $filter An e-mail, or as list of e-mails, to filter by. 214 */ 215 public function setIteratorFilter($mask = 0, $filter = null) 216 { 217 $this->_filter = array(); 218 219 if ($mask) { 220 $this->_filter['mask'] = $mask; 221 } 222 223 if (!is_null($filter)) { 224 $rfc822 = new Horde_Mail_Rfc822(); 225 $this->_filter['filter'] = $rfc822->parseAddressList($filter); 226 } 227 } 228 229 /** 230 */ 231 protected function _writeAddress($opts) 232 { 233 $out = array(); 234 235 foreach ($this->_data as $val) { 236 $out[] = $val->writeAddress($opts); 237 } 238 239 return implode(', ', $out); 240 } 241 242 /** 243 */ 244 public function match($ob) 245 { 246 if (!($ob instanceof Horde_Mail_Rfc822_List)) { 247 $ob = new Horde_Mail_Rfc822_List($ob); 248 } 249 250 $a = $this->bare_addresses; 251 sort($a); 252 $b = $ob->bare_addresses; 253 sort($b); 254 255 return ($a == $b); 256 } 257 258 /** 259 * Does this list contain the given e-mail address? 260 * 261 * @param mixed $address An e-mail address. 262 * 263 * @return boolean True if the e-mail address is contained in the list. 264 */ 265 public function contains($address) 266 { 267 $ob = new Horde_Mail_Rfc822_Address($address); 268 269 foreach ($this->raw_addresses as $val) { 270 if ($val->match($ob)) { 271 return true; 272 } 273 } 274 275 return false; 276 } 277 278 /** 279 * Normalize objects to add to list. 280 * 281 * @param mixed $obs Address data to store in this object. 282 * 283 * @return array Entries to add. 284 */ 285 protected function _normalize($obs) 286 { 287 $add = array(); 288 289 if (!($obs instanceof Horde_Mail_Rfc822_List) && 290 !is_array($obs)) { 291 $obs = array($obs); 292 } 293 294 foreach ($obs as $val) { 295 if (is_string($val)) { 296 $rfc822 = new Horde_Mail_Rfc822(); 297 $val = $rfc822->parseAddressList($val); 298 } 299 300 if ($val instanceof Horde_Mail_Rfc822_List) { 301 $val->setIteratorFilter(self::BASE_ELEMENTS); 302 foreach ($val as $val2) { 303 $add[] = $val2; 304 } 305 } elseif ($val instanceof Horde_Mail_Rfc822_Object) { 306 $add[] = $val; 307 } 308 } 309 310 return $add; 311 } 312 313 /* ArrayAccess methods. */ 314 315 /** 316 */ 317 public function offsetExists($offset) 318 { 319 return !is_null($this[$offset]); 320 } 321 322 /** 323 */ 324 public function offsetGet($offset) 325 { 326 try { 327 $this->seek($offset); 328 return $this->current(); 329 } catch (OutOfBoundsException $e) { 330 return null; 331 } 332 } 333 334 /** 335 */ 336 public function offsetSet($offset, $value) 337 { 338 if ($ob = $this[$offset]) { 339 if (is_null($this->_ptr['subidx'])) { 340 $tmp = $this->_normalize($value); 341 if (isset($tmp[0])) { 342 $this->_data[$this->_ptr['idx']] = $tmp[0]; 343 } 344 } else { 345 $ob[$offset] = $value; 346 } 347 $this->_ptr = null; 348 } 349 } 350 351 /** 352 */ 353 public function offsetUnset($offset) 354 { 355 if ($ob = $this[$offset]) { 356 if (is_null($this->_ptr['subidx'])) { 357 unset($this->_data[$this->_ptr['idx']]); 358 $this->_data = array_values($this->_data); 359 } else { 360 unset($ob->addresses[$this->_ptr['subidx']]); 361 } 362 $this->_ptr = null; 363 } 364 } 365 366 /* Countable methods. */ 367 368 /** 369 * Address count. 370 * 371 * @return integer The number of addresses. 372 */ 373 public function count() 374 { 375 return count($this->addresses); 376 } 377 378 /* Iterator methods. */ 379 380 public function current() 381 { 382 if (!$this->valid()) { 383 return null; 384 } 385 386 $ob = $this->_data[$this->_ptr['idx']]; 387 388 return is_null($this->_ptr['subidx']) 389 ? $ob 390 : $ob->addresses[$this->_ptr['subidx']]; 391 } 392 393 public function key() 394 { 395 return $this->_ptr['key']; 396 } 397 398 public function next() 399 { 400 if (is_null($this->_ptr['subidx'])) { 401 $curr = $this->current(); 402 if (($curr instanceof Horde_Mail_Rfc822_Group) && count($curr)) { 403 $this->_ptr['subidx'] = 0; 404 } else { 405 ++$this->_ptr['idx']; 406 } 407 $curr = $this->current(); 408 } elseif (!($curr = $this->_data[$this->_ptr['idx']]->addresses[++$this->_ptr['subidx']])) { 409 $this->_ptr['subidx'] = null; 410 ++$this->_ptr['idx']; 411 $curr = $this->current(); 412 } 413 414 if (!is_null($curr)) { 415 if (!empty($this->_filter) && $this->_iteratorFilter($curr)) { 416 $this->next(); 417 } else { 418 ++$this->_ptr['key']; 419 } 420 } 421 } 422 423 public function rewind() 424 { 425 $this->_ptr = array( 426 'idx' => 0, 427 'key' => 0, 428 'subidx' => null 429 ); 430 431 if ($this->valid() && 432 !empty($this->_filter) && 433 $this->_iteratorFilter($this->current())) { 434 $this->next(); 435 $this->_ptr['key'] = 0; 436 } 437 } 438 439 public function valid() 440 { 441 return (!empty($this->_ptr) && isset($this->_data[$this->_ptr['idx']])); 442 } 443 444 public function seek($position) 445 { 446 if (!$this->valid() || 447 ($position < $this->_ptr['key'])) { 448 $this->rewind(); 449 } 450 451 for ($i = $this->_ptr['key']; ; ++$i) { 452 if ($i == $position) { 453 return; 454 } 455 456 $this->next(); 457 if (!$this->valid()) { 458 throw new OutOfBoundsException('Position not found.'); 459 } 460 } 461 } 462 463 protected function _iteratorFilter($ob) 464 { 465 if (!empty($this->_filter['mask'])) { 466 if (($this->_filter['mask'] & self::HIDE_GROUPS) && 467 ($ob instanceof Horde_Mail_Rfc822_Group)) { 468 return true; 469 } 470 471 if (($this->_filter['mask'] & self::BASE_ELEMENTS) && 472 !is_null($this->_ptr['subidx'])) { 473 return true; 474 } 475 } 476 477 if (!empty($this->_filter['filter']) && 478 ($ob instanceof Horde_Mail_Rfc822_Address)) { 479 foreach ($this->_filter['filter'] as $val) { 480 if ($ob->match($val)) { 481 return true; 482 } 483 } 484 } 485 486 return false; 487 } 488 489 /* Serializable methods. */ 490 491 public function serialize() 492 { 493 return serialize($this->_data); 494 } 495 496 public function unserialize($data) 497 { 498 $this->_data = unserialize($data); 499 } 500 501 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Thu Aug 11 10:00:09 2016 | Cross-referenced by PHPXref 0.7.1 |