Allow users to delete Shorthand Stories

Created on 25 March 2025, about 2 months ago

Problem/Motivation

Currently, users cannot delete shorthand stories from Drupal, which, over time, fills the file system up with data that cannot be removed, including repulls of new versions the old versions cannot be removed.

Steps to reproduce

Pull a story
Try to delete it (There is no delete option)
Over time the filesystem size will grow.

Proposed resolution

Allow users to delete content and old versions of the stories.

✨ Feature request
Status

Active

Version

5.0

Component

Code

Created by

πŸ‡¦πŸ‡ΊAustralia shorthand

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @shorthand
  • πŸ‡ΊπŸ‡¦Ukraine ooa33

    I've created a drush command to remove unused shorthand files. The drush command depends on the content type and uses shorthand, so pay attention to the constant SHORTHAND_STORY_NODE_TYPE. Here is a code of the drush command:

    
    use Drupal\Core\Entity\EntityTypeManagerInterface;
    use Drupal\Core\File\FileSystemInterface;
    use Drupal\node\NodeStorageInterface;
    use Drush\Commands\DrushCommands;
    
    /**
     * Command for clean up unused shorthands.
     */
    class CleanUpShorthandCommand extends DrushCommands {
    
      /**
       * Shorthand story node type.
       */
      const string SHORTHAND_STORY_NODE_TYPE = 'shorthand_story';
    
      const string SHORTHAND_STORY_BASE_PATH = 'shorthand/stories';
    
      /**
       * Entity type manager.
       *
       * @var \Drupal\node\NodeStorageInterface
       */
      protected NodeStorageInterface $nodeStorage;
    
      /**
       * The file system service.
       *
       * @var \Drupal\Core\File\FileSystemInterface
       */
      protected FileSystemInterface $fileSystem;
    
      /**
       * UpdatePressReleasesCommand constructor.
       *
       * @param \Drupal\Core\Entity\EntityTypeManagerInterface $nodeStorage
       *   Entity type manager.
       * @param \Drupal\Core\File\FileSystemInterface $file_system
       *   The file handler.
       *
       * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
       * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
       */
      public function __construct(EntityTypeManagerInterface $nodeStorage, FileSystemInterface $file_system) {
        parent::__construct();
        $this->nodeStorage = $nodeStorage->getStorage('node');
        $this->fileSystem = $file_system;
      }
    
      /**
       * Drush command to clean up not used shorthands.
       *
       * @command common:clean-up-shorthand
       * @aliases cush
       */
      public function run() {
        $confirm = $this->io()->confirm('Are you sure you want to delete all not used shorthands?', TRUE);
        if (!$confirm) {
          $this->output()->writeln('Command cancelled.');
          return;
        }
    
        // Shorthand nodes.
        $nodes = $this->nodeStorage->loadByProperties([
          'type' => self::SHORTHAND_STORY_NODE_TYPE,
        ]);
    
        $usedShorthands = [];
        if ($nodes) {
          foreach ($nodes as $node) {
            $parts = explode('/', $node->field_shorthand->value);
            if (count($parts)) {
              $usedShorthands[$parts[0]] = $parts[1];
            }
          }
        }
    
        $destination_uri = 'public://' . static::SHORTHAND_STORY_BASE_PATH;
        $storyFolders = $this->fileSystem->scanDirectory($destination_uri, '/.*/', [
          'recurse' => FALSE,
          'key' => 'filename',
        ]);
        $localStories = array_keys($storyFolders);
        foreach ($localStories as $story) {
          $storyVariants = $this->fileSystem->scanDirectory($destination_uri . '/' . $story, '/.*/', [
            'recurse' => FALSE,
            'key' => 'filename',
          ]);
          if (empty($usedShorthands[$story])) {
            // Remove the story folder.
            $folder = $destination_uri . '/' . $story;
            $this->fileSystem->deleteRecursive($folder);
            $this->writeln(t('Removed shorthand: @title', [
              '@title' => $story,
            ]));
          }
          else {
            foreach ($storyVariants as $storyVariant => $data) {
              if ($storyVariant != $usedShorthands[$story]) {
                $folder = $destination_uri . '/' . $story . '/' . $storyVariant;
                $this->fileSystem->deleteRecursive($folder);
                $this->writeln(t('Removed shorthand: @title @version', [
                  '@title' => $story,
                  '@version' => $storyVariant,
                ]));
              }
            }
          }
        }
    
        $this->io()->success('All unused shorthand stories removed.');
      }
    
    }
    
  • πŸ‡¦πŸ‡ΊAustralia jannakha Brisbane!

    @ooa33 - do you mind putting your code as a merge request?

Production build 0.71.5 2024