3 namespace Drupal\entityqueue\Controller;
5 use Drupal\Core\Controller\ControllerBase;
6 use Drupal\Core\Entity\EntityInterface;
7 use Drupal\Core\Routing\RouteMatch;
8 use Drupal\entityqueue\EntityQueueInterface;
9 use Symfony\Component\HttpFoundation\Request;
10 use Drupal\Core\Ajax\AjaxResponse;
11 use Drupal\Core\Ajax\ReplaceCommand;
12 use Drupal\entityqueue\EntitySubqueueInterface;
14 use Drupal\Core\Routing\RouteMatchInterface;
15 use Drupal\Core\Access\AccessResult;
18 * Returns responses for Entityqueue UI routes.
20 class EntityQueueUIController extends ControllerBase {
23 * Provides a list of all the subqueues of an entity queue.
25 * @param \Drupal\entityqueue\EntityQueueInterface $entity_queue
31 public function subqueueList(EntityQueueInterface $entity_queue) {
32 $list_builder = $this->entityTypeManager()->getListBuilder('entity_subqueue');
33 $list_builder->setQueueId($entity_queue->id());
35 return $list_builder->render();
39 * Provides a list of subqueues where an entity can be added.
41 * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
43 * @param string $entity_type_id
44 * (optional) The entity type ID.
45 * @param \Drupal\Core\Entity\EntityInterface $entity
46 * (optional) An entity object.
49 * Array of page elements to render.
51 public function subqueueListForEntity(RouteMatchInterface $route_match, $entity_type_id = NULL, EntityInterface $entity = NULL) {
53 $entity = $route_match->getParameter($entity_type_id);
56 $queues = $this->getAvailableQueuesForEntity($entity);
57 $subqueues = $this->entityTypeManager()->getStorage('entity_subqueue')->loadByProperties(['queue' => array_keys($queues)]);
58 $list_builder = $this->entityTypeManager()->getListBuilder('entity_subqueue');
60 $build['#title'] = $this->t('Entityqueues for %title', ['%title' => $entity->label()]);
61 $build['#type'] = 'container';
62 $build['#attributes']['id'] = 'entity-subqueue-list';
63 $build['#attached']['library'][] = 'core/drupal.ajax';
66 '#header' => $list_builder->buildHeader(),
69 '#empty' => $this->t('There are no queues available.'),
72 /** @var \Drupal\entityqueue\EntitySubqueueInterface $subqueue */
73 foreach ($subqueues as $subqueue_id => $subqueue) {
74 $row = $list_builder->buildRow($subqueue);
76 // Check if entity is in queue
77 $subqueue_items = $subqueue->get('items')->getValue();
78 if (in_array($entity->id(), array_column($subqueue_items, 'target_id'), TRUE)) {
79 $row['operations']['data']['#links'] = [
81 'title' => $this->t('Remove from queue'),
82 'url' => Url::fromRoute('entity.entity_subqueue.remove_item', ['entity_queue' => $queues[$subqueue->bundle()]->id(), 'entity_subqueue' => $subqueue_id, 'entity' => $entity->id()]),
84 'class' => ['use-ajax'],
90 $row['operations']['data']['#links'] = [
92 'title' => $this->t('Add to queue'),
93 'url' => Url::fromRoute('entity.entity_subqueue.add_item', ['entity_queue' => $queues[$subqueue->bundle()]->id(), 'entity_subqueue' => $subqueue_id, 'entity' => $entity->id()]),
95 'class' => ['use-ajax'],
101 // Add an operation for editing the subqueue items.
102 // First, compute the destination to send the user back to the
103 // entityqueue tab they're currently on. We can't rely on <current>
104 // since if any of the AJAX links are used and the page is rebuilt,
105 // <current> will point to the most recent AJAX callback, not the
106 // original entityqueue tab.
107 $destination = Url::fromRoute("entity.$entity_type_id.entityqueue", [$entity_type_id => $entity->id()])->toString();
108 $row['operations']['data']['#links']['edit-subqueue-items'] = [
109 'title' => $this->t('Edit subqueue items'),
110 'url' => $subqueue->toUrl('edit-form', ['query' => ['destination' => $destination]]),
113 $build['table']['#rows'][$subqueue->id()] = $row;
120 * Returns a form to add a new subqeue.
122 * @param \Drupal\entityqueue\EntityQueueInterface $entity_queue
123 * The queue this subqueue will be added to.
126 * The entity subqueue add form.
128 public function addForm(EntityQueueInterface $entity_queue) {
129 $subqueue = $this->entityTypeManager()->getStorage('entity_subqueue')->create(['queue' => $entity_queue->id()]);
130 return $this->entityFormBuilder()->getForm($subqueue);
134 * Calls a method on an entity queue and reloads the listing page.
136 * @param \Drupal\entityqueue\EntityQueueInterface $entity_queue
137 * The view being acted upon.
139 * The operation to perform, e.g., 'enable' or 'disable'.
140 * @param \Symfony\Component\HttpFoundation\Request $request
141 * The current request.
143 * @return \Drupal\Core\Ajax\AjaxResponse|\Symfony\Component\HttpFoundation\RedirectResponse
144 * Either returns a rebuilt listing page as an AJAX response, or redirects
145 * back to the listing page.
147 public function ajaxOperation(EntityQueueInterface $entity_queue, $op, Request $request) {
148 // Perform the operation.
149 $entity_queue->$op()->save();
151 // If the request is via AJAX, return the rendered list as JSON.
152 if ($request->request->get('js')) {
153 $list = $this->entityTypeManager()->getListBuilder('entity_queue')->render();
154 $response = new AjaxResponse();
155 $response->addCommand(new ReplaceCommand('#entity-queue-list', $list));
159 // Otherwise, redirect back to the page.
160 return $this->redirect('entity.entity_queue.collection');
164 * Calls a method on an entity subqueue page and reloads the page.
166 * @param \Drupal\entityqueue\EntitySubqueueInterface $entity_subqueue
167 * The subqueue being acted upon.
169 * The operation to perform, e.g., 'addItem' or 'removeItem'.
170 * @param \Symfony\Component\HttpFoundation\Request $request
171 * The current request.
173 * @return \Drupal\Core\Ajax\AjaxResponse|\Symfony\Component\HttpFoundation\RedirectResponse
174 * Either returns a rebuilt listing page as an AJAX response, or redirects
175 * back to the current page.
177 public function subqueueAjaxOperation(EntitySubqueueInterface $entity_subqueue, $op, Request $request) {
178 $entity_id = $request->get('entity');
179 $entity = $this->entityTypeManager()->getStorage($entity_subqueue->getQueue()->getTargetEntityTypeId())->load($entity_id);
181 // Perform the operation.
182 $entity_subqueue->$op($entity)->save();
184 // If the request is via AJAX, return the rendered list as JSON.
185 if ($request->request->get('js')) {
186 $route_match = RouteMatch::createFromRequest($request);
187 $list = $this->subqueueListForEntity($route_match, $entity->getEntityTypeId(), $entity);
188 $response = new AjaxResponse();
189 $response->addCommand(new ReplaceCommand('#entity-subqueue-list', $list));
193 // Otherwise, redirect back to the page.
194 return $this->redirect('<current>');
198 * Checks access for a specific request.
200 * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
202 * @param string $entity_type_id
203 * (optional) The entity type ID.
205 * @return \Drupal\Core\Access\AccessResultInterface
208 public function access(RouteMatchInterface $route_match, $entity_type_id = NULL) {
209 /** @var \Drupal\Core\Entity\EntityInterface $entity */
210 $entity = $route_match->getParameter($entity_type_id);
212 if ($this->getAvailableQueuesForEntity($entity)) {
213 return AccessResult::allowed();
216 return AccessResult::forbidden();
220 * Gets a list of queues which can hold this entity.
222 * @param \Drupal\Core\Entity\EntityInterface $entity
225 * @return \Drupal\entityqueue\EntityQueueInterface[]
226 * An array of entity queues which can hold this entity.
228 protected function getAvailableQueuesForEntity(EntityInterface $entity) {
229 $storage = $this->entityTypeManager()->getStorage('entity_queue');
231 $queue_ids = $storage->getQuery()
232 ->condition('entity_settings.target_type', $entity->getEntityTypeId(), '=')
233 ->condition('status', TRUE)
236 $queues = $storage->loadMultiple($queue_ids);
237 $queues = array_filter($queues, function ($queue) use ($entity) {
238 /** @var \Drupal\entityqueue\EntityQueueInterface $queue */
239 $queue_settings = $queue->getEntitySettings();
240 $target_bundles = &$queue_settings['handler_settings']['target_bundles'];
241 return ($target_bundles === NULL || in_array($entity->bundle(), $target_bundles, TRUE));