builder = $builder; $this->expression = $builder->expr(); } /** * Execute logic AND expression with expression builder * * @param mixed $expressions - nested expressions * * @return CompositeExpression|null */ public function andX(...$expressions): ?CompositeExpression { if (Utilities::is_gte4Doctrine()) { if (empty($expressions)) { return null; } return $this->expression->and(...$expressions); } return $this->expression->andX(...$expressions); } /** * Execute logic OR expression with expression builder * * @param mixed $expressions - nested expressions * * @return CompositeExpression|null */ public function orX(...$expressions): ?CompositeExpression { if (Utilities::is_gte4Doctrine()) { if (empty($expressions)) { return null; } return $this->expression->or(...$expressions); } return $this->expression->orX(...$expressions); } /** * Execute logic EQUALITY expression * * @param string $field - expression field * @param mixed $value - expression value * * @return string */ public function eq(string $field, $value): string { $fieldName = $this->getJsonFieldName($field, $value); $fieldValue = $this->getJsonFieldValue($field, $value); $value = $this->getJsonPropertyValue($value); if (Utilities::is_gte4Doctrine()) { $this->builder->setParameter( $fieldName, $value, is_bool($value) ? \Doctrine\DBAL\ParameterType::BOOLEAN : \Doctrine\DBAL\ParameterType::STRING ); } else { $this->builder->setParameter($fieldName, $value, is_bool($value) ? \PDO::PARAM_BOOL : null); } return $this->expression->eq($fieldValue, sprintf(":%s", $fieldName)); } /** * Execute logic NOT EQUAL expression * * @param string $field - expression field * @param mixed $value - expression value * * @return string */ public function neq(string $field, $value): string { $fieldName = $this->getJsonFieldName($field, $value); $fieldValue = $this->getJsonFieldValue($field, $value); $this->builder->setParameter($fieldName, $this->getJsonPropertyValue($value)); return $this->builder ->expr() ->or( $this->builder->expr()->neq($fieldValue, sprintf(":%s", $fieldName)), $this->builder->expr()->isNull($fieldValue) ); } /** * Execute logic LESS THAN expression * * @param string $field - expression field * @param mixed $value - expression value * * @return string */ public function lt(string $field, $value): string { $fieldName = $this->getJsonFieldName($field, $value); $fieldValue = $this->getJsonFieldValue($field, $value); $this->builder->setParameter($fieldName, $this->getJsonPropertyValue($value)); return $this->expression->lt($fieldValue, sprintf(":%s", $fieldName)); } /** * Execute logic LESS THAN OR EQUAL expression * * @param string $field - expression field * @param mixed $value - expression value * * @return string */ public function lte(string $field, $value): string { $fieldName = $this->getJsonFieldName($field, $value); $fieldValue = $this->getJsonFieldValue($field, $value); $this->builder->setParameter($fieldName, $this->getJsonPropertyValue($value)); return $this->expression->lte($fieldValue, sprintf(":%s", $fieldName)); } public function search(string $field, $value): string { $parameter = $this->getJsonFieldName($field, $value); $field = str_replace(';', ',', $field); $field = sprintf('CONCAT(%s)::text', $field); $value = str_replace('%', '', $value); $value = sprintf('%%%s%%', $value); $this->builder->setParameter(':' . $parameter, $value); return sprintf("%s ILIKE :%s", $field, $parameter); } /** * Execute logic GREATER THAN expression * * @param string $field - expression field * @param mixed $value - expression value * * @return string */ public function gt(string $field, $value): string { $fieldName = $this->getJsonFieldName($field, $value); $fieldValue = $this->getJsonFieldValue($field, $value); $this->builder->setParameter($fieldName, $this->getJsonPropertyValue($value)); return $this->expression->gt($fieldValue, sprintf(":%s", $fieldName)); } /** * Execute logic GREATER THAN OR EQUAL expression * * @param string $field - expression field * @param mixed $value - expression value * * @return string */ public function gte(string $field, $value): string { $fieldName = $this->getJsonFieldName($field, $value); $fieldValue = $this->getJsonFieldValue($field, $value); $this->builder->setParameter($fieldName, $this->getJsonPropertyValue($value)); return $this->expression->gte($fieldValue, sprintf(":%s", $fieldName)); } /** * Execute logic IS NULL expression * * @param string $field - expression field * * @return string */ public function isNull(string $field): string { return $this->expression->isNull($field); } /** * Execute logic IS NOT NULL expression * * @param string $field - expression field * * @return string */ public function isNotNull(string $field): string { return $this->expression->isNotNull($field); } /** * Execute logic LIKE expression * * @param string $field - expression field * @param mixed $value - expression value * * @return string */ public function like(string $field, $value): string { $fieldName = $this->getJsonFieldName($field, $value); $fieldValue = $this->getJsonFieldValue($field, $value); $this->builder->setParameter($fieldName, $this->getJsonPropertyValue($value)); return sprintf("%s::text ILIKE :%s ESCAPE '•'", $fieldValue, $fieldName); } /** * Execute logic NOT LIKE expression * * @param string $field - expression field * @param mixed $value - expression value * * @return string */ public function notLike(string $field, $value): string { $fieldName = $this->getJsonFieldName($field, $value); $fieldValue = $this->getJsonFieldValue($field, $value); $this->builder->setParameter($fieldName, $this->getJsonPropertyValue($value)); return sprintf("%s::text NOT ILIKE :%s ESCAPE '•'", $fieldValue, $fieldName); } /** * Execute logic IN expression * * @param string $field - expression field * @param mixed $initValue - expression value * * @return string */ public function in(string $field, $initValue): string { if ($this->isJsonField($initValue)) { $fieldName = $this->getJsonFieldName($field, $initValue); $fieldValue = $this->getJsonFieldValue($field, $initValue, true); $value = $this->getJsonPropertyValue($initValue); } else { $fieldName = $field; $fieldValue = $field; $value = $initValue; } $value = is_string($value) ? explode(',', $value) : $value; if ($this->containsString($value)) { if (Utilities::is_gte4Doctrine()) { $this->builder->setParameter($fieldName, $value, \Doctrine\DBAL\ArrayParameterType::STRING); } else { $this->builder->setParameter($fieldName, $value, \Doctrine\DBAL\Connection::PARAM_STR_ARRAY); } return $this->expression->in($fieldValue, sprintf(":%s", $fieldName)); } else { $value = array_map(function ($val) { return trim($val); }, (array) $value); return $this->expression->in($fieldValue, $value); } } /** * Execute logic NOT IN expression * * @param string $field - expression field * @param mixed $initValue - expression value * * @return string */ public function notIn(string $field, $initValue): string { if ($this->isJsonField($initValue)) { $fieldName = $this->getJsonFieldName($field, $initValue); $fieldValue = $this->getJsonFieldValue($field, $initValue, true); $value = $this->getJsonPropertyValue($initValue); } else { $fieldName = $field; $fieldValue = $field; $value = $initValue; } $value = is_string($value) ? explode(',', $value) : $value; if ($this->containsString($value)) { if (Utilities::is_gte4Doctrine()) { $this->builder->setParameter($fieldName, $value, \Doctrine\DBAL\ArrayParameterType::STRING); } else { $this->builder->setParameter($fieldName, $value, \Doctrine\DBAL\Connection::PARAM_STR_ARRAY); } return $this->expression->notIn($fieldValue, sprintf(":%s", $fieldName)); } else { $value = array_map(function ($val) { return trim($val); }, (array) $value); return $this->expression->notIn($fieldValue, $value); } } /** * Execute specification expression * * @param string $specName - specification name * @param mixed $data - specification data * * @return mixed */ /** * Executes a specification expression based on the provided name and data. * * If the data is an array, it will create a new instance of the specification class using the first key as the parameter and the corresponding value as the value. If the first key is 0, it will create a new instance with only the value. * If the data is not an array, it will create a new instance of the specification class with the provided data. * * @param string $specName The name of the specification class to create. * @param mixed $data The data to pass to the specification class constructor. * @return mixed The result of calling the `match` method on the created specification instance. */ public function spec(string $specName, $data) { if (is_array($data)) { $parameter = array_key_first($data); $value = $data[$parameter]; $spec = $parameter === 0 ? new $specName($value) : $spec = new $specName($parameter, $value); } else { $spec = new $specName($data); } return $spec->match($this->builder); } /** * Add field to SELECT part * * @param string $field - field name */ public function addSelect(string $field): void { $this->builder->addSelect($field); } /** * Set limit part * * @param int $limit - limit */ public function setMaxResults(int $limit): void { $this->builder->setMaxResults($limit); } /** * Set offset part * * @param int $offset - offset */ public function setFirstResult(int $offset): void { $this->builder->setFirstResult($offset); } /** * Set ordering * * @param string $field - field * @param string $orderType - order type asc|desc */ public function addOrderBy(string $field, string $orderType = null): void { $this->builder->addOrderBy($field, $orderType); } /** * Set grouping * * @param array $fields - group fields */ public function addGroupBy(array $fields): void { if (Utilities::is_gte4Doctrine()) { $this->builder->addGroupBy(...$fields); } else { $this->builder->addGroupBy($fields); } } /** * Set where * * @param mixed $where - where */ public function andWhere($where): void { $where && $this->builder->andWhere($where); } /** * Return query part * * @param string $part - Query part * * @return array */ public function getQueryPart(string $part): array { if (Utilities::is_gte4Doctrine()) { try { $sql = $this->builder->getSQL(); } catch (\Throwable $th) { return []; } return [ "not empty" ]; } return $this->builder->getQueryPart($part); } }