]> git.ipfire.org Git - thirdparty/bacula.git/commitdiff
baculum: Add second dimension of sorting in jobs objects endpoint
authorMarcin Haba <marcin.haba@bacula.pl>
Mon, 26 Jun 2023 07:23:30 +0000 (09:23 +0200)
committerMarcin Haba <marcin.haba@bacula.pl>
Mon, 3 Jul 2023 08:46:57 +0000 (10:46 +0200)
gui/baculum/protected/API/Modules/Database.php
gui/baculum/protected/API/Modules/JobManager.php
gui/baculum/protected/API/Pages/API/JobsObjects.php
gui/baculum/protected/API/openapi_baculum.json

index 322a6eac045ce2a05fe8304e7d085d7ff6823f93..a8176d996e60f0dcbb3e5bff26f7920e0228efc5 100644 (file)
@@ -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;
+       }
 }
 ?>
index 0ffa03f49a34ef65d9e4cfbf4bbd9bccfeb1806e..57cf3c8d6437cd9792d43bb13f841482c069497d 100644 (file)
@@ -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();
index 038707e7a8262961384fb9a9b67d0eaf57c53d18..de42ad52e9433ef83be81960fa12d186a729c6d4 100644 (file)
@@ -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;
index 5aa8eb8f5ad9c1a6f2891fd29e3842e9967970f3..9382996515063ad8f478dd122413ab5a35bccdc8 100644 (file)
                                                        "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",