phplib/REST/Dashboard.php

Summary

Maintainability
A
3 hrs
Test Coverage
<?php

namespace FOO;

/**
 * Class Dashboard_REST
 * REST endpoint for dashboard data.
 * @package FOO
 */
class Dashboard_REST extends REST {
    const RANGE = 15;

    public function GET(array $get) {
        $data = [];
        $meta = new DBMeta;
        $cfg = new DBConfig;
        $client = new ESClient;

        $dates = $this->dateRange(-self::RANGE);

        // Get a count of how many Searches are failing.
        $sql = sprintf('SELECT COUNT(*) FROM `%s` WHERE `site_id` = ? AND `archived` = 0 AND `enabled` = ? AND `last_execution_date` = `last_failure_date` AND `last_execution_date` > 0',
            Search::$TABLE
        );
        $data['failing_searches'] = (int)DB::query($sql, [SiteFinder::getCurrentId(), true], DB::VAL);

        // Get a count of active Alerts and their priorities.
        $data['active_alerts'] = $client->getActiveAlertCounts();

        // Generate data for an Alert creation histogram.
        $data['historical_alerts'] = $client->getAlertActivityCounts(self::RANGE);

        // Generate data for an Alert action histogram.
        if (DB::getType() == 'mysql') {
            $sql = sprintf('
            SELECT DATE_FORMAT(FROM_UNIXTIME(create_date), "%%Y-%%m-%%d") as `date`, `action`, COUNT(*) as `count` FROM `%s` INNER JOIN (
                SELECT DATE_FORMAT(FROM_UNIXTIME(create_date), "%%Y-%%m-%%d"), `alert_id`, MAX(`create_date`) as `create_date`
                FROM `%s` WHERE `site_id` = ? AND `archived` = 0 AND (
                    (`action` = ? AND `a` = 1) OR
                    (`action` = ? AND (`a` != 0 OR `b` != 0)) OR
                    (`action` = ? AND `a` = 2)
                ) AND `create_date` > ? AND DATE_FORMAT(FROM_UNIXTIME(create_date), "%%Y-%%m-%%d") > DATE_FORMAT(FROM_UNIXTIME(?), "%%Y-%%m-%%d") GROUP BY 1, 2
            ) AS `tbl` USING(`alert_id`, `create_date`) GROUP BY 1, 2;
            ', AlertLog::$TABLE, AlertLog::$TABLE);
        } else {
              $sql = sprintf('
              SELECT DATE(create_date, "unixepoch") as `date`, `action`, COUNT(*) as `count` FROM `%s` INNER JOIN (
                  SELECT DATE(create_date, "unixepoch"), `alert_id`, MAX(`create_date`) as `create_date`
                  FROM `%s` WHERE `site_id` = ? AND `archived` = 0 AND (
                      (`action` = ? AND `a` = 1) OR
                      (`action` = ? AND (`a` != 0 OR `b` != 0)) OR
                      (`action` = ? AND `a` = 2)
                  ) AND `create_date` > ? AND DATE(create_date, "unixepoch") > DATE(?, "unixepoch") GROUP BY 1, 2
              ) AS `tbl` USING(`alert_id`, `create_date`) GROUP BY 1, 2;
              ', AlertLog::$TABLE, AlertLog::$TABLE);
        }
        $ret = DB::query($sql, [
            SiteFinder::getCurrentId(),
            AlertLog::A_ESCALATE,
            AlertLog::A_ASSIGN,
            AlertLog::A_SWITCH,
            strtotime(sprintf('now -%d days', self::RANGE + 1)), strtotime(sprintf('now -%d days', self::RANGE))
        ]);
        $groups = [[], [], []];
        foreach($ret as $row) {
            switch($row['action']) {
                case AlertLog::A_ESCALATE:
                    $groups[0][] = $row;
                    break;
                case AlertLog::A_ASSIGN: // Assign
                    $groups[1][] = $row;
                    break;
                case AlertLog::A_SWITCH:
                    $groups[2][] = $row;
                    break;
            }
        }
        $func = function($data) {
            return [$data['date'], Util::get($data, 'count', 0)];
        };
        $data['historical_actions'] = [
            $this->fillDates($groups[0], $dates, $func),
            $this->fillDates($groups[1], $dates, $func),
            $this->fillDates($groups[2], $dates, $func),
        ];

        // Cron hasn't run in more than 20 minutes.
        $data['no_recent_cron'] = (int) $meta['last_cron_date'] < ($_SERVER['REQUEST_TIME'] - 20 * 60);

        $data['announcement'] = $cfg['announcement'] ?? '';

        return self::format($data);
    }

    private function dateRange($delta) {
        $start = $delta > 0 ? 0:$delta;
        $end = $delta > 0 ? $delta:0;
        return array_map(function($x) { return date('Y-m-d', strtotime("now $x days")); }, range($start, $end));
    }

    private function fillDates($data, $range, $func) {
        $i = 0;
        $ret = [];
        foreach($range as $date) {
            if($i < count($data) && $data[$i]['date'] == $date) {
                $ret[] = $func($data[$i]);
                ++$i;
            } else {
                $ret[] = $func(['date' => $date]);
            }
        }

        return $ret;
    }
}