Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
TYPO3
sg_mail
Commits
bf3c79af
Commit
bf3c79af
authored
Feb 08, 2021
by
Kevin von Spiczak
Browse files
[TASK] add DeleteOldMailsCommand
parent
9d5e95f9
Changes
1
Hide whitespace changes
Inline
Side-by-side
Classes/Command/DeleteOldMailsCommand.php
View file @
bf3c79af
...
...
@@ -34,6 +34,8 @@ use Symfony\Component\Console\Output\OutputInterface;
use
Symfony\Component\Console\Style\SymfonyStyle
;
use
TYPO3\CMS\Core\Database\Connection
;
use
TYPO3\CMS\Core\Database\ConnectionPool
;
use
TYPO3\CMS\Core\Resource\Exception\ResourceDoesNotExistException
;
use
TYPO3\CMS\Core\Resource\ResourceFactory
;
use
TYPO3\CMS\Core\Utility\GeneralUtility
;
use
TYPO3\CMS\Core\Utility\VersionNumberUtility
;
use
TYPO3\CMS\Extbase\Object\Exception
;
...
...
@@ -45,7 +47,11 @@ use TYPO3\CMS\Extbase\Object\ObjectManager;
* @package SGalinski\SgMail\Command
*/
class
DeleteOldMailsCommand
extends
Command
{
private
const
TABLE_NAME
=
'tx_sgmail_domain_model_mail'
;
private
const
TABLE_NAME_MAIL
=
'tx_sgmail_domain_model_mail'
;
private
const
TABLE_NAME_FILE_REFERENCE
=
'sys_file_reference'
;
private
const
TABLE_NAME_FILE
=
'sys_file'
;
private
const
TABLE_NAME_REFINDEX
=
'sys_refindex'
;
/**
* @var int
*/
...
...
@@ -79,7 +85,7 @@ class DeleteOldMailsCommand extends Command {
if
(
$maxAgeInDays
<=
0
)
{
$io
->
error
(
'Please enter a maximum age (in days) for the mail\'s to be deleted.'
);
return
;
return
0
;
}
if
(
version_compare
(
VersionNumberUtility
::
getCurrentTypo3Version
(),
'10.4.0'
,
'<'
))
{
...
...
@@ -93,11 +99,11 @@ class DeleteOldMailsCommand extends Command {
$mailUidsForDeletion
=
$mailRepository
->
findMailsForDeletion
(
$maxAgeInDays
);
if
(
!
$mailUidsForDeletion
)
{
$io
->
success
(
"No matching mails found for deletion criteria: older than
$maxAgeInDays
days"
);
return
;
return
0
;
}
$this
->
markR
el
a
te
d
Attachments
AsDeleted
(
$mailUidsForDeletion
);
$this
->
mark
OldMails
AsDeleted
(
$mailUidsForDeletion
);
$this
->
d
el
e
teAttachments
(
$mailUidsForDeletion
);
$this
->
delete
OldMails
(
$mailUidsForDeletion
);
if
(
$this
->
amountOfDeletedRecords
>
0
)
{
$io
->
success
(
'Successfully deleted '
.
$this
->
amountOfDeletedRecords
.
' records.'
);
...
...
@@ -109,43 +115,128 @@ class DeleteOldMailsCommand extends Command {
}
/**
* Deletes all tx_sgmail_domain_model_mail records, where the uid matches one of the uids in $mailUidsForDeletion
*
* @param array $mailUidsForDeletion
*/
private
function
markOldMailsAsDeleted
(
array
$mailUidsForDeletion
):
void
{
$queryBuilder
=
GeneralUtility
::
makeInstance
(
ConnectionPool
::
class
)
->
getQueryBuilderForTable
(
self
::
TABLE_NAME
);
$queryBuilder
->
update
(
self
::
TABLE_NAME
)
->
set
(
'deleted'
,
1
)
private
function
deleteOldMails
(
array
$mailUidsForDeletion
):
void
{
$queryBuilder
=
GeneralUtility
::
makeInstance
(
ConnectionPool
::
class
)
->
getQueryBuilderForTable
(
self
::
TABLE_NAME_MAIL
);
$this
->
amountOfDeletedRecords
+=
$queryBuilder
->
delete
(
self
::
TABLE_NAME_MAIL
)
->
where
(
$queryBuilder
->
expr
()
->
in
(
'uid'
,
$queryBuilder
->
createNamedParameter
(
$mailUidsForDeletion
,
Connection
::
PARAM_INT_ARRAY
)
)
);
$result
=
$queryBuilder
->
execute
();
$this
->
amountOfDeletedRecords
+=
$result
;
)
->
execute
();
}
private
function
markRelatedAttachmentsAsDeleted
(
array
$mailUidsForDeletion
):
void
{
$queryBuilder
=
GeneralUtility
::
makeInstance
(
ConnectionPool
::
class
)
->
getQueryBuilderForTable
(
self
::
TABLE_NAME
);
$queryBuilder
->
update
(
'sys_file_reference'
)
->
set
(
'deleted'
,
1
)
/**
* Deletes the attachments (sys_file_reference / sys_file records), referenced in the mails to be deleted.
* For every file reference found in a mail record, we check if it is the only reference,
* or if we can find more records, referencing the same sys_file.
*
* The sys_file_reference found in the mail record is always deleted.
* If the referenced file has no more references, besides the one we just deleted, both the sys_file record and
* the actual file in the file system is deleted as well.
*
* @param array $mailUidsForDeletion
*/
private
function
deleteAttachments
(
array
$mailUidsForDeletion
):
void
{
$fileReferenceQueryBuilder
=
GeneralUtility
::
makeInstance
(
ConnectionPool
::
class
)
->
getQueryBuilderForTable
(
self
::
TABLE_NAME_FILE_REFERENCE
);
// Fetch all sys_file_reference records, with a relation to the mails we want to delete.
$sysFileReferencesToDelete
=
$fileReferenceQueryBuilder
->
select
(
'uid'
,
'uid_local'
)
->
from
(
self
::
TABLE_NAME_FILE_REFERENCE
)
->
where
(
$
q
ueryBuilder
->
expr
()
->
in
(
$
fileReferenceQ
ueryBuilder
->
expr
()
->
in
(
'uid_foreign'
,
$queryBuilder
->
createNamedParameter
(
$mailUidsForDeletion
,
Connection
::
PARAM_INT_ARRAY
)
$fileReferenceQueryBuilder
->
createNamedParameter
(
$mailUidsForDeletion
,
Connection
::
PARAM_INT_ARRAY
)
),
$queryBuilder
->
expr
()
->
eq
(
'tablenames'
,
$queryBuilder
->
createNamedParameter
(
self
::
TABLE_NAME
,
Connection
::
PARAM_STR
)
$fileReferenceQueryBuilder
->
expr
()
->
eq
(
'tablenames'
,
$fileReferenceQueryBuilder
->
createNamedParameter
(
self
::
TABLE_NAME_MAIL
,
Connection
::
PARAM_STR
)
),
$queryBuilder
->
expr
()
->
eq
(
'fieldname'
,
$queryBuilder
->
createNamedParameter
(
'attachments'
,
Connection
::
PARAM_STR
)
$fileReferenceQueryBuilder
->
expr
()
->
eq
(
'fieldname'
,
$fileReferenceQueryBuilder
->
createNamedParameter
(
'attachments'
,
Connection
::
PARAM_STR
)
),
);
$result
=
$queryBuilder
->
execute
();
$this
->
amountOfDeletedRecords
+=
$result
;
)
->
execute
()
->
fetchAllAssociative
();
foreach
(
$sysFileReferencesToDelete
as
$sysFileReferenceToDelete
)
{
$sysFileReferenceUid
=
(
int
)
$sysFileReferenceToDelete
[
'uid'
];
$sysFileUid
=
(
int
)
$sysFileReferenceToDelete
[
'uid_local'
];
$resourceFactory
=
GeneralUtility
::
makeInstance
(
ResourceFactory
::
class
);
try
{
$sysFileReference
=
$resourceFactory
->
getFileReferenceObject
(
$sysFileReferenceUid
);
}
catch
(
ResourceDoesNotExistException
$e
)
{
$sysFileReference
=
NULL
;
}
if
(
$sysFileReference
===
NULL
)
{
return
;
}
$referencedSysFile
=
$sysFileReference
->
getOriginalFile
();
$refIndexQueryBuilder
=
GeneralUtility
::
makeInstance
(
ConnectionPool
::
class
)
->
getConnectionForTable
(
self
::
TABLE_NAME_REFINDEX
)
->
createQueryBuilder
();
// Check if there are more rows in sys_refindex,
// referencing the same file as the current $sysFileReferenceToDelete.
// If we do not find any rows here, we delete
// * the sys_file_reference record,
// * the sys_file record,
// * the actual file in the filesystem
// If we find more rows here, only the sys_file_reference record is deleted.
$countRefIndexEntries
=
$refIndexQueryBuilder
->
count
(
'*'
)
->
from
(
self
::
TABLE_NAME_REFINDEX
)
->
where
(
$refIndexQueryBuilder
->
expr
()
->
eq
(
'ref_table'
,
$refIndexQueryBuilder
->
createNamedParameter
(
self
::
TABLE_NAME_FILE
,
Connection
::
PARAM_STR
)
),
$refIndexQueryBuilder
->
expr
()
->
eq
(
'ref_uid'
,
$refIndexQueryBuilder
->
createNamedParameter
(
$sysFileUid
,
Connection
::
PARAM_INT
)
),
// exclude current sys_file_reference record
$refIndexQueryBuilder
->
expr
()
->
neq
(
'recuid'
,
$refIndexQueryBuilder
->
createNamedParameter
(
$sysFileReferenceUid
,
Connection
::
PARAM_INT
)
)
)
->
execute
()
->
fetchOne
();
if
(
$countRefIndexEntries
<=
0
)
{
$referencedSysFile
->
delete
();
}
$deleteFileReferenceQueryBuilder
=
GeneralUtility
::
makeInstance
(
ConnectionPool
::
class
)
->
getConnectionForTable
(
self
::
TABLE_NAME_FILE_REFERENCE
)
->
createQueryBuilder
();
// delete the sys_file_reference
$this
->
amountOfDeletedRecords
+=
$deleteFileReferenceQueryBuilder
->
delete
(
self
::
TABLE_NAME_FILE_REFERENCE
)
->
where
(
$deleteFileReferenceQueryBuilder
->
expr
()
->
eq
(
'uid'
,
$deleteFileReferenceQueryBuilder
->
createNamedParameter
(
$sysFileReferenceUid
,
Connection
::
PARAM_INT
)
)
)
->
execute
();
}
}
}
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment