6f7549fa7a
Joomla: Extension CI / Release Readiness Check (pull_request) Failing after 10s
Universal: Auto Version Bump / Version Bump (push) Successful in 15s
Universal: Secret Scanning / Gitleaks Secret Scan (pull_request) Successful in 15s
Universal: PR Check / Branch Policy (pull_request) Successful in 3s
Universal: PR Check / Validate PR (pull_request) Failing after 7s
Universal: Pre-Release / Build Pre-Release (${{ inputs.stability || github.ref_name }}) (push) Successful in 29s
Generic: Project CI / Lint & Validate (pull_request) Successful in 51s
Platform: moko-platform CI / Gate 1: Code Quality (push) Failing after 52s
Generic: Repo Health / Site Health (pull_request) Has been skipped
Joomla: Extension CI / Lint & Validate (pull_request) Failing after 52s
Generic: Repo Health / Access control (pull_request) Successful in 1s
Platform: moko-platform CI / Gate 1: Code Quality (pull_request) Failing after 1m1s
Joomla: Metadata Validation / Validate Joomla Metadata (pull_request) Successful in 41s
Platform: moko-platform CI / Gate 2: Unit Tests (8.1) (push) Has been cancelled
Platform: moko-platform CI / Gate 2: Unit Tests (8.2) (push) Has been cancelled
Platform: moko-platform CI / Gate 2: Unit Tests (8.3) (push) Has been cancelled
Platform: moko-platform CI / Gate 3: Self-Health Check (push) Has been cancelled
Platform: moko-platform CI / Gate 4: Governance (push) Has been cancelled
Platform: moko-platform CI / Gate 5: Template Integrity (push) Has been cancelled
Platform: moko-platform CI / CI Summary (push) Has been cancelled
Generic: Project CI / Tests (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.2) (pull_request) Has been cancelled
Joomla: Extension CI / Tests (PHP 8.3) (pull_request) Has been cancelled
Joomla: Extension CI / PHPStan Analysis (pull_request) Has been cancelled
Joomla: Extension CI / Build RC Pre-Release (pull_request) Has been cancelled
Platform: moko-platform CI / Gate 2: Unit Tests (8.1) (pull_request) Has been cancelled
Platform: moko-platform CI / Gate 2: Unit Tests (8.2) (pull_request) Has been cancelled
Platform: moko-platform CI / Gate 2: Unit Tests (8.3) (pull_request) Has been cancelled
Platform: moko-platform CI / Gate 3: Self-Health Check (pull_request) Has been cancelled
Platform: moko-platform CI / Gate 4: Governance (pull_request) Has been cancelled
Platform: moko-platform CI / Gate 5: Template Integrity (pull_request) Has been cancelled
Platform: moko-platform CI / CI Summary (pull_request) Has been cancelled
Universal: PR Check / Build RC Package (pull_request) Has been cancelled
Universal: PR Check / Report Issues (pull_request) Has been cancelled
Generic: Repo Health / Scripts governance (pull_request) Has been cancelled
Generic: Repo Health / Repository health (pull_request) Has been cancelled
Generic: Repo Health / Report Issues (pull_request) Has been cancelled
- togglePlugin: restrict scope to mokosuiteclient plugins only (was any plugin) - DevTools: replace full-table hits reset on every request with config toggle - CurrentIpField: prefer REMOTE_ADDR over spoofable X-Forwarded-For - SQL: explicit (int) cast on $days interpolation in chart queries - Heartbeat: enable SSL peer verification (was disabled) - script.php: remove orphaned docblock
195 lines
4.9 KiB
PHP
195 lines
4.9 KiB
PHP
<?php
|
|
/**
|
|
* @package MokoSuiteClient
|
|
* @subpackage plg_system_mokosuiteclient_devtools
|
|
* @copyright Copyright (C) 2026 Moko Consulting. All rights reserved.
|
|
* @license GNU General Public License version 3 or later; see LICENSE
|
|
*/
|
|
|
|
namespace Moko\Plugin\System\MokoSuiteClientDevTools\Extension;
|
|
|
|
defined('_JEXEC') or die;
|
|
|
|
use Joomla\CMS\Factory;
|
|
use Joomla\CMS\Log\Log;
|
|
use Joomla\CMS\Plugin\CMSPlugin;
|
|
use Joomla\Event\SubscriberInterface;
|
|
|
|
/**
|
|
* MokoSuiteClient Developer Tools Plugin
|
|
*
|
|
* Provides development mode (disables caching, enables debug), hit counter
|
|
* reset, and content version cleanup.
|
|
*
|
|
* @since 02.32.00
|
|
*/
|
|
class DevTools extends CMSPlugin implements SubscriberInterface
|
|
{
|
|
protected $autoloadLanguage = true;
|
|
|
|
public static function getSubscribedEvents(): array
|
|
{
|
|
return [
|
|
'onAfterInitialise' => 'onAfterInitialise',
|
|
'onExtensionAfterSave' => 'onExtensionAfterSave',
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Apply dev mode settings at runtime.
|
|
*/
|
|
public function onAfterInitialise(): void
|
|
{
|
|
if (!$this->params->get('dev_mode', 0))
|
|
{
|
|
return;
|
|
}
|
|
|
|
$config = Factory::getConfig();
|
|
$config->set('caching', 0);
|
|
$config->set('debug', 1);
|
|
|
|
// Show offline page on primary domain
|
|
$primaryDomain = $this->params->get('primary_domain', '');
|
|
$currentHost = $_SERVER['HTTP_HOST'] ?? '';
|
|
|
|
if (!empty($primaryDomain) && $currentHost === $primaryDomain)
|
|
{
|
|
$config->set('offline', 1);
|
|
}
|
|
|
|
// Suppress hit recording by disabling the content hit counter
|
|
$config->set('record_hits', 0);
|
|
}
|
|
|
|
/**
|
|
* Handle maintenance actions when this plugin's params are saved.
|
|
*/
|
|
public function onExtensionAfterSave($event): void
|
|
{
|
|
// Joomla 6: single event object; Joomla 5: individual args
|
|
if (is_object($event) && method_exists($event, 'getArgument'))
|
|
{
|
|
$context = $event->getArgument('context', $event->getArgument(0, ''));
|
|
$table = $event->getArgument('subject', $event->getArgument(1, null));
|
|
}
|
|
else
|
|
{
|
|
$context = $event;
|
|
$table = func_get_arg(1);
|
|
}
|
|
|
|
if ($context !== 'com_plugins.plugin' || !$table)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Only process saves to this plugin
|
|
if (($table->element ?? '') !== 'mokosuiteclient_devtools' || ($table->folder ?? '') !== 'system')
|
|
{
|
|
return;
|
|
}
|
|
|
|
$params = new \Joomla\Registry\Registry($table->params ?? '{}');
|
|
|
|
// Reset hits on save if toggled on
|
|
if ($params->get('reset_hits', 0))
|
|
{
|
|
$this->resetAllHits();
|
|
$params->set('reset_hits', 0);
|
|
}
|
|
|
|
// Delete versions on save if toggled on
|
|
if ($params->get('delete_versions', 0))
|
|
{
|
|
$this->deleteAllVersions();
|
|
$params->set('delete_versions', 0);
|
|
}
|
|
|
|
// Reset download keys on save if toggled on
|
|
if ($params->get('reset_download_keys', 0))
|
|
{
|
|
$this->resetDownloadKeys();
|
|
$params->set('reset_download_keys', 0);
|
|
}
|
|
|
|
// Reset the one-shot toggles
|
|
if ($table->params !== $params->toString())
|
|
{
|
|
$db = Factory::getDbo();
|
|
$db->setQuery(
|
|
$db->getQuery(true)
|
|
->update($db->quoteName('#__extensions'))
|
|
->set($db->quoteName('params') . ' = ' . $db->quote($params->toString()))
|
|
->where($db->quoteName('extension_id') . ' = ' . (int) $table->extension_id)
|
|
)->execute();
|
|
}
|
|
}
|
|
|
|
private function resetAllHits(): int
|
|
{
|
|
$db = Factory::getDbo();
|
|
$db->setQuery(
|
|
$db->getQuery(true)
|
|
->update($db->quoteName('#__content'))
|
|
->set($db->quoteName('hits') . ' = 0')
|
|
->where($db->quoteName('hits') . ' > 0')
|
|
)->execute();
|
|
|
|
$count = $db->getAffectedRows();
|
|
$this->getApplication()->enqueueMessage(\sprintf('Reset hits on %d articles.', $count), 'message');
|
|
|
|
return $count;
|
|
}
|
|
|
|
private function deleteAllVersions(): int
|
|
{
|
|
$db = Factory::getDbo();
|
|
$db->setQuery(
|
|
$db->getQuery(true)->delete($db->quoteName('#__history'))
|
|
)->execute();
|
|
|
|
$count = $db->getAffectedRows();
|
|
$this->getApplication()->enqueueMessage(\sprintf('Deleted %d version history records.', $count), 'message');
|
|
|
|
return $count;
|
|
}
|
|
|
|
private function resetDownloadKeys(): int
|
|
{
|
|
$db = Factory::getDbo();
|
|
|
|
// Find update sites that have a dlid in extra_query
|
|
$db->setQuery(
|
|
$db->getQuery(true)
|
|
->select([$db->quoteName('update_site_id'), $db->quoteName('extra_query')])
|
|
->from($db->quoteName('#__update_sites'))
|
|
->where($db->quoteName('extra_query') . ' LIKE ' . $db->quote('%dlid=%'))
|
|
);
|
|
|
|
$sites = $db->loadObjectList();
|
|
$count = 0;
|
|
|
|
foreach ($sites as $site)
|
|
{
|
|
// Parse the query string, remove dlid, rebuild
|
|
parse_str($site->extra_query, $parsed);
|
|
unset($parsed['dlid']);
|
|
$newQuery = http_build_query($parsed);
|
|
|
|
$db->setQuery(
|
|
$db->getQuery(true)
|
|
->update($db->quoteName('#__update_sites'))
|
|
->set($db->quoteName('extra_query') . ' = ' . $db->quote($newQuery))
|
|
->where($db->quoteName('update_site_id') . ' = ' . (int) $site->update_site_id)
|
|
)->execute();
|
|
|
|
$count++;
|
|
}
|
|
|
|
$this->getApplication()->enqueueMessage(\sprintf('Cleared download keys from %d update sites.', $count), 'message');
|
|
|
|
return $count;
|
|
}
|
|
}
|