View source
<?php
namespace Drupal\commerce_order\Controller;
use Drupal\commerce_order\AddressBookInterface;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Cache\CacheableMetadata;
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
use Drupal\Core\Entity\EntityFormBuilderInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Messenger\MessengerTrait;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\Url;
use Drupal\profile\Entity\ProfileInterface;
use Drupal\profile\Entity\ProfileTypeInterface;
use Drupal\user\UserInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
class AddressBookController implements ContainerInjectionInterface {
use MessengerTrait;
use StringTranslationTrait;
protected $addressBook;
protected $entityFormBuilder;
protected $entityTypeManager;
public function __construct(AddressBookInterface $address_book, EntityFormBuilderInterface $entity_form_builder, EntityTypeManagerInterface $entity_type_manager) {
$this->addressBook = $address_book;
$this->entityFormBuilder = $entity_form_builder;
$this->entityTypeManager = $entity_type_manager;
}
public static function create(ContainerInterface $container) {
return new static($container
->get('commerce_order.address_book'), $container
->get('entity.form_builder'), $container
->get('entity_type.manager'));
}
public function editTitle(ProfileInterface $profile) {
return $this
->t('Edit %label', [
'%label' => $profile
->label(),
]);
}
public function deleteTitle(ProfileInterface $profile) {
return $this
->t('Delete %label', [
'%label' => $profile
->label(),
]);
}
public function setDefault(ProfileInterface $profile) {
$profile
->setDefault(TRUE);
$profile
->save();
$this
->messenger()
->addMessage($this
->t('%label is now the default address.', [
'%label' => $profile
->label(),
]));
$overview_url = Url::fromRoute('commerce_order.address_book.overview', [
'user' => $profile
->getOwnerId(),
'profile' => $profile
->id(),
]);
return new RedirectResponse($overview_url
->toString());
}
public function overviewPage(UserInterface $user) {
$profile_types = $this->addressBook
->loadTypes();
$profile_types = $this
->filterTypesByViewAccess($profile_types, $user);
$profile_entity_type = $this->entityTypeManager
->getDefinition('profile');
$view_builder = $this->entityTypeManager
->getViewBuilder('profile');
$wrapper_element_type = count($profile_types) > 1 ? 'details' : 'container';
$cacheability = new CacheableMetadata();
$cacheability
->addCacheContexts($profile_entity_type
->getListCacheContexts());
$cacheability
->addCacheTags($profile_entity_type
->getListCacheTags());
$build = [];
$build['#attached']['library'][] = 'commerce_order/address_book';
foreach ($profile_types as $profile_type_id => $profile_type) {
$add_form_url = Url::fromRoute('commerce_order.address_book.add_form', [
'user' => $user
->id(),
'profile_type' => $profile_type
->id(),
]);
if ($profile_type
->allowsMultiple()) {
$profiles = $this->addressBook
->loadAll($user, $profile_type_id);
}
else {
$profile = $this->addressBook
->load($user, $profile_type_id);
$profiles = [];
if ($profile) {
$profiles[$profile
->id()] = $profile;
}
}
$build[$profile_type_id] = [
'#type' => $wrapper_element_type,
'#title' => $profile_type
->getDisplayLabel() ?: $profile_type
->label(),
'#open' => TRUE,
'#attributes' => [
'class' => [
'address-book__container',
'address-book__container--' . $profile_type_id,
],
],
];
$build[$profile_type_id]['add'] = [
'#type' => 'link',
'#title' => $this
->t('Add address'),
'#url' => $add_form_url,
'#attributes' => [
'class' => [
'address-book__add-link',
],
],
'#access' => $add_form_url
->access(),
];
$build[$profile_type_id]['profiles'] = [
'#type' => 'container',
'#attributes' => [
'class' => [
'address-book__profiles',
],
],
'#access' => !empty($profiles),
];
foreach ($profiles as $profile_id => $profile) {
$build[$profile_type_id]['profiles'][$profile_id] = [
'#type' => 'container',
'#attributes' => [
'class' => [
'address-book__profile',
],
],
'profile' => $view_builder
->view($profile),
'operations' => $this
->buildOperations($profile, $profile_type),
];
if ($profile
->isDefault()) {
$build[$profile_type_id]['profiles'][$profile_id]['#attributes']['class'][] = 'address-book__profile--default';
}
}
if (empty($profiles)) {
$build[$profile_type_id]['empty_text'] = [
'#type' => 'container',
'#attributes' => [
'class' => [
'address-book__empty-text',
],
],
'#plain_text' => $this
->t('There are no addresses yet.'),
'#access' => $wrapper_element_type == 'container' || !$add_form_url
->access(),
];
}
$cacheability
->addCacheableDependency($profile_type);
}
$cacheability
->applyTo($build);
return $build;
}
public function addForm(UserInterface $user, ProfileTypeInterface $profile_type) {
$profile = $this->entityTypeManager
->getStorage('profile')
->create([
'uid' => $user
->id(),
'type' => $profile_type
->id(),
]);
return $this->entityFormBuilder
->getForm($profile, 'address-book-add');
}
public function checkOverviewAccess(UserInterface $user, AccountInterface $account) {
$user_access = $user
->access('view', $account, TRUE);
if (!$user_access
->isAllowed()) {
return $user_access;
}
$profile_types = $this->addressBook
->loadTypes();
$profile_types = $this
->filterTypesByViewAccess($profile_types, $user, $account);
return AccessResult::allowedIf(!empty($profile_types))
->addCacheTags([
'config:profile_type_list',
]);
}
public function checkCreateAccess(UserInterface $user, ProfileTypeInterface $profile_type, AccountInterface $account) {
$user_access = $user
->access('view', $account, TRUE);
if (!$user_access
->isAllowed()) {
return $user_access;
}
$access_control_handler = $this->entityTypeManager
->getAccessControlHandler('profile');
$result = $access_control_handler
->createAccess($profile_type
->id(), $account, [
'profile_owner' => $user,
], TRUE);
if ($result
->isAllowed()) {
$admin_permission = $this->entityTypeManager
->getDefinition('profile')
->getAdminPermission();
$owner_result = AccessResult::allowedIfHasPermission($account, $admin_permission)
->orIf(AccessResult::allowedIf($account
->id() == $user
->id()))
->cachePerUser();
$result = $result
->andIf($owner_result);
if (!$profile_type
->allowsMultiple()) {
$profile = $this->addressBook
->load($user, $profile_type
->id());
$other_result = AccessResult::allowedIf(empty($profile))
->mergeCacheMaxAge(0);
$result = $result
->andIf($other_result);
}
$result
->addCacheableDependency($profile_type);
}
return $result;
}
protected function filterTypesByViewAccess(array $profile_types, UserInterface $owner, AccountInterface $account = NULL) {
$storage = $this->entityTypeManager
->getStorage('profile');
$access_control_handler = $this->entityTypeManager
->getAccessControlHandler('profile');
foreach ($profile_types as $profile_type_id => $profile_type) {
$profile_stub = $storage
->create([
'type' => $profile_type_id,
'uid' => $owner
->id(),
]);
if (!$access_control_handler
->access($profile_stub, 'view', $account)) {
unset($profile_types[$profile_type_id]);
}
}
return $profile_types;
}
protected function buildOperations(ProfileInterface $profile, ProfileTypeInterface $profile_type) {
$operations = [
'#type' => 'container',
'#attributes' => [
'class' => [
'address-book__operations',
],
],
'#weight' => 999,
];
$operations['edit'] = [
'#type' => 'link',
'#title' => $this
->t('Edit'),
'#url' => Url::fromRoute('commerce_order.address_book.edit_form', [
'user' => $profile
->getOwnerId(),
'profile' => $profile
->id(),
]),
'#attributes' => [
'class' => [
'address-book__edit-link',
],
],
'#access' => $profile
->access('update'),
];
if ($profile_type
->allowsMultiple()) {
$operations['delete'] = [
'#type' => 'link',
'#title' => $this
->t('Delete'),
'#url' => Url::fromRoute('commerce_order.address_book.delete_form', [
'user' => $profile
->getOwnerId(),
'profile' => $profile
->id(),
]),
'#attributes' => [
'class' => [
'address-book__delete-link',
],
],
'#access' => $profile
->access('delete'),
];
$operations['set_default'] = [
'#type' => 'link',
'#title' => $this
->t('Set as default'),
'#url' => Url::fromRoute('commerce_order.address_book.set_default', [
'user' => $profile
->getOwnerId(),
'profile' => $profile
->id(),
]),
'#attributes' => [
'class' => [
'address-book__set-default-link',
],
],
'#access' => $profile
->access('update') && !$profile
->isDefault(),
];
}
return $operations;
}
}