Commit bae2036f authored by Marcin Haba's avatar Marcin Haba
Browse files

baculum: Add group_limit, order_by and order_direction parameters to objects endpoint

parent 9f3421aa
......@@ -213,5 +213,33 @@ class Database extends APIModule {
}
return array('where' => $where, 'params' => $parameters);
}
/**
* Group database records by specific column.
*
* @param string $group_by column to use as group
* @param array $result database results/records (please note - reference)
* @param integer $group_limit group limit (zero means no limit)
*/
public static function groupBy($group_by, &$result, $group_limit = 0) {
if (is_string($group_by) && is_array($result)) {
// Group results
$new_result = [];
for ($i = 0; $i < count($result); $i++) {
if (!property_exists($result[$i], $group_by)) {
continue;
}
if (!key_exists($result[$i]->{$group_by}, $new_result)) {
$new_result[$result[$i]->{$group_by}] = [];
}
if ($group_limit > 0 && count($new_result[$result[$i]->{$group_by}]) >= $group_limit) {
// limit per group reached
continue;
}
$new_result[$result[$i]->{$group_by}][] = $result[$i];
}
$result = $new_result;
}
}
}
?>
......@@ -29,18 +29,36 @@ namespace Baculum\API\Modules;
* @category Module
* @package Baculum API
*/
class ObjectManager extends APIModule {
class ObjectManager extends APIModule
{
public function getObjects($criteria = array(), $limit_val = null, $groupby = null) {
$sort_col = 'ObjectId';
/**
* Get objects.
*
* @param array $criteria criteria in nested array format (@see Databaes::getWhere)
* @param integer $limit_val maximum number of elements to return
* @param string $sort_col column to sort
* @param string $sort_order sort order (asc - ascending, desc - descending)
* @param string $group_by column to group
* @param integer $group_limit maximum number of elements in one group
* @return array object list
*/
public function getObjects($criteria = array(), $limit_val = null, $sort_col = 'ObjectId', $sort_order = 'DESC', $group_by = null, $group_limit = 0) {
$db_params = $this->getModule('api_config')->getConfig('db');
if ($db_params['type'] === Database::PGSQL_TYPE) {
$sort_col = strtolower($sort_col);
}
$order = ' ORDER BY ' . $sort_col . ' DESC';
$order = sprintf(
' ORDER BY %s %s',
$sort_col,
$sort_order
);
$limit = '';
if(is_int($limit_val) && $limit_val > 0) {
$limit = ' LIMIT ' . $limit_val;
$limit = sprintf(
' LIMIT %s',
$limit_val
);
}
$where = Database::getWhere($criteria);
......@@ -52,20 +70,7 @@ LEFT JOIN Job USING (JobId) '
. $where['where'] . $order . $limit;
$result = ObjectRecord::finder()->findAllBySql($sql, $where['params']);
if (is_string($groupby) && is_array($result)) {
// Group results
$new_result = [];
for ($i = 0; $i < count($result); $i++) {
if (!property_exists($result[$i], $groupby)) {
continue;
}
if (!key_exists($result[$i]->{$groupby}, $new_result)) {
$new_result[$result[$i]->{$groupby}] = [];
}
$new_result[$result[$i]->{$groupby}][] = $result[$i];
}
$result = $new_result;
}
Database::groupBy($group_by, $result, $group_limit);
return $result;
}
......
......@@ -238,8 +238,13 @@ class Jobs extends BaculumAPIServer {
}
if ($error === false) {
$jobs = $this->getModule('job')->getJobs($params, $limit, $order_by, $order_direction);
$this->output = $jobs;
$result = $this->getModule('job')->getJobs(
$params,
$limit,
$order_by,
$order_direction
);
$this->output = $result;
$this->error = JobError::ERROR_NO_ERRORS;
}
} else {
......
......@@ -43,7 +43,8 @@ class Objects extends BaculumAPIServer {
$objectstatus = $this->Request->contains('objectstatus') && $misc->isValidState($this->Request['objectstatus']) ? $this->Request['objectstatus'] : null;
$jobname = $this->Request->contains('jobname') && $misc->isValidName($this->Request['jobname']) ? $this->Request['jobname'] : null;
$jobids = $this->Request->contains('jobids') && $misc->isValidIdsList($this->Request['jobids']) ? explode(',', $this->Request['jobids']) : [];
$groupby = $this->Request->contains('groupby') && $misc->isValidColumn($this->Request['groupby']) ? strtolower($this->Request['groupby']) : null;
$group_by = $this->Request->contains('groupby') && $misc->isValidColumn($this->Request['groupby']) ? strtolower($this->Request['groupby']) : null;
$group_limit = $this->Request->contains('group_limit') ? intval($this->Request['group_limit']) : 0;
$schedtime_from = $this->Request->contains('schedtime_from') && $misc->isValidInteger($this->Request['schedtime_from']) ? (int)$this->Request['schedtime_from'] : null;
$schedtime_to = $this->Request->contains('schedtime_to') && $misc->isValidInteger($this->Request['schedtime_to']) ? (int)$this->Request['schedtime_to'] : null;
$starttime_from = $this->Request->contains('starttime_from') && $misc->isValidInteger($this->Request['starttime_from']) ? (int)$this->Request['starttime_from'] : null;
......@@ -52,14 +53,16 @@ class Objects extends BaculumAPIServer {
$endtime_to = $this->Request->contains('endtime_to') && $misc->isValidInteger($this->Request['endtime_to']) ? (int)$this->Request['endtime_to'] : null;
$realendtime_from = $this->Request->contains('realendtime_from') && $misc->isValidInteger($this->Request['realendtime_from']) ? (int)$this->Request['realendtime_from'] : null;
$realendtime_to = $this->Request->contains('realendtime_to') && $misc->isValidInteger($this->Request['realendtime_to']) ? (int)$this->Request['realendtime_to'] : null;
$order_by = $this->Request->contains('order_by') && $misc->isValidColumn($this->Request['order_by']) ? $this->Request['order_by']: 'ObjectId';
$order_direction = $this->Request->contains('order_direction') && $misc->isValidOrderDirection($this->Request['order_direction']) ? $this->Request['order_direction']: 'DESC';
if (is_string($groupby)) {
$or = new \ReflectionClass('Baculum\API\Modules\ObjectRecord');
$group_cols = $or->getProperties();
$cols_excl = ['jobname'];
$or = new \ReflectionClass('Baculum\API\Modules\ObjectRecord');
$prop_cols = $or->getProperties();
$cols_excl = ['jobname'];
$columns = [];
if (is_string($group_by)) {
$columns = [];
foreach ($group_cols as $cols) {
foreach ($prop_cols as $cols) {
$name = $cols->getName();
// skip columns not existing in the catalog
if (in_array($name, $cols_excl)) {
......@@ -68,13 +71,30 @@ class Objects extends BaculumAPIServer {
$columns[] = $name;
}
if (!in_array($groupby, $columns)) {
if (!in_array($group_by, $columns)) {
$this->output = ObjectError::MSG_ERROR_INVALID_PROPERTY;
$this->error = ObjectError::ERROR_INVALID_PROPERTY;
return;
}
}
$order_by_lc = strtolower($order_by);
$columns = [];
foreach ($prop_cols as $cols) {
$name = $cols->getName();
// skip columns not existing in the catalog
if (in_array($name, $cols_excl)) {
continue;
}
$columns[] = $name;
}
if (!in_array($order_by_lc, $columns)) {
$this->output = ObjectError::MSG_ERROR_INVALID_PROPERTY;
$this->error = ObjectError::ERROR_INVALID_PROPERTY;
return;
}
$params = [];
if (!empty($objecttype)) {
$params['Object.ObjectType'] = [];
......@@ -194,7 +214,14 @@ class Objects extends BaculumAPIServer {
}
}
$objects = $this->getModule('object')->getObjects($params, $limit, $groupby);
$objects = $this->getModule('object')->getObjects(
$params,
$limit,
$order_by_lc,
$order_direction,
$group_by,
$group_limit
);
$this->output = $objects;
$this->error = ObjectError::ERROR_NO_ERRORS;
}
......
......@@ -6503,6 +6503,34 @@
"type": "string"
}
},
{
"name": "group_limit",
"in": "query",
"required": false,
"description": "Maximum number elements per group.",
"schema": {
"type": "string"
}
},
{
"name": "order_by",
"in": "query",
"required": false,
"description": "Sort by selected object property (default objectid). There can be any object property (objectid, objectname, objectsource ...etc.) except jobname.",
"schema": {
"type": "string"
}
},
{
"name": "order_direction",
"in": "query",
"required": false,
"description": "Order direction. It can be 'asc' (ascending order) or 'desc' (descending order - default)",
"schema": {
"type": "string",
"enum": ["asc", "desc"]
}
},
{
"name": "schedtime_from",
"in": "query",
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment