blob: e4e5329c14e28a9de73f5078da7c0b8a18559d6c [file] [log] [blame]
Matthias Andreas Benkard7b2a3a12021-08-16 10:57:25 +02001<?php
2
3namespace Adldap\Query;
4
5use Adldap\Models\Entry;
6use Adldap\Models\Model;
7use InvalidArgumentException;
8use Adldap\Schemas\SchemaInterface;
9use Adldap\Connections\ConnectionInterface;
10
11class Processor
12{
13 /**
14 * @var Builder
15 */
16 protected $builder;
17
18 /**
19 * @var ConnectionInterface
20 */
21 protected $connection;
22
23 /**
24 * @var SchemaInterface
25 */
26 protected $schema;
27
28 /**
29 * Constructor.
30 *
31 * @param Builder $builder
32 */
33 public function __construct(Builder $builder)
34 {
35 $this->builder = $builder;
36 $this->schema = $builder->getSchema();
37 $this->connection = $builder->getConnection();
38 }
39
40 /**
41 * Processes LDAP search results and constructs their model instances.
42 *
43 * @param array $entries The LDAP entries to process.
44 *
45 * @return Collection|array
46 */
47 public function process($entries)
48 {
49 if ($this->builder->isRaw()) {
50 // If the builder is asking for a raw
51 // LDAP result, we can return here.
52 return $entries;
53 }
54
55 $models = [];
56
57 if (array_key_exists('count', $entries)) {
58 for ($i = 0; $i < $entries['count']; $i++) {
59 // We'll go through each entry and construct a new
60 // model instance with the raw LDAP attributes.
61 $models[] = $this->newLdapEntry($entries[$i]);
62 }
63 }
64
65 // If the query contains paginated results, we'll return them here.
66 if ($this->builder->isPaginated()) {
67 return $models;
68 }
69
70 // If the query is requested to be sorted, we'll perform
71 // that here and return the resulting collection.
72 if ($this->builder->isSorted()) {
73 return $this->processSort($models);
74 }
75
76 // Otherwise, we'll return a regular unsorted collection.
77 return $this->newCollection($models);
78 }
79
80 /**
81 * Processes paginated LDAP results.
82 *
83 * @param array $pages
84 * @param int $perPage
85 * @param int $currentPage
86 *
87 * @return Paginator
88 */
89 public function processPaginated(array $pages = [], $perPage = 50, $currentPage = 0)
90 {
91 $models = [];
92
93 foreach ($pages as $entries) {
94 // Go through each page and process the results into an objects array.
95 $models = array_merge($models, $this->process($entries));
96 }
97
98 $models = $this->processSort($models)->toArray();
99
100 return $this->newPaginator($models, $perPage, $currentPage, count($pages));
101 }
102
103 /**
104 * Returns a new LDAP Entry instance.
105 *
106 * @param array $attributes
107 *
108 * @return Entry
109 */
110 public function newLdapEntry(array $attributes = [])
111 {
112 $objectClass = $this->schema->objectClass();
113
114 // We need to ensure the record contains an object class to be able to
115 // determine its type. Otherwise, we create a default Entry model.
116 if (array_key_exists($objectClass, $attributes) && array_key_exists(0, $attributes[$objectClass])) {
117 // Retrieve all of the object classes from the LDAP
118 // entry and lowercase them for comparisons.
119 $classes = array_map('strtolower', $attributes[$objectClass]);
120
121 // Retrieve the model mapping.
122 $models = $this->schema->objectClassModelMap();
123
124 // Retrieve the object class mappings (with strtolower keys).
125 $mappings = array_map('strtolower', array_keys($models));
126
127 // Retrieve the model from the map using the entry's object class.
128 $map = array_intersect($mappings, $classes);
129
130 if (count($map) > 0) {
131 // Retrieve the model using the object class.
132 $model = $models[current($map)];
133
134 // Construct and return a new model.
135 return $this->newModel([], $model)
136 ->setRawAttributes($attributes);
137 }
138 }
139
140 // A default entry model if the object class isn't found.
141 return $this->newModel()->setRawAttributes($attributes);
142 }
143
144 /**
145 * Creates a new model instance.
146 *
147 * @param array $attributes
148 * @param string|null $model
149 *
150 * @throws InvalidArgumentException
151 *
152 * @return mixed|Entry
153 */
154 public function newModel($attributes = [], $model = null)
155 {
156 $model = (class_exists($model) ? $model : $this->schema->entryModel());
157
158 if (!is_subclass_of($model, $base = Model::class)) {
159 throw new InvalidArgumentException("The given model class '{$model}' must extend the base model class '{$base}'");
160 }
161
162 return new $model($attributes, $this->builder->newInstance());
163 }
164
165 /**
166 * Returns a new Paginator object instance.
167 *
168 * @param array $models
169 * @param int $perPage
170 * @param int $currentPage
171 * @param int $pages
172 *
173 * @return Paginator
174 */
175 public function newPaginator(array $models = [], $perPage = 25, $currentPage = 0, $pages = 1)
176 {
177 return new Paginator($models, $perPage, $currentPage, $pages);
178 }
179
180 /**
181 * Returns a new collection instance.
182 *
183 * @param array $items
184 *
185 * @return Collection
186 */
187 public function newCollection(array $items = [])
188 {
189 return new Collection($items);
190 }
191
192 /**
193 * Sorts LDAP search results.
194 *
195 * @param array $models
196 *
197 * @return Collection
198 */
199 protected function processSort(array $models = [])
200 {
201 $field = $this->builder->getSortByField();
202
203 $flags = $this->builder->getSortByFlags();
204
205 $direction = $this->builder->getSortByDirection();
206
207 $desc = ($direction === 'desc' ? true : false);
208
209 return $this->newCollection($models)->sortBy($field, $flags, $desc);
210 }
211}