Browse Source

Add node actions for media file privacy

main
astanley 2 weeks ago
parent
commit
484f1d1a13
  1. 11
      config/install/system.action.media_file_privacy_move_node_media_private.yml
  2. 11
      config/install/system.action.media_file_privacy_move_node_media_public.yml
  3. 42
      media_file_privacy.install
  4. 114
      src/Plugin/Action/MoveNodeMediaFilesPrivate.php
  5. 114
      src/Plugin/Action/MoveNodeMediaFilesPublic.php

11
config/install/system.action.media_file_privacy_move_node_media_private.yml

@ -0,0 +1,11 @@
langcode: en
status: true
dependencies:
module:
- media_file_privacy
- node
id: media_file_privacy_move_node_media_private
label: 'Move associated unpublished media files to private storage'
type: node
plugin: media_file_privacy_move_node_media_private
configuration: { }

11
config/install/system.action.media_file_privacy_move_node_media_public.yml

@ -0,0 +1,11 @@
langcode: en
status: true
dependencies:
module:
- media_file_privacy
- node
id: media_file_privacy_move_node_media_public
label: 'Move associated published media files to public storage'
type: node
plugin: media_file_privacy_move_node_media_public
configuration: { }

42
media_file_privacy.install

@ -0,0 +1,42 @@
<?php
/**
* @file
* Install and update hooks for Media File Privacy.
*/
use Drupal\system\Entity\Action;
/**
* Adds the node action for moving associated unpublished media files private.
*/
function media_file_privacy_update_10001(): void {
$id = 'media_file_privacy_move_node_media_private';
if (!Action::load($id)) {
Action::create([
'id' => $id,
'label' => 'Move associated unpublished media files to private storage',
'type' => 'node',
'plugin' => 'media_file_privacy_move_node_media_private',
'configuration' => [],
])->save();
}
}
/**
* Adds the node action for moving associated published media files public.
*/
function media_file_privacy_update_10002(): void {
$id = 'media_file_privacy_move_node_media_public';
if (!Action::load($id)) {
Action::create([
'id' => $id,
'label' => 'Move associated published media files to public storage',
'type' => 'node',
'plugin' => 'media_file_privacy_move_node_media_public',
'configuration' => [],
])->save();
}
}

114
src/Plugin/Action/MoveNodeMediaFilesPrivate.php

@ -0,0 +1,114 @@
<?php
namespace Drupal\media_file_privacy\Plugin\Action;
use Drupal\Core\Action\ActionBase;
use Drupal\Core\Action\ActionManager;
use Drupal\Core\Action\Attribute\Action;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\media\MediaInterface;
use Drupal\node\NodeInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Moves files for media associated with a node to private storage.
*
* Associated media are discovered through field_media_of. The existing
* media_file_privacy_move_unpublished_private action is then applied to each
* media item, so publication-state checks and file-moving behavior remain in
* one place.
*/
#[Action(
id: 'media_file_privacy_move_node_media_private',
label: new TranslatableMarkup('Move associated unpublished media files to private storage'),
type: 'node',
)]
final class MoveNodeMediaFilesPrivate extends ActionBase implements ContainerFactoryPluginInterface {
/**
* Constructs the action.
*/
public function __construct(
array $configuration,
$plugin_id,
$plugin_definition,
protected EntityTypeManagerInterface $entityTypeManager,
protected ActionManager $actionManager,
protected AccountProxyInterface $currentUser,
) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
}
/**
* {@inheritdoc}
*/
public static function create(
ContainerInterface $container,
array $configuration,
$plugin_id,
$plugin_definition,
): static {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('entity_type.manager'),
$container->get('plugin.manager.action'),
$container->get('current_user'),
);
}
/**
* {@inheritdoc}
*/
public function execute($entity = NULL): void {
if (!$entity instanceof NodeInterface || !$entity->id()) {
return;
}
$media_storage = $this->entityTypeManager->getStorage('media');
// Find all media whose field_media_of references this node.
$media_ids = $media_storage->getQuery()
->accessCheck(FALSE)
->condition('field_media_of.target_id', $entity->id())
->execute();
if (!$media_ids) {
return;
}
$media_action = $this->actionManager->createInstance(
'media_file_privacy_move_unpublished_private',
);
foreach ($media_storage->loadMultiple($media_ids) as $media) {
if (!$media instanceof MediaInterface) {
continue;
}
// Reuse the access rules of the media action before executing it.
if (!$media_action->access($media, $this->currentUser)) {
continue;
}
$media_action->execute($media);
}
}
/**
* {@inheritdoc}
*/
public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
if (!$object instanceof NodeInterface) {
return FALSE;
}
return $object->access('update', $account, $return_as_object);
}
}

114
src/Plugin/Action/MoveNodeMediaFilesPublic.php

@ -0,0 +1,114 @@
<?php
namespace Drupal\media_file_privacy\Plugin\Action;
use Drupal\Core\Action\ActionBase;
use Drupal\Core\Action\ActionManager;
use Drupal\Core\Action\Attribute\Action;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\media\MediaInterface;
use Drupal\node\NodeInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Moves files for published media associated with a node to public storage.
*
* Associated media are discovered through field_media_of. The existing
* media_file_privacy_move_published_public action is then applied to each
* media item, so publication-state checks and file-moving behavior remain in
* one place.
*/
#[Action(
id: 'media_file_privacy_move_node_media_public',
label: new TranslatableMarkup('Move associated published media files to public storage'),
type: 'node',
)]
final class MoveNodeMediaFilesPublic extends ActionBase implements ContainerFactoryPluginInterface {
/**
* Constructs the action.
*/
public function __construct(
array $configuration,
$plugin_id,
$plugin_definition,
protected EntityTypeManagerInterface $entityTypeManager,
protected ActionManager $actionManager,
protected AccountProxyInterface $currentUser,
) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
}
/**
* {@inheritdoc}
*/
public static function create(
ContainerInterface $container,
array $configuration,
$plugin_id,
$plugin_definition,
): static {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('entity_type.manager'),
$container->get('plugin.manager.action'),
$container->get('current_user'),
);
}
/**
* {@inheritdoc}
*/
public function execute($entity = NULL): void {
if (!$entity instanceof NodeInterface || !$entity->id()) {
return;
}
$media_storage = $this->entityTypeManager->getStorage('media');
// Find all media whose field_media_of references this node.
$media_ids = $media_storage->getQuery()
->accessCheck(FALSE)
->condition('field_media_of.target_id', $entity->id())
->execute();
if (!$media_ids) {
return;
}
$media_action = $this->actionManager->createInstance(
'media_file_privacy_move_published_public',
);
foreach ($media_storage->loadMultiple($media_ids) as $media) {
if (!$media instanceof MediaInterface) {
continue;
}
// Reuse the access rules of the media action before executing it.
if (!$media_action->access($media, $this->currentUser)) {
continue;
}
$media_action->execute($media);
}
}
/**
* {@inheritdoc}
*/
public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
if (!$object instanceof NodeInterface) {
return FALSE;
}
return $object->access('update', $account, $return_as_object);
}
}
Loading…
Cancel
Save