From: Marcin Haba Date: Mon, 26 Jun 2023 07:23:30 +0000 (+0200) Subject: baculum: Add second dimension of sorting in jobs objects endpoint X-Git-Tag: Release-13.0.4~58 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d4cf1b1aafe2c3872ee961d2804e41fb35f4d26c;p=thirdparty%2Fbacula.git baculum: Add second dimension of sorting in jobs objects endpoint --- diff --git a/gui/baculum/protected/API/Modules/Database.php b/gui/baculum/protected/API/Modules/Database.php index 322a6eac0..a8176d996 100644 --- a/gui/baculum/protected/API/Modules/Database.php +++ b/gui/baculum/protected/API/Modules/Database.php @@ -25,6 +25,7 @@ namespace Baculum\API\Modules; use Baculum\Common\Modules\Logging; use Baculum\Common\Modules\Errors\DatabaseError; use Baculum\API\Modules\JobRecord; +use Prado\Prado; use Prado\Data\TDbConnection; use Prado\Exceptions\TDbException; @@ -373,5 +374,32 @@ class Database extends APIModule { } return $statement; } + + /** + * Get SQL order clause. + * + * @param array $order order by and order direction in form [[by1, direction1], [by2, direction2]...etc.] + * @param boolean $with_clause return with 'ORDER BY' clause + * @return string SQL order clause with values or empty string if no order criteria given + */ + public static function getOrder(array $order, $with_clause = true) { + $odr_str = ''; + $odr = []; + // Prepare order_by and order_direction values + $db_params = Prado::getApplication()->getModule('api_config')->getConfig('db'); + for ($i = 0; $i < count($order); $i++) { + list($order_by, $order_direction) = $order[$i]; + if ($db_params['type'] === self::PGSQL_TYPE) { + $order_by = strtolower($order_by); + } + $sorder = strtoupper($order_direction); + $odr[] = sprintf('%s %s', $order_by, $sorder); + } + if (count($odr) > 0) { + $ob = $with_clause ? ' ORDER BY ' : ''; + $odr_str = $ob . implode(',', $odr); + } + return $odr_str; + } } ?> diff --git a/gui/baculum/protected/API/Modules/JobManager.php b/gui/baculum/protected/API/Modules/JobManager.php index 0ffa03f49..57cf3c8d6 100644 --- a/gui/baculum/protected/API/Modules/JobManager.php +++ b/gui/baculum/protected/API/Modules/JobManager.php @@ -193,10 +193,11 @@ LEFT JOIN FileSet USING (FilesetId)' * @param array $criteria SQL criteria to get job list * @param mixed $limit_val result limit value * @param int $offset_val result offset value + * @param array $sort order by and order direction in form [[by1, direction1], [by2, direction2]...etc.] * @param string $view job records view (basic, full) * @return array job record list with objects or empty list if no job found */ - public function getJobsObjectsOverview($criteria = array(), $limit_val = null, $offset_val = 0, $sort_col = 'EndTime', $sort_order = 'DESC', $view = self::JOB_RESULT_VIEW_FULL) { + public function getJobsObjectsOverview($criteria = array(), $limit_val = null, $offset_val = 0, $sort = [['EndTime', 'DESC']], $view = self::JOB_RESULT_VIEW_FULL) { $connection = JobRecord::finder()->getDbConnection(); $connection->setActive(true); @@ -207,17 +208,19 @@ LEFT JOIN FileSet USING (FilesetId)' // start transaction $pdo->beginTransaction(); - // Prepare order_by and order_direction values - $db_params = $this->getModule('api_config')->getConfig('db'); - if ($db_params['type'] === Database::PGSQL_TYPE) { - $sort_col = strtolower($sort_col); - } - $sorder = strtoupper($sort_order); - $order = ' ORDER BY ' . $sort_col . ' ' . $sorder; + $sort_copy = $sort; + for ($i = 0, $j = 0; $i < count($sort); $i++, $j++) { + if (strcasecmp($sort[$i][0], 'jobstatus') == 0) { + // if one from sorting condition is jobstatus, add sorting by joberrors as next element + array_splice($sort_copy, ($j+1), 0, [['joberrors', $sort_copy[$j][1]]]); - if ($sort_col == 'jobstatus') { - $order .= ',joberrors ' . $sorder; + // take into account $sort_copy counter + $j++; + } } + $sort = $sort_copy; + + $order = Database::getOrder($sort); // create temporary table $jobid_jobstatus_tname = 'jobid_jobstatus_' . getmypid(); diff --git a/gui/baculum/protected/API/Pages/API/JobsObjects.php b/gui/baculum/protected/API/Pages/API/JobsObjects.php index 038707e7a..de42ad52e 100644 --- a/gui/baculum/protected/API/Pages/API/JobsObjects.php +++ b/gui/baculum/protected/API/Pages/API/JobsObjects.php @@ -84,18 +84,37 @@ class JobsObjects extends BaculumAPIServer { $age = $this->Request->contains('age') && $misc->isValidInteger($this->Request['age']) ? (int)$this->Request['age'] : null; $order_by = $this->Request->contains('order_by') && $misc->isValidColumn($this->Request['order_by']) ? $this->Request['order_by']: 'EndTime'; $order_direction = $this->Request->contains('order_direction') && $misc->isValidOrderDirection($this->Request['order_direction']) ? $this->Request['order_direction']: 'DESC'; + $sec_order_by = $this->Request->contains('sec_order_by') && $misc->isValidColumn($this->Request['sec_order_by']) ? $this->Request['sec_order_by']: 'name'; + $sec_order_direction = $this->Request->contains('sec_order_direction') && $misc->isValidOrderDirection($this->Request['sec_order_direction']) ? $this->Request['sec_order_direction']: 'ASC'; + $order = [ + [ + $order_by, + $order_direction + ], + [ + $sec_order_by, + $sec_order_direction + ] + ]; + $view = ($this->Request->contains('view') && $misc->isValidResultView($this->Request['view'])) ? $this->Request['view'] : JobManager::JOB_RESULT_VIEW_FULL; $jr = new \ReflectionClass('Baculum\API\Modules\JobRecord'); $sort_cols = $jr->getProperties(); - $order_by_lc = strtolower($order_by); $columns = []; foreach ($sort_cols as $cols) { - $name = $cols->getName(); - $columns[] = $name; + $columns[] = $cols->getName(); } - if (!in_array($order_by_lc, $columns)) { - $this->output = JobError::MSG_ERROR_INVALID_PROPERTY; + $col_err = null; + for ($i = 0; $i < count($order); $i++) { + $order_by_lc = strtolower($order[$i][0]); + if (!in_array($order_by_lc, $columns)) { + $col_err = $order[$i][0]; + break; + } + } + if ($col_err) { + $this->output = JobError::MSG_ERROR_INVALID_PROPERTY . ' Prop=>' . $col_err; $this->error = JobError::ERROR_INVALID_PROPERTY; return; } @@ -129,8 +148,7 @@ class JobsObjects extends BaculumAPIServer { $params, null, 0, - $order_by, - $order_direction, + $order, $view ); $this->output = $result; @@ -480,8 +498,7 @@ class JobsObjects extends BaculumAPIServer { $params, $limit, $offset, - $order_by, - $order_direction, + $order, $view ); $this->output = $result; diff --git a/gui/baculum/protected/API/openapi_baculum.json b/gui/baculum/protected/API/openapi_baculum.json index 5aa8eb8f5..938299651 100644 --- a/gui/baculum/protected/API/openapi_baculum.json +++ b/gui/baculum/protected/API/openapi_baculum.json @@ -2387,6 +2387,25 @@ "enum": ["asc", "desc"] } }, + { + "name": "sec_order_by", + "in": "query", + "required": false, + "description": "Second dimension sort by selected job property (default 'name'). There can be any job property (jobid, job, clientid ...etc.)", + "schema": { + "type": "string" + } + }, + { + "name": "sec_order_direction", + "in": "query", + "required": false, + "description": "Direction for second dimension of sorting. It can be 'asc' (ascending order) or 'desc' (ascending order - default)", + "schema": { + "type": "string", + "enum": ["asc", "desc"] + } + }, { "name": "view", "in": "query",