composer package updates
[openemr.git] / vendor / adldap2 / adldap2 / src / Query / Builder.php
blobf99e3848d0b9eb5b7f4f91824eb92092de06bae0
1 <?php
3 namespace Adldap\Query;
5 use Closure;
6 use Illuminate\Support\Arr;
7 use Illuminate\Support\Str;
8 use InvalidArgumentException;
9 use Adldap\Utilities;
10 use Adldap\Models\Model;
11 use Adldap\Schemas\SchemaInterface;
12 use Adldap\Schemas\ActiveDirectory;
13 use Adldap\Models\ModelNotFoundException;
14 use Adldap\Connections\ConnectionInterface;
16 class Builder
18 /**
19 * The selected columns to retrieve on the query.
21 * @var array
23 public $columns = ['*'];
25 /**
26 * The query filters.
28 * @var array
30 public $filters = [
31 'and' => [],
32 'or' => [],
33 'raw' => [],
36 /**
37 * The size limit of the query.
39 * @var int
41 public $limit = 0;
43 /**
44 * Determines whether the current query is paginated.
46 * @var bool
48 public $paginated = false;
50 /**
51 * The field to sort search results by.
53 * @var string
55 protected $sortByField = '';
57 /**
58 * The direction to sort the results by.
60 * @var string
62 protected $sortByDirection = '';
64 /**
65 * The sort flags for sorting query results.
67 * @var int
69 protected $sortByFlags;
71 /**
72 * The distinguished name to perform searches upon.
74 * @var string|null
76 protected $dn;
78 /**
79 * The default query type.
81 * @var string
83 protected $type = 'search';
85 /**
86 * Determines whether or not to return LDAP results in their raw array format.
88 * @var bool
90 protected $raw = false;
92 /**
93 * Determines whether the query is nested.
95 * @var bool
97 protected $nested = false;
99 /**
100 * The current connection instance.
102 * @var ConnectionInterface
104 protected $connection;
107 * The current grammar instance.
109 * @var Grammar
111 protected $grammar;
114 * The current schema instance.
116 * @var SchemaInterface
118 protected $schema;
121 * Constructor.
123 * @param ConnectionInterface $connection
124 * @param Grammar|null $grammar
125 * @param SchemaInterface|null $schema
127 public function __construct(ConnectionInterface $connection, Grammar $grammar = null, SchemaInterface $schema = null)
129 $this->setConnection($connection)
130 ->setGrammar($grammar)
131 ->setSchema($schema);
135 * Sets the current connection.
137 * @param ConnectionInterface $connection
139 * @return Builder
141 public function setConnection(ConnectionInterface $connection)
143 $this->connection = $connection;
145 return $this;
149 * Sets the current filter grammar.
151 * @param Grammar|null $grammar
153 * @return Builder
155 public function setGrammar(Grammar $grammar = null)
157 $this->grammar = $grammar ?: new Grammar();
159 return $this;
163 * Sets the current schema.
165 * @param SchemaInterface|null $schema
167 * @return Builder
169 public function setSchema(SchemaInterface $schema = null)
171 $this->schema = $schema ?: new ActiveDirectory();
173 return $this;
177 * Returns the current schema.
179 * @return SchemaInterface
181 public function getSchema()
183 return $this->schema;
187 * Returns a new Query Builder instance.
189 * @param string $baseDn
191 * @return Builder
193 public function newInstance($baseDn = null)
195 // We'll set the base DN of the new Builder so
196 // developers don't need to do this manually.
197 $dn = is_null($baseDn) ? $this->getDn() : $baseDn;
199 return (new static($this->connection, $this->grammar, $this->schema))
200 ->setDn($dn);
204 * Returns a new nested Query Builder instance.
206 * @param Closure|null $closure
208 * @return $this
210 public function newNestedInstance(Closure $closure = null)
212 $query = $this->newInstance()->nested();
214 if ($closure) {
215 call_user_func($closure, $query);
218 return $query;
222 * Returns the current query.
224 * @return \Illuminate\Support\Collection|array
226 public function get()
228 // We'll mute any warnings / errors here. We just need to
229 // know if any query results were returned.
230 return @$this->query($this->getQuery());
234 * Compiles and returns the current query string.
236 * @return string
238 public function getQuery()
240 return $this->grammar->compile($this);
244 * Returns the unescaped query.
246 * @return string
248 public function getUnescapedQuery()
250 return Utilities::unescape($this->getQuery());
254 * Returns the current Grammar instance.
256 * @return Grammar
258 public function getGrammar()
260 return $this->grammar;
264 * Returns the current Connection instance.
266 * @return ConnectionInterface
268 public function getConnection()
270 return $this->connection;
274 * Returns the builders DN to perform searches upon.
276 * @return string
278 public function getDn()
280 return $this->dn;
284 * Sets the DN to perform searches upon.
286 * @param string|null $dn
288 * @return Builder
290 public function setDn($dn = null)
292 $this->dn = (string) $dn;
294 return $this;
298 * Alias for setting the base DN of the query.
300 * @param string $dn
302 * @return Builder
304 public function in($dn)
306 return $this->setDn($dn);
310 * Sets the size limit of the current query.
312 * @param int $limit
314 * @return Builder
316 public function limit($limit = 0)
318 $this->limit = $limit;
320 return $this;
324 * Performs the specified query on the current LDAP connection.
326 * @param string $query
328 * @return \Illuminate\Support\Collection|array
330 public function query($query)
332 $results = $this->connection->{$this->type}(
333 $this->getDn(),
334 $query,
335 $this->getSelects(),
336 $onlyAttributes = false,
337 $this->limit
340 return $this->newProcessor()->process($results);
344 * Paginates the current LDAP query.
346 * @param int $perPage
347 * @param int $currentPage
348 * @param bool $isCritical
350 * @return Paginator
352 public function paginate($perPage = 50, $currentPage = 0, $isCritical = true)
354 $this->paginated = true;
356 $pages = [];
358 $cookie = '';
360 do {
361 $this->connection->controlPagedResult($perPage, $isCritical, $cookie);
363 // Run the search.
364 $resource = @$this->connection->search($this->getDn(), $this->getQuery(), $this->getSelects());
366 if ($resource) {
367 $this->connection->controlPagedResultResponse($resource, $cookie);
369 // We'll collect each resource result into the pages array.
370 $pages[] = $resource;
372 } while (!empty($cookie));
374 $paginator = $this->newProcessor()->processPaginated($pages, $perPage, $currentPage);
376 // Reset paged result on the current connection. We won't pass in the current $perPage
377 // parameter since we want to reset the page size to the default '1000'. Sending '0'
378 // eliminates any further opportunity for running queries in the same request,
379 // even though that is supposed to be the correct usage.
380 $this->connection->controlPagedResult();
382 return $paginator;
386 * Returns the first entry in a search result.
388 * @param array|string $columns
390 * @return Model|array|null
392 public function first($columns = [])
394 $results = $this->select($columns)->limit(1)->get();
396 return Arr::get($results, 0);
400 * Returns the first entry in a search result.
402 * If no entry is found, an exception is thrown.
404 * @param array|string $columns
406 * @throws ModelNotFoundException
408 * @return Model
410 public function firstOrFail($columns = [])
412 $record = $this->first($columns);
414 if (!$record) {
415 throw (new ModelNotFoundException())
416 ->setQuery($this->getUnescapedQuery(), $this->getDn());
419 return $record;
423 * Finds a record by the specified attribute and value.
425 * @param string $attribute
426 * @param string $value
427 * @param array|string $columns
429 * @return mixed
431 public function findBy($attribute, $value, $columns = [])
433 return $this->whereEquals($attribute, $value)->first($columns);
437 * Finds a record by the specified attribute and value.
439 * If no record is found an exception is thrown.
441 * @param string $attribute
442 * @param string $value
443 * @param array|string $columns
445 * @throws ModelNotFoundException
447 * @return mixed
449 public function findByOrFail($attribute, $value, $columns = [])
451 return $this->whereEquals($attribute, $value)->firstOrFail($columns);
455 * Finds a record using ambiguous name resolution.
457 * @param string|array $anr
458 * @param array|string $columns
460 * @return mixed
462 public function find($anr, $columns = [])
464 if (is_array($anr)) {
465 return $this->findMany($anr, $columns);
468 return $this->findBy($this->schema->anr(), $anr, $columns);
472 * Finds multiple records using ambiguous name resolution.
474 * @param array $anrs
475 * @param array $columns
477 * @return mixed
479 public function findMany(array $anrs = [], $columns = [])
481 return $this->findManyBy($this->schema->anr(), $anrs, $columns);
485 * Finds many records by the specified attribute.
487 * @param string $attribute
488 * @param array $values
489 * @param array $columns
491 * @return mixed
493 public function findManyBy($attribute, array $values = [], $columns = [])
495 $query = $this->select($columns);
497 foreach ($values as $value) {
498 $query->orWhere([$attribute => $value]);
501 return $query->get();
505 * Finds a record using ambiguous name resolution.
507 * If a record is not found, an exception is thrown.
509 * @param string $anr
510 * @param array|string $columns
512 * @throws ModelNotFoundException
514 * @return mixed
516 public function findOrFail($anr, $columns = [])
518 $entry = $this->find($anr, $columns);
520 // Make sure we check if the result is an entry or an array before
521 // we throw an exception in case the user wants raw results.
522 if (!$entry instanceof Model && !is_array($entry)) {
523 throw (new ModelNotFoundException())
524 ->setQuery($this->getUnescapedQuery(), $this->getDn());
527 return $entry;
531 * Finds a record by its distinguished name.
533 * @param string|array $dn
534 * @param array|string $columns
536 * @return bool|Model
538 public function findByDn($dn, $columns = [])
540 return $this
541 ->setDn($dn)
542 ->read()
543 ->whereHas($this->schema->objectClass())
544 ->first($columns);
548 * Finds a record by its distinguished name.
550 * Fails upon no records returned.
552 * @param string $dn
553 * @param array|string $columns
555 * @throws ModelNotFoundException
557 * @return Model
559 public function findByDnOrFail($dn, $columns = [])
561 return $this
562 ->setDn($dn)
563 ->read()
564 ->whereHas($this->schema->objectClass())
565 ->firstOrFail($columns);
569 * Finds a record by its string GUID.
571 * @param string $guid
572 * @param array|string $columns
574 * @return Model
576 public function findByGuid($guid, $columns = [])
578 if ($this->schema->objectGuidRequiresConversion()) {
579 $guid = Utilities::stringGuidToHex($guid);
582 return $this->select($columns)->whereRaw([
583 $this->schema->objectGuid() => $guid
584 ])->first();
588 * Finds a record by its string GUID.
590 * Fails upon no records returned.
592 * @param string $guid
593 * @param array|string $columns
595 * @throws ModelNotFoundException
597 * @return mixed
599 public function findByGuidOrFail($guid, $columns = [])
601 if ($this->schema->objectGuidRequiresConversion()) {
602 $guid = Utilities::stringGuidToHex($guid);
605 return $this->select($columns)->whereRaw([
606 $this->schema->objectGuid() => $guid
607 ])->firstOrFail();
611 * Finds a record by its Object SID.
613 * @param string $sid
614 * @param array|string $columns
616 * @return mixed
618 public function findBySid($sid, $columns = [])
620 return $this->findBy($this->schema->objectSid(), $sid, $columns);
624 * Finds a record by its Object SID.
626 * Fails upon no records returned.
628 * @param string $sid
629 * @param array|string $columns
631 * @throws ModelNotFoundException
633 * @return mixed
635 public function findBySidOrFail($sid, $columns = [])
637 return $this->findByOrFail($this->schema->objectSid(), $sid, $columns);
641 * Finds the Base DN of your domain controller.
643 * @return string|bool
645 public function findBaseDn()
647 $result = $this->setDn(null)
648 ->read()
649 ->raw()
650 ->whereHas($this->schema->objectClass())
651 ->first();
653 $key = $this->schema->defaultNamingContext();
655 if (is_array($result) && array_key_exists($key, $result)) {
656 if (array_key_exists(0, $result[$key])) {
657 return $result[$key][0];
661 return false;
665 * Adds the inserted fields to query on the current LDAP connection.
667 * @param array|string $columns
669 * @return Builder
671 public function select($columns = [])
673 $columns = is_array($columns) ? $columns : func_get_args();
675 if (!empty($columns)) {
676 $this->columns = $columns;
679 return $this;
683 * Adds a raw filter to the current query.
685 * @param array|string $filters
687 * @return Builder
689 public function rawFilter($filters = [])
691 $filters = is_array($filters) ? $filters : func_get_args();
693 foreach ($filters as $filter) {
694 $this->filters['raw'][] = $filter;
697 return $this;
701 * Adds a nested 'and' filter to the current query.
703 * @param Closure $closure
705 * @return Builder
707 public function andFilter(Closure $closure)
709 $query = $this->newNestedInstance($closure);
711 $filter = $this->grammar->compileAnd($query->getQuery());
713 return $this->rawFilter($filter);
717 * Adds a nested 'or' filter to the current query.
719 * @param Closure $closure
721 * @return Builder
723 public function orFilter(Closure $closure)
725 $query = $this->newNestedInstance($closure);
727 $filter = $this->grammar->compileOr($query->getQuery());
729 return $this->rawFilter($filter);
733 * Adds a nested 'not' filter to the current query.
735 * @param Closure $closure
737 * @return Builder
739 public function notFilter(Closure $closure)
741 $query = $this->newNestedInstance($closure);
743 $filter = $this->grammar->compileNot($query->getQuery());
745 return $this->rawFilter($filter);
749 * Adds a where clause to the current query.
751 * @param string|array $field
752 * @param string $operator
753 * @param string $value
754 * @param string $boolean
755 * @param bool $raw
757 * @throws InvalidArgumentException
759 * @return Builder
761 public function where($field, $operator = null, $value = null, $boolean = 'and', $raw = false)
763 if (is_array($field)) {
764 // If the column is an array, we will assume it is an array of
765 // key-value pairs and can add them each as a where clause.
766 return $this->addArrayOfWheres($field, $boolean, $raw);
769 // We'll bypass the 'has' and 'notHas' operator since they
770 // only require two arguments inside the where method.
771 $bypass = [Operator::$has, Operator::$notHas];
773 // Here we will make some assumptions about the operator. If only
774 // 2 values are passed to the method, we will assume that
775 // the operator is 'equals' and keep going.
776 if (func_num_args() === 2 && in_array($operator, $bypass) === false) {
777 list($value, $operator) = [$operator, '='];
780 if (!in_array($operator, Operator::all())) {
781 throw new InvalidArgumentException("Invalid where operator: {$operator}");
784 // We'll escape the value if raw isn't requested.
785 $value = $raw ? $value : $this->escape($value);
787 $field = $this->escape($field, $ignore = null, 3);
789 $this->filters[$boolean][] = compact('field', 'operator', 'value');
791 return $this;
795 * Adds a raw where clause to the current query.
797 * Values given to this method are not escaped.
799 * @param string|array $field
800 * @param string $operator
801 * @param string $value
803 * @return Builder
805 public function whereRaw($field, $operator = null, $value = null)
807 return $this->where($field, $operator, $value, 'and', true);
811 * Adds a 'where equals' clause to the current query.
813 * @param string $field
814 * @param string $value
816 * @return Builder
818 public function whereEquals($field, $value)
820 return $this->where($field, Operator::$equals, $value);
824 * Adds a 'where not equals' clause to the current query.
826 * @param string $field
827 * @param string $value
829 * @return Builder
831 public function whereNotEquals($field, $value)
833 return $this->where($field, Operator::$doesNotEqual, $value);
837 * Adds a 'where approximately equals' clause to the current query.
839 * @param string $field
840 * @param string $value
842 * @return Builder
844 public function whereApproximatelyEquals($field, $value)
846 return $this->where($field, Operator::$approximatelyEquals, $value);
850 * Adds a 'where has' clause to the current query.
852 * @param string $field
854 * @return Builder
856 public function whereHas($field)
858 return $this->where($field, Operator::$has);
862 * Adds a 'where not has' clause to the current query.
864 * @param string $field
866 * @return Builder
868 public function whereNotHas($field)
870 return $this->where($field, Operator::$notHas);
874 * Adds a 'where contains' clause to the current query.
876 * @param string $field
877 * @param string $value
879 * @return Builder
881 public function whereContains($field, $value)
883 return $this->where($field, Operator::$contains, $value);
887 * Adds a 'where contains' clause to the current query.
889 * @param string $field
890 * @param string $value
892 * @return Builder
894 public function whereNotContains($field, $value)
896 return $this->where($field, Operator::$notContains, $value);
900 * Adds a 'between' clause to the current query.
902 * @param string $field
903 * @param array $values
905 * @return Builder
907 public function whereBetween($field, array $values)
909 return $this->where([
910 [$field, '>=', $values[0]],
911 [$field, '<=', $values[1]],
916 * Adds a 'where starts with' clause to the current query.
918 * @param string $field
919 * @param string $value
921 * @return Builder
923 public function whereStartsWith($field, $value)
925 return $this->where($field, Operator::$startsWith, $value);
929 * Adds a 'where *not* starts with' clause to the current query.
931 * @param string $field
932 * @param string $value
934 * @return Builder
936 public function whereNotStartsWith($field, $value)
938 return $this->where($field, Operator::$notStartsWith, $value);
942 * Adds a 'where ends with' clause to the current query.
944 * @param string $field
945 * @param string $value
947 * @return Builder
949 public function whereEndsWith($field, $value)
951 return $this->where($field, Operator::$endsWith, $value);
955 * Adds a 'where *not* ends with' clause to the current query.
957 * @param string $field
958 * @param string $value
960 * @return Builder
962 public function whereNotEndsWith($field, $value)
964 return $this->where($field, Operator::$notEndsWith, $value);
968 * Adds a enabled filter to the current query.
970 * @return Builder
972 public function whereEnabled()
974 return $this->rawFilter($this->schema->filterEnabled());
978 * Adds a disabled filter to the current query.
980 * @return Builder
982 public function whereDisabled()
984 return $this->rawFilter($this->schema->filterDisabled());
988 * Adds a 'member of' filter to the current query.
990 * @param string $dn
992 * @return Builder
994 public function whereMemberOf($dn)
996 return $this->whereEquals($this->schema->memberOfRecursive(), $dn);
1000 * Adds an 'or where' clause to the current query.
1002 * @param array|string $field
1003 * @param string|null $operator
1004 * @param string|null $value
1006 * @return Builder
1008 public function orWhere($field, $operator = null, $value = null)
1010 return $this->where($field, $operator, $value, 'or');
1014 * Adds a raw or where clause to the current query.
1016 * Values given to this method are not escaped.
1018 * @param string $field
1019 * @param string $operator
1020 * @param string $value
1022 * @return Builder
1024 public function orWhereRaw($field, $operator = null, $value = null)
1026 return $this->where($field, $operator, $value, 'or', true);
1030 * Adds an 'or where has' clause to the current query.
1032 * @param string $field
1034 * @return Builder
1036 public function orWhereHas($field)
1038 return $this->orWhere($field, Operator::$has);
1042 * Adds a 'where not has' clause to the current query.
1044 * @param string $field
1046 * @return Builder
1048 public function orWhereNotHas($field)
1050 return $this->orWhere($field, Operator::$notHas);
1054 * Adds an 'or where equals' clause to the current query.
1056 * @param string $field
1057 * @param string $value
1059 * @return Builder
1061 public function orWhereEquals($field, $value)
1063 return $this->orWhere($field, Operator::$equals, $value);
1067 * Adds an 'or where not equals' clause to the current query.
1069 * @param string $field
1070 * @param string $value
1072 * @return Builder
1074 public function orWhereNotEquals($field, $value)
1076 return $this->orWhere($field, Operator::$doesNotEqual, $value);
1080 * Adds a 'or where approximately equals' clause to the current query.
1082 * @param string $field
1083 * @param string $value
1085 * @return Builder
1087 public function orWhereApproximatelyEquals($field, $value)
1089 return $this->orWhere($field, Operator::$approximatelyEquals, $value);
1093 * Adds an 'or where contains' clause to the current query.
1095 * @param string $field
1096 * @param string $value
1098 * @return Builder
1100 public function orWhereContains($field, $value)
1102 return $this->orWhere($field, Operator::$contains, $value);
1106 * Adds an 'or where *not* contains' clause to the current query.
1108 * @param string $field
1109 * @param string $value
1111 * @return Builder
1113 public function orWhereNotContains($field, $value)
1115 return $this->orWhere($field, Operator::$notContains, $value);
1119 * Adds an 'or where starts with' clause to the current query.
1121 * @param string $field
1122 * @param string $value
1124 * @return Builder
1126 public function orWhereStartsWith($field, $value)
1128 return $this->orWhere($field, Operator::$startsWith, $value);
1132 * Adds an 'or where *not* starts with' clause to the current query.
1134 * @param string $field
1135 * @param string $value
1137 * @return Builder
1139 public function orWhereNotStartsWith($field, $value)
1141 return $this->orWhere($field, Operator::$notStartsWith, $value);
1145 * Adds an 'or where ends with' clause to the current query.
1147 * @param string $field
1148 * @param string $value
1150 * @return Builder
1152 public function orWhereEndsWith($field, $value)
1154 return $this->orWhere($field, Operator::$endsWith, $value);
1158 * Adds an 'or where *not* ends with' clause to the current query.
1160 * @param string $field
1161 * @param string $value
1163 * @return Builder
1165 public function orWhereNotEndsWith($field, $value)
1167 return $this->orWhere($field, Operator::$notEndsWith, $value);
1171 * Adds an 'or where member of' filter to the current query.
1173 * @param string $dn
1175 * @return Builder
1177 public function orWhereMemberOf($dn)
1179 return $this->orWhereEquals($this->schema->memberOfRecursive(), $dn);
1183 * Returns true / false depending if the current object
1184 * contains selects.
1186 * @return bool
1188 public function hasSelects()
1190 return count($this->getSelects()) > 0;
1194 * Returns the current selected fields to retrieve.
1196 * @return array
1198 public function getSelects()
1200 $selects = $this->columns;
1202 // If the asterisk is not provided in the selected columns, we need to
1203 // ensure we always select the object class and category, as these
1204 // are used for constructing models. The asterisk indicates that
1205 // we want all attributes returned for LDAP records.
1206 if (!in_array('*', $selects)) {
1207 $selects[] = $this->schema->objectCategory();
1208 $selects[] = $this->schema->objectClass();
1211 return $selects;
1215 * Sorts the LDAP search results by the specified field and direction.
1217 * @param string $field
1218 * @param string $direction
1219 * @param int|null $flags
1221 * @return Builder
1223 public function sortBy($field, $direction = 'asc', $flags = null)
1225 $this->sortByField = $field;
1227 // Normalize direction.
1228 $direction = strtolower($direction);
1230 if ($direction === 'asc' || $direction === 'desc') {
1231 $this->sortByDirection = $direction;
1234 if (is_null($flags)) {
1235 $this->sortByFlags = SORT_NATURAL + SORT_FLAG_CASE;
1238 return $this;
1242 * Set the query to search on the base distinguished name.
1244 * This will result in one record being returned.
1246 * @return Builder
1248 public function read()
1250 $this->type = 'read';
1252 return $this;
1256 * Set the query to search one level on the base distinguished name.
1258 * @return Builder
1260 public function listing()
1262 $this->type = 'listing';
1264 return $this;
1268 * Sets the query to search the entire directory on the base distinguished name.
1270 * @return Builder
1272 public function recursive()
1274 $this->type = 'search';
1276 return $this;
1280 * Sets the recursive property to tell the search whether or
1281 * not to return the LDAP results in their raw format.
1283 * @param bool $raw
1285 * @return Builder
1287 public function raw($raw = true)
1289 $this->raw = (bool) $raw;
1291 return $this;
1295 * Sets the nested property to tell the Grammar instance whether
1296 * or not the current query is already nested.
1298 * @param bool $nested
1300 * @return Builder
1302 public function nested($nested = true)
1304 $this->nested = (bool) $nested;
1306 return $this;
1310 * Returns true / false if the current query is nested.
1312 * @return bool
1314 public function isNested()
1316 return $this->nested === true;
1320 * Returns an escaped string for use in an LDAP filter.
1322 * @param string $value
1323 * @param string $ignore
1324 * @param int $flags
1326 * @return string
1328 public function escape($value, $ignore = '', $flags = 0)
1330 return Utilities::escape($value, $ignore, $flags);
1334 * Returns the query builders sort by field.
1336 * @return string
1338 public function getSortByField()
1340 return $this->sortByField;
1344 * Returns the query builders sort by direction.
1346 * @return string
1348 public function getSortByDirection()
1350 return $this->sortByDirection;
1354 * Returns the query builders sort by flags.
1356 * @return int
1358 public function getSortByFlags()
1360 return $this->sortByFlags;
1364 * Returns bool that determines whether the current
1365 * query builder will return raw results.
1367 * @return bool
1369 public function isRaw()
1371 return $this->raw;
1375 * Returns bool that determines whether the current
1376 * query builder will return paginated results.
1378 * @return bool
1380 public function isPaginated()
1382 return $this->paginated;
1386 * Returns bool that determines whether the current
1387 * query builder will return sorted results.
1389 * @return bool
1391 public function isSorted()
1393 return $this->sortByField ? true : false;
1397 * Handle dynamic method calls on the query builder
1398 * object to be directed to the query processor.
1400 * @param string $method
1401 * @param array $parameters
1403 * @return mixed
1405 public function __call($method, $parameters)
1407 if (Str::startsWith($method, 'where')) {
1408 return $this->dynamicWhere($method, $parameters);
1411 return call_user_func_array([$this->newProcessor(), $method], $parameters);
1415 * Handles dynamic "where" clauses to the query.
1417 * @param string $method
1418 * @param string $parameters
1420 * @return Builder
1422 public function dynamicWhere($method, $parameters)
1424 $finder = substr($method, 5);
1426 $segments = preg_split('/(And|Or)(?=[A-Z])/', $finder, -1, PREG_SPLIT_DELIM_CAPTURE);
1428 // The connector variable will determine which connector will be used for the
1429 // query condition. We will change it as we come across new boolean values
1430 // in the dynamic method strings, which could contain a number of these.
1431 $connector = 'and';
1433 $index = 0;
1435 foreach ($segments as $segment) {
1436 // If the segment is not a boolean connector, we can assume it is a column's name
1437 // and we will add it to the query as a new constraint as a where clause, then
1438 // we can keep iterating through the dynamic method string's segments again.
1439 if ($segment != 'And' && $segment != 'Or') {
1440 $this->addDynamic($segment, $connector, $parameters, $index);
1442 $index++;
1445 // Otherwise, we will store the connector so we know how the next where clause we
1446 // find in the query should be connected to the previous ones, meaning we will
1447 // have the proper boolean connector to connect the next where clause found.
1448 else {
1449 $connector = $segment;
1453 return $this;
1457 * Adds an array of wheres to the current query.
1459 * @param array $wheres
1460 * @param string $boolean
1461 * @param bool $raw
1463 * @return Builder
1465 protected function addArrayOfWheres($wheres, $boolean, $raw)
1467 foreach ($wheres as $key => $value) {
1468 if (is_numeric($key) && is_array($value)) {
1469 // If the key is numeric and the value is an array, we'll
1470 // assume we've been given an array with conditionals.
1471 list($field, $condition) = $value;
1473 // Since a value is optional for some conditionals, we will
1474 // try and retrieve the third parameter from the array,
1475 // but is entirely optional.
1476 $value = Arr::get($value, 2);
1478 $this->where($field, $condition, $value, $boolean);
1479 } else {
1480 // If the value is not an array, we will assume an equals clause.
1481 $this->where($key, Operator::$equals, $value, $boolean, $raw);
1485 return $this;
1489 * Add a single dynamic where clause statement to the query.
1491 * @param string $segment
1492 * @param string $connector
1493 * @param array $parameters
1494 * @param int $index
1496 * @return void
1498 protected function addDynamic($segment, $connector, $parameters, $index)
1500 // Once we have parsed out the columns and formatted the boolean operators we
1501 // are ready to add it to this query as a where clause just like any other
1502 // clause on the query. Then we'll increment the parameter index values.
1503 $bool = strtolower($connector);
1505 $this->where(Str::snake($segment), '=', $parameters[$index], $bool);
1509 * Returns a new query Processor instance.
1511 * @return Processor
1513 protected function newProcessor()
1515 return new Processor($this);