From 2755ef709f02df141df9d3de83d4f2519cd06c04 Mon Sep 17 00:00:00 2001 From: Jonathan Miller Date: Sat, 6 Jun 2026 07:24:33 -0500 Subject: [PATCH] feat: interactive directory tree browser for exclude filters Replace plain text ExcludeList with DirectoryFilter field that provides a browsable server directory tree with checkboxes, removable pills, and manual path entry. Backward compatible storage format. Authored-by: Moko Consulting Co-Authored-By: Claude Opus 4.6 (1M context) --- src/packages/com_mokobackup/forms/profile.xml | 2 +- .../language/en-GB/com_mokobackup.ini | 5 +- .../src/Field/DirectoryFilterField.php | 259 ++++++++++++++++++ 3 files changed, 264 insertions(+), 2 deletions(-) create mode 100644 src/packages/com_mokobackup/src/Field/DirectoryFilterField.php diff --git a/src/packages/com_mokobackup/forms/profile.xml b/src/packages/com_mokobackup/forms/profile.xml index 123e01c..5c3fd2d 100644 --- a/src/packages/com_mokobackup/forms/profile.xml +++ b/src/packages/com_mokobackup/forms/profile.xml @@ -124,7 +124,7 @@
+ * @copyright Copyright (C) 2026 Moko Consulting. All rights reserved. + * @license GNU General Public License version 3 or later; see LICENSE + * + * Interactive directory tree field with checkboxes for exclude/include filtering. + * Loads the directory tree from the server via AJAX (browseDir endpoint). + */ + +namespace Joomla\Component\MokoBackup\Administrator\Field; + +defined('_JEXEC') or die; + +use Joomla\CMS\Form\FormField; +use Joomla\CMS\Language\Text; + +class DirectoryFilterField extends FormField +{ + protected $type = 'DirectoryFilter'; + + protected function getInput(): string + { + $id = htmlspecialchars($this->id, ENT_QUOTES, 'UTF-8'); + $name = htmlspecialchars($this->name, ENT_QUOTES, 'UTF-8'); + $mode = htmlspecialchars((string) ($this->element['mode'] ?? 'exclude'), ENT_QUOTES, 'UTF-8'); + + // Parse current values (newline-separated) + $items = []; + + if (!empty($this->value)) { + $items = array_values(array_filter(array_map('trim', explode("\n", str_replace("\r", '', $this->value))))); + } + + $itemsJson = json_encode($items); + $jRoot = json_encode(JPATH_ROOT); + + $labelExclude = Text::_('COM_MOKOBACKUP_FILTER_EXCLUDED'); + $labelInclude = Text::_('COM_MOKOBACKUP_FILTER_INCLUDED'); + $labelManual = Text::_('COM_MOKOBACKUP_FILTER_ADD_MANUAL'); + $addLabel = Text::_('JGLOBAL_FIELD_ADD'); + $placeholder = htmlspecialchars((string) ($this->element['hint'] ?? 'path/to/directory'), ENT_QUOTES, 'UTF-8'); + + return << + + + +
+ + +
+ + +
+ + +
+
+ + +
+
+
+ + + + + +HTML; + } +}