1<?php 2/** 3 * This file is part of the FreeDSx LDAP package. 4 * 5 * (c) Chad Sikorra <Chad.Sikorra@gmail.com> 6 * 7 * For the full copyright and license information, please view the LICENSE 8 * file that was distributed with this source code. 9 */ 10 11namespace FreeDSx\Ldap\Search\Filter; 12 13use FreeDSx\Asn1\Asn1; 14use FreeDSx\Asn1\Type\AbstractType; 15use FreeDSx\Asn1\Type\IncompleteType; 16use FreeDSx\Asn1\Type\SetType; 17use FreeDSx\Ldap\Exception\ProtocolException; 18use FreeDSx\Ldap\Protocol\Factory\FilterFactory; 19use FreeDSx\Ldap\Protocol\LdapEncoder; 20 21/** 22 * Methods needed to implement the filter container interface. 23 * 24 * @author Chad Sikorra <Chad.Sikorra@gmail.com> 25 */ 26trait FilterContainerTrait 27{ 28 /** 29 * @var FilterInterface[] 30 */ 31 protected $filters = []; 32 33 /** 34 * @param FilterInterface[] ...$filters 35 */ 36 public function __construct(FilterInterface ...$filters) 37 { 38 $this->filters = $filters; 39 } 40 41 /** 42 * @param FilterInterface[] ...$filters 43 * @return $this 44 */ 45 public function add(FilterInterface ...$filters) 46 { 47 foreach ($filters as $filter) { 48 $this->filters[] = $filter; 49 } 50 51 return $this; 52 } 53 54 /** 55 * @param FilterInterface $filter 56 * @return bool 57 */ 58 public function has(FilterInterface $filter): bool 59 { 60 return array_search($filter, $this->filters, true) !== false; 61 } 62 63 /** 64 * @param FilterInterface[] ...$filters 65 * @return $this 66 */ 67 public function remove(FilterInterface ...$filters) 68 { 69 foreach ($filters as $filter) { 70 if (($i = array_search($filter, $this->filters, true)) !== false) { 71 unset($this->filters[$i]); 72 } 73 } 74 75 return $this; 76 } 77 78 /** 79 * @param FilterInterface[] ...$filters 80 * @return $this 81 */ 82 public function set(FilterInterface ...$filters) 83 { 84 $this->filters = $filters; 85 86 return $this; 87 } 88 89 /** 90 * @return FilterInterface[] 91 */ 92 public function get(): array 93 { 94 return $this->filters; 95 } 96 97 /** 98 * {@inheritdoc} 99 */ 100 public function toAsn1(): AbstractType 101 { 102 return Asn1::context(self::CHOICE_TAG, Asn1::setOf( 103 ...array_map(function ($filter) { 104 /** @var FilterInterface $filter */ 105 return $filter->toAsn1(); 106 }, $this->filters) 107 )); 108 } 109 110 /** 111 * {@inheritdoc} 112 */ 113 public function toString(): string 114 { 115 return self::PAREN_LEFT 116 . self::FILTER_OPERATOR 117 . implode('', array_map(function ($filter) { 118 /** @var FilterInterface $filter */ 119 return $filter->toString(); 120 }, $this->filters)) 121 . self::PAREN_RIGHT; 122 } 123 124 /** 125 * @return \ArrayIterator 126 */ 127 public function getIterator() 128 { 129 return new \ArrayIterator($this->filters); 130 } 131 132 /** 133 * @return int 134 */ 135 public function count() 136 { 137 return count($this->filters); 138 } 139 140 /** 141 * @return string 142 */ 143 public function __toString() 144 { 145 return $this->toString(); 146 } 147 148 /** 149 * {@inheritdoc} 150 */ 151 public static function fromAsn1(AbstractType $type) 152 { 153 $type = $type instanceof IncompleteType ? (new LdapEncoder())->complete($type, AbstractType::TAG_TYPE_SET) : $type; 154 if (!($type instanceof SetType)) { 155 throw new ProtocolException('The filter is malformed'); 156 } 157 158 $filters = []; 159 foreach ($type->getChildren() as $child) { 160 $filters[] = FilterFactory::get($child); 161 } 162 163 return new self(...$filters); 164 } 165} 166