foldershare-8.x-1.2/src/Entity/Builder/FolderShareBreadcrumbBuilder.php

src/Entity/Builder/FolderShareBreadcrumbBuilder.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
<?php
 
namespace Drupal\foldershare\Entity\Builder;
 
use Drupal\Core\Breadcrumb\Breadcrumb;
use Drupal\Core\Breadcrumb\BreadcrumbBuilderInterface;
use Drupal\Core\Controller\TitleResolver;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Access\AccessManagerInterface;
use Drupal\Core\Link;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Routing\RouteProviderInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Symfony\Component\HttpFoundation\Request;
 
use Drupal\foldershare\Constants;
use Drupal\foldershare\FolderShareInterface;
use Drupal\foldershare\Entity\FolderShare;
 
/**
 * Builds a page breadcrumb showing the ancestors of the given entity.
 *
 * <B>Warning:</B> This class is strictly internal to the FolderShare
 * module. The class's existance, name, and content may change from
 * release to release without any promise of backwards compatability.
 *
 * This class builds a breadcrumb that includes a chain of links to
 * each of the ancestors of the given entity. The chain starts with a link
 * to the site's home page. This is followed by a link to the canonical
 * root folder list page. The remaining links lead to ancestors of the
 * entity. Per Drupal convention, the entity itself is not included on
 * the end of the breadcrumb.
 *
 * <b>Service:</b>
 * A service for this breadcrumb builder should be registered in
 * MODULE.services.yml.
 *
 * <b>Parameters:</b>
 * The service for this breadcrumb builder must pass a FolderShare entity.
 *
 * @ingroup foldershare
 *
 * @see \Drupal\foldershare\Entity\FolderShare
 */
class FolderShareBreadcrumbBuilder implements BreadcrumbBuilderInterface {
 
  use StringTranslationTrait;
 
  /*---------------------------------------------------------------------
   *
   * Fields.
   *
   * These fields cache values from construction and dependency injection.
   *
   *---------------------------------------------------------------------*/
 
  /**
   * The entity storage manager, set at construction time.
   *
   * @var \Drupal\Core\Entity\EntityStorageInterface
   */
  protected $entityStorage;
 
  /**
   * The route provider, set at construction time.
   *
   * @var \Drupal\Core\Routing\RouteProviderInterface
   */
  protected $routeProvider;
 
  /**
   * The current user account, set at construction time.
   *
   * @var \Drupal\Core\Session\AccountInterface
   */
  protected $currentUser;
 
  /**
   * The route title resolver, set at construction time.
   *
   * @var \Drupal\Core\Controller\TitleResolver
   */
  protected $titleResolver;
 
  /*---------------------------------------------------------------------
   *
   * Construct.
   *
   *---------------------------------------------------------------------*/
 
  /**
   * Constructs the bread crumb builder.
   *
   * The arguments here must match those in the service declaration in
   * MODULE.services.yml.
   *
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager
   *   The entity manager service for the FolderShare entity type.
   * @param \Drupal\Core\Routing\RouteProviderInterface $routeProvider
   *   The route provider services.
   * @param \Drupal\Core\Access\AccessManagerInterface $accessManager
   *   The access manager service.
   * @param \Drupal\Core\Session\AccountInterface $currentUser
   *   The current user account.
   * @param \Drupal\Core\Controller\TitleResolver $titleResolver
   *   The page title resolver.
   */
  public function __construct(
    EntityTypeManagerInterface $entityTypeManager,
    RouteProviderInterface $routeProvider,
    AccessManagerInterface $accessManager,
    AccountInterface $currentUser,
    TitleResolver $titleResolver) {
 
    $this->entityStorage = $entityTypeManager->getStorage(FolderShare::ENTITY_TYPE_ID);
    $this->currentUser   = $currentUser;
    $this->routeProvider = $routeProvider;
    $this->titleResolver = $titleResolver;
  }
 
  /*---------------------------------------------------------------------
   *
   * Build.
   *
   *---------------------------------------------------------------------*/
 
  /**
   * {@inheritdoc}
   */
  public function applies(RouteMatchInterface $routeMatch) {
    //
    // There are several cases where this breadcrumb builder applies:
    //
    // - The route names the root folder groups page, or one of the individual
    //   group pages.
    //
    // - The route names a single FolderShare entity, such as for a view
    //   or edit page.
    //
    // - The route is for a "command" form that works with a selection
    //   of FolderShare entities, such as for delete, rename, copy, move,
    //   or change owner.
    //
    $routeName = $routeMatch->getRouteName();
 
    switch ($routeName) {
      case Constants::ROUTE_FOLDERSHARE_COMMAND_FORM:
        // The route is for a command form. Get the encoded parameter,
        // which should be there for all command form routes.
        $encoded = $routeMatch->getRawParameter('encoded');
        return ($encoded !== NULL);
 
      case Constants::ROUTE_FOLDERSHARE:
        // The route is for an entity page. There should be a FolderShare
        // entity ID.
        $entity = $routeMatch->getParameter(FolderShare::ENTITY_TYPE_ID);
        return ($entity instanceof FolderShareInterface);
 
      case Constants::ROUTE_ROOT_ITEMS_PERSONAL:
      case Constants::ROUTE_ROOT_ITEMS_PUBLIC:
      case Constants::ROUTE_ROOT_ITEMS_ALL:
        // The route is for page listing root items.
        return TRUE;
 
      default:
        // The route is not recognized.
        return FALSE;
    }
  }
 
  /**
   * {@inheritdoc}
   */
  public function build(RouteMatchInterface $routeMatch) {
    //
    // There are three cases this breadcrumb builder needs to handle:
    //
    // - The route names a single FolderShare entity, such as for a view
    //   or edit page.
    //
    // - The route is for a "command" form that works with a selection
    //   of FolderShare entities, such as for delete, rename, copy, move,
    //   or change owner.
    //
    // - The route is for FolderShare, but there is no entity ID. This can
    //   be for the main root folder groups page, or for one of the group
    //   pages.
    //
    $routeName = $routeMatch->getRouteName();
 
    switch ($routeName) {
      case Constants::ROUTE_FOLDERSHARE_COMMAND_FORM:
        // The route is for a command form.
        return $this->buildForCommandForm($routeMatch);
 
      case Constants::ROUTE_FOLDERSHARE:
        // The route is for an entity page. There should be a FolderShare
        // entity ID.
        $entity = $routeMatch->getParameter(FolderShare::ENTITY_TYPE_ID);
        if ($entity !== NULL) {
          return $this->buildForEntityPage($routeMatch, $entity);
        }
 
        // The route is for an entity, but the entity isn't ours. This
        // should not occur because the applies() method earlier should
        // already have rejected such a page.
        return $this->buildDefault($routeMatch);
 
      case Constants::ROUTE_ROOT_ITEMS_PERSONAL:
      case Constants::ROUTE_ROOT_ITEMS_PUBLIC:
      case Constants::ROUTE_ROOT_ITEMS_ALL:
        // The route is for page listing root items.
        return $this->buildForRootListPage($routeMatch);
 
      default:
        // The route is not recognized. This should not occur because
        // the applies() method earlier should already have rejected
        // such a page.
        return $this->buildDefault($routeMatch);
    }
  }
 
  /**
   * Builds an array of breadcrumb links when there is no entity or form.
   *
   * When a page is for FolderShare, but it doesn't have an entity ID or
   * command form parameters, we cannot build a breadcrumb of ancestor
   * links. Instead, this function returns an abbreviated breadcrumb that
   * only includes a home page link and a root folder list link.
   *
   * @param \Drupal\Core\Routing\RouteMatchInterface $routeMatch
   *   The route description, including the name of the route and its
   *   parameters.
   *
   * @return \Drupal\Core\Link[]
   *   Returns an array of links for the breadcrumb, from the site's home
   *   page to the current FolderShare entity.
   */
  private function buildDefault(RouteMatchInterface $routeMatch) {
    //
    // Cache control
    // -------------
    // Breadcrumbs vary per user because viewing permissions
    // vary per user role and per folder.
    $breadcrumb = new Breadcrumb();
    $breadcrumb->addCacheableDependency($this->currentUser);
    $breadcrumb->addCacheableDependency($routeMatch);
 
    $dummyRequest = new Request();
 
    //
    // Link to home page
    // -----------------
    // The first link goes to the site's home page.
    $links = [];
    $route = $this->routeProvider->getRouteByName('<front>');
    $title = $this->titleResolver->getTitle($dummyRequest, $route);
    $links[] = Link::createFromRoute($title, '<front>');
 
    $breadcrumb->setLinks($links);
    return $breadcrumb;
  }
 
  /**
   * Builds an array of breadcrumb links for a root list page.
   *
   * When a page is for a root list, we cannot build a breadcrumb of ancestor
   * links. Instead, this function returns an abbreviated breadcrumb that
   * only includes a home page link.
   *
   * @param \Drupal\Core\Routing\RouteMatchInterface $routeMatch
   *   The route description, including the name of the route and its
   *   parameters.
   *
   * @return \Drupal\Core\Link[]
   *   Returns an array of links for the breadcrumb, from the site's home
   *   page to the current FolderShare entity.
   */
  private function buildForRootListPage(
    RouteMatchInterface $routeMatch) {
    //
    // Cache control
    // -------------
    // Breadcrumbs vary per user because viewing permissions
    // vary per user role and per folder.
    $breadcrumb = new Breadcrumb();
    $breadcrumb->addCacheableDependency($this->currentUser);
    $breadcrumb->addCacheableDependency($routeMatch);
 
    $dummyRequest = new Request();
 
    //
    // Link to home page
    // -----------------
    // The first link goes to the site's home page.
    $links = [];
    $route = $this->routeProvider->getRouteByName('<front>');
    $title = $this->titleResolver->getTitle($dummyRequest, $route);
    $links[] = Link::createFromRoute($title, '<front>');
 
    $breadcrumb->setLinks($links);
    return $breadcrumb;
  }
 
  /**
   * Builds an array of breadcrumb links for a FolderShare entity page.
   *
   * FolderShare entity pages are those that view or edit a single entity
   * and where the ID of the entity is a well-known argument on the URL.
   *
   * For these pages, this function gets the ancestors of the entity and
   * returns an array of links to those ancestors. The first link in the
   * returned array is, by convention, for the site's home page. The next
   * link is for the canonical root folder list. The next links are for
   * ancestors, from the root folder to the parent of the page's item.
   * The last link in the returned array is for the page's item.
   *
   * @param \Drupal\Core\Routing\RouteMatchInterface $routeMatch
   *   The route description, including the name of the route and its
   *   parameters.
   * @param \Drupal\foldershare\FolderShareInterface $item
   *   The FolderShare entity for the breadcrumbs.
   * @param bool $includeItem
   *   When TRUE, the current FolderShare entity (whether a file or a folder)
   *   is included at the end of the breadcrumb. When FALSE, it is not.
   *
   * @return \Drupal\Core\Link[]
   *   Returns an array of links for the breadcrumb, from the site's home
   *   page to the current FolderShare entity.
   */
  private function buildForEntityPage(
    RouteMatchInterface $routeMatch,
    FolderShareInterface $item,
    bool $includeItem = FALSE) {
 
    //
    // Cache control
    // -------------
    // Breadcrumbs vary per user because viewing permissions
    // vary per user role and per folder.
    $breadcrumb = new Breadcrumb();
    $breadcrumb->addCacheableDependency($this->currentUser);
    $breadcrumb->addCacheableDependency($routeMatch);
 
    $currentRequest = \Drupal::request();
    $dummyRequest = new Request();
 
    //
    // Link to home page.
    // ------------------
    // Link to the site's home page.
    $links = [];
    $route = $this->routeProvider->getRouteByName('<front>');
    $title = $this->titleResolver->getTitle($dummyRequest, $route);
    $links[] = Link::createFromRoute($title, '<front>');
 
    //
    // Link to root list page.
    // -----------------------
    // Link to one of the root list pages.
    //
    // Several cases:
    // - The root is owned by the current user.
    //   - If the current user is anonymous, use PUBLIC_ROOT_LIST.
    //   - Otherwise use USER_ROOT_LIST.
    //
    // - The root is owned by someone else.
    //   - If the current user is an admin, use ALL_ROOT_LIST.
    //   - If the root is shared with anonymous, use PUBLIC_ROOT_LIST.
    //   - Otherwise use USER_ROOT_LIST.
    $rootItem = $item->getRootItem();
    $rootOwner = $rootItem->getOwner();
 
    if ((int) $this->currentUser->id() === (int) $rootOwner->id()) {
      if ($this->currentUser->isAnonymous() === TRUE) {
        $routeName = Constants::ROUTE_ROOT_ITEMS_PUBLIC;
      }
      else {
        $routeName = Constants::ROUTE_ROOT_ITEMS_PERSONAL;
      }
    }
    elseif ($this->currentUser->hasPermission(Constants::ADMINISTER_PERMISSION) === TRUE) {
      $routeName = Constants::ROUTE_ROOT_ITEMS_ALL;
    }
    elseif ($this->currentUser->isAnonymous() === TRUE) {
      $routeName = Constants::ROUTE_ROOT_ITEMS_PUBLIC;
    }
    elseif ($rootItem->isAccessPublic() === TRUE) {
      $routeName = Constants::ROUTE_ROOT_ITEMS_PUBLIC;
    }
    else {
      $routeName = Constants::ROUTE_ROOT_ITEMS_PERSONAL;
    }
 
    $route = $this->routeProvider->getRouteByName($routeName);
    $title = $this->titleResolver->getTitle($dummyRequest, $route);
    $links[] = Link::createFromRoute($title, $routeName);
 
    //
    // Link to ancestors
    // -----------------
    // When VIEWing a file or folder, the breadcrumb ends with the
    // parent folder.
    //
    // When EDITing a file or folder, the breadcrumb ends with the action
    // after the item name.
    //
    // Distinguishing between these is a little awkward. VIEW routes
    // do not have a fixed title because the title comes
    // via a callback to get the item's title.  For EDIT routes,
    // there is a fixed title.
    //
    // Get ancestors of this item. The list does not include this item.
    // The first entry in the list is the root.
    $ancestors = $item->findAncestorFolders();
 
    // Loop through the ancestors, starting at the root. For each one,
    // add a link to the item's page.
    $routeName = Constants::ROUTE_FOLDERSHARE;
    $routeParam = Constants::ROUTE_FOLDERSHARE_ID;
 
    foreach ($ancestors as $ancestor) {
      // Breadcrumb cacheing also depends on this ancestor.
      $breadcrumb->addCacheableDependency($ancestor);
 
      // The BreadcrumbBuilderInterface that this class is implementing,
      // and the build() method in particular, is required to return a
      // Breadcrumb object. And that object is strictly a list of Link
      // objects.
      //
      // This is a problem here because an ancestor might not provide
      // 'view' access to this account. If it does not, we'd like to
      // return straight text instead of a link, since clicking on
      // the link would get an error anyway.
      //
      // Unfortunately, there is no way to do this. We must return
      // a Link, regardless of viewing permissions.
      //
      // No need to HTML escape the folder name here. This is done
      // automatically by Link.
      $links[] = Link::createFromRoute(
        $ancestor->getName(),
        $routeName,
        [$routeParam => (int) $ancestor->id()]);
    }
 
    // The last item in the link array is either:
    // - The entity's page if the current route is for editing it.
    // - A parent entity when a command is operating on its children.
    $route = $routeMatch->getRouteObject();
    $addedLast = FALSE;
 
    if ($route !== NULL) {
      $breadcrumb->addCacheableDependency($route);
      $title = $this->titleResolver->getTitle($currentRequest, $route);
      if (empty($title) === FALSE) {
        // Yes, the route has a title. This is for an edit page.
        // Add a link to the view page for the entity.
        $links[] = Link::createFromRoute(
          $item->getName(),
          $routeName,
          [$routeParam => $item->id()]);
 
        $addedLast = TRUE;
      }
    }
 
    if ($includeItem === TRUE && $addedLast === FALSE) {
      // This is a command and we're showing its edit/confirmation form.
      // Add a link to the view page for the entity.
      $links[] = Link::createFromRoute(
        $item->getName(),
        $routeName,
        [$routeParam => $item->id()]);
    }
 
    // Breadcrumbs vary per item.
    $breadcrumb->addCacheableDependency($item);
 
    $breadcrumb->setLinks($links);
    return $breadcrumb;
  }
 
  /**
   * Builds an array of breadcrumb links for a FolderShare command form.
   *
   * FolderShare command forms are a response from a command plugin.
   * Such plugins are invoked from the GUI menu and they may have multiple
   * values, including:
   * - an optional parent folder.
   * - an optional destination folder (such as for move and copy).
   * - an optional selection.
   *
   * The selection may have any number of FolderShare entity IDs, with any
   * mix of kinds. There may be no selection. And there may be no parent
   * or destination.
   *
   * All of these parameters are encoded as a single cryptic argument on
   * the command form URL - because they are too much and too complex to
   * encode with ? arguments, and because it would encourage users to fiddle
   * with them. This means they all come through as a single "encoded"
   * argument on the route.
   *
   * This function returns breadcrumbs based upon the decoded argument.
   *
   * @param \Drupal\Core\Routing\RouteMatchInterface $routeMatch
   *   The route description, including the name of the route and its
   *   parameters.
   *
   * @return \Drupal\Core\Link[]
   *   Returns an array of links for the breadcrumb, from the site's home
   *   page to the current FolderShare entity.
   */
  private function buildForCommandForm(RouteMatchInterface $routeMatch) {
    //
    // Command parameters
    // ------------------
    // Get the encoded parameters and decode them.
    $encoded = $routeMatch->getRawParameter('encoded');
    $parameters = (array) json_decode(base64_decode($encoded), TRUE);
 
    // If there are no parameters (which should not be possible), then
    // we can only build a generic abbreviated breadcrumb.
    if (empty($parameters) === TRUE ||
        isset($parameters['configuration']) === FALSE) {
      return $this->buildDefault($routeMatch);
    }
 
    $configuration = (array) $parameters['configuration'];
 
    // If there is a selection, and the selection has just one entity ID,
    // then we can build a normal breadcrumb using that entity ID.
    if (isset($configuration['selectionIds']) === TRUE) {
      $selectionIds = $configuration['selectionIds'];
 
      if (count($selectionIds) === 1) {
        $itemId = $selectionIds[0];
        $item = FolderShare::load($itemId);
        if ($item === NULL) {
          // The selection ID is bad. Revert to the default breadcrumb.
          return $this->buildDefault($routeMatch);
        }
 
        // Use the item to build an entity page breadcrumb.
        return $this->buildForEntityPage($routeMatch, $item, TRUE);
      }
 
      // Otherwise the selection is empty or it has more than one items.
    }
 
    // If there is a parent, use it.
    if (isset($configuration['parentId']) === TRUE) {
      $parentId = $configuration['parentId'];
      $item = FolderShare::load($parentId);
      if ($item === NULL) {
        // The parent ID is bad. Revert to the default breadcrumb.
        return $this->buildDefault($routeMatch);
      }
 
      // Use the item to build an entity page breadcrumb.
      return $this->buildForEntityPage($routeMatch, $item, TRUE);
    }
 
    // There is no selection and no parent. It doesn't make sense to use
    // the destination ID, so fall back to the default breadcrumb.
    return $this->buildDefault($routeMatch);
  }
 
}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc