foldershare-8.x-1.2/src/Plugin/FolderShareCommand/DeleteBase.php
src/Plugin/FolderShareCommand/DeleteBase.php
<?php
namespace Drupal\foldershare\Plugin\FolderShareCommand;
use Drupal\Core\Form\FormStateInterface;
use Drupal\foldershare\Settings;
use Drupal\foldershare\Entity\FolderShare;
/**
* Provides the base class for command plugins that delete files or folders.
*
* The command deletes all selected entities. Deletion recurses and
* deletes all folder content as well.
*
* Configuration parameters:
* - 'parentId': the parent folder, if any.
* - 'selectionIds': selected entities to delete.
*
* @ingroup foldershare
*/
class DeleteBase extends FolderShareCommandBase {
/*--------------------------------------------------------------------
*
* Configuration form.
*
*--------------------------------------------------------------------*/
/**
* {@inheritdoc}
*/
public function hasConfigurationForm() {
return TRUE;
}
/**
* {@inheritdoc}
*/
public function getDescription(bool $forPage) {
if ($forPage === TRUE) {
return $this->getDescriptionForPage();
}
return $this->getDescriptionForDialog();
}
/**
* Returns a description for the page.
*
* @return \Drupal\Core\StringTranslation\TranslatableMarkup
* Returns the description for the form. Return an empty string for
* no description.
*/
private function getDescriptionForPage() {
$selectionIds = $this->getSelectionIds();
//
// Handle single-item case.
// ------------------------
// Be specific on the kind of item being deleted.
if (count($selectionIds) === 1) {
$item = FolderShare::load(reset($selectionIds));
$isShared = $item->getRootItem()->isAccessShared();
$kind = $item->getKind();
unset($item);
if ($isShared === TRUE) {
return t(
'Delete this shared @operand? This will affect all users sharing it. This cannot be undone.',
[
'@operand' => FolderShare::translateKind($kind),
]);
}
return t(
'Delete this @operand? This cannot be undone.',
[
'@operand' => FolderShare::translateKind($kind),
]);
}
//
// Handle multiple item case.
// --------------------------
// With multiple items to delete, use plural wording. Try to be specific
// on the kind of items being deleted, if they are all of the same kind.
$selectionKinds = FolderShare::findKindsForIds($selectionIds);
if (count($selectionKinds) === 1) {
$operand = FolderShare::translateKinds(key($selectionKinds));
}
else {
$operand = FolderShare::translateKinds('items');
}
// If there is no parent, then the selection are all root items.
// Load them all and check if any of them are shared.
//
// If there is a parent, then just check that parent to get the root
// and see if it is shared. Don't load the selection.
$parent = $this->getParent();
if ($parent === NULL) {
$isShared = FALSE;
foreach ($selectionIds as $id) {
$item = FolderShare::load($id);
if ($item === NULL) {
// The item does not exist.
continue;
}
if ($item->isAccessShared() === TRUE) {
$isShared = TRUE;
unset($item);
break;
}
unset($item);
}
}
else {
$root = $parent->getRootItem();
$isShared = $root->isAccessShared();
unset($root);
}
// Garbage collect.
gc_collect_cycles();
if ($isShared === TRUE) {
return t(
'Delete these shared @operand? This will affect all users sharing them. This cannot be undone.',
[
'@operand' => $operand,
]);
}
return t(
'Delete these @operand? This cannot be undone.',
[
'@operand' => $operand,
]);
}
/**
* Returns a description for the dialog.
*
* @return \Drupal\Core\StringTranslation\TranslatableMarkup[]
* Returns an array containing the primary and secondary description for
* the form. The primary description is often brief and in bold, while the
* secondary description provides more explanation and is not bold.
* The returned array may be empty if there is no description, or it may
* contain only a single message if there is only a primary description.
*/
private function getDescriptionForDialog() {
$selectionIds = $this->getSelectionIds();
//
// Handle single item.
// -------------------
// With one item, include the item's name.
$nItems = count($selectionIds);
if ($nItems === 1) {
$item = FolderShare::load(reset($selectionIds));
$isShared = $item->getRootItem()->isAccessShared();
$kind = $item->getKind();
$name = $item->getName();
unset($item);
if ($isShared === TRUE) {
return [
t(
'Delete shared @operand "@name"?',
[
'@operand' => FolderShare::translateKind($kind),
'@name' => $name,
]),
t('This item is shared. Deleting it may affect other users. This cannot be undone.'),
];
}
return [
t(
'Delete @operand "@name"?',
[
'@operand' => FolderShare::translateKind($kind),
'@name' => $name,
]),
t('This cannot be undone.'),
];
}
//
// Handle multiple items.
// ----------------------
// With multiple items, include the items' kind.
$selectionKinds = FolderShare::findKindsForIds($selectionIds);
if (count($selectionKinds) === 1) {
$operand = FolderShare::translateKinds(key($selectionKinds));
}
else {
$operand = FolderShare::translateKinds('items');
}
// If there is no parent, then the selection are all root items.
// Load them all and check if any of them are shared.
//
// If there is a parent, then just check that parent to get the root
// and see if it is shared. Don't load the selection.
$someShared = FALSE;
$allShared = FALSE;
$parent = $this->getParent();
if ($parent === NULL) {
$nShared = 0;
foreach ($selectionIds as $id) {
$item = FolderShare::load($id);
if ($item === NULL) {
// The item does not exist.
continue;
}
if ($item->isAccessShared() === TRUE) {
$nShared++;
}
unset($item);
}
if ($nShared !== 0) {
if (count($selectionIds) === $nShared) {
$allShared = TRUE;
}
else {
$someShared = TRUE;
}
}
}
else {
$root = $parent->getRootItem();
$allShared = $root->isAccessShared();
unset($root);
}
// Garbage collect.
gc_collect_cycles();
if ($allShared === TRUE) {
return [
t(
'Delete @count shared @operand?',
[
'@count' => $nItems,
'@operand' => $operand,
]),
t(
'These @operand are shared. Deleting them may affect other users. This cannot be undone.',
[
'@operand' => $operand,
]),
];
}
if ($someShared === TRUE) {
return [
t(
'Delete @count @operand?',
[
'@count' => $nItems,
'@operand' => $operand,
]),
t(
'Some of these @operand are shared. Deleting them may affect other users. This cannot be undone.',
[
'@operand' => $operand,
]),
];
}
return [
t(
'Delete @count @operand?',
[
'@count' => $nItems,
'@operand' => $operand,
]),
t('This cannot be undone.'),
];
}
/**
* {@inheritdoc}
*/
public function getTitle(bool $forPage) {
// The title varies for page vs. dialog:
//
// - Dialog: "Delete".
//
// - Page: "Delete NAME?", "Delete shared NAME"", "Delete COUNT OPERANDS?",
// or "Delete COUNT shared OPERANDS?". This follows Drupal convention.
if ($forPage === FALSE) {
return t('Delete');
}
$selectionIds = $this->getSelectionIds();
//
// Handle single item.
// -------------------
// Load the item and determine if it is shared.
if (count($selectionIds) === 1) {
$item = FolderShare::load($selectionIds[0]);
$isShared = $item->getRootItem()->isAccessShared();
$name = $item->getName();
unset($name);
if ($isShared === TRUE) {
return t(
'Delete shared "@name"?',
[
'@name' => $name,
]);
}
else {
return t(
'Delete "@name"?',
[
'@name' => $name,
]);
}
}
//
// Handle multiple items.
// ----------------------
// When there are multiple items, determine if they are of uniform
// kind or mixed.
$selectionKinds = FolderShare::findKindsForIds($selectionIds);
if (count($selectionKinds) === 1) {
$operand = FolderShare::translateKinds(key($selectionKinds));
}
else {
$operand = FolderShare::translateKinds('items');
}
// If there is no parent, then the selection are all root items.
// Load them all and check if any of them are shared.
//
// If there is a parent, then just check that parent to get the root
// and see if it is shared. Don't load the selection.
$allShared = FALSE;
if ($this->parent === NULL) {
$nShared = 0;
foreach ($selectionIds as $id) {
$item = FolderShare::load($id);
if ($item === NULL) {
// The item does not exist.
continue;
}
if ($item->isAccessShared() === TRUE) {
$nShared++;
}
unset($item);
}
if ($nShared !== 0) {
if (count($selectionIds) === $nShared) {
$allShared = TRUE;
}
}
}
else {
$root = $this->parent->getRootItem();
$allShared = $root->isAccessShared();
unset($root);
}
// Garbage collect.
gc_collect_cycles();
// Include the count and operand kind.
if ($allShared === TRUE) {
return t(
"Delete @count shared @operand?",
[
'@count' => count($selectionIds),
'@operand' => $operand,
]);
}
return t(
"Delete @count @operand?",
[
'@count' => count($selectionIds),
'@operand' => $operand,
]);
}
/**
* {@inheritdoc}
*/
public function getSubmitButtonName() {
return t('Delete');
}
/**
* {@inheritdoc}
*/
public function buildConfigurationForm(
array $form,
FormStateInterface $formState) {
// The command wrapper provides form basics:
// - Attached libraries.
// - Page title (if not an AJAX dialog).
// - Description (from ::getDescription()).
// - Submit buttion (labeled with ::getSubmitButtonName()).
// - Cancel button (if AJAX dialog).
$form['#attributes']['class'][] = 'confirmation';
$form['#theme'] = 'confirm_form';
return $form;
}
/**
* {@inheritdoc}
*/
public function validateConfigurationForm(
array &$form,
FormStateInterface $formState) {
// Nothing to do.
}
/**
* {@inheritdoc}
*/
public function submitConfigurationForm(
array &$form,
FormStateInterface $formState) {
$this->execute();
}
/*--------------------------------------------------------------------
*
* Execute.
*
*--------------------------------------------------------------------*/
/**
* {@inheritdoc}
*/
public function execute() {
$ids = $this->getSelectionIds();
try {
FolderShare::deleteMultiple($ids);
}
catch (\Exception $e) {
\Drupal::messenger()->addMessage($e->getMessage(), 'error');
}
if (Settings::getCommandNormalCompletionReportEnable() === TRUE) {
\Drupal::messenger()->addMessage(
\Drupal::translation()->formatPlural(
count($ids),
"The item has been deleted.",
"@count items have been deleted."),
'status');
}
}
}
