Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions config/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ services:

OpenDxp\Bundle\AdminBundle\Service\Email\UnusableRecipientDetector: ~
OpenDxp\Bundle\AdminBundle\Service\Email\EmailLogListingFactory: ~
OpenDxp\Bundle\AdminBundle\Service\Email\EmailLogCleaner: ~

OpenDxp\Bundle\AdminBundle\Service\Login\LoginPageService: ~

Expand Down
112 changes: 95 additions & 17 deletions public/js/opendxp/settings/email/log.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ opendxp.registerNS('opendxp.settings.email.log');
opendxp.settings.email.log = Class.create({

filterField: null,
cleanupUrl: null,
exportPrepareUrl: null,
exportProcessUrl: null,
exportDownloadUrl: null,
Expand All @@ -26,6 +27,7 @@ opendxp.settings.email.log = Class.create({

initialize: function(document) {
this.document = document;
this.cleanupUrl = Routing.generate('opendxp_admin_email_cleanupemaillogs');
this.exportPrepareUrl = Routing.generate('opendxp_admin_email_exportemaillogs_prepare');
this.exportProcessUrl = Routing.generate('opendxp_admin_email_exportemaillogs');
this.exportDownloadUrl = Routing.generate('opendxp_admin_email_exportemaillogs_download');
Expand Down Expand Up @@ -421,7 +423,9 @@ opendxp.settings.email.log = Class.create({
tooltip: t('delete'),
icon: '/bundles/opendxpadmin/img/flat-color-icons/delete.svg',
handler: function (grid, rowIndex) {

let data = grid.getStore().getAt(rowIndex);

opendxp.helpers.deleteConfirm(t('email_log'), data.id, function () {
var rec = grid.getStore().getAt(rowIndex);
Ext.Ajax.request({
Expand All @@ -430,21 +434,18 @@ opendxp.settings.email.log = Class.create({
success: function(response){
var data = Ext.decode( response.responseText );
if(!data.success){
Ext.Msg.alert(t('error'),
t('error_deleting_item'));
Ext.Msg.alert(t('error'), t('error_deleting_item'));
}

grid.getStore().reload();
},
failure: function () {
Ext.Msg.alert(t('error'),
t('error_deleting_item'));
Ext.Msg.alert(t('error'), t('error_deleting_item'));
},
params: { id : rec.get('id') }
});
}.bind(this));


}.bind(this)
}]
}
Expand All @@ -471,20 +472,30 @@ opendxp.settings.email.log = Class.create({

this.selectionColumn = new Ext.selection.CheckboxModel();

var toolbarItems = ['->'];

// cleaning up belongs to the global email panel only!
if (!this.document) {
toolbarItems.push({
text: t('cleanup'),
iconCls: 'opendxp_icon_cleanup',
handler: this.showCleanupWindow.bind(this)
}, '-');
}

toolbarItems.push({
text: t('export_csv'),
iconCls: 'opendxp_icon_export',
handler: this.doExport.bind(this)
}, '-', {
text: t('filter') + '/' + t('search'),
xtype: 'tbtext',
style: 'margin: 0 10px 0 0;'
}, this.filterField);

var toolbar = Ext.create('Ext.Toolbar', {
cls: 'opendxp_main_toolbar',
items: [
'->',
{
text: t('export_csv'),
iconCls: 'opendxp_icon_export',
handler: this.doExport.bind(this)
}, '-', {
text: t('filter') + '/' + t('search'),
xtype: 'tbtext',
style: 'margin: 0 10px 0 0;'
},this.filterField
]
items: toolbarItems
});

this.grid = new Ext.grid.GridPanel({
Expand All @@ -511,6 +522,73 @@ opendxp.settings.email.log = Class.create({
return this.grid;
},

showCleanupWindow: function () {

var daysField = new Ext.form.field.Number({
fieldLabel: t('email_log_cleanup_older_than_days'),
value: 30,
minValue: 1,
allowBlank: false,
allowDecimals: false,
labelWidth: 280,
anchor: '100%'
});

var win = new Ext.Window({
title: t('email_log_cleanup'),
iconCls: 'opendxp_icon_cleanup',
width: 480,
modal: true,
bodyStyle: 'padding: 10px;',
layout: 'anchor',
items: [daysField],
buttons: [{
text: t('cancel'),
handler: function () {
win.close();
}
}, {
text: t('cleanup'),
iconCls: 'opendxp_icon_cleanup',
handler: function () {
if (!daysField.isValid()) {
return;
}

this.cleanup(daysField.getValue(), win);
}.bind(this)
}]
});

win.show();
},

cleanup: function (olderThanDays, win) {

win.setLoading(t('please_wait'));

Ext.Ajax.request({
url: this.cleanupUrl,
method: 'DELETE',
params: {
olderThanDays: olderThanDays
},
callback: function () {
win.setLoading(false);
},
success: function (response) {
var rdata = Ext.decode(response.responseText);
win.close();

if (rdata) {
opendxp.helpers.showNotification(t('success'), sprintf(t('email_log_cleanup_success'), rdata.deleted), 'success');
}

this.store.reload();
}.bind(this)
});
},

doExport: function () {
var params = {};

Expand Down
11 changes: 11 additions & 0 deletions src/Controller/Admin/EmailController.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
use OpenDxp\Bundle\AdminBundle\Handler\Email\Blocklist\DeleteBlocklistEntry\DeleteBlocklistEntryHandler;
use OpenDxp\Bundle\AdminBundle\Handler\Email\Blocklist\UpdateBlocklistEntry\UpdateBlocklistEntryHandler;
use OpenDxp\Bundle\AdminBundle\Handler\Email\BlocklistPayload;
use OpenDxp\Bundle\AdminBundle\Handler\Email\CleanupEmailLogs\CleanupEmailLogsHandler;
use OpenDxp\Bundle\AdminBundle\Handler\Email\CleanupEmailLogs\CleanupEmailLogsPayload;
use OpenDxp\Bundle\AdminBundle\Handler\Email\DeleteEmailLog\DeleteEmailLogHandler;
use OpenDxp\Bundle\AdminBundle\Handler\Email\DoEmailLogExport\DoEmailLogExportHandler;
use OpenDxp\Bundle\AdminBundle\Handler\Email\DoEmailLogExport\DoEmailLogExportPayload;
Expand Down Expand Up @@ -160,6 +162,15 @@ public function showEmailLogDetailsAction(
return $this->apiJson($handler($payload), envelope: false);
}

#[IsGranted(CorePermission::Emails->value)]
#[Route('/cleanup-email-logs', name: 'opendxp_admin_email_cleanupemaillogs', methods: ['DELETE'])]
public function cleanupEmailLogsAction(
CleanupEmailLogsHandler $handler,
CleanupEmailLogsPayload $payload,
): JsonResponse {
return $this->apiJson($handler($payload));
}

#[IsGranted(CorePermission::Emails->value)]
#[Route('/delete-email-log', name: 'opendxp_admin_email_deleteemaillog', methods: ['DELETE'])]
public function deleteEmailLogAction(
Expand Down
42 changes: 42 additions & 0 deletions src/Handler/Email/CleanupEmailLogs/CleanupEmailLogsHandler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<?php

declare(strict_types=1);

/**
* OpenDXP
*
* This source file is licensed under the GNU General Public License version 3 (GPLv3).
*
* Full copyright and license information is available in
* LICENSE.md which is distributed with this source code.
*
* @copyright Copyright (c) OpenDXP (https://www.opendxp.io)
* @license https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3 (GPLv3)
*/

namespace OpenDxp\Bundle\AdminBundle\Handler\Email\CleanupEmailLogs;

use OpenDxp\Bundle\AdminBundle\Exception\AdminOperationFailedException;
use OpenDxp\Bundle\AdminBundle\Service\Email\EmailLogCleaner;

final class CleanupEmailLogsHandler
{
public function __construct(private readonly EmailLogCleaner $cleaner)
{
}

public function __invoke(CleanupEmailLogsPayload $payload): CleanupEmailLogsResult
{
if ($payload->olderThanDays < CleanupEmailLogsPayload::MINIMUM_DAYS) {
throw new AdminOperationFailedException(
sprintf(
'Email logs can only be cleaned up from an age of %d day(s) on, got %d.',
CleanupEmailLogsPayload::MINIMUM_DAYS,
$payload->olderThanDays
)
);
}

return new CleanupEmailLogsResult(deleted: $this->cleaner->deleteOlderThanDays($payload->olderThanDays));
}
}
37 changes: 37 additions & 0 deletions src/Handler/Email/CleanupEmailLogs/CleanupEmailLogsPayload.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

declare(strict_types=1);

/**
* OpenDXP
*
* This source file is licensed under the GNU General Public License version 3 (GPLv3).
*
* Full copyright and license information is available in
* LICENSE.md which is distributed with this source code.
*
* @copyright Copyright (c) OpenDXP (https://www.opendxp.io)
* @license https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3 (GPLv3)
*/

namespace OpenDxp\Bundle\AdminBundle\Handler\Email\CleanupEmailLogs;

use OpenDxp\Bundle\AdminBundle\Payload\ExtJsPayloadInterface;
use Symfony\Component\HttpFoundation\Request;

final readonly class CleanupEmailLogsPayload implements ExtJsPayloadInterface
{
public const int MINIMUM_DAYS = 1;

public function __construct(
public readonly int $olderThanDays,
) {
}

public static function fromRequest(Request $request): static
{
return new static(
olderThanDays: (int) $request->request->getString('olderThanDays'),
);
}
}
27 changes: 27 additions & 0 deletions src/Handler/Email/CleanupEmailLogs/CleanupEmailLogsResult.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

declare(strict_types=1);

/**
* OpenDXP
*
* This source file is licensed under the GNU General Public License version 3 (GPLv3).
*
* Full copyright and license information is available in
* LICENSE.md which is distributed with this source code.
*
* @copyright Copyright (c) OpenDXP (https://www.opendxp.io)
* @license https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3 (GPLv3)
*/

namespace OpenDxp\Bundle\AdminBundle\Handler\Email\CleanupEmailLogs;

use OpenDxp\Bundle\AdminBundle\Handler\ResultInterface;

final readonly class CleanupEmailLogsResult implements ResultInterface
{
public function __construct(
public int $deleted,
) {
}
}
59 changes: 59 additions & 0 deletions src/Service/Email/EmailLogCleaner.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?php

declare(strict_types=1);

/**
* OpenDXP
*
* This source file is licensed under the GNU General Public License version 3 (GPLv3).
*
* Full copyright and license information is available in
* LICENSE.md which is distributed with this source code.
*
* @copyright Copyright (c) OpenDXP (https://www.opendxp.io)
* @license https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License version 3 (GPLv3)
*/

namespace OpenDxp\Bundle\AdminBundle\Service\Email;

use DateTimeImmutable;
use InvalidArgumentException;
use OpenDxp\Model\Tool\Email;

final class EmailLogCleaner
{
private const int PAGE_SIZE = 100;

public function deleteOlderThanDays(int $days, ?callable $onProgress = null): int
{
if ($days < 0) {
throw new InvalidArgumentException(sprintf('Days must not be negative, got %d.', $days));
}

$cutoff = (new DateTimeImmutable(sprintf('-%d days', $days)))->getTimestamp();
$deleted = 0;

do {
$list = new Email\Log\Listing();
$list->setCondition('sentDate < ?', [$cutoff]);

$list->setOrderKey('id');
$list->setOrder('ASC');
$list->setLimit(self::PAGE_SIZE);

$entries = $list->getEmailLogs();

foreach ($entries as $entry) {
$entry->delete();
$deleted++;
}

if ($entries !== [] && $onProgress !== null) {
$onProgress($deleted);
}

} while ($entries !== []);

return $deleted;
}
}
3 changes: 3 additions & 0 deletions translations/admin.de.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,9 @@ email_log_resend_window_error_message: 'Ein Fehler ist aufgetreten. Die E-Mail k
email_log_resend_window_msg: 'Bitte bestätige, dass du die E-Mail wiederholt an alle Empfänger versenden möchtest.'
email_log_resend_window_success_message: 'Die E-Mail wurde erfolgreich an alle Empfänger versendet.'
email_log_sent_Date: 'Datum gesendet'
email_log_cleanup: 'Email-Logs bereinigen'
email_log_cleanup_older_than_days: 'Einträge löschen, die älter sind als (Tage)'
email_log_cleanup_success: '%s Email-Log-Einträge gelöscht.'
email_log_export_confirmation: 'Sie sind dabei, %s Email-Log-Einträge zu exportieren. Möchten Sie fortfahren?'
email_log_subject: 'Subject'
email_log_to: 'An'
Expand Down
3 changes: 3 additions & 0 deletions translations/admin.en.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,9 @@ email_log_resend_window_error_message: 'An error occurred. The email has not bee
email_log_resend_window_msg: 'Please confirm that you want to send the email again to all recipients.'
email_log_resend_window_success_message: 'The email has been sent successfully to all recipients.'
email_log_sent_Date: 'Date sent'
email_log_cleanup: 'Clean Up Email Logs'
email_log_cleanup_older_than_days: 'Delete entries older than (days)'
email_log_cleanup_success: '%s email log entries deleted.'
email_log_export_confirmation: 'You are about to export %s email log entries. Do you want to continue?'
email_log_subject: 'Subject'
email_log_to: 'To'
Expand Down
Loading