5 changed files with 292 additions and 0 deletions
@ -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: { } |
||||
@ -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: { } |
||||
@ -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(); |
||||
} |
||||
} |
||||
@ -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); |
||||
} |
||||
|
||||
} |
||||
@ -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…
Reference in new issue