Merge branch 'master' into bugfix/pgsql-queries-apply-lower-on-select-columns-10364
This commit is contained in:
commit
e58d747d4a
|
@ -37,7 +37,16 @@ userpassword: password
|
||||||
dn: cn=Users,ou=groups,dc=icinga,dc=org
|
dn: cn=Users,ou=groups,dc=icinga,dc=org
|
||||||
objectClass: groupOfUniqueNames
|
objectClass: groupOfUniqueNames
|
||||||
cn: Users
|
cn: Users
|
||||||
uniqueMember: cn=Jon Doe,ou=people,dc=icinga,dc=org
|
uniqueMember: cn=John Doe,ou=people,dc=icinga,dc=org
|
||||||
uniqueMember: cn=Jane Smith,ou=people,dc=icinga,dc=org
|
uniqueMember: cn=Jane Smith,ou=people,dc=icinga,dc=org
|
||||||
uniqueMember: cn=John Q. Public,ou=people,dc=icinga,dc=org
|
uniqueMember: cn=John Q. Public,ou=people,dc=icinga,dc=org
|
||||||
uniqueMember: cn=Richard Roe,ou=people,dc=icinga,dc=org
|
uniqueMember: cn=Richard Roe,ou=people,dc=icinga,dc=org
|
||||||
|
|
||||||
|
dn: cn=PosixUsers,ou=groups,dc=icinga,dc=org
|
||||||
|
objectClass: posixGroup
|
||||||
|
cn: PosixUsers
|
||||||
|
gidNumber: 2001
|
||||||
|
memberUid: jdoe
|
||||||
|
memberUid: jsmith
|
||||||
|
memberUid: jqpublic
|
||||||
|
memberUid: rroe
|
||||||
|
|
|
@ -136,6 +136,16 @@ class Logger
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the logging level being used
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function getLevel()
|
||||||
|
{
|
||||||
|
return $this->level;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register the given message as config error
|
* Register the given message as config error
|
||||||
*
|
*
|
||||||
|
|
|
@ -190,24 +190,6 @@ class LdapUserBackend extends LdapRepository implements UserBackendInterface, In
|
||||||
->setFilter($config->filter);
|
->setFilter($config->filter);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a new query for the given columns
|
|
||||||
*
|
|
||||||
* @param array $columns The desired columns, if null all columns will be queried
|
|
||||||
*
|
|
||||||
* @return RepositoryQuery
|
|
||||||
*/
|
|
||||||
public function select(array $columns = null)
|
|
||||||
{
|
|
||||||
$query = parent::select($columns);
|
|
||||||
$query->getQuery()->setBase($this->baseDn);
|
|
||||||
if ($this->filter) {
|
|
||||||
$query->getQuery()->setNativeFilter($this->filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $query;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize this repository's virtual tables
|
* Initialize this repository's virtual tables
|
||||||
*
|
*
|
||||||
|
@ -335,6 +317,28 @@ class LdapUserBackend extends LdapRepository implements UserBackendInterface, In
|
||||||
return ((int) $value) >= $bigBang->diff($now)->days;
|
return ((int) $value) >= $bigBang->diff($now)->days;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate that the requested table exists
|
||||||
|
*
|
||||||
|
* @param string $table The table to validate
|
||||||
|
* @param RepositoryQuery $query An optional query to pass as context
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*
|
||||||
|
* @throws ProgrammingError In case the given table does not exist
|
||||||
|
*/
|
||||||
|
public function requireTable($table, RepositoryQuery $query = null)
|
||||||
|
{
|
||||||
|
if ($query !== null) {
|
||||||
|
$query->getQuery()->setBase($this->baseDn);
|
||||||
|
if ($this->filter) {
|
||||||
|
$query->getQuery()->setNativeFilter($this->filter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return parent::requireTable($table, $query);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate that the given column is a valid query target and return it or the actual name if it's an alias
|
* Validate that the given column is a valid query target and return it or the actual name if it's an alias
|
||||||
*
|
*
|
||||||
|
|
|
@ -72,6 +72,13 @@ class LdapUserGroupBackend extends LdapRepository implements UserGroupBackendInt
|
||||||
*/
|
*/
|
||||||
protected $groupMemberAttribute;
|
protected $groupMemberAttribute;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the attribute name where to find a group's member holds ambiguous values
|
||||||
|
*
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
protected $ambiguousMemberAttribute;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The custom LDAP filter to apply on a user query
|
* The custom LDAP filter to apply on a user query
|
||||||
*
|
*
|
||||||
|
@ -358,17 +365,36 @@ class LdapUserGroupBackend extends LdapRepository implements UserGroupBackendInt
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a new query for the given columns
|
* Return whether the attribute name where to find a group's member holds ambiguous values
|
||||||
*
|
*
|
||||||
* @param array $columns The desired columns, if null all columns will be queried
|
* @return bool
|
||||||
*
|
*
|
||||||
* @return RepositoryQuery
|
* @throws ProgrammingError In case either $this->groupClass or $this->groupMemberAttribute
|
||||||
|
* has not been set yet
|
||||||
*/
|
*/
|
||||||
public function select(array $columns = null)
|
protected function isMemberAttributeAmbiguous()
|
||||||
{
|
{
|
||||||
$query = parent::select($columns);
|
if ($this->ambiguousMemberAttribute === null) {
|
||||||
$query->getQuery()->setBase($this->groupBaseDn);
|
if ($this->groupClass === null) {
|
||||||
return $query;
|
throw new ProgrammingError(
|
||||||
|
'It is required to set the objectClass where to look for groups first'
|
||||||
|
);
|
||||||
|
} elseif ($this->groupMemberAttribute === null) {
|
||||||
|
throw new ProgrammingError(
|
||||||
|
'It is required to set a attribute name where to find a group\'s members first'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$sampleValue = $this->ds
|
||||||
|
->select()
|
||||||
|
->from($this->groupClass, array($this->groupMemberAttribute))
|
||||||
|
->setUnfoldAttribute($this->groupMemberAttribute)
|
||||||
|
->setBase($this->groupBaseDn)
|
||||||
|
->fetchOne();
|
||||||
|
$this->ambiguousMemberAttribute = !$this->isRelatedDn($sampleValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->ambiguousMemberAttribute;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -445,19 +471,9 @@ class LdapUserGroupBackend extends LdapRepository implements UserGroupBackendInt
|
||||||
* Initialize this repository's conversion rules
|
* Initialize this repository's conversion rules
|
||||||
*
|
*
|
||||||
* @return array
|
* @return array
|
||||||
*
|
|
||||||
* @throws ProgrammingError In case either $this->groupClass or $this->groupMemberAttribute
|
|
||||||
* has not been set yet
|
|
||||||
*/
|
*/
|
||||||
protected function initializeConversionRules()
|
protected function initializeConversionRules()
|
||||||
{
|
{
|
||||||
if ($this->groupClass === null) {
|
|
||||||
throw new ProgrammingError('It is required to set the objectClass where to look for groups first');
|
|
||||||
}
|
|
||||||
if ($this->groupMemberAttribute === null) {
|
|
||||||
throw new ProgrammingError('It is required to set a attribute name where to find a group\'s members first');
|
|
||||||
}
|
|
||||||
|
|
||||||
$rules = array(
|
$rules = array(
|
||||||
'group' => array(
|
'group' => array(
|
||||||
'created_at' => 'generalized_time',
|
'created_at' => 'generalized_time',
|
||||||
|
@ -468,7 +484,7 @@ class LdapUserGroupBackend extends LdapRepository implements UserGroupBackendInt
|
||||||
'last_modified' => 'generalized_time'
|
'last_modified' => 'generalized_time'
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
if (! $this->isAmbiguous($this->groupClass, $this->groupMemberAttribute)) {
|
if (! $this->isMemberAttributeAmbiguous()) {
|
||||||
$rules['group_membership']['user_name'] = 'user_name';
|
$rules['group_membership']['user_name'] = 'user_name';
|
||||||
$rules['group_membership']['user'] = 'user_name';
|
$rules['group_membership']['user'] = 'user_name';
|
||||||
$rules['group']['user_name'] = 'user_name';
|
$rules['group']['user_name'] = 'user_name';
|
||||||
|
@ -492,6 +508,7 @@ class LdapUserGroupBackend extends LdapRepository implements UserGroupBackendInt
|
||||||
->select()
|
->select()
|
||||||
->from($this->userClass, array())
|
->from($this->userClass, array())
|
||||||
->where($this->userNameAttribute, $name)
|
->where($this->userNameAttribute, $name)
|
||||||
|
->setBase($this->userBaseDn)
|
||||||
->setUsePagedResults(false)
|
->setUsePagedResults(false)
|
||||||
->fetchDn();
|
->fetchDn();
|
||||||
if ($userDn) {
|
if ($userDn) {
|
||||||
|
@ -502,6 +519,7 @@ class LdapUserGroupBackend extends LdapRepository implements UserGroupBackendInt
|
||||||
->select()
|
->select()
|
||||||
->from($this->groupClass, array())
|
->from($this->groupClass, array())
|
||||||
->where($this->groupNameAttribute, $name)
|
->where($this->groupNameAttribute, $name)
|
||||||
|
->setBase($this->groupBaseDn)
|
||||||
->setUsePagedResults(false)
|
->setUsePagedResults(false)
|
||||||
->fetchDn();
|
->fetchDn();
|
||||||
if ($groupDn) {
|
if ($groupDn) {
|
||||||
|
@ -543,8 +561,11 @@ class LdapUserGroupBackend extends LdapRepository implements UserGroupBackendInt
|
||||||
*/
|
*/
|
||||||
public function requireTable($table, RepositoryQuery $query = null)
|
public function requireTable($table, RepositoryQuery $query = null)
|
||||||
{
|
{
|
||||||
if ($query !== null && $table === 'group' && $this->groupFilter) {
|
if ($query !== null) {
|
||||||
$query->getQuery()->setNativeFilter($this->groupFilter);
|
$query->getQuery()->setBase($this->groupBaseDn);
|
||||||
|
if ($table === 'group' && $this->groupFilter) {
|
||||||
|
$query->getQuery()->setNativeFilter($this->groupFilter);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return parent::requireTable($table, $query);
|
return parent::requireTable($table, $query);
|
||||||
|
@ -580,7 +601,7 @@ class LdapUserGroupBackend extends LdapRepository implements UserGroupBackendInt
|
||||||
*/
|
*/
|
||||||
public function getMemberships(User $user)
|
public function getMemberships(User $user)
|
||||||
{
|
{
|
||||||
if ($this->isAmbiguous($this->groupClass, $this->groupMemberAttribute)) {
|
if ($this->isMemberAttributeAmbiguous()) {
|
||||||
$queryValue = $user->getUsername();
|
$queryValue = $user->getUsername();
|
||||||
} elseif (($queryValue = $user->getAdditional('ldap_dn')) === null) {
|
} elseif (($queryValue = $user->getAdditional('ldap_dn')) === null) {
|
||||||
$userQuery = $this->ds
|
$userQuery = $this->ds
|
||||||
|
|
|
@ -378,14 +378,7 @@ class LdapConnection implements Selectable, Inspectable
|
||||||
}
|
}
|
||||||
|
|
||||||
$ds = $this->getConnection();
|
$ds = $this->getConnection();
|
||||||
$results = @ldap_search(
|
$results = $this->ldapSearch($query, array('dn'));
|
||||||
$ds,
|
|
||||||
$query->getBase() ?: $this->getDn(),
|
|
||||||
(string) $query,
|
|
||||||
array('dn'),
|
|
||||||
0,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
|
|
||||||
if ($results === false) {
|
if ($results === false) {
|
||||||
if (ldap_errno($ds) !== self::LDAP_NO_SUCH_OBJECT) {
|
if (ldap_errno($ds) !== self::LDAP_NO_SUCH_OBJECT) {
|
||||||
|
@ -483,8 +476,28 @@ class LdapConnection implements Selectable, Inspectable
|
||||||
*/
|
*/
|
||||||
public function fetchOne(LdapQuery $query, array $fields = null)
|
public function fetchOne(LdapQuery $query, array $fields = null)
|
||||||
{
|
{
|
||||||
$row = (array) $this->fetchRow($query, $fields);
|
$row = $this->fetchRow($query, $fields);
|
||||||
return array_shift($row) ?: false;
|
if ($row === false) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$values = get_object_vars($row);
|
||||||
|
if (empty($values)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($fields === null) {
|
||||||
|
// Fetch the desired columns from the query if not explicitly overriden in the method's parameter
|
||||||
|
$fields = $query->getColumns();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($fields)) {
|
||||||
|
// The desired columns may be empty independently whether provided by the query or the method's parameter
|
||||||
|
return array_shift($values);
|
||||||
|
}
|
||||||
|
|
||||||
|
$alias = key($fields);
|
||||||
|
return $values[is_string($alias) ? $alias : $fields[$alias]];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -712,14 +725,10 @@ class LdapConnection implements Selectable, Inspectable
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$results = @ldap_search(
|
$results = $this->ldapSearch(
|
||||||
$ds,
|
$query,
|
||||||
$query->getBase() ?: $this->rootDn,
|
array_values($fields),
|
||||||
(string) $query,
|
0,
|
||||||
$unfoldAttribute
|
|
||||||
? array_unique(array_values($fields))
|
|
||||||
: array_values($fields),
|
|
||||||
0, // Attributes and values
|
|
||||||
$serverSorting && $limit ? $offset + $limit : 0
|
$serverSorting && $limit ? $offset + $limit : 0
|
||||||
);
|
);
|
||||||
if ($results === false) {
|
if ($results === false) {
|
||||||
|
@ -808,8 +817,6 @@ class LdapConnection implements Selectable, Inspectable
|
||||||
|
|
||||||
$limit = $query->getLimit();
|
$limit = $query->getLimit();
|
||||||
$offset = $query->hasOffset() ? $query->getOffset() : 0;
|
$offset = $query->hasOffset() ? $query->getOffset() : 0;
|
||||||
$queryString = (string) $query;
|
|
||||||
$base = $query->getBase() ?: $this->rootDn;
|
|
||||||
|
|
||||||
if ($fields === null) {
|
if ($fields === null) {
|
||||||
$fields = $query->getColumns();
|
$fields = $query->getColumns();
|
||||||
|
@ -853,14 +860,10 @@ class LdapConnection implements Selectable, Inspectable
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
$results = @ldap_search(
|
$results = $this->ldapSearch(
|
||||||
$ds,
|
$query,
|
||||||
$base,
|
array_values($fields),
|
||||||
$queryString,
|
0,
|
||||||
$unfoldAttribute
|
|
||||||
? array_unique(array_values($fields))
|
|
||||||
: array_values($fields),
|
|
||||||
0, // Attributes and values
|
|
||||||
$serverSorting && $limit ? $offset + $limit : 0
|
$serverSorting && $limit ? $offset + $limit : 0
|
||||||
);
|
);
|
||||||
if ($results === false) {
|
if ($results === false) {
|
||||||
|
@ -870,8 +873,8 @@ class LdapConnection implements Selectable, Inspectable
|
||||||
|
|
||||||
throw new LdapException(
|
throw new LdapException(
|
||||||
'LDAP query "%s" (base %s) failed. Error: %s',
|
'LDAP query "%s" (base %s) failed. Error: %s',
|
||||||
$queryString,
|
(string) $query,
|
||||||
$base,
|
$query->getBase() ?: $this->getDn(),
|
||||||
ldap_error($ds)
|
ldap_error($ds)
|
||||||
);
|
);
|
||||||
} elseif (ldap_count_entries($ds, $results) === 0) {
|
} elseif (ldap_count_entries($ds, $results) === 0) {
|
||||||
|
@ -950,7 +953,8 @@ class LdapConnection implements Selectable, Inspectable
|
||||||
// pagedResultsControl with the size set to zero (0) and the cookie set to the last cookie returned by
|
// pagedResultsControl with the size set to zero (0) and the cookie set to the last cookie returned by
|
||||||
// the server: https://www.ietf.org/rfc/rfc2696.txt
|
// the server: https://www.ietf.org/rfc/rfc2696.txt
|
||||||
ldap_control_paged_result($ds, 0, false, $cookie);
|
ldap_control_paged_result($ds, 0, false, $cookie);
|
||||||
ldap_search($ds, $base, $queryString); // Returns no entries, due to the page size
|
// Returns no entries, due to the page size
|
||||||
|
ldap_search($ds, $query->getBase() ?: $this->getDn(), (string) $query);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! $serverSorting && $query->hasOrder()) {
|
if (! $serverSorting && $query->hasOrder()) {
|
||||||
|
@ -1164,6 +1168,77 @@ class LdapConnection implements Selectable, Inspectable
|
||||||
return $ds;
|
return $ds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform a LDAP search and return the result
|
||||||
|
*
|
||||||
|
* @param LdapQuery $query
|
||||||
|
* @param array $attributes An array of the required attributes
|
||||||
|
* @param int $attrsonly Should be set to 1 if only attribute types are wanted
|
||||||
|
* @param int $sizelimit Enables you to limit the count of entries fetched
|
||||||
|
* @param int $timelimit Sets the number of seconds how long is spend on the search
|
||||||
|
* @param int $deref
|
||||||
|
*
|
||||||
|
* @return resource|bool A search result identifier or false on error
|
||||||
|
*/
|
||||||
|
public function ldapSearch(
|
||||||
|
LdapQuery $query,
|
||||||
|
array $attributes = null,
|
||||||
|
$attrsonly = 0,
|
||||||
|
$sizelimit = 0,
|
||||||
|
$timelimit = 0,
|
||||||
|
$deref = LDAP_DEREF_NEVER
|
||||||
|
) {
|
||||||
|
$queryString = (string) $query;
|
||||||
|
$baseDn = $query->getBase() ?: $this->getDn();
|
||||||
|
|
||||||
|
if (Logger::getInstance()->getLevel() === Logger::DEBUG) {
|
||||||
|
// We're checking the level by ourself to avoid rendering the ldapsearch commandline for nothing
|
||||||
|
$starttlsParam = $this->encryption === static::STARTTLS ? ' -ZZ' : '';
|
||||||
|
$ldapUrl = ($this->encryption === static::LDAPS ? 'ldaps://' : 'ldap://')
|
||||||
|
. $this->hostname
|
||||||
|
. ($this->port ? ':' . $this->port : '');
|
||||||
|
|
||||||
|
if ($this->bound) {
|
||||||
|
$bindParams = ' -D "' . $this->bindDn . '"' . ($this->bindPw ? ' -w "' . $this->bindPw . '"' : '');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($deref === LDAP_DEREF_NEVER) {
|
||||||
|
$derefName = 'never';
|
||||||
|
} elseif ($deref === LDAP_DEREF_ALWAYS) {
|
||||||
|
$derefName = 'always';
|
||||||
|
} elseif ($deref === LDAP_DEREF_SEARCHING) {
|
||||||
|
$derefName = 'search';
|
||||||
|
} else { // $deref === LDAP_DEREF_FINDING
|
||||||
|
$derefName = 'find';
|
||||||
|
}
|
||||||
|
|
||||||
|
Logger::debug("Issueing LDAP search. Use '%s' to reproduce.", sprintf(
|
||||||
|
'ldapsearch -P 3%s -H "%s"%s -b "%s" -s "sub" -z %u -l %u -a "%s"%s%s%s',
|
||||||
|
$starttlsParam,
|
||||||
|
$ldapUrl,
|
||||||
|
$bindParams,
|
||||||
|
$baseDn,
|
||||||
|
$sizelimit,
|
||||||
|
$timelimit,
|
||||||
|
$derefName,
|
||||||
|
$attrsonly ? ' -A' : '',
|
||||||
|
$queryString ? ' "' . $queryString . '"' : '',
|
||||||
|
$attributes ? ' "' . join('" "', $attributes) . '"' : ''
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
return @ldap_search(
|
||||||
|
$this->getConnection(),
|
||||||
|
$baseDn,
|
||||||
|
$queryString,
|
||||||
|
$attributes,
|
||||||
|
$attrsonly,
|
||||||
|
$sizelimit,
|
||||||
|
$timelimit,
|
||||||
|
$deref
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an LDAP entry
|
* Create an LDAP entry
|
||||||
*
|
*
|
||||||
|
|
|
@ -42,15 +42,6 @@ abstract class LdapRepository extends Repository
|
||||||
'groupofuniquenames' => 'groupOfUniqueNames'
|
'groupofuniquenames' => 'groupOfUniqueNames'
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
|
||||||
* Object attributes whose value is not distinguished name
|
|
||||||
*
|
|
||||||
* @var array
|
|
||||||
*/
|
|
||||||
protected $ambiguousAttributes = array(
|
|
||||||
'posixGroup' => 'memberUid'
|
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new LDAP repository object
|
* Create a new LDAP repository object
|
||||||
*
|
*
|
||||||
|
@ -79,15 +70,19 @@ abstract class LdapRepository extends Repository
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return whether the given object attribute's value is not a distinguished name
|
* Return whether the given object DN is related to the given base DN
|
||||||
*
|
*
|
||||||
* @param string $objectClass
|
* Will use the current connection's root DN if $baseDn is not given.
|
||||||
* @param string $attributeName
|
*
|
||||||
|
* @param string $dn The object DN to check
|
||||||
|
* @param string $baseDn The base DN to compare the object DN with
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
protected function isAmbiguous($objectClass, $attributeName)
|
protected function isRelatedDn($dn, $baseDn = null)
|
||||||
{
|
{
|
||||||
return isset($this->ambiguousAttributes[$objectClass][$attributeName]);
|
$normalizedDn = strtolower(join(',', array_map('trim', explode(',', $dn))));
|
||||||
|
$normalizedBaseDn = strtolower(join(',', array_map('trim', explode(',', $baseDn ?: $this->ds->getDn()))));
|
||||||
|
return strpos($normalizedDn, $normalizedBaseDn) !== false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,9 +86,8 @@ class RepositoryQuery implements QueryInterface, SortRules, FilterColumns, Itera
|
||||||
*/
|
*/
|
||||||
public function from($target, array $columns = null)
|
public function from($target, array $columns = null)
|
||||||
{
|
{
|
||||||
$this->query = $this->repository->getDataSource()->select()->from(
|
$this->query = $this->repository->getDataSource()->select();
|
||||||
$this->repository->requireTable($target, $this)
|
$this->query->from($this->repository->requireTable($target, $this));
|
||||||
);
|
|
||||||
$this->query->columns($this->prepareQueryColumns($target, $columns));
|
$this->query->columns($this->prepareQueryColumns($target, $columns));
|
||||||
$this->target = $target;
|
$this->target = $target;
|
||||||
return $this;
|
return $this;
|
||||||
|
|
|
@ -203,6 +203,7 @@ class Controller extends ModuleActionController
|
||||||
'sort', // setupSortControl()
|
'sort', // setupSortControl()
|
||||||
'dir', // setupSortControl()
|
'dir', // setupSortControl()
|
||||||
'backend', // Framework
|
'backend', // Framework
|
||||||
|
'view', // Framework
|
||||||
'_dev' // Framework
|
'_dev' // Framework
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue