858364fe407993efbb016559a05b190ebfe1a5de
[yaffs-website] / web / core / modules / system / src / Form / PrepareModulesEntityUninstallForm.php
1 <?php
2
3 namespace Drupal\system\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 Symfony\Component\DependencyInjection\ContainerInterface;
10 use Symfony\Component\HttpFoundation\RedirectResponse;
11 use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
12
13 /**
14  * Provides a form removing module content entities data before uninstallation.
15  */
16 class PrepareModulesEntityUninstallForm extends ConfirmFormBase {
17
18   /**
19    * The entity type ID of the entities to delete.
20    *
21    * @var string
22    */
23   protected $entityTypeId;
24
25   /**
26    * The entity type manager.
27    *
28    * @var \Drupal\Core\Entity\EntityTypeManagerInterface
29    */
30   protected $entityTypeManager;
31
32   /**
33    * Constructs a PrepareModulesEntityUninstallForm object.
34    *
35    * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
36    *   The entity type manager.
37    */
38   public function __construct(EntityTypeManagerInterface $entity_type_manager) {
39     $this->entityTypeManager = $entity_type_manager;
40   }
41
42   /**
43    * {@inheritdoc}
44    */
45   public static function create(ContainerInterface $container) {
46     return new static(
47       $container->get('entity_type.manager')
48     );
49   }
50
51   /**
52    * {@inheritdoc}
53    */
54   public function getFormId() {
55     return 'system_prepare_modules_entity_uninstall';
56   }
57
58   /**
59    * {@inheritdoc}
60    */
61   public function getQuestion() {
62     $entity_type = $this->entityTypeManager->getDefinition($this->entityTypeId);
63
64     return $this->t('Are you sure you want to delete all @entity_type_plural?', ['@entity_type_plural' => $entity_type->getPluralLabel()]);
65   }
66
67   /**
68    * {@inheritdoc}
69    */
70   public function getDescription() {
71     return $this->t('This action cannot be undone.<br />Make a backup of your database if you want to be able to restore these items.');
72   }
73
74   /**
75    * {@inheritdoc}
76    */
77   public function getConfirmText() {
78     $entity_type = $this->entityTypeManager->getDefinition($this->entityTypeId);
79
80     return $this->t('Delete all @entity_type_plural', ['@entity_type_plural' => $entity_type->getPluralLabel()]);
81   }
82
83   /**
84    * {@inheritdoc}
85    */
86   public function getCancelUrl() {
87     return Url::fromRoute('system.modules_uninstall');
88   }
89
90   /**
91    * {@inheritdoc}
92    */
93   public function buildForm(array $form, FormStateInterface $form_state, $entity_type_id = NULL) {
94     $this->entityTypeId = $entity_type_id;
95     if (!$this->entityTypeManager->hasDefinition($this->entityTypeId)) {
96       throw new NotFoundHttpException();
97     }
98     $form = parent::buildForm($form, $form_state);
99
100     $storage = $this->entityTypeManager->getStorage($entity_type_id);
101     $count = $storage->getQuery()->count()->execute();
102
103     $form['entity_type_id'] = [
104       '#type' => 'value',
105       '#value' => $entity_type_id,
106     ];
107
108     // Display a list of the 10 entity labels, if possible.
109     $entity_type = $this->entityTypeManager->getDefinition($entity_type_id);
110     if ($count == 0) {
111       $form['total'] = [
112         '#markup' => $this->t(
113           'There are 0 @entity_type_plural to delete.',
114           ['@entity_type_plural' => $entity_type->getPluralLabel()]
115         ),
116       ];
117     }
118     elseif ($entity_type->hasKey('label')) {
119       $recent_entity_ids = $storage->getQuery()
120         ->sort($entity_type->getKey('id'), 'DESC')
121         ->pager(10)
122         ->execute();
123       $recent_entities = $storage->loadMultiple($recent_entity_ids);
124
125       $labels = [];
126       foreach ($recent_entities as $entity) {
127         $labels[] = $entity->label();
128       }
129
130       if ($labels) {
131         $form['recent_entity_labels'] = [
132           '#theme' => 'item_list',
133           '#items' => $labels,
134         ];
135         $more_count = $count - count($labels);
136         $form['total'] = [
137           '#markup' => $this->formatPlural(
138             $more_count,
139             'And <strong>@count</strong> more @entity_type_singular.',
140             'And <strong>@count</strong> more @entity_type_plural.',
141             [
142               '@entity_type_singular' => $entity_type->getSingularLabel(),
143               '@entity_type_plural' => $entity_type->getPluralLabel(),
144             ]
145           ),
146           '#access' => (bool) $more_count,
147         ];
148       }
149     }
150     else {
151       $form['total'] = [
152         '#markup' => $this->formatPlural(
153           $count,
154           'This will delete <strong>@count</strong> @entity_type_singular.',
155           'This will delete <strong>@count</strong> @entity_type_plural.',
156           [
157             '@entity_type_singular' => $entity_type->getSingularLabel(),
158             '@entity_type_plural' => $entity_type->getPluralLabel(),
159           ]
160         )
161       ];
162     }
163
164     $form['description']['#prefix'] = '<p>';
165     $form['description']['#suffix'] = '</p>';
166     $form['description']['#weight'] = 5;
167
168     // Only show the delete button if there are entities to delete.
169     $form['actions']['submit']['#access'] = (bool) $count;
170
171     return $form;
172   }
173
174   /**
175    * {@inheritdoc}
176    */
177   public function submitForm(array &$form, FormStateInterface $form_state) {
178     $entity_type_id = $form_state->getValue('entity_type_id');
179
180     $entity_type_plural = $this->entityTypeManager->getDefinition($entity_type_id)->getPluralLabel();
181     $batch = [
182       'title' => t('Deleting @entity_type_plural', [
183         '@entity_type_plural' => $entity_type_plural,
184       ]),
185       'operations' => [
186         [
187           [__CLASS__, 'deleteContentEntities'], [$entity_type_id],
188         ],
189       ],
190       'finished' => [__CLASS__, 'moduleBatchFinished'],
191       'progress_message' => '',
192     ];
193     batch_set($batch);
194   }
195
196   /**
197    * Deletes the content entities of the specified entity type.
198    *
199    * @param string $entity_type_id
200    *   The entity type ID from which data will be deleted.
201    * @param array|\ArrayAccess $context
202    *   The batch context array, passed by reference.
203    *
204    * @internal
205    *   This batch callback is only meant to be used by this form.
206    */
207   public static function deleteContentEntities($entity_type_id, &$context) {
208     $storage = \Drupal::entityTypeManager()->getStorage($entity_type_id);
209
210     // Set the entity type ID in the results array so we can access it in the
211     // batch finished callback.
212     $context['results']['entity_type_id'] = $entity_type_id;
213
214     if (!isset($context['sandbox']['progress'])) {
215       $context['sandbox']['progress'] = 0;
216       $context['sandbox']['max'] = $storage->getQuery()->count()->execute();
217     }
218
219     $entity_type = \Drupal::entityTypeManager()->getDefinition($entity_type_id);
220     $entity_ids = $storage->getQuery()
221       ->sort($entity_type->getKey('id'), 'ASC')
222       ->range(0, 10)
223       ->execute();
224     if ($entities = $storage->loadMultiple($entity_ids)) {
225       $storage->delete($entities);
226     }
227     // Sometimes deletes cause secondary deletes. For example, deleting a
228     // taxonomy term can cause it's children to be be deleted too.
229     $context['sandbox']['progress'] = $context['sandbox']['max'] - $storage->getQuery()->count()->execute();
230
231     // Inform the batch engine that we are not finished and provide an
232     // estimation of the completion level we reached.
233     if (count($entity_ids) > 0 && $context['sandbox']['progress'] != $context['sandbox']['max']) {
234       $context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
235       $context['message'] = t('Deleting items... Completed @percentage% (@current of @total).', ['@percentage' => round(100 * $context['sandbox']['progress'] / $context['sandbox']['max']), '@current' => $context['sandbox']['progress'], '@total' => $context['sandbox']['max']]);
236
237     }
238     else {
239       $context['finished'] = 1;
240     }
241   }
242
243   /**
244    * Implements callback_batch_finished().
245    *
246    * Finishes the module batch, redirect to the uninstall page and output the
247    * successful data deletion message.
248    */
249   public static function moduleBatchFinished($success, $results, $operations) {
250     $entity_type_plural = \Drupal::entityTypeManager()->getDefinition($results['entity_type_id'])->getPluralLabel();
251     drupal_set_message(t('All @entity_type_plural have been deleted.', ['@entity_type_plural' => $entity_type_plural]));
252
253     return new RedirectResponse(Url::fromRoute('system.modules_uninstall')->setAbsolute()->toString());
254   }
255
256 }