Commit 57fd3dd7 authored by Samuel Mortenson's avatar Samuel Mortenson Committed by Sam Mortenson
Browse files

Issue #3260511 by samuel.mortenson: Add new sub-module to Tome Sync that...

Issue #3260511 by samuel.mortenson: Add new sub-module to Tome Sync that automatically deletes unused files
parent 9f97494e
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -131,3 +131,15 @@ services:
  tome_sync.file_sync:
    class: Drupal\tome_sync\NullFileSync
```

AUTOMATICALLY DELETING UNUSED FILE EXPORTS
==========================================

An experimental sub-module can be enabled to automatically perform the same
operation as "drush tome:clean-files" any time content or config is exported by
Tome Sync. Enabling this sub-module could lead to data loss, and would break
revision reverts (unless the file was re-saved on revert), so please use with
caution. This is a good module for users who upload/remove many files during
the content editing process, and are tired of accidentally committing them.

If you're confident you want to use it, you can enable "tome_sync_autoclean".
+123 −0
Original line number Diff line number Diff line
<?php

namespace Drupal\tome_sync_autoclean\EventSubscriber;

use Drupal\Core\Config\ConfigCrudEvent;
use Drupal\Core\Config\ConfigEvents;
use Drupal\Core\Config\StorageInterface;
use Drupal\Core\File\FileSystemInterface;
use Drupal\tome_base\PathTrait;
use Drupal\tome_sync\CleanFilesTrait;
use Drupal\tome_sync\ContentIndexerTrait;
use Drupal\tome_sync\Event\ContentCrudEvent;
use Drupal\tome_sync\Event\TomeSyncEvents;
use Drupal\tome_sync\FileSyncInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
 * Automatically deletes unused files after content/config is exported.
 *
 * @internal
 */
class ExportEventSubscriber implements EventSubscriberInterface {

  use PathTrait;
  use ContentIndexerTrait;
  use CleanFilesTrait;

  /**
   * The target content storage.
   *
   * @var \Drupal\Core\Config\StorageInterface
   */
  protected $contentStorage;

  /**
   * The config storage.
   *
   * @var \Drupal\Core\Config\StorageInterface
   */
  protected $configStorage;

  /**
   * The file system.
   *
   * @var \Drupal\Core\File\FileSystemInterface
   */
  protected $fileSystem;

  /**
   * The file sync service.
   *
   * @var \Drupal\tome_sync\FileSyncInterface
   */
  protected $fileSync;

  /**
   * Creates a ExportEventSubscriber object.
   *
   * @param \Drupal\Core\Config\StorageInterface $content_storage
   *   The target content storage.
   * @param \Drupal\Core\Config\StorageInterface $config_storage
   *   The target config storage.
   * @param \Drupal\tome_sync\FileSyncInterface $file_sync
   *   The file sync service.
   * @param \Drupal\Core\File\FileSystemInterface $file_system
   *   The file system.
   */
  public function __construct(StorageInterface $content_storage, StorageInterface $config_storage, FileSyncInterface $file_sync, FileSystemInterface $file_system) {
    $this->contentStorage = $content_storage;
    $this->configStorage = $config_storage;
    $this->fileSync = $file_sync;
    $this->fileSystem = $file_system;
  }

  /**
   * Removes unused files.
   */
  protected function deleteUnusedFiles() {
    $files = $this->getUnusedFiles();
    foreach ($files as $uuid => $filename) {
      $this->contentStorage->delete("file.$uuid");
      $this->unIndexContentByName("file.$uuid");
      $this->fileSync->deleteFile($filename);
    }
  }

  /**
   * Reacts to content events.
   *
   * @param \Drupal\tome_sync\Event\ContentCrudEvent $event
   *   The event.
   */
  public function exportContent(ContentCrudEvent $event) {
    if ($event->getContent()->getEntityTypeId() === 'file') {
      return;
    }
    $this->deleteUnusedFiles();
  }

  /**
   * Reacts to config events.
   *
   * @param \Drupal\Core\Config\ConfigCrudEvent $event
   *   The event.
   */
  public function exportConfig(ConfigCrudEvent $event) {
    if (!\Drupal::isConfigSyncing() && !isset($GLOBALS['_tome_sync_installing'])) {
      $this->deleteUnusedFiles();
    }
  }

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents() {
    $events[TomeSyncEvents::EXPORT_CONTENT][] = ['exportContent', -1];
    $events[TomeSyncEvents::DELETE_CONTENT][] = ['exportContent', -1];
    $events[ConfigEvents::SAVE][] = ['exportConfig', -1];
    $events[ConfigEvents::DELETE][] = ['exportConfig', -1];
    return $events;
  }

}
+8 −0
Original line number Diff line number Diff line
name: 'Tome Sync Autoclean (Experimental)'
type: module
description: 'Automatically deletes files that are unused. This module could definitely lead to data loss, use with caution!'
core: 8.x
core_version_requirement: ^8 || ^9
package: Tome
dependencies:
  - tome:tome_sync
+6 −0
Original line number Diff line number Diff line
services:
  tome_sync_autoclean.export_event_subscriber:
    class: Drupal\tome_sync_autoclean\EventSubscriber\ExportEventSubscriber
    arguments: ['@tome_sync.storage.content', '@config.storage.sync', '@tome_sync.file_sync', '@file_system']
    tags:
    - { name: event_subscriber }