| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390 |
- <?php
- namespace Adldap\Query;
- class Grammar
- {
- /**
- * Wraps a query string in brackets.
- *
- * Produces: (query)
- *
- * @param string $query
- * @param string $prefix
- * @param string $suffix
- *
- * @return string
- */
- public function wrap($query, $prefix = '(', $suffix = ')')
- {
- return $prefix.$query.$suffix;
- }
- /**
- * Compiles the Builder instance into an LDAP query string.
- *
- * @param Builder $builder
- *
- * @return string
- */
- public function compile(Builder $builder)
- {
- $ands = $builder->filters['and'];
- $ors = $builder->filters['or'];
- $raws = $builder->filters['raw'];
- $query = $this->concatenate($raws);
- $query = $this->compileWheres($ands, $query);
- $query = $this->compileOrWheres($ors, $query);
- // We need to check if the query is already nested, otherwise
- // we'll nest it here and return the result.
- if (!$builder->isNested()) {
- $total = count($ands) + count($raws);
- // Make sure we wrap the query in an 'and' if using
- // multiple filters. We also need to check if only
- // one where is used with multiple orWheres, that
- // we wrap it in an `and` query.
- if ($total > 1 || (count($ands) === 1 && count($ors) > 0)) {
- $query = $this->compileAnd($query);
- }
- }
- return $query;
- }
- /**
- * Concatenates filters into a single string.
- *
- * @param array $bindings
- *
- * @return string
- */
- public function concatenate(array $bindings = [])
- {
- // Filter out empty query segments.
- $bindings = array_filter($bindings, function ($value) {
- return (string) $value !== '';
- });
- return implode('', $bindings);
- }
- /**
- * Returns a query string for equals.
- *
- * Produces: (field=value)
- *
- * @param string $field
- * @param string $value
- *
- * @return string
- */
- public function compileEquals($field, $value)
- {
- return $this->wrap($field.Operator::$equals.$value);
- }
- /**
- * Returns a query string for does not equal.
- *
- * Produces: (!(field=value))
- *
- * @param string $field
- * @param string $value
- *
- * @return string
- */
- public function compileDoesNotEqual($field, $value)
- {
- return $this->compileNot($this->compileEquals($field, $value));
- }
- /**
- * Alias for does not equal operator (!=) operator.
- *
- * Produces: (!(field=value))
- *
- * @param string $field
- * @param string $value
- *
- * @return string
- */
- public function compileDoesNotEqualAlias($field, $value)
- {
- return $this->compileDoesNotEqual($field, $value);
- }
- /**
- * Returns a query string for greater than or equals.
- *
- * Produces: (field>=value)
- *
- * @param string $field
- * @param string $value
- *
- * @return string
- */
- public function compileGreaterThanOrEquals($field, $value)
- {
- return $this->wrap($field.Operator::$greaterThanOrEquals.$value);
- }
- /**
- * Returns a query string for less than or equals.
- *
- * Produces: (field<=value)
- *
- * @param string $field
- * @param string $value
- *
- * @return string
- */
- public function compileLessThanOrEquals($field, $value)
- {
- return $this->wrap($field.Operator::$lessThanOrEquals.$value);
- }
- /**
- * Returns a query string for approximately equals.
- *
- * Produces: (field~=value)
- *
- * @param string $field
- * @param string $value
- *
- * @return string
- */
- public function compileApproximatelyEquals($field, $value)
- {
- return $this->wrap($field.Operator::$approximatelyEquals.$value);
- }
- /**
- * Returns a query string for starts with.
- *
- * Produces: (field=value*)
- *
- * @param string $field
- * @param string $value
- *
- * @return string
- */
- public function compileStartsWith($field, $value)
- {
- return $this->wrap($field.Operator::$equals.$value.Operator::$has);
- }
- /**
- * Returns a query string for does not start with.
- *
- * Produces: (!(field=*value))
- *
- * @param string $field
- * @param string $value
- *
- * @return string
- */
- public function compileNotStartsWith($field, $value)
- {
- return $this->compileNot($this->compileStartsWith($field, $value));
- }
- /**
- * Returns a query string for ends with.
- *
- * Produces: (field=*value)
- *
- * @param string $field
- * @param string $value
- *
- * @return string
- */
- public function compileEndsWith($field, $value)
- {
- return $this->wrap($field.Operator::$equals.Operator::$has.$value);
- }
- /**
- * Returns a query string for does not end with.
- *
- * Produces: (!(field=value*))
- *
- * @param string $field
- * @param string $value
- *
- * @return string
- */
- public function compileNotEndsWith($field, $value)
- {
- return $this->compileNot($this->compileEndsWith($field, $value));
- }
- /**
- * Returns a query string for contains.
- *
- * Produces: (field=*value*)
- *
- * @param string $field
- * @param string $value
- *
- * @return string
- */
- public function compileContains($field, $value)
- {
- return $this->wrap($field.Operator::$equals.Operator::$has.$value.Operator::$has);
- }
- /**
- * Returns a query string for does not contain.
- *
- * Produces: (!(field=*value*))
- *
- * @param string $field
- * @param string $value
- *
- * @return string
- */
- public function compileNotContains($field, $value)
- {
- return $this->compileNot($this->compileContains($field, $value));
- }
- /**
- * Returns a query string for a where has.
- *
- * Produces: (field=*)
- *
- * @param string $field
- *
- * @return string
- */
- public function compileHas($field)
- {
- return $this->wrap($field.Operator::$equals.Operator::$has);
- }
- /**
- * Returns a query string for a where does not have.
- *
- * Produces: (!(field=*))
- *
- * @param string $field
- *
- * @return string
- */
- public function compileNotHas($field)
- {
- return $this->compileNot($this->compileHas($field));
- }
- /**
- * Wraps the inserted query inside an AND operator.
- *
- * Produces: (&query)
- *
- * @param string $query
- *
- * @return string
- */
- public function compileAnd($query)
- {
- return $query ? $this->wrap($query, '(&') : '';
- }
- /**
- * Wraps the inserted query inside an OR operator.
- *
- * Produces: (|query)
- *
- * @param string $query
- *
- * @return string
- */
- public function compileOr($query)
- {
- return $query ? $this->wrap($query, '(|') : '';
- }
- /**
- * Wraps the inserted query inside an NOT operator.
- *
- * @param string $query
- *
- * @return string
- */
- public function compileNot($query)
- {
- return $query ? $this->wrap($query, '(!') : '';
- }
- /**
- * Assembles all where clauses in the current wheres property.
- *
- * @param array $wheres
- * @param string $query
- *
- * @return string
- */
- protected function compileWheres(array $wheres = [], $query = '')
- {
- foreach ($wheres as $where) {
- $query .= $this->compileWhere($where);
- }
- return $query;
- }
- /**
- * Assembles all or where clauses in the current orWheres property.
- *
- * @param array $orWheres
- * @param string $query
- *
- * @return string
- */
- protected function compileOrWheres(array $orWheres = [], $query = '')
- {
- $or = '';
- foreach ($orWheres as $where) {
- $or .= $this->compileWhere($where);
- }
- // Make sure we wrap the query in an 'or' if using multiple
- // orWheres. For example (|(QUERY)(ORWHEREQUERY)).
- if (($query && count($orWheres) > 0) || count($orWheres) > 1) {
- $query .= $this->compileOr($or);
- } else {
- $query .= $or;
- }
- return $query;
- }
- /**
- * Assembles a single where query based
- * on its operator and returns it.
- *
- * @param array $where
- *
- * @return string|null
- */
- protected function compileWhere(array $where)
- {
- // Get the name of the operator.
- if ($name = array_search($where['operator'], Operator::all())) {
- // If the name was found we'll camel case it
- // to run it through the compile method.
- $method = 'compile'.ucfirst($name);
- // Make sure the compile method exists for the operator.
- if (method_exists($this, $method)) {
- return $this->{$method}($where['field'], $where['value']);
- }
- }
- }
- }
|