1<?php 2/** 3 * List of Css Selector Sequences. 4 * 5 * @license http://www.opensource.org/licenses/mit-license.php The MIT License 6 * @copyright Copyright 2010-2014 PhpCss Team 7 */ 8 9namespace PhpCss\Ast\Selector { 10 11 use ArrayAccess; 12 use ArrayIterator; 13 use Countable; 14 use InvalidArgumentException; 15 use IteratorAggregate; 16 use PhpCss\Ast; 17 18 /** 19 * List of Css Selector Sequences. 20 * 21 * This is the root element of a standard selector string like: 22 * "element, .class" 23 * 24 * Because it is a list the some standard interfaces are implemented for 25 * easier usage. 26 * 27 * @package PhpCss 28 * @subpackage Ast 29 */ 30 class Group 31 extends Ast\Selector 32 implements ArrayAccess, Countable, IteratorAggregate { 33 34 private $_sequences = []; 35 36 /** 37 * Create the object and assign sequences if provided. They 38 * can be added later of course. 39 * 40 * @param array $sequences 41 */ 42 public function __construct(array $sequences = []) { 43 foreach ($sequences as $sequence) { 44 $this->offsetSet(NULL, $sequence); 45 } 46 } 47 48 /** 49 * Check if a sequence at the given position is available in the list. 50 * 51 * @param integer $offset 52 * @return boolean 53 * @see ArrayAccess::offsetExists() 54 */ 55 public function offsetExists($offset): bool { 56 return isset($this->_sequences[$offset]); 57 } 58 59 /** 60 * Return the sequence at the given position. 61 * 62 * @param integer $offset 63 * @return Sequence 64 * @see ArrayAccess::offsetGet() 65 */ 66 public function offsetGet($offset): Sequence { 67 return $this->_sequences[$offset]; 68 } 69 70 /** 71 * Set/Add and sequence at the given position or top the end 72 * 73 * @param integer|NULL $offset 74 * @param Sequence $value 75 * @throws InvalidArgumentException 76 * @see \ArrayAccess::offsetSet() 77 */ 78 public function offsetSet($offset, $value): void { 79 if (!$value instanceof Sequence) { 80 throw new InvalidArgumentException( 81 sprintf( 82 '$sequence is not an instance of %s but %s.', 83 Sequence::CLASS, 84 is_object($value) ? get_class($value) : gettype($value) 85 ) 86 ); 87 } 88 if (is_null($offset)) { 89 $this->_sequences[] = $value; 90 } else { 91 $this->_sequences[(int)$offset] = $value; 92 $this->_sequences = array_values($this->_sequences); 93 } 94 } 95 96 /** 97 * Remove the sequence at the given position 98 * 99 * @param integer $offset 100 * @see ArrayAccess::offsetUnset() 101 */ 102 public function offsetUnset($offset): void { 103 unset($this->_sequences[$offset]); 104 $this->_sequences = array_values($this->_sequences); 105 } 106 107 /** 108 * Return the sequence list count. 109 * 110 * @return integer 111 * @see Countable::count() 112 */ 113 public function count(): int { 114 return count($this->_sequences); 115 } 116 117 /** 118 * Return an iterator for the sequences 119 * 120 * @return ArrayIterator 121 * @see IteratorAggregate::getIterator() 122 */ 123 public function getIterator(): ArrayIterator { 124 return new ArrayIterator($this->_sequences); 125 } 126 127 /** 128 * Accept visitors, because this element has children, enter and leave are called. 129 * 130 * @param Ast\Visitor $visitor 131 * @return void 132 */ 133 public function accept(Ast\Visitor $visitor): void { 134 if ($visitor->visitEnter($this)) { 135 /** 136 * @var Sequence $sequence 137 */ 138 foreach ($this as $sequence) { 139 $sequence->accept($visitor); 140 } 141 $visitor->visitLeave($this); 142 } 143 } 144 } 145} 146