154 lines
		
	
	
	
		
			4.5 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			154 lines
		
	
	
	
		
			4.5 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| 
 | |
| namespace Nest\Database\Query\Where;
 | |
| 
 | |
| use Nest\Database\Exceptions\Query\NoPrimaryFieldException;
 | |
| use Nest\Model\Entities;
 | |
| use Nest\Model\Entity;
 | |
| 
 | |
| /**
 | |
|  * Add where capacity to a query builder.
 | |
|  */
 | |
| trait HasWhere
 | |
| {
 | |
| 	/**
 | |
| 	 * Conditions in where clause.
 | |
| 	 * @var ConditionBuilder[]
 | |
| 	 */
 | |
| 	protected array $wheres = [];
 | |
| 
 | |
| 	/**
 | |
| 	 * Reset WHERE conditions.
 | |
| 	 * @return $this
 | |
| 	 */
 | |
| 	public function resetWheres(): static
 | |
| 	{
 | |
| 		$this->wheres = [];
 | |
| 		return $this;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Add a where condition.
 | |
| 	 * @param string|callable $column The column of the condition, or a condition builder callable.
 | |
| 	 * @param mixed|null $operator The operator of the condition (or the value if no value is passed).
 | |
| 	 * @param mixed|null $value The value of the condition.
 | |
| 	 * @return $this
 | |
| 	 */
 | |
| 	public function where(string|callable $column, mixed $operator = null, mixed $value = null): static
 | |
| 	{
 | |
| 		if (is_callable($column))
 | |
| 		{ // Callable condition builder.
 | |
| 			$this->wheres[] = $column(new ConditionBuilder());
 | |
| 		}
 | |
| 		else
 | |
| 		{ // Simple condition, registering it.
 | |
| 			if (!empty($operator) && empty($value))
 | |
| 			{ // If there are 2 parameters, considering the second one as the value, with default operator.
 | |
| 				$value = $operator;
 | |
| 				$operator = null;
 | |
| 			}
 | |
| 
 | |
| 			if (!empty($value))
 | |
| 			{ // A value is defined.
 | |
| 				// Default operator: "=".
 | |
| 				if (empty($operator)) $operator = "=";
 | |
| 
 | |
| 				// Create the simple condition.
 | |
| 				$this->wheres[] = (new ConditionBuilder())->column($column)->operator($operator)->value($value);
 | |
| 			}
 | |
| 			else
 | |
| 			{ // No value is given, considering a simple existence check.
 | |
| 				$this->whereExists($column);
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		return $this;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Add a where IN condition.
 | |
| 	 * @param string $column The column of the condition.
 | |
| 	 * @param array $values The values of the condition.
 | |
| 	 * @return $this
 | |
| 	 */
 | |
| 	public function whereIn(string $column, array $values): static
 | |
| 	{
 | |
| 		return $this->where($column, "IN", $values);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Add a where condition on a column as a value.
 | |
| 	 * @param string $column The column of the condition.
 | |
| 	 * @param string $operator The operator of the condition (or the value column if no value is passed).
 | |
| 	 * @param string|null $valueColumn The value column of the condition.
 | |
| 	 * @return $this
 | |
| 	 */
 | |
| 	public function whereColumn(string $column, string $operator, ?string $valueColumn = null): static
 | |
| 	{
 | |
| 		if (!empty($operator) && empty($valueColumn))
 | |
| 		{ // If there are 2 parameters, considering the second one as the value, with default operator.
 | |
| 			$valueColumn = $operator;
 | |
| 			$operator = "=";
 | |
| 		}
 | |
| 
 | |
| 		// Create the simple condition.
 | |
| 		$this->wheres[] = (new ConditionBuilder())->column($column)->operator($operator)->column($valueColumn);
 | |
| 
 | |
| 		return $this;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Add a where exists condition.
 | |
| 	 * @param string $column The column to check for existence.
 | |
| 	 * @return $this
 | |
| 	 */
 | |
| 	public function whereExists(string $column): static
 | |
| 	{
 | |
| 		// Create an existence check.
 | |
| 		$this->wheres[] = (new ConditionBuilder())->column($column)->exists();
 | |
| 		return $this;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Add condition to find given entities.
 | |
| 	 * @param Entity|Entities $entities Entity or entities to find.
 | |
| 	 * @return $this
 | |
| 	 * @throws NoPrimaryFieldException
 | |
| 	 */
 | |
| 	public function whereKeyOf(Entity|Entities $entities): static
 | |
| 	{
 | |
| 		// Normalize parameter to a simple entities array.
 | |
| 		if ($entities instanceof Entities)
 | |
| 			$entitiesArray = $entities->get();
 | |
| 		else
 | |
| 			$entitiesArray = [$entities];
 | |
| 
 | |
| 		// Initialize entities conditions.
 | |
| 		$entitiesConditions = [];
 | |
| 		foreach ($entitiesArray as $entity)
 | |
| 		{ // Add condition for each entity to find.
 | |
| 			// Get current entity primary fields and normalize it to an array.
 | |
| 			$primaryFields = $entity->getPrimaryFields();
 | |
| 			if (!is_array($primaryFields)) $primaryFields = [$primaryFields];
 | |
| 
 | |
| 			if (empty($primaryFields))
 | |
| 				// If there are no primary fields, thrown an exception to ensure not to do something on EVERY rows.
 | |
| 				throw new NoPrimaryFieldException($entity);
 | |
| 
 | |
| 			// Create conditions for current entity.
 | |
| 			$entityConditions = [];
 | |
| 			foreach ($primaryFields as $primaryField)
 | |
| 				// Create a condition builder for each field.
 | |
| 				$entityConditions[] = fn (ConditionBuilder $condition) =>
 | |
| 					$condition->column($primaryField)->equals()->value($entity->$primaryField);
 | |
| 
 | |
| 			// Add the full entity condition to the entities conditions array.
 | |
| 			$entitiesConditions[] = fn (ConditionBuilder $condition) => $condition->and(...$entityConditions);
 | |
| 		}
 | |
| 
 | |
| 		// Add condition to match every entities.
 | |
| 		return $this->where(fn (ConditionBuilder $condition) => (
 | |
| 			$condition->or(...$entitiesConditions)
 | |
| 		));
 | |
| 	}
 | |
| }
 |