A Silverstripe module that provides a single queued job to delete old form submission DataObjects on a daily schedule. Target classes, retention periods, and exclude rules are all defined in YAML config.
- silverstripe/framework ^6
- symbiote/silverstripe-queuedjobs ^6.2
- silverstripe/userforms ^7 (optional — only required if targeting
SubmittedFormrecords)
composer require plasticstudio/form-submission-cleanupSetup a cron job:
*/1 * * * * /path/to/silverstripe/vendor/bin/sake tasks:ProcessJobQueueTaskCopy the relevant blocks into your project's _config/config.yml.
PlasticStudio\FormSubmissionCleanup\Jobs\FormSubmissionCleanupJob:
default_retention_days: 365 # applied to any target without its own retention_days
default_date_field: Created # field used to determine record ageAdd one entry per DataObject class to clean up. UserForms is shown as an example; omit it if the module is not installed.
PlasticStudio\FormSubmissionCleanup\Jobs\FormSubmissionCleanupJob:
targets:
'SilverStripe\UserForms\Model\Submission\SubmittedForm':
retention_days: 365 # optional — overrides default_retention_days
date_field: Created # optional — overrides default_date_field
exclude: # optional — ORM exclude filter (same syntax as DataList::exclude)
IsArchived: true
'App\Model\AnotherSubmission':
retention_days: 90Per-target options
| Key | Type | Description |
|---|---|---|
retention_days |
int | Overrides the global default for this class only |
date_field |
string | DataObject field to measure age against (default Created) |
exclude |
map | ORM filter passed to DataList::exclude() — matching records are kept |
Register the job as a QueuedJobs default job so it is automatically re-queued after each run.
SilverStripe\Core\Injector\Injector:
Symbiote\QueuedJobs\Services\QueuedJobService:
properties:
defaultJobs:
FormSubmissionCleanup:
type: 'PlasticStudio\FormSubmissionCleanup\Jobs\FormSubmissionCleanupJob'
filter:
JobTitle: 'Form Submission Cleanup'
recreate: 1
startDateFormat: 'Y-m-d H:i:s'
startTimeString: 'tomorrow 02:00'Run a dev/build, then queue the first instance manually via the CMS (Admin > Jobs). Subsequent runs are scheduled automatically.
setup()iterates every configured target class, applies the retention cutoff and any exclude filter, and collects matching record IDs.process()deletes one record per step. Cascade-delete rules on each DataObject handle any related records (e.g.SubmittedFormFieldchildren onSubmittedForm).- After the job completes, the default jobs feature re-queues it for the next scheduled run.