Skip to content

Soft Delete and Hard Delete

XELOS provides the SoftDeleteInterface and the SoftDeleteTrait to move documents in a trash when they are deleted.

Trashed documents can be restored if they are a DocumentModel.

Trash

The related document index of the deleted document can be found in the audit log. The audit log can be used to restore the document.

Hard Delete

When a document model is marked as soft deleted, the related document index stores the date for the scheduled removal based on the config variable "Trash Folder TTL".

If the variable is changed the scheduled removal is unchanged. However, if the variable was increased, the deletion is delayed until the deleted_at property of the document index is so many days in the past.

E.g. A document is deleted and the document index is marked for deletion in 30 days on the 30th January. If the "Trash Folder TTL" is reduced to 20, the document will still be deleted on the 30th. If the variable is increased to 50, the document won't be deleted before the 19th February.

Implementation

The document model has to implement both the interface and the trait:

use XELOS\Framework\Module\Model\Interfaces\SoftDeleteInterface;
use XELOS\Framework\Module\Model\Traits\SoftDeleteTrait;

class Page extends DocumentModel implements SoftDeleteInterface {

    use SoftDeleteTrait;

}

The database.yml for the model table has to be extended with the deleted_at property which is automatically created as a timestamp column if added to the YAML file:

page:
  id:
  title: {type: varchar, size: 100}
  created_at:
  updated_at:
  deleted_at:

This implementation causes the delete method to always set the deleted_at column, instead of deleting the document.

Finding deleted models

Deleted models are not returned by the find_by methods.

The SoftDeleteTrait provides the scope withDeleted which enables searching for deleted documents:

$this->mod->model->page->withDeleted()->find_by_id(42);

If a model has related documents, it can implement the delete events defined in the SoftDeleteInterface, e.g. the Wiki page has many history entries and links.

The related documents have to implement the interface and the trait and add the deleted_at column to the database table.

class Page {
  /**
   * Restore the history and links.
   */
  public function onRestore() {
    $this->mod->model->page_history->withDeleted()->find_all_by_page_id($this->id)->invoke('restore');
    $this->mod->model->page_link->withDeleted()->find_all_by_from_page_id($this->id)->invoke('restore');
  }

  /**
   * Delete the history and links.
   */
  public function onForceDelete() {
    $this->mod->model->page_history->withDeleted()->find_all_by_page_id($this->id)->invoke('forceDelete');
    $this->mod->model->page_link->withDeleted()->find_all_by_from_page_id($this->id)->invoke('forceDelete');
  }
}

Make sure to only implement the event in one model to prevent circular calls.