Security update for Core, with self-updated composer
[yaffs-website] / web / core / modules / media / src / Form / MediaDeleteMultipleConfirmForm.php
1 <?php
2
3 namespace Drupal\media\Form;
4
5 use Drupal\Core\Entity\EntityTypeManagerInterface;
6 use Drupal\Core\Form\ConfirmFormBase;
7 use Drupal\Core\Form\FormStateInterface;
8 use Drupal\Core\Url;
9 use Drupal\user\PrivateTempStoreFactory;
10 use Symfony\Component\DependencyInjection\ContainerInterface;
11 use Symfony\Component\HttpFoundation\RedirectResponse;
12
13 /**
14  * Provides a confirmation form to delete multiple media items at once.
15  */
16 class MediaDeleteMultipleConfirmForm extends ConfirmFormBase {
17
18   /**
19    * The array of media items to delete, indexed by ID and language.
20    *
21    * @var string[][]
22    */
23   protected $mediaItems = [];
24
25   /**
26    * The tempstore factory.
27    *
28    * @var \Drupal\user\PrivateTempStoreFactory
29    */
30   protected $tempStoreFactory;
31
32   /**
33    * The entity storage.
34    *
35    * @var \Drupal\Core\Entity\EntityStorageInterface
36    */
37   protected $storage;
38
39   /**
40    * Constructs a MediaDeleteMultipleConfirmForm form object.
41    *
42    * @param \Drupal\user\PrivateTempStoreFactory $temp_store_factory
43    *   The tempstore factory.
44    * @param \Drupal\Core\Entity\EntityTypeManagerInterface $manager
45    *   The entity type manager.
46    */
47   public function __construct(PrivateTempStoreFactory $temp_store_factory, EntityTypeManagerInterface $manager) {
48     $this->tempStoreFactory = $temp_store_factory;
49     $this->storage = $manager->getStorage('media');
50   }
51
52   /**
53    * {@inheritdoc}
54    */
55   public static function create(ContainerInterface $container) {
56     return new static(
57       $container->get('user.private_tempstore'),
58       $container->get('entity_type.manager')
59     );
60   }
61
62   /**
63    * {@inheritdoc}
64    */
65   public function getFormId() {
66     return 'media_multiple_delete_confirm';
67   }
68
69   /**
70    * {@inheritdoc}
71    */
72   public function getQuestion() {
73     return $this->formatPlural(count($this->mediaItems), 'Are you sure you want to delete this item?', 'Are you sure you want to delete these items?');
74   }
75
76   /**
77    * {@inheritdoc}
78    */
79   public function getCancelUrl() {
80     // @todo Change to media library when #2834729 is done.
81     // https://www.drupal.org/node/2834729.
82     return new Url('system.admin_content');
83   }
84
85   /**
86    * {@inheritdoc}
87    */
88   public function getConfirmText() {
89     return $this->t('Delete');
90   }
91
92   /**
93    * {@inheritdoc}
94    *
95    * @todo Change to trait or base class when #2843395 is done.
96    * @see https://www.drupal.org/node/2843395
97    */
98   public function buildForm(array $form, FormStateInterface $form_state) {
99     $this->mediaItems = $this->tempStoreFactory->get('media_multiple_delete_confirm')->get($this->currentUser()->id());
100     if (empty($this->mediaItems)) {
101       return new RedirectResponse($this->getCancelUrl()->setAbsolute()->toString());
102     }
103     /** @var \Drupal\media\MediaInterface[] $entities */
104     $entities = $this->storage->loadMultiple(array_keys($this->mediaItems));
105
106     $items = [];
107     foreach ($this->mediaItems as $id => $langcodes) {
108       foreach ($langcodes as $langcode) {
109         $entity = $entities[$id]->getTranslation($langcode);
110         $key = $id . ':' . $langcode;
111         $default_key = $id . ':' . $entity->getUntranslated()->language()->getId();
112
113         // If we have a translated entity we build a nested list of translations
114         // that will be deleted.
115         $languages = $entity->getTranslationLanguages();
116         if (count($languages) > 1 && $entity->isDefaultTranslation()) {
117           $names = [];
118           foreach ($languages as $translation_langcode => $language) {
119             $names[] = $language->getName();
120             unset($items[$id . ':' . $translation_langcode]);
121           }
122           $items[$default_key] = [
123             'label' => [
124               '#markup' => $this->t('@label (Original translation) - <em>The following translations will be deleted:</em>', ['@label' => $entity->label()]),
125             ],
126             'deleted_translations' => [
127               '#theme' => 'item_list',
128               '#items' => $names,
129             ],
130           ];
131         }
132         elseif (!isset($items[$default_key])) {
133           $items[$key] = $entity->label();
134         }
135       }
136     }
137
138     $form['entities'] = [
139       '#theme' => 'item_list',
140       '#items' => $items,
141     ];
142     return parent::buildForm($form, $form_state);
143   }
144
145   /**
146    * {@inheritdoc}
147    *
148    * @todo Change to trait or base class when #2843395 is done.
149    * @see https://www.drupal.org/node/2843395
150    */
151   public function submitForm(array &$form, FormStateInterface $form_state) {
152     if ($form_state->getValue('confirm') && !empty($this->mediaItems)) {
153       $total_count = 0;
154       $delete_entities = [];
155       /** @var \Drupal\Core\Entity\ContentEntityInterface[][] $delete_translations */
156       $delete_translations = [];
157       /** @var \Drupal\media\MediaInterface[] $entities */
158       $entities = $this->storage->loadMultiple(array_keys($this->mediaItems));
159
160       foreach ($this->mediaItems as $id => $langcodes) {
161         foreach ($langcodes as $langcode) {
162           $entity = $entities[$id]->getTranslation($langcode);
163           if ($entity->isDefaultTranslation()) {
164             $delete_entities[$id] = $entity;
165             unset($delete_translations[$id]);
166             $total_count += count($entity->getTranslationLanguages());
167           }
168           elseif (!isset($delete_entities[$id])) {
169             $delete_translations[$id][] = $entity;
170           }
171         }
172       }
173
174       if ($delete_entities) {
175         $this->storage->delete($delete_entities);
176         $this->logger('media')->notice('Deleted @count media items.', ['@count' => count($delete_entities)]);
177       }
178
179       if ($delete_translations) {
180         $count = 0;
181         foreach ($delete_translations as $id => $translations) {
182           $entity = $entities[$id]->getUntranslated();
183           foreach ($translations as $translation) {
184             $entity->removeTranslation($translation->language()->getId());
185           }
186           $entity->save();
187           $count += count($translations);
188         }
189         if ($count) {
190           $total_count += $count;
191           $this->logger('media')->notice('Deleted @count media translations.', ['@count' => $count]);
192         }
193       }
194
195       if ($total_count) {
196         drupal_set_message($this->formatPlural($total_count, 'Deleted 1 media item.', 'Deleted @count media items.'));
197       }
198
199       $this->tempStoreFactory->get('media_multiple_delete_confirm')->delete(\Drupal::currentUser()->id());
200     }
201
202     // @todo Change to media library when #2834729 is done.
203     // https://www.drupal.org/node/2834729.
204     $form_state->setRedirect('system.admin_content');
205   }
206
207 }