collection-8.x-1.x-dev/collection.module
collection.module
<?php
/**
* @file
* Contains collection.module.
*/
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Entity\ContentEntityForm;
use Drupal\Core\Field\Entity\BaseFieldOverride;
use Drupal\Core\Url;
use Drupal\Core\Access\AccessResult;
/**
* Implements hook_help().
*/
function collection_help($route_name, RouteMatchInterface $route_match) {
switch ($route_name) {
// Main module help for the collection module.
case 'help.page.collection':
$output = '';
$output .= '<h3>' . t('About') . '</h3>';
$output .= '<p>' . t('Allows collections of content and configuration entities.') . '</p>';
return $output;
default:
}
}
/**
* Implements hook_toolbar_alter().
*/
function collection_toolbar_alter(&$items) {
$items['administration']['#attached']['library'][] = 'collection/toolbar';
}
/**
* Implements hook_theme().
*/
function collection_theme() {
$theme = [];
$theme['collection'] = [
'render element' => 'elements',
'file' => 'collection.page.inc',
'template' => 'collection',
];
$theme['collection_content_add_list'] = [
'render element' => 'content',
'variables' => ['content' => NULL],
'file' => 'collection.page.inc',
];
return $theme;
}
/**
* Implements hook_entity_bundle_field_info().
*
* Update the settings for the collection_item `item` field from collection item
* type configuration.
*
* The dynamic entity reference field on collection items uses these settings on
* the form widget.
*
* @see Drupal\collection\Form\CollectionItemTypeForm
*/
function collection_entity_bundle_field_info(EntityTypeInterface $entity_type, $bundle, array $base_field_definitions) {
$fields = [];
// Apply custom settings to different collection item types.
if ($entity_type->id() === 'collection_item') {
$collection_item_type_storage = \Drupal::service('entity_type.manager')->getStorage('collection_item_type');
// Get the `allowed_bundles` setting for this collection item type. They
// will be an array of items in the form `entity_type_id.bundle` (e.g.
// `node.article`).
$collection_item_type = $collection_item_type_storage->load($bundle);
$entity_bundles = [];
// Place the allowed bundles in a multidimensional array for later use.
foreach ($collection_item_type->getAllowedBundles() as $entity_and_bundle) {
list($entity_type_id, $bundle_name) = explode('.', $entity_and_bundle);
$entity_bundles[$entity_type_id][$bundle_name] = $bundle_name;
}
// Load the item field for this collection item bundle.
$fields['item'] = BaseFieldOverride::createFromBaseFieldDefinition($base_field_definitions['item'], $bundle);
// Append any non-node entity types to the `entity_type_ids` setting.
$entity_type_ids_setting = $fields['item']->getSetting('entity_type_ids');
$fields['item']
->setSetting('entity_type_ids', $entity_type_ids_setting + array_combine(array_keys($entity_bundles), array_keys($entity_bundles)));
// Set config for the allowed entity types, especially the `target_bundles`,
// for this collection item type.
foreach ($entity_bundles as $entity_type_id => $bundles) {
$fields['item']
->setSetting($entity_type_id, [
'handler' => 'default:' . $entity_type_id,
'handler_settings' => [
'target_bundles' => $bundles,
]
]);
}
}
return $fields;
}
/**
* Implements hook_form_BASE_FORM_ID_alter().
*/
function collection_form_collection_form_alter(&$form, FormStateInterface $form_state) {
$form['settings'] = [
'#type' => 'details',
'#title' => t('Settings'),
'#group' => 'advanced',
'#weight' => 50,
'#optional' => TRUE,
'#open' => FALSE,
];
$form['collectible']['#group'] = 'settings';
$form['user_id']['#group'] = 'settings';
}
/**
* Implements hook_theme_suggestions_HOOK().
*/
function collection_theme_suggestions_collection(array $variables) {
$suggestions = [];
$entity = $variables['elements']['#collection'];
$sanitized_view_mode = strtr($variables['elements']['#view_mode'], '.', '_');
$suggestions[] = 'collection__' . $sanitized_view_mode;
$suggestions[] = 'collection__' . $entity->bundle();
$suggestions[] = 'collection__' . $entity->bundle() . '__' . $sanitized_view_mode;
$suggestions[] = 'collection__' . $entity->id();
$suggestions[] = 'collection__' . $entity->id() . '__' . $sanitized_view_mode;
return $suggestions;
}
/**
* Implements hook_entity_update().
*
* Update the name of collection items when an entity is modified.
*/
function collection_entity_update(EntityInterface $entity) {
// Don't run on collection_items or paragraphs.
if (in_array($entity->getEntityTypeId(), ['collection_item', 'paragraph'])) {
return;
}
// Don't run if entity label is unchanged.
if ($entity->label() === $entity->original->label()) {
return;
}
$item_storage = \Drupal::service('entity_type.manager')->getStorage('collection_item');
$collection_items = $item_storage->loadByProperties([
'item__target_id' => $entity->id(),
'item__target_type' => $entity->getEntityTypeId()
]);
foreach ($collection_items as $collection_item) {
// This should trigger CollectionItem::preSave() and update the
// collection_item label.
$collection_item->save();
}
}
/**
* Implements hook_entity_predelete().
*
* Delete any corresponding collection items when an entity is deleted.
*/
function collection_entity_predelete(EntityInterface $entity) {
$item_storage = \Drupal::service('entity_type.manager')->getStorage('collection_item');
$collection_items = $item_storage->loadByProperties([
'item__target_id' => $entity->id(),
'item__target_type' => $entity->getEntityTypeId()
]);
foreach ($collection_items as $collection_item) {
$collection_item->delete();
}
}
/**
* Implements hook_entity_extra_field_info().
*/
function collection_entity_extra_field_info() {
return \Drupal::service('collection.content_entity_form.alter')->getExtraFieldInfo();
}
/**
* Implements hook_form_alter().
*/
function collection_form_alter(&$form, FormStateInterface $form_state, $form_id) {
\Drupal::service('collection.content_entity_form.alter')->alterForm($form, $form_state, $form_id);
}
/**
* Implements hook_entity_field_access_alter().
*/
function collection_entity_field_access_alter(array &$grants, array $context) {
// Prevent change of collected item reference when editing a collection item.
if ($context['field_definition']->getTargetEntityTypeId() === 'collection_item' && $context['field_definition']->getName() === 'item' && $context['operation'] === 'edit') {
$grants[':default'] = AccessResult::allowedIf($context['items']->getEntity()->isNew());
}
// Restrict access to collection item attributes.
if ($context['field_definition']->getTargetEntityTypeId() === 'collection_item' && $context['field_definition']->getName() === 'attributes' && $context['operation'] === 'edit') {
$attributes_access = $context['items']->getEntity()->type->entity->get('attributes_access');
if ($attributes_access === 'administrators') {
$grants[':default'] = AccessResult::allowedIfHasPermission($context['account'], 'administer collections');
}
elseif ($attributes_access === 'owners') {
$is_owner = in_array($context['account']->id(), $context['items']->getEntity()->collection->entity->getOwnerIds());
$grants[':default'] = AccessResult::allowedIf($is_owner);
}
else {
$grants[':default'] = AccessResult::forbidden();
}
}
}
/**
* Implements hook_entity_operation().
*
* Add operation links to collection and collection item entities.
*/
function collection_entity_operation(EntityInterface $entity) {
if ($entity->getEntityTypeId() == 'collection_item' && $entity->item->entity->access('update')) {
$item_entity_type = ($entity->item->entity instanceof ContentEntityInterface) ? 'content' : 'configuration';
$operations = [];
$operations['edit_item'] = [
'title' => t('Edit @entity_type', ['@entity_type' => $item_entity_type]),
'url' => $entity->item->entity->toUrl('edit-form'),
'weight' => -1,
];
return $operations;
}
if ($entity->getEntityTypeId() === 'collection' && $entity->access('update')) {
$operations = [];
$collection_items_url = Url::fromRoute(
'entity.collection_item.collection',
['collection' => $entity->id()]
);
$operations['view_items'] = [
'title' => t('Items'),
'url' => $collection_items_url,
'weight' => -1,
];
return $operations;
}
}
/**
* Implements hook_entity_operation_alter().
*
* Update the edit and delete operations titles for collection items.
*/
function collection_entity_operation_alter(array &$operations, EntityInterface $entity) {
if ($entity->getEntityTypeId() == 'collection_item') {
if (isset($operations['edit'])) {
$operations['edit']['title'] = t('Edit collection item');
}
if (isset($operations['delete'])) {
$operations['delete']['title'] = t('Remove from collection');
}
}
}
