name : ScanalertsModel.php
<?php
/**
 * @package   admintools
 * @copyright Copyright (c)2010-2025 Nicholas K. Dionysopoulos / Akeeba Ltd
 * @license   GNU General Public License version 3, or later
 */

namespace Akeeba\Component\AdminTools\Administrator\Model;

defined('_JEXEC') or die;

use Joomla\CMS\Factory;
use Joomla\CMS\MVC\Factory\MVCFactoryInterface;
use Joomla\CMS\MVC\Model\ListModel;
use Joomla\Database\ParameterType;

#[\AllowDynamicProperties]
class ScanalertsModel extends ListModel
{
	public function __construct($config = [], MVCFactoryInterface $factory = null)
	{
		$config['filter_fields'] = $config['filter_fields'] ?? [];
		$config['filter_fields'] = $config['filter_fields'] ?: [
			'search',
			'id',
			'path',
			'scan_id',
			'diff',
			'threat_score',
			'acknowledged',
			'status',
			'newfile',
			'suspicious',
			'filestatus',
		];

		parent::__construct($config, $factory);
	}

	/**
	 * Mark all entries of the specified scan as safe.
	 *
	 * @param   int  $scan_id  The ID of the scan
	 *
	 * @since   5.2.1
	 */
	public function markAllSafe($scan_id)
	{
		$scan_id = max(0, (int) $scan_id);

		if ($scan_id == 0)
		{
			return;
		}

		$db    = $this->getDatabase();
		$query = (method_exists($db, 'createQuery') ? $db->createQuery() : $db->getQuery(true))
			->update($db->qn('#__admintools_scanalerts'))
			->set([
				$db->qn('acknowledged') . ' = ' . $db->q(1),
			])
			->where($db->qn('scan_id') . ' = ' . $db->q($scan_id))
			->where($db->qn('threat_score') . ' > ' . $db->q(0));
		$db->setQuery($query)->execute();
	}

	protected function populateState($ordering = 'path', $direction = 'asc')
	{
		$app = Factory::getApplication();

		$search = $app->getUserStateFromRequest($this->context . 'filter.search', 'filter_search', '', 'string');
		$this->setState('filter.search', $search);

		$status = $app->getUserStateFromRequest($this->context . 'filter.status', 'filter_status', '', 'string');
		$this->setState('filter.status', $status);

		$scan_id = $app->getUserStateFromRequest($this->context . 'filter.scan_id', 'filter_scan_id', '', 'string');
		$this->setState('filter.scan_id', ($scan_id === '') ? $scan_id : (int) $scan_id);

		$acknowledged = $app->getUserStateFromRequest($this->context . 'filter.acknowledged', 'filter_acknowledged', '', 'string');
		$this->setState('filter.acknowledged', ($acknowledged === '') ? $acknowledged : (int) $acknowledged);

		parent::populateState($ordering, $direction);
	}

	protected function getStoreId($id = '')
	{
		$id .= ':' . $this->getState('filter.search');
		$id .= ':' . $this->getState('filter.scan_id');
		$id .= ':' . $this->getState('filter.status');
		$id .= ':' . $this->getState('filter.acknowledged');

		return parent::getStoreId($id);
	}

	protected function getListQuery()
	{
		$db = $this->getDatabase();

		$query = (method_exists($db, 'createQuery') ? $db->createQuery() : $db->getQuery(true))
			->select([
				$db->quoteName('a.id'),
				'IF(' . $db->quoteName('diff') . ' = "" AND '.$db->quoteName('threat_score').' = 0,1,0) AS ' . $db->quoteName('newfile'),
				'IF(' . $db->quoteName('diff') . ' LIKE ' . $db->q('###SUSPICIOUS FILE###%') . ' OR (' . $db->quoteName('diff') . ' = ' . $db->quote("") . ' AND ' . $db->quoteName('threat_score') . ' > 0), 1, 0) AS ' . $db->quoteName('suspicious'),
				'IF('.$db->quoteName('diff').' = '.$db->quote("").' AND '.$db->quoteName('threat_score').' = 0, '.$db->quote('1-new').', IF('.$db->quoteName('diff').' LIKE '.$db->quote('###SUSPICIOUS FILE###%').' OR ('.$db->quoteName('diff').' = '.$db->quote('').' AND '.$db->quoteName('threat_score').' > 0), '.$db->quote('0-suspicious').', '.$db->quote('2-modified').')) AS ' . $db->quoteName('filestatus'),

				'CASE WHEN ' . $db->quoteName('threat_score') . ' = 0 THEN ' . $db->quote('none') .
				'WHEN ' . $db->quoteName('threat_score') . ' < 10 THEN ' . $db->quote('low') .
				'WHEN ' . $db->quoteName('threat_score') . ' < 100 THEN ' . $db->quote('medium') .
				'ELSE ' . $db->quote('high') . ' END AS ' . $db->quoteName('threatindex'),
				$db->qn('path'),
				$db->qn('threat_score'),
				$db->qn('acknowledged'),
				$db->qn('scan_id'),
				$db->qn('s.scanstart', 'scandate'),
			])
			->from($db->quoteName('#__admintools_scanalerts', 'a'))
			->join('inner', $db->quoteName('#__admintools_scans', 's'),
				$db->quoteName('s.id') . ' = ' . $db->quoteName('a.scan_id')
			);

		$search = $this->getState('filter.search');

		if (!empty($search))
		{
			if (substr($search, 0, 3) === 'id:')
			{
				$id = (int) substr($search, 3);

				$query->where($db->quoteName('id') . ' = :id')
					->bind(':id', $id, ParameterType::INTEGER);
			}
			else
			{
				$search = '%' . $search . '%';

				$query->where($db->quoteName('path') . ' LIKE :search')
					->bind(':search', $search, ParameterType::STRING);
			}
		}

		$scan_id = $this->getState('filter.scan_id');

		if (is_numeric($scan_id))
		{
			$scan_id = (int) $scan_id;

			$query->where($db->quoteName('scan_id') . ' = :scan_id')
				->bind(':scan_id', $scan_id);
		}

		$status = $this->getState('filter.status');

		switch ($status)
		{
			case 'new':
				$query->where('IF(' . $db->qn('diff') . ' != "",0,1) = ' . $db->q(1));
				break;

			case 'suspicious':
				$query->where('IF(' . $db->qn('diff') . ' LIKE "###SUSPICIOUS FILE###%",1,0)  = ' . $db->q(1));
				break;

			case 'modified':
				$query->where('IF(' . $db->qn('diff') . ' != "",0,1) = ' . $db->q(0));
				$query->where('IF(' . $db->qn('diff') . ' LIKE "###SUSPICIOUS FILE###%",1,0)  = ' . $db->q(0));
				break;
		}

		$acknowledged = $this->getState('filter.acknowledged');

		if (is_numeric($acknowledged))
		{
			$acknowledged = (int) $acknowledged;

			$query->where($db->quoteName('acknowledged') . ' = :acknowledged')
				->bind(':acknowledged', $acknowledged, ParameterType::INTEGER);
		}

		// List ordering clause
		$orderCol  = $this->state->get('list.ordering', 'path');
		$orderDirn = $this->state->get('list.direction', 'asc');
		$ordering  = $db->escape($orderCol) . ' ' . $db->escape($orderDirn);

		$query->order($ordering);

		return $query;
	}
}

© 2025 Cubjrnet7