- First commit, User loading and Authentication are working
This commit is contained in:
commit
8d1a310921
|
@ -0,0 +1,26 @@
|
||||||
|
{
|
||||||
|
"name": "mcnd/ulmus-ldap",
|
||||||
|
"description": "A simple LDAP extension for Ulmus.",
|
||||||
|
"type": "library",
|
||||||
|
"license": "MIT",
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Dave Mc Nicoll",
|
||||||
|
"email": "mcndave@gmail.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"require": {
|
||||||
|
"mcnd/ulmus": "dev-master"
|
||||||
|
},
|
||||||
|
"repositories": [
|
||||||
|
{
|
||||||
|
"type": "vcs",
|
||||||
|
"url": "https://github.com/mcNdave/ulmus.git"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Ulmus\\Ldap\\": "src/"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,165 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ulmus\Ldap\Adapter;
|
||||||
|
|
||||||
|
use Ulmus\{ Common\PdoObject, Exception\AdapterConfigurationException };
|
||||||
|
|
||||||
|
use Ulmus\Ldap\Common\LdapObject;
|
||||||
|
|
||||||
|
use function ldap_set_option, ldap_start_tls, ldap_bind, ldap_unbind, ldap_connect, ldap_close, ldap_get_entries;
|
||||||
|
|
||||||
|
class Ldap implements \Ulmus\Adapter\AdapterInterface {
|
||||||
|
|
||||||
|
public const IDENTIFIER_DN = 101;
|
||||||
|
|
||||||
|
public const IDENTIFIER_FILTER = 102;
|
||||||
|
|
||||||
|
public int $version = 3;
|
||||||
|
|
||||||
|
public bool $encrypt;
|
||||||
|
|
||||||
|
public array $hosts;
|
||||||
|
|
||||||
|
public string $baseDn;
|
||||||
|
|
||||||
|
public string $username;
|
||||||
|
|
||||||
|
public string $password;
|
||||||
|
|
||||||
|
public string $accountSuffix;
|
||||||
|
|
||||||
|
public string $pathCertCrt;
|
||||||
|
|
||||||
|
public string $pathCertKey;
|
||||||
|
|
||||||
|
public LdapObject $ldapObject;
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
? string $host = null,
|
||||||
|
? string $baseDn = null,
|
||||||
|
? string $username = null,
|
||||||
|
? string $password = null,
|
||||||
|
? string $accountSuffix = null
|
||||||
|
) {
|
||||||
|
if ($host) {
|
||||||
|
$this->hosts = [ $host ];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($baseDn) {
|
||||||
|
$this->baseDn = $baseDn;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($username) {
|
||||||
|
$this->username = $username;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($password) {
|
||||||
|
$this->password = $password;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($accountSuffix) {
|
||||||
|
$this->accountSuffix = $accountSuffix;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function authenticate(string $username, string $password) : bool
|
||||||
|
{
|
||||||
|
$this->ldapObject = $this->getLdapObject();
|
||||||
|
|
||||||
|
$bind = $this->ldapObject->bind($username, $password);
|
||||||
|
|
||||||
|
return $bind;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function connect() : object
|
||||||
|
{
|
||||||
|
$this->ldapObject = $this->getLdapObject();
|
||||||
|
|
||||||
|
$this->bindUser();
|
||||||
|
|
||||||
|
return $this->ldapObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function bindUser() : void
|
||||||
|
{
|
||||||
|
if ( ! $this->ldapObject->bind($this->username, $this->password) ) {
|
||||||
|
throw new \Exception("LDAP bind failed with given user $usr.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getLdapObject() : LdapObject
|
||||||
|
{
|
||||||
|
$ldapObject = new LdapObject();
|
||||||
|
|
||||||
|
$ldapObject->connect($this->hosts[0], $this->baseDn);
|
||||||
|
|
||||||
|
$ldapObject->setOptions([
|
||||||
|
\LDAP_OPT_PROTOCOL_VERSION => $this->version,
|
||||||
|
\LDAP_OPT_REFERRALS => 0,
|
||||||
|
]);
|
||||||
|
|
||||||
|
if ( isset($this->pathCertCrt) && isset($this->pathCertKey) ) {
|
||||||
|
$ldapObject->setOptions([
|
||||||
|
\LDAP_OPT_X_TLS_CERTFILE => $this->pathCertCrt,
|
||||||
|
\LDAP_OPT_X_TLS_KEYFILE => $this->pathCertKey,
|
||||||
|
], false);
|
||||||
|
|
||||||
|
$ldapObject->startTLS();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $ldapObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function buildDataSourceName() : string
|
||||||
|
{
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setup(array $configuration) : void
|
||||||
|
{
|
||||||
|
$configuration = array_change_key_case($configuration, \CASE_LOWER);
|
||||||
|
|
||||||
|
if ( false === ( $this->hosts = $configuration['hosts'] ?? false ) ) {
|
||||||
|
throw new AdapterConfigurationException("Your `host` setting is missing. It is a mandatory parameter for this driver.");
|
||||||
|
}
|
||||||
|
elseif ( false === ( $this->baseDn = $configuration['base_dn'] ?? false ) ) {
|
||||||
|
throw new AdapterConfigurationException("Your `base_dn` setting is missing. The adapter won't connect without it.");
|
||||||
|
}
|
||||||
|
elseif ( false === ( $this->username = $configuration['username'] ?? false ) ) {
|
||||||
|
throw new AdapterConfigurationException("Your `username` is missing from your configuration array");
|
||||||
|
}
|
||||||
|
elseif ( false === ( $this->password = $configuration['password'] ?? false ) ) {
|
||||||
|
throw new AdapterConfigurationException("Your `password` is missing from your configuration array");
|
||||||
|
}
|
||||||
|
elseif ( false === ( $this->accountSuffix = $configuration['account_suffix'] ?? false ) ) {
|
||||||
|
throw new AdapterConfigurationException("Your `account_suffix` is missing from your configuration array");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
if ( false !== ( $configuration['app'] ?? false ) ) {
|
||||||
|
$this->app = $configuration['app'];
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function escapeIdentifier(string $segment, int $type, string $ignore = "") : string
|
||||||
|
{
|
||||||
|
switch($type) {
|
||||||
|
case static::IDENTIFIER_DN:
|
||||||
|
return ldap_escape($segment, $ignore, LDAP_ESCAPE_DN);
|
||||||
|
|
||||||
|
case static::IDENTIFIER_FIELD:
|
||||||
|
case static::IDENTIFIER_FILTER:
|
||||||
|
return ldap_escape($segment, $ignore, LDAP_ESCAPE_FILTER);
|
||||||
|
|
||||||
|
default:
|
||||||
|
return ldap_escape($segment, $ignore);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function defaultEngine(): ? string
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,174 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ulmus\Ldap\Common;
|
||||||
|
|
||||||
|
use function ldap_set_option, ldap_start_tls, ldap_bind, ldap_unbind, ldap_connect, ldap_close, ldap_get_entries, ldap_count_entries;
|
||||||
|
|
||||||
|
class LdapObject {
|
||||||
|
|
||||||
|
public static ? string $dump = null;
|
||||||
|
|
||||||
|
public $connection;
|
||||||
|
|
||||||
|
public $search;
|
||||||
|
|
||||||
|
public int $rowCount = 0;
|
||||||
|
|
||||||
|
public int $bufferedRows = 0;
|
||||||
|
|
||||||
|
public string $dn;
|
||||||
|
|
||||||
|
public bool $binded = false;
|
||||||
|
|
||||||
|
public function __destruct()
|
||||||
|
{
|
||||||
|
isset($this->connection) and ldap_close($this->connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function connect(string $host, string $baseDn) : bool
|
||||||
|
{
|
||||||
|
$this->connection = ldap_connect($host);
|
||||||
|
|
||||||
|
$this->dn = $baseDn;
|
||||||
|
|
||||||
|
return $this->connection !== false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setOptions(array $options, $useConnectionRessource = true) : void
|
||||||
|
{
|
||||||
|
foreach($options as $field => $value) {
|
||||||
|
ldap_set_option($useConnectionRessource ? $this->connection : null, $field, $value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function startTLS() : void
|
||||||
|
{
|
||||||
|
ldap_start_tls($this->connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function bind(? string $dn, ? string $password) : bool
|
||||||
|
{
|
||||||
|
if ($this->binded) {
|
||||||
|
throw new \Exception("LdapObject is already binded with a user. Use the unbind() method to release it.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->binded = ldap_bind($this->connection, $dn, $password);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function unbind() : void
|
||||||
|
{
|
||||||
|
if ($this->binded) {
|
||||||
|
$this->binded = ! ldap_unbind($this->connection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function select(array $filter, array $fields = [])
|
||||||
|
{
|
||||||
|
static::$dump && call_user_func_array(static::$dump, [ $sql, $parameters ]);
|
||||||
|
|
||||||
|
$this->search = ldap_search($this->connection, $this->dn, $filter['filters'], $filter['fields'], 0, $filter['limit'] ?? -1);
|
||||||
|
|
||||||
|
$this->rowCount = $this->bufferedRows = ldap_count_entries($this->connection, $this->search);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function fetch() /* : bool|array */
|
||||||
|
{
|
||||||
|
if (! $this->search ) {
|
||||||
|
throw new \Exception('Impossible to fetch from LdapObject from which select() was not called first.');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! $this->bufferedRows ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ( $this->rowCount === $this->bufferedRows ) {
|
||||||
|
$result = ldap_first_entry($this->connection, $this->search);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$result = ldap_next_entry($this->connection, $this->search);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($result) {
|
||||||
|
$this->bufferedRows--;
|
||||||
|
|
||||||
|
$dataset = [];
|
||||||
|
|
||||||
|
if ( $attributes = ldap_get_attributes($this->connection, $result) ) {
|
||||||
|
for ($i = 0; $i < $attributes['count']; $i++) {
|
||||||
|
$key = $attributes[$i];
|
||||||
|
|
||||||
|
$dataset[strtolower($key)] = $attributes[$key][0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $dataset;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function rowCount() : int
|
||||||
|
{
|
||||||
|
return $this->rowCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function fetchAll()
|
||||||
|
{
|
||||||
|
return ldap_get_entries($this->connection, $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function closeCursor() : void {}
|
||||||
|
|
||||||
|
public function runQuery(string $sql, array $parameters = [])
|
||||||
|
{
|
||||||
|
static::$dump && call_user_func_array(static::$dump, [ $sql, $parameters ]);
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (false !== ( $statement = $this->prepare($sql) )) {
|
||||||
|
return $this->execute($statement, $parameters, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (\PDOException $e) {
|
||||||
|
throw new \PdoException($e->getMessage() . " `$sql` with data:" . json_encode($parameters));
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function execute(PDOStatement $statement, array $parameters = [], bool $commit = true)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
if ( ! $this->inTransaction() ) {
|
||||||
|
$this->beginTransaction();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($parameters) ? $statement->execute() : $statement->execute($parameters)) {
|
||||||
|
$statement->lastInsertId = $this->lastInsertId();
|
||||||
|
|
||||||
|
if ( $commit ) {
|
||||||
|
$this->commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $statement;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new \PDOException($statement->errorCode() . " - " . json_encode($statement->errorInfo()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (\PDOException $e) {
|
||||||
|
$this->rollback();
|
||||||
|
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
catch (\Throwable $e) {
|
||||||
|
if ( function_exists("debogueur") ) {
|
||||||
|
debogueur($statement, $parameters, $commit);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,70 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ulmus\Ldap;
|
||||||
|
|
||||||
|
use Ulmus\Adapter\AdapterInterface;
|
||||||
|
|
||||||
|
use Ulmus\Common\PdoObject;
|
||||||
|
|
||||||
|
class ConnectionAdapter extends \Ulmus\ConnectionAdapter
|
||||||
|
{
|
||||||
|
public string $name;
|
||||||
|
|
||||||
|
public array $configuration;
|
||||||
|
|
||||||
|
protected AdapterInterface $adapter;
|
||||||
|
|
||||||
|
public $connection;
|
||||||
|
|
||||||
|
public function resolveConfiguration() : void
|
||||||
|
{
|
||||||
|
$connection = $this->configuration['connections'][$this->name] ?? [];
|
||||||
|
|
||||||
|
if ( false !== ( $adapterName = $connection['adapter'] ?? false ) ) {
|
||||||
|
$this->adapter = $this->instanciateAdapter($adapterName);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$this->adapter = new Adapter\Ldap();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->adapter->setup($connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getConfiguration() : array
|
||||||
|
{
|
||||||
|
return $this->configuration['connections'][$this->name];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Connect the adapter
|
||||||
|
* @return self
|
||||||
|
*/
|
||||||
|
public function connect() : self
|
||||||
|
{
|
||||||
|
$this->connection = $this->adapter->connect();
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function connector() : object
|
||||||
|
{
|
||||||
|
return $this->connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function adapter() : AdapterInterface
|
||||||
|
{
|
||||||
|
return $this->adapter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instanciate an adapter which interact with the data source
|
||||||
|
* @param string $name An Ulmus adapter or full class name implementing AdapterInterface
|
||||||
|
* @return AdapterInterface
|
||||||
|
*/
|
||||||
|
protected function instanciateAdapter($name) : AdapterInterface
|
||||||
|
{
|
||||||
|
$class = substr($name, 0, 2) === "\\" ? $name : "\\Ulmus\\Adapter\\$name";
|
||||||
|
|
||||||
|
return new $class();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
namespace Ulmus\Ldap\Entity;
|
||||||
|
|
||||||
|
|
||||||
|
class Computer
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
namespace Ulmus\Ldap\Entity;
|
||||||
|
|
||||||
|
|
||||||
|
class Container
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ulmus\Ldap\Entity\Field;
|
||||||
|
|
||||||
|
class Datetime extends \Ulmus\Entity\Field\Datetime {
|
||||||
|
|
||||||
|
public function load(...$arguments)
|
||||||
|
{
|
||||||
|
return new static(substr($arguments[0], 0, 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,130 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ulmus\Ldap\Entity;
|
||||||
|
|
||||||
|
use Ulmus\Ldap\Entity\Field\{ Datetime };
|
||||||
|
|
||||||
|
class User
|
||||||
|
{
|
||||||
|
use \Ulmus\Ldap\EntityTrait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Id
|
||||||
|
*/
|
||||||
|
public string $samaccountname;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Field
|
||||||
|
*/
|
||||||
|
public string $mail;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Field
|
||||||
|
*/
|
||||||
|
public string $mailNickname;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Field('name' => 'givenname')
|
||||||
|
*/
|
||||||
|
public string $firstname;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Field('name' => 'sn')
|
||||||
|
*/
|
||||||
|
public string $lastname;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Field
|
||||||
|
*/
|
||||||
|
public string $displayName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Field
|
||||||
|
*/
|
||||||
|
public string $name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Field
|
||||||
|
*/
|
||||||
|
public string $userPrincipalName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Field
|
||||||
|
*/
|
||||||
|
public string $description;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Field('name' => "st")
|
||||||
|
*/
|
||||||
|
public string $state;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Field('name' => 'physicalDeliveryOfficeName')
|
||||||
|
*/
|
||||||
|
public string $officeName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Field
|
||||||
|
*/
|
||||||
|
public string $company;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Field
|
||||||
|
*/
|
||||||
|
public string $department;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Field
|
||||||
|
*/
|
||||||
|
public string $title;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Field
|
||||||
|
*/
|
||||||
|
public string $userAccountControl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Field
|
||||||
|
*/
|
||||||
|
public string $extensionAttribute1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Field
|
||||||
|
*/
|
||||||
|
public string $extensionAttribute2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Field
|
||||||
|
*/
|
||||||
|
public string $extensionAttribute3;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Field
|
||||||
|
*/
|
||||||
|
public string $extensionAttribute4;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Field
|
||||||
|
*/
|
||||||
|
public int $logonCount;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Field
|
||||||
|
*/
|
||||||
|
public Datetime $lastLogonDate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Field('name' => 'createTimeStamp')
|
||||||
|
*/
|
||||||
|
public Datetime $createdAt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Field('name' => 'modifyTimeStamp')
|
||||||
|
*/
|
||||||
|
public Datetime $updatedAt;
|
||||||
|
|
||||||
|
public function __toString() : string
|
||||||
|
{
|
||||||
|
return $this->displayName;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ulmus\Ldap;
|
||||||
|
|
||||||
|
use Ulmus\{ Ulmus, EventTrait, Query, Common\EntityResolver, Common\EntityField };
|
||||||
|
|
||||||
|
use Ulmus\Annotation\Classes\{ Method, Table, Collation, };
|
||||||
|
use Ulmus\Annotation\Property\{ Field, Filter, Relation, OrderBy, Where, Join, Virtual, On, WithJoin, };
|
||||||
|
use Ulmus\Annotation\Property\Field\{ Id, ForeignKey, CreatedAt, UpdatedAt, Datetime as DateTime, Date, Time, Bigint, Tinyint, Text, Mediumtext, Longtext, };
|
||||||
|
use Ulmus\Annotation\Property\Relation\{ Ignore as RelationIgnore };
|
||||||
|
|
||||||
|
trait EntityTrait {
|
||||||
|
use \Ulmus\EntityTrait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Ignore
|
||||||
|
*/
|
||||||
|
public static function resolveEntity() : EntityResolver
|
||||||
|
{
|
||||||
|
return Ulmus::resolveEntity(static::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Ignore
|
||||||
|
*/
|
||||||
|
public static function repository(string $alias = Repository::DEFAULT_ALIAS) : Repository
|
||||||
|
{
|
||||||
|
return new Repository(static::class, $alias);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Ignore
|
||||||
|
*/
|
||||||
|
public static function field($name, ? string $alias = null) : EntityField
|
||||||
|
{
|
||||||
|
return new EntityField(static::class, $name, $alias ?: Repository::DEFAULT_ALIAS, Ulmus::resolveEntity(static::class));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Ignore
|
||||||
|
*/
|
||||||
|
public static function fields(array $fields, ? string $alias = null) : string
|
||||||
|
{
|
||||||
|
return implode(', ', array_map(function($item) use ($alias){
|
||||||
|
return static::field($item, $alias);
|
||||||
|
}, $fields));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,148 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ulmus\Ldap\Query;
|
||||||
|
|
||||||
|
use Ulmus\Common\{ EntityField, Sql };
|
||||||
|
|
||||||
|
use Ulmus\Query\{ QueryBuilderInterface, Fragment };
|
||||||
|
|
||||||
|
class Filter extends Fragment {
|
||||||
|
const OPERATOR_LIKE = "LIKE";
|
||||||
|
const OPERATOR_EQUAL = "=";
|
||||||
|
const OPERATOR_NOT_EQUAL = "<>";
|
||||||
|
const CONDITION_AND = "&";
|
||||||
|
const CONDITION_OR = "|";
|
||||||
|
const CONDITION_NOT = "!";
|
||||||
|
const COMPARISON_IN = "IN";
|
||||||
|
const COMPARISON_IS = "IS";
|
||||||
|
const COMPARISON_NULL = "NULL";
|
||||||
|
|
||||||
|
public array $conditionList;
|
||||||
|
|
||||||
|
public QueryBuilderInterface $queryBuilder;
|
||||||
|
|
||||||
|
public ? Filter $parent = null;
|
||||||
|
|
||||||
|
public string $condition = self::CONDITION_AND;
|
||||||
|
|
||||||
|
public function __construct(? QueryBuilderInterface $queryBuilder, $condition = self::CONDITION_AND)
|
||||||
|
{
|
||||||
|
$this->queryBuilder = $queryBuilder;
|
||||||
|
$this->condition = $condition;
|
||||||
|
$this->parent = $queryBuilder->Filter ?? null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function add($field, $value, string $operator, string $condition, bool $not = false) : self
|
||||||
|
{
|
||||||
|
$this->conditionList[] = [
|
||||||
|
$field,
|
||||||
|
$value,
|
||||||
|
$operator ?: $this->queryBuilder->conditionOperator,
|
||||||
|
$condition,
|
||||||
|
$not
|
||||||
|
];
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function render(bool $skipToken = false) : array
|
||||||
|
{
|
||||||
|
$stack = [];
|
||||||
|
|
||||||
|
foreach ($this->conditionList ?? [] as $key => $item) {
|
||||||
|
if ( $item instanceof Filter ) {
|
||||||
|
if ( $item->conditionList ?? false ) {
|
||||||
|
$stack[] = ( $key !== 0 ? "{$item->condition} " : "" ) . "(" . implode('', $item->render($skipToken)) . ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
list($field, $value, $operator, $condition, $not) = $item;
|
||||||
|
$stack[] = $latest = $this->FilterCondition($field, $value, $operator, $key !== 0 ? $condition : "", $not);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [
|
||||||
|
'filters' => implode('', $stack)
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function FilterCondition($field, $value, string $operator = self::OPERATOR_EQUAL, string $condition = self::CONDITION_AND, bool $not = false) {
|
||||||
|
return new class($this->queryBuilder, $field, $value, $operator, $condition, $not) {
|
||||||
|
|
||||||
|
public $value;
|
||||||
|
public bool $not = false;
|
||||||
|
public string $field;
|
||||||
|
public string $operator;
|
||||||
|
public string $condition;
|
||||||
|
public QueryBuilderInterface $queryBuilder;
|
||||||
|
|
||||||
|
protected string $content = "";
|
||||||
|
|
||||||
|
public function __construct(QueryBuilderInterface $queryBuilder, string $field, $value, string $operator, string $condition, bool $not) {
|
||||||
|
$this->queryBuilder = $queryBuilder;
|
||||||
|
$this->field = $field;
|
||||||
|
$this->value = $value;
|
||||||
|
$this->condition = $condition;
|
||||||
|
$this->operator = $operator;
|
||||||
|
$this->not = $not;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function render() : string
|
||||||
|
{
|
||||||
|
$value = $this->value();
|
||||||
|
|
||||||
|
return $this->content ?: $this->content = implode("", array_filter([
|
||||||
|
"(",
|
||||||
|
$this->condition,
|
||||||
|
$this->not ? Filter::CONDITION_NOT : "",
|
||||||
|
$this->field,
|
||||||
|
$this->operator(),
|
||||||
|
$value,
|
||||||
|
")",
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function operator() : string
|
||||||
|
{
|
||||||
|
if ( is_array($this->value) ) {
|
||||||
|
return (in_array($this->operator, [ '!=', '<>' ]) ? Filter::CONDITION_NOT . " " : "") . Filter::COMPARISON_IN;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->operator;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function value()
|
||||||
|
{
|
||||||
|
if ( is_array($this->value) ) {
|
||||||
|
$stack = [];
|
||||||
|
|
||||||
|
foreach($this->value as $item) {
|
||||||
|
$stack[] = $this->filterValue($item);
|
||||||
|
}
|
||||||
|
|
||||||
|
return "(" . implode(", ", $stack) . ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->filterValue($this->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function filterValue($value)
|
||||||
|
{
|
||||||
|
if ( $value === null ) {
|
||||||
|
throw new \Exception("NULL is not an acceptable value for filter request.");
|
||||||
|
}
|
||||||
|
elseif ( is_object($value) && ( $value instanceof EntityField ) ) {
|
||||||
|
return $value->name();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __toString() : string
|
||||||
|
{
|
||||||
|
return $this->render();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ulmus\Ldap\Query;
|
||||||
|
|
||||||
|
class Limit extends \Ulmus\Query\Fragment {
|
||||||
|
|
||||||
|
public int $limit = 0;
|
||||||
|
|
||||||
|
public function set($limit) : self
|
||||||
|
{
|
||||||
|
$this->limit = $limit;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function render() : array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'limit' => $this->limit,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ulmus\Ldap\Query;
|
||||||
|
|
||||||
|
class Select extends \Ulmus\Query\Fragment {
|
||||||
|
|
||||||
|
public bool $distinct = false;
|
||||||
|
|
||||||
|
public bool $union = false;
|
||||||
|
|
||||||
|
public ? int $top = null;
|
||||||
|
|
||||||
|
protected array $fields = [];
|
||||||
|
|
||||||
|
public function set($fields) : self
|
||||||
|
{
|
||||||
|
$this->fields = is_array($fields) ? $fields : [ $fields ];
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function add($fields) : self
|
||||||
|
{
|
||||||
|
if ( is_array($fields) ) {
|
||||||
|
$this->fields = array_merge($this->fields, $fields);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$this->fields[] = $fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function render() : array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'fields' => $this->fields
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,236 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ulmus\Ldap;
|
||||||
|
|
||||||
|
use Ulmus;
|
||||||
|
|
||||||
|
class QueryBuilder implements Ulmus\Query\QueryBuilderInterface
|
||||||
|
{
|
||||||
|
public Query\Filter $where;
|
||||||
|
|
||||||
|
public Ulmus\Query\QueryBuilderInterface $parent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Those are the parameters we are going to bind to PDO.
|
||||||
|
*/
|
||||||
|
public array $parameters = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Those values are to be inserted or updated
|
||||||
|
*/
|
||||||
|
public array $values = [];
|
||||||
|
|
||||||
|
public string $whereConditionOperator = Ulmus\Query\Where::CONDITION_AND;
|
||||||
|
|
||||||
|
public string $havingConditionOperator = Ulmus\Query\Where::CONDITION_AND;
|
||||||
|
|
||||||
|
protected int $parameterIndex = 0;
|
||||||
|
|
||||||
|
protected array $queryStack = [];
|
||||||
|
|
||||||
|
public function select($field) : self
|
||||||
|
{
|
||||||
|
if ( null !== ( $select = $this->getFragment(Query\Select::class) ) ) {
|
||||||
|
$select->add($field);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$select = new Query\Select();
|
||||||
|
$select->set($field);
|
||||||
|
$this->push($select);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function from(string $table, ? string $alias, ? string $schema) : self
|
||||||
|
{
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(string $table, ? string $alias = null, ? string $database = null, ? string $schema = null) : self
|
||||||
|
{
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function delete() : self
|
||||||
|
{
|
||||||
|
if ( ! $this->getFragment(Ulmus\Query\Delete::class) ) {
|
||||||
|
$this->push(new Ulmus\Query\Delete());
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function open(string $condition = Ulmus\Query\Where::CONDITION_AND) : self
|
||||||
|
{
|
||||||
|
if ( null !== ($this->where ?? null) ) {
|
||||||
|
$this->where->conditionList[] = $new = new Query\Filter($this, $condition);
|
||||||
|
$this->where = $new;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$this->where = new Query\Filter($this, $condition);
|
||||||
|
$this->push($this->where);
|
||||||
|
$this->where->conditionList[] = $new = new Query\Filter($this, $condition);
|
||||||
|
$this->where = $new;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function close() : self
|
||||||
|
{
|
||||||
|
if ( null !== ($this->where ?? null) && $this->where->parent ) {
|
||||||
|
|
||||||
|
# if an enclosure was opened, and nothing done, we must remove the unused node
|
||||||
|
if ( empty($this->where->conditionList) && (count($this->where->parent->conditionList) === 1) ) {
|
||||||
|
unset($this->where->parent->conditionList);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->where = $this->where->parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function where(/* stringable*/ $field, $value, string $operator = Ulmus\Query\Where::OPERATOR_EQUAL, string $condition = Ulmus\Query\Where::CONDITION_AND, bool $not = false) : self
|
||||||
|
{
|
||||||
|
# Empty IN case
|
||||||
|
if ( [] === $value ) {
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( $this->where ?? false ) {
|
||||||
|
$where = $this->where;
|
||||||
|
}
|
||||||
|
elseif ( null === ( $where = $this->getFragment(Query\Filter::class) ) ) {
|
||||||
|
$this->where = $where = new Query\Filter($this);
|
||||||
|
$this->push($where);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->whereConditionOperator = $operator;
|
||||||
|
|
||||||
|
$where->add($field, $value, $operator, $condition, $not);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function notWhere($field, $value, string $operator = Ulmus\Query\Where::CONDITION_AND) : self
|
||||||
|
{
|
||||||
|
return $this->where($field, $value, $operator, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function limit(int $value) : self
|
||||||
|
{
|
||||||
|
if ( null === $limit = $this->getFragment(Ulmus\Query\Limit::class) ) {
|
||||||
|
$limit = new Query\Limit();
|
||||||
|
$this->push($limit);
|
||||||
|
}
|
||||||
|
|
||||||
|
$limit->set($value);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function offset(int $value) : self
|
||||||
|
{
|
||||||
|
if ( null === $offset = $this->getFragment(Ulmus\Query\Offset::class) ) {
|
||||||
|
$offset = new Ulmus\Query\Offset();
|
||||||
|
$this->push($offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
$offset->set($value);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function orderBy(string $field, ? string $direction = null) : self
|
||||||
|
{
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function create(array $fieldlist, string $table, ? string $database = null, ? string $schema = null) : self
|
||||||
|
{
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function push(Ulmus\Query\Fragment $queryFragment) : self
|
||||||
|
{
|
||||||
|
$this->queryStack[] = $queryFragment;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function pull(Ulmus\Query\Fragment $queryFragment) : self
|
||||||
|
{
|
||||||
|
return array_shift($this->queryStack);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function render(bool $skipToken = false) : array
|
||||||
|
{
|
||||||
|
$stack = [];
|
||||||
|
|
||||||
|
foreach($this->queryStack as $fragment) {
|
||||||
|
$stack = array_merge($stack, (array) $fragment->render($skipToken));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $stack;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function reset() : void
|
||||||
|
{
|
||||||
|
$this->parameters = $this->values = $this->queryStack = [];
|
||||||
|
$this->whereConditionOperator = Ulmus\Query\Where::CONDITION_AND;
|
||||||
|
$this->havingConditionOperator = Ulmus\Query\Where::CONDITION_AND;
|
||||||
|
$this->parameterIndex = 0;
|
||||||
|
|
||||||
|
unset($this->where, $this->having);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFragment(string $class, int $index = 0) : ? Ulmus\Query\Fragment
|
||||||
|
{
|
||||||
|
foreach($this->queryStack as $item) {
|
||||||
|
if ( get_class($item) === $class ) {
|
||||||
|
if ( $index-- === 0 ) {
|
||||||
|
return $item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function removeFragment(Ulmus\Query\Fragment $fragment) : void
|
||||||
|
{
|
||||||
|
foreach($this->queryStack as $key => $item) {
|
||||||
|
if ( $item === $fragment ) {
|
||||||
|
unset($this->queryStack[$key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __toString() : string
|
||||||
|
{
|
||||||
|
return $this->render();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addParameter($value, string $key = null) : string
|
||||||
|
{
|
||||||
|
if ( $this->parent ?? false ) {
|
||||||
|
return $this->parent->addParameter($value, $key);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( $key === null ) {
|
||||||
|
$key = ":p" . $this->parameterIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->parameters[$key] = $value;
|
||||||
|
|
||||||
|
return $key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function addValues(array $values) : void
|
||||||
|
{
|
||||||
|
$this->values = $values;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ulmus\Ldap;
|
||||||
|
|
||||||
|
use Ulmus\Ulmus;
|
||||||
|
use Ulmus\Annotation\Property\{ Where, Having, Relation, Join, WithJoin, Relation\Ignore as RelationIgnore };
|
||||||
|
use Ulmus\Common\EntityResolver;
|
||||||
|
|
||||||
|
class Repository extends \Ulmus\Repository
|
||||||
|
{
|
||||||
|
const DEFAULT_ALIAS = "";
|
||||||
|
|
||||||
|
public array $events = [];
|
||||||
|
|
||||||
|
public function __construct(string $entity, string $alias = self::DEFAULT_ALIAS, ConnectionAdapter $adapter = null) {
|
||||||
|
parent::__construct($entity, $alias, $adapter);
|
||||||
|
|
||||||
|
$this->queryBuilder = new QueryBuilder();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function selectSqlQuery() : self
|
||||||
|
{
|
||||||
|
if ( null === $this->queryBuilder->getFragment(Query\Select::class) ) {
|
||||||
|
$this->select(array_keys($this->entityResolver->fieldList(EntityResolver::KEY_COLUMN_NAME)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,153 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Ulmus\Ldap\Repository;
|
||||||
|
|
||||||
|
use Ulmus\Query;
|
||||||
|
|
||||||
|
trait ConditionTrait
|
||||||
|
{
|
||||||
|
public function open(string $condition = Query\Where::CONDITION_AND) : self
|
||||||
|
{
|
||||||
|
$this->queryBuilder->open($condition);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function orOpen() : self
|
||||||
|
{
|
||||||
|
return $this->open(Query\Where::CONDITION_OR);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function close() : self
|
||||||
|
{
|
||||||
|
$this->queryBuilder->close();
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function where($field, $value, string $operator = Query\Where::OPERATOR_EQUAL, $condition = Query\Where::CONDITION_AND) : self
|
||||||
|
{
|
||||||
|
$this->queryBuilder->where($field, $value, $operator, $condition);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function wheres(array $fieldValues, string $operator = Query\Where::OPERATOR_EQUAL) : self
|
||||||
|
{
|
||||||
|
foreach($fieldValues as $field => $value) {
|
||||||
|
$this->where($field, $value, $operator);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function and($field, $value, string $operator = Query\Where::OPERATOR_EQUAL) : self
|
||||||
|
{
|
||||||
|
return $this->where($field, $value, $operator);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function or($field, $value, string $operator = Query\Where::OPERATOR_EQUAL) : self
|
||||||
|
{
|
||||||
|
$this->queryBuilder->where($field, $value, $operator, Query\Where::CONDITION_OR);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function notWhere($field, $value, string $operator = Query\Where::OPERATOR_NOT_EQUAL) : self
|
||||||
|
{
|
||||||
|
$this->queryBuilder->where($field, $value, $operator, Query\Where::CONDITION_AND, true);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function orNot($field, $value, string $operator = Query\Where::OPERATOR_NOT_EQUAL) : self
|
||||||
|
{
|
||||||
|
$this->queryBuilder->notWhere($field, $value, $operator, Query\Where::CONDITION_OR, true);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function having($field, $value, string $operator = Query\Where::OPERATOR_EQUAL, $condition = Query\Where::CONDITION_AND) : self
|
||||||
|
{
|
||||||
|
$this->queryBuilder->having($field, $value, $operator, $condition);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function orHaving($field, $value, string $operator = Query\Where::OPERATOR_EQUAL) : self
|
||||||
|
{
|
||||||
|
$this->queryBuilder->having($field, $value, $operator, Query\Where::CONDITION_OR);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function notHaving($field, $value, string $operator = Query\Where::OPERATOR_NOT_EQUAL) : self
|
||||||
|
{
|
||||||
|
$this->queryBuilder->having($field, $value, $operator, Query\Where::CONDITION_AND, true);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function orNotHaving($field, $value) : self
|
||||||
|
{
|
||||||
|
$this->queryBuilder->having($field, $value, Query\Where::OPERATOR_NOT_EQUAL, Query\Where::CONDITION_OR, true);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function in($field, $value, string $operator = Query\Where::OPERATOR_EQUAL) : self
|
||||||
|
{
|
||||||
|
$this->queryBuilder->where($field, $value, $operator);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function orIn($field, $value, string $operator = Query\Where::OPERATOR_EQUAL) : self
|
||||||
|
{
|
||||||
|
$this->queryBuilder->where($field, $value, $operator, Query\Where::CONDITION_OR);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function notIn($field, $value) : self
|
||||||
|
{
|
||||||
|
$this->queryBuilder->where($field, $value, Query\Where::OPERATOR_NOT_EQUAL);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function orNotIn($field, $value) : self
|
||||||
|
{
|
||||||
|
return $this->orNot($field, $value, Query\Where::OPERATOR_NOT_EQUAL, Query\Where::CONDITION_OR, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function like($field, $value) : self
|
||||||
|
{
|
||||||
|
$this->where($field, $value, Query\Where::OPERATOR_LIKE);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function orLike($field, $value) : self
|
||||||
|
{
|
||||||
|
$this->or($field, $value, Query\Where::OPERATOR_LIKE);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function notLike($field, $value) : self
|
||||||
|
{
|
||||||
|
$this->notWhere($field, $value, Query\Where::OPERATOR_LIKE);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function likes(array $fieldValues, string $condition = Query\Where::CONDITION_AND) : self
|
||||||
|
{
|
||||||
|
foreach($fieldValues as $field => $value) {
|
||||||
|
$this->like($field, $value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue