ace33b60fe
Generic: Repo Health / Site Health (push) Has been skipped
Generic: Repo Health / Access control (push) Successful in 2s
Universal: Auto Version Bump / Version Bump (push) Successful in 10s
Generic: Repo Health / Scripts governance (push) Has been cancelled
Generic: Repo Health / Repository health (push) Has been cancelled
Generic: Repo Health / Report Issues (push) Has been cancelled
Renames all sub-extensions from mokojoombackup to mokosuitebackup
(package, component, 7 plugins, language files, manifests).
Adds [HOME] placeholder to BackupDirectory and PlaceholderResolver
so users can set backup_dir to [HOME]/backups (outside web root).
Fixes folder browser "access denied" on PHP-FPM shared hosting
where getenv('HOME') returns empty by adding POSIX and JPATH_ROOT
fallback detection.
126 lines
4.6 KiB
PHP
126 lines
4.6 KiB
PHP
<?php
|
|
|
|
/**
|
|
* @package MokoSuiteBackup
|
|
* @subpackage com_mokosuitebackup
|
|
* @author Moko Consulting <hello@mokoconsulting.tech>
|
|
* @copyright Copyright (C) 2026 Moko Consulting. All rights reserved.
|
|
* @license GNU General Public License version 3 or later; see LICENSE
|
|
*/
|
|
|
|
defined('_JEXEC') or die;
|
|
|
|
use Joomla\CMS\HTML\HTMLHelper;
|
|
use Joomla\CMS\Language\Text;
|
|
use Joomla\CMS\Router\Route;
|
|
use Joomla\CMS\Session\Session;
|
|
|
|
$ajaxToken = Session::getFormToken();
|
|
$ajaxUrl = Route::_('index.php?option=com_mokosuitebackup&format=json', false);
|
|
?>
|
|
<div class="main-card">
|
|
<div class="card-body">
|
|
<h2><?php echo $this->escape($this->item->description); ?></h2>
|
|
|
|
<table class="table table-striped">
|
|
<tbody>
|
|
<tr>
|
|
<th scope="row"><?php echo Text::_('COM_MOKOJOOMBACKUP_FIELD_STATUS'); ?></th>
|
|
<td>
|
|
<?php
|
|
$statusClass = match ($this->item->status) {
|
|
'complete' => 'badge bg-success',
|
|
'running' => 'badge bg-info',
|
|
'fail' => 'badge bg-danger',
|
|
default => 'badge bg-secondary',
|
|
};
|
|
?>
|
|
<span class="<?php echo $statusClass; ?>"><?php echo $this->escape($this->item->status); ?></span>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row"><?php echo Text::_('COM_MOKOJOOMBACKUP_FIELD_BACKUP_TYPE'); ?></th>
|
|
<td><?php echo $this->escape($this->item->backup_type); ?></td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row"><?php echo Text::_('COM_MOKOJOOMBACKUP_FIELD_ORIGIN'); ?></th>
|
|
<td><?php echo $this->escape($this->item->origin); ?></td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row"><?php echo Text::_('COM_MOKOJOOMBACKUP_FIELD_SIZE'); ?></th>
|
|
<td>
|
|
<?php echo HTMLHelper::_('number.bytes', $this->item->total_size); ?>
|
|
<?php if ($this->item->db_size > 0) : ?>
|
|
<small class="text-muted">(<?php echo Text::_('COM_MOKOJOOMBACKUP_FIELD_DB_SIZE'); ?>: <?php echo HTMLHelper::_('number.bytes', $this->item->db_size); ?>)</small>
|
|
<?php endif; ?>
|
|
</td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row"><?php echo Text::_('COM_MOKOJOOMBACKUP_FIELD_START'); ?></th>
|
|
<td><?php echo HTMLHelper::_('date', $this->item->backupstart, Text::_('DATE_FORMAT_LC2')); ?></td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row"><?php echo Text::_('COM_MOKOJOOMBACKUP_FIELD_END'); ?></th>
|
|
<td><?php echo HTMLHelper::_('date', $this->item->backupend, Text::_('DATE_FORMAT_LC2')); ?></td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row"><?php echo Text::_('COM_MOKOJOOMBACKUP_FIELD_ARCHIVE'); ?></th>
|
|
<td><code><?php echo $this->escape($this->item->archivename); ?></code></td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row"><?php echo Text::_('COM_MOKOJOOMBACKUP_FIELD_PATH'); ?></th>
|
|
<td><code><?php echo $this->escape($this->item->absolute_path); ?></code></td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row"><?php echo Text::_('COM_MOKOJOOMBACKUP_FIELD_FILES_COUNT'); ?></th>
|
|
<td><?php echo (int) $this->item->files_count; ?></td>
|
|
</tr>
|
|
<tr>
|
|
<th scope="row"><?php echo Text::_('COM_MOKOJOOMBACKUP_FIELD_TABLES_COUNT'); ?></th>
|
|
<td><?php echo (int) $this->item->tables_count; ?></td>
|
|
</tr>
|
|
<?php if (!empty($this->item->checksum)) : ?>
|
|
<tr>
|
|
<th scope="row"><?php echo Text::_('COM_MOKOJOOMBACKUP_FIELD_CHECKSUM'); ?></th>
|
|
<td><code class="font-monospace" style="font-size:0.85em;"><?php echo $this->escape($this->item->checksum); ?></code></td>
|
|
</tr>
|
|
<?php endif; ?>
|
|
<?php if (!empty($this->item->remote_filename)) : ?>
|
|
<tr>
|
|
<th scope="row"><?php echo Text::_('COM_MOKOJOOMBACKUP_FIELD_REMOTE'); ?></th>
|
|
<td><code><?php echo $this->escape($this->item->remote_filename); ?></code></td>
|
|
</tr>
|
|
<?php endif; ?>
|
|
</tbody>
|
|
</table>
|
|
|
|
<!-- Backup Log -->
|
|
<h4 class="mt-4"><?php echo Text::_('COM_MOKOJOOMBACKUP_VIEW_LOG'); ?></h4>
|
|
<div id="mb-detail-log" class="bg-light p-3 rounded" style="max-height:400px; overflow-y:auto;">
|
|
<pre id="mb-detail-log-body" style="white-space:pre-wrap; word-break:break-word; font-size:0.85rem; margin:0;">Loading...</pre>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
(function() {
|
|
var form = new URLSearchParams();
|
|
form.append('task', 'ajax.viewLog');
|
|
form.append('id', <?php echo (int) $this->item->id; ?>);
|
|
form.append(<?php echo json_encode($ajaxToken); ?>, '1');
|
|
|
|
fetch(<?php echo json_encode($ajaxUrl); ?>, {
|
|
method: 'POST',
|
|
body: form,
|
|
headers: { 'X-Requested-With': 'XMLHttpRequest' }
|
|
})
|
|
.then(function(r) { return r.json(); })
|
|
.then(function(data) {
|
|
document.getElementById('mb-detail-log-body').textContent = data.error ? data.message : data.log;
|
|
})
|
|
.catch(function(err) {
|
|
document.getElementById('mb-detail-log-body').textContent = 'Error: ' + err.message;
|
|
});
|
|
})();
|
|
</script>
|