|
@@ -35,15 +35,11 @@ class AclQueryBuilder {
|
|
|
$this->isNotInstances = [];
|
|
$this->isNotInstances = [];
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- public function select($propertyName) { // TODO: ogc:propertyName, *, xpath, @instances, etc...
|
|
|
|
|
- if (!empty($propertyName) && !in_array($propertyName, $this->select)) $this->select[] = $propertyName;
|
|
|
|
|
- return $this;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
public function from($from, $prefix = 't') {
|
|
public function from($from, $prefix = 't') {
|
|
|
DBG::log([
|
|
DBG::log([
|
|
|
'from instanceof Core_AclBase' => ($from instanceof Core_AclBase),
|
|
'from instanceof Core_AclBase' => ($from instanceof Core_AclBase),
|
|
|
'from instanceof AntAclBase' => ($from instanceof AntAclBase),
|
|
'from instanceof AntAclBase' => ($from instanceof AntAclBase),
|
|
|
|
|
+ 'from instanceof TableAcl' => ($from instanceof TableAcl),
|
|
|
], 'array', "\$from class(".get_class($from).")");
|
|
], 'array', "\$from class(".get_class($from).")");
|
|
|
if ($this->from) throw new Exception("Duplicate FROM");
|
|
if ($this->from) throw new Exception("Duplicate FROM");
|
|
|
$this->from = $from;
|
|
$this->from = $from;
|
|
@@ -51,13 +47,49 @@ class AclQueryBuilder {
|
|
|
return $this;
|
|
return $this;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- public function where($params) {
|
|
|
|
|
- if (!empty($params['rawWhere'])) {
|
|
|
|
|
- $this->where[] = $params['rawWhere'];
|
|
|
|
|
- } else {
|
|
|
|
|
- DBG::log($params, 'array', "Where not supported");
|
|
|
|
|
- throw new Exception("Where not supported");
|
|
|
|
|
|
|
+ public function select($propertyName) { // TODO: ogc:propertyName, *, xpath, @instances, etc...
|
|
|
|
|
+ if (empty($propertyName)) return $this; // SKIP empty values, null's, etc.
|
|
|
|
|
+ DBG::log($propertyName, 'array', "AclQueryBuilder->select");
|
|
|
|
|
+ if (is_array($propertyName) && !empty($propertyName['rawSelect'])) {
|
|
|
|
|
+ $this->select['__rawSelect__'] = $propertyName['rawSelect'];
|
|
|
|
|
+ return $this;
|
|
|
}
|
|
}
|
|
|
|
|
+ if (!in_array($propertyName, $this->select)) $this->select[] = $propertyName; // TODO: split by property source
|
|
|
|
|
+ return $this;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public function where($fieldName, $comparisonSign = null, $value = null) {
|
|
|
|
|
+ if (!in_array($comparisonSign, [
|
|
|
|
|
+ '=', '>=', '<=', '<>', '!='
|
|
|
|
|
+ , 'like', 'not like'
|
|
|
|
|
+ , 'is not null', 'is null'
|
|
|
|
|
+ , 'Intersects', 'GeometryType'
|
|
|
|
|
+ ])) {
|
|
|
|
|
+ throw new Exception("Not implemented comparisonSign '{$comparisonSign}'");
|
|
|
|
|
+ }
|
|
|
|
|
+ $sqlFieldName = $fieldName; // TODO: getSqlFieldName
|
|
|
|
|
+ switch ($comparisonSign) {
|
|
|
|
|
+ case 'is not null': $this->where[] = "{$this->_fromPrefix}.{$sqlFieldName} is not null"; break;
|
|
|
|
|
+ case 'is null': $this->where[] = "{$this->_fromPrefix}.{$sqlFieldName} is null"; break;
|
|
|
|
|
+ case 'Intersects': $this->where[] = "Intersects(GeomFromText('{$value}'), {$this->_fromPrefix}.`{$sqlFieldName}`)=1"; break;
|
|
|
|
|
+ case 'GeometryType': $this->where[] = "GeometryType({$this->_fromPrefix}.`{$sqlFieldName}`)='{$value}'"; break;
|
|
|
|
|
+ default: $this->where[] = "{$this->_fromPrefix}.{$sqlFieldName} {$comparisonSign} " . DB::getPDO()->quote($value);
|
|
|
|
|
+ }
|
|
|
|
|
+ return $this;
|
|
|
|
|
+ }
|
|
|
|
|
+ public function whereIsNotNull($fieldName) {
|
|
|
|
|
+ $this->where[] = "{$this->_fromPrefix}.{$fieldName} is not null";
|
|
|
|
|
+ return $this;
|
|
|
|
|
+ }
|
|
|
|
|
+ public function whereRaw($rawWhere) {
|
|
|
|
|
+ $this->where[] = $rawWhere;
|
|
|
|
|
+ return $this;
|
|
|
|
|
+ }
|
|
|
|
|
+ // public function whereFunction($column, $operator = null, $value = null) {
|
|
|
|
|
+ public function whereFunction($fieldName, $comparisonSign = null, $value = null) {
|
|
|
|
|
+ throw new Exception("whereFunction not supported");
|
|
|
|
|
+ $this->where[] = '';
|
|
|
|
|
+ return $this;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
public function join($join, $prefix, $params) {
|
|
public function join($join, $prefix, $params) {
|
|
@@ -68,9 +100,41 @@ class AclQueryBuilder {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
public function orderBy($orderBy) { // TODO: ogc: order by ...
|
|
public function orderBy($orderBy) { // TODO: ogc: order by ...
|
|
|
-
|
|
|
|
|
|
|
+ if (null !== $this->orderBy) throw new Exception("OrderBy already set!");
|
|
|
|
|
+ $this->orderBy = [];
|
|
|
|
|
+ if (!$orderBy) return $this;
|
|
|
|
|
+ // ID A,COL_X D,COL_Y A,...
|
|
|
|
|
+ $sortByEx = array_map('trim', explode(',', $orderBy));
|
|
|
|
|
+ $sortByEx = array_filter($sortByEx, function ($part) { return !empty($part); });
|
|
|
|
|
+ foreach ($sortByEx as $sortPart) {
|
|
|
|
|
+ $sortPartEx = explode(' ', $sortPart);
|
|
|
|
|
+ if (count($sortPartEx) > 2) throw new Exception("SortBy parse error #" . __LINE__);
|
|
|
|
|
+ $fieldName = trim($sortPartEx[0]);
|
|
|
|
|
+ if (!$this->isFieldAllowedToOrderBy($fieldName)) throw new Exception("SortBy parse error for field '{$fieldName}' #" . __LINE__);
|
|
|
|
|
+ $colSortDir = 'ASC';
|
|
|
|
|
+ if (count($sortPartEx) == 2) {
|
|
|
|
|
+ if ('A' == strtoupper($sortPartEx[1]) || 'ASC' == strtoupper($sortPartEx[1])) {
|
|
|
|
|
+ } else if ('D' == strtoupper($sortPartEx[1]) || 'DESC' == strtoupper($sortPartEx[1])) {
|
|
|
|
|
+ $colSortDir = 'DESC';
|
|
|
|
|
+ } else throw new Exception("SortBy parse error - unknown sort order '{$sortPartEx[1]}' #" . __LINE__);
|
|
|
|
|
+ }
|
|
|
|
|
+ $this->orderBy[] = [$fieldName, $colSortDir];
|
|
|
|
|
+ }
|
|
|
return $this;
|
|
return $this;
|
|
|
}
|
|
}
|
|
|
|
|
+ public function isFieldAllowedToOrderBy($fieldName) {
|
|
|
|
|
+ return true;
|
|
|
|
|
+ }
|
|
|
|
|
+ public function generateOrderBySql() {
|
|
|
|
|
+ if (empty($this->orderBy)) return '';
|
|
|
|
|
+ $sortByList = [];
|
|
|
|
|
+ foreach ($this->orderBy as $orderBy) {
|
|
|
|
|
+ $sortByList[] = "t.`{$orderBy[0]}` {$orderBy[1]}";
|
|
|
|
|
+ }
|
|
|
|
|
+ return (!empty($sortByList))
|
|
|
|
|
+ ? "order by " . implode(", ", $sortByList)
|
|
|
|
|
+ : '';
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
public function limit($limit) {
|
|
public function limit($limit) {
|
|
|
$this->limit = (int)$limit;
|
|
$this->limit = (int)$limit;
|
|
@@ -104,11 +168,21 @@ class AclQueryBuilder {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
public function execute() {
|
|
public function execute() {
|
|
|
|
|
+ return $this->fetchAll();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public function fetchAll() {
|
|
|
$sql = $this->generateSql();
|
|
$sql = $this->generateSql();
|
|
|
- DBG::log((array)$this, 'array', "AclQueryBuilder");
|
|
|
|
|
|
|
+ DBG::log((array)$this, 'array', "AclQueryBuilder::fetchAll");
|
|
|
return DB::getPDO()->fetchAll($sql);
|
|
return DB::getPDO()->fetchAll($sql);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ public function fetchValue() {
|
|
|
|
|
+ $sql = $this->generateSql();
|
|
|
|
|
+ DBG::log((array)$this, 'array', "AclQueryBuilder::fetchValue");
|
|
|
|
|
+ return DB::getPDO()->fetchValue($sql);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
public function generateSql() {
|
|
public function generateSql() {
|
|
|
if (!$this->from) throw new Exception("Missing FROM");
|
|
if (!$this->from) throw new Exception("Missing FROM");
|
|
|
$tableName = $this->_getTableName($this->from);
|
|
$tableName = $this->_getTableName($this->from);
|
|
@@ -118,6 +192,7 @@ class AclQueryBuilder {
|
|
|
if ($this->from instanceof Core_AclBase) $sqlPk = $this->from->getSqlPrimaryKeyField();
|
|
if ($this->from instanceof Core_AclBase) $sqlPk = $this->from->getSqlPrimaryKeyField();
|
|
|
|
|
|
|
|
$sqlJoin = [];
|
|
$sqlJoin = [];
|
|
|
|
|
+ DBG::log($this, 'array', '$this');
|
|
|
foreach ($this->isInstances as $k => $ns) {
|
|
foreach ($this->isInstances as $k => $ns) {
|
|
|
$idInstance = ACL::getInstanceId($ns);
|
|
$idInstance = ACL::getInstanceId($ns);
|
|
|
$instanceTable = ACL::getInstanceTable($ns);
|
|
$instanceTable = ACL::getInstanceTable($ns);
|
|
@@ -172,8 +247,12 @@ class AclQueryBuilder {
|
|
|
$sqlLimit = ($limit > 0) ? "limit {$limit} offset {$offset}" : '';
|
|
$sqlLimit = ($limit > 0) ? "limit {$limit} offset {$offset}" : '';
|
|
|
|
|
|
|
|
$sqlSelect = [];
|
|
$sqlSelect = [];
|
|
|
- $sqlSelect[] = "{$this->_fromPrefix}.{$sqlPk}";
|
|
|
|
|
- if (in_array('*', $this->select)) $sqlSelect[] = "{$this->_fromPrefix}.*";
|
|
|
|
|
|
|
+ if (!empty($this->select['__rawSelect__'])) {
|
|
|
|
|
+ $sqlSelect[] = $this->select['__rawSelect__'];
|
|
|
|
|
+ } else {
|
|
|
|
|
+ $sqlSelect[] = "{$this->_fromPrefix}.{$sqlPk}";
|
|
|
|
|
+ if (in_array('*', $this->select)) $sqlSelect[] = "{$this->_fromPrefix}.*";
|
|
|
|
|
+ }
|
|
|
if (in_array('@instances', $this->select)) {
|
|
if (in_array('@instances', $this->select)) {
|
|
|
if (!($this->from instanceof Core_AclBase)) throw new Exception("select @instances allowed only for Acl object");
|
|
if (!($this->from instanceof Core_AclBase)) throw new Exception("select @instances allowed only for Acl object");
|
|
|
$instanceTable = ACL::getInstanceTable($this->from->getNamespace());
|
|
$instanceTable = ACL::getInstanceTable($this->from->getNamespace());
|
|
@@ -186,12 +265,14 @@ class AclQueryBuilder {
|
|
|
) as `@instances`
|
|
) as `@instances`
|
|
|
";
|
|
";
|
|
|
}
|
|
}
|
|
|
|
|
+ $sqlOrderBy = $this->generateOrderBySql();
|
|
|
$sqlSelect = (!empty($sqlSelect)) ? implode(", ", $sqlSelect) : "{$this->_fromPrefix}.*";
|
|
$sqlSelect = (!empty($sqlSelect)) ? implode(", ", $sqlSelect) : "{$this->_fromPrefix}.*";
|
|
|
return "
|
|
return "
|
|
|
select {$sqlSelect}
|
|
select {$sqlSelect}
|
|
|
from `{$tableName}` {$this->_fromPrefix}
|
|
from `{$tableName}` {$this->_fromPrefix}
|
|
|
{$sqlJoin}
|
|
{$sqlJoin}
|
|
|
{$sqlWhere}
|
|
{$sqlWhere}
|
|
|
|
|
+ {$sqlOrderBy}
|
|
|
{$sqlLimit}
|
|
{$sqlLimit}
|
|
|
";
|
|
";
|
|
|
}
|
|
}
|