Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multiple breadcrumb parent fields #873

Merged
merged 4 commits into from
May 18, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
maxDepth: -1
includeSelf: FALSE
referenceField: field_member_of
referenceFields:
- field_member_of
dependencies:
module:
- islandora
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ islandora_breadcrumbs.breadcrumbs:
includeSelf:
type: boolean
label: 'Include Self'
referenceField:
type: string
label: 'Reference Field'
referenceFields:
type: sequence
label: 'Reference Fields'
sequence:
type: string
label: 'Reference Field'
18 changes: 18 additions & 0 deletions modules/islandora_breadcrumbs/islandora_breadcrumbs.install
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

/**
* @file
* Install/update hook implementations.
*/

/**
* Update referenceField config to referenceFields.
*/
function islandora_breadcrumbs_update_8001() {
$config_factory = \Drupal::configFactory();
$config = $config_factory->getEditable('islandora_breadcrumbs.breadcrumbs');
$config->set('referenceFields', [$config->get('referenceField')]);
$config->clear('referenceField');
$config->save();
return "Updated referenceFields config.";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
system.islandora_breadcrumbs_settings:
title: 'Breadcrumbs Settings'
parent: system.admin_config_islandora
route_name: system.islandora_breadcrumbs_settings
description: 'Configure Islandora breadcrumb settings'
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
system.islandora_breadcrumbs_settings:
path: '/admin/config/islandora/breadcrumbs'
defaults:
_form: 'Drupal\islandora_breadcrumbs\Form\IslandoraBreadcrumbsSettingsForm'
_title: 'Islandora Breadcrumbs Settings'
requirements:
_permission: 'administer site configuration'
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
<?php

namespace Drupal\islandora_breadcrumbs\Form;

use Drupal\Core\Form\ConfigFormBase;
use Drupal\Core\Form\FormStateInterface;

/**
* Configure islandora_breadcrumbs settings.
*/
class IslandoraBreadcrumbsSettingsForm extends ConfigFormBase {

/**
* Config settings.
*
* @var string
*/
const SETTINGS = 'islandora_breadcrumbs.breadcrumbs';

/**
* {@inheritdoc}
*/
public function getFormId() {
return 'islandora_breadcrumbs_settings';
}

/**
* {@inheritdoc}
*/
protected function getEditableConfigNames() {
return [
static::SETTINGS,
];
}

/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {

$config = $this->config(static::SETTINGS);

$form['maxDepth'] = [
'#type' => 'number',
'#default_value' => $config->get('maxDepth'),
'#min' => -1,
'#step' => 1,
'#title' => $this->t('Maximum number of ancestor breadcrumbs'),
'#description' => $this->t("Stops adding ancestor references when the chain reaches this number. The count does not include the current node when enabled. The default value, '-1' disables this feature."),
];

$form['includeSelf'] = [
'#type' => 'checkbox',
'#title' => $this->t('Include the current node in the breadcrumbs?'),
'#default_value' => $config->get('includeSelf'),
];

// Using the textarea instead of a select so the site maintainer can
// provide an ordered list of items rather than simply selecting from a
// list which enforces it's own order.
$form['referenceFields'] = [
'#type' => 'textarea',
'#title' => $this->t('Entity Reference fields to follow'),
'#default_value' => implode("\n", $config->get('referenceFields')),
'#description' => $this->t("Entity Reference field machine names to follow when building the breadcrumbs.<br>One per line.<br>Valid options: @options",
[
"@options" => implode(", ", static::getNodeEntityReferenceFields()),
]
),
'#element_validate' => [[get_class($this), 'validateReferenceFields']],

];

return parent::buildForm($form, $form_state);
}

/**
* Returns a list of node entity reference field machine names.
*
* We use this for building the form field description and for
* validating the reference fields value.
*/
protected static function getNodeEntityReferenceFields() {
return array_keys(\Drupal::service('entity_field.manager')->getFieldMapByFieldType('entity_reference')['node']);
jordandukart marked this conversation as resolved.
Show resolved Hide resolved
}

/**
* Turns a text area into an array of values.
*
* Used for validating the field reference text area
* and saving the form state.
*/
protected static function textToArray($string) {
return array_filter(array_map('trim', explode("\n", $string)), 'strlen');
}

/**
* Callback for settings form.
*
* @param array $element
* An associative array containing the properties and children of the
* generic form element.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the form for the form this element belongs to.
*
* @see \Drupal\Core\Render\Element\FormElement::processPattern()
*/
public static function validateReferenceFields(array $element, FormStateInterface $form_state) {

$valid_fields = static::getNodeEntityReferenceFields();

foreach (static::textToArray($element['#value']) as $value) {
if (!in_array($value, $valid_fields)) {
$form_state->setError($element, t('"@field" is not a valid entity reference field!', ["@field" => $value]));
}
}
}

/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
$this->configFactory->getEditable(static::SETTINGS)
->set('referenceFields', static::textToArray($form_state->getValue('referenceFields')))
->set('maxDepth', $form_state->getValue('maxDepth'))
->set('includeSelf', $form_state->getValue('includeSelf'))
->save();

parent::submitForm($form, $form_state);
}

}
14 changes: 11 additions & 3 deletions modules/islandora_breadcrumbs/src/IslandoraBreadcrumbBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,14 @@ public function applies(RouteMatchInterface $attributes) {
$nid = $attributes->getRawParameters()->get('node');
if (!empty($nid)) {
$node = $this->nodeStorage->load($nid);
return (!empty($node) && $node->hasField($this->config->get('referenceField')));
if (empty($node)) {
return FALSE;
}
foreach ($this->config->get('referenceFields') as $field) {
if ($node->hasField($field)) {
return TRUE;
}
}
}
}

Expand All @@ -76,17 +83,18 @@ public function build(RouteMatchInterface $route_match) {
$nid = $route_match->getRawParameters()->get('node');
$node = $this->nodeStorage->load($nid);
$breadcrumb = new Breadcrumb();
$breadcrumb->addCacheableDependency($this->config);
$breadcrumb->addLink(Link::createFromRoute($this->t('Home'), '<front>'));

$chain = array_reverse($this->utils->findAncestors($node, [$this->config->get('referenceField')], $this->config->get('maxDepth')));
$chain = array_reverse($this->utils->findAncestors($node, $this->config->get('referenceFields'), $this->config->get('maxDepth')));

// XXX: Handle a looping breadcrumb scenario by filtering the present
// node out and then optionally re-adding it after if set to do so.
$chain = array_filter($chain, function ($link) use ($nid) {
return $link !== $nid;
});
if ($this->config->get('includeSelf')) {
array_push($chain, $node);
array_push($chain, $nid);
jordandukart marked this conversation as resolved.
Show resolved Hide resolved
}
$breadcrumb->addCacheableDependency($node);
jordandukart marked this conversation as resolved.
Show resolved Hide resolved

Expand Down
2 changes: 1 addition & 1 deletion src/IslandoraUtils.php
Original file line number Diff line number Diff line change
Expand Up @@ -714,7 +714,7 @@ public function findAncestors(ContentEntityInterface $entity, array $fields = [s
* @param int $current_height
* The current height of the recursion.
*/
protected function findAncestorsByEntityReference(ContentEntityInterface $entity, array &$context, array $fields = [self::MEMBER_OF_FIELD], int $current_height = 0): void {
protected function findAncestorsByEntityReference(ContentEntityInterface $entity, array &$context, array $fields = [self::MEMBER_OF_FIELD], int $current_height = 1): void {
$parents = $this->getParentsByEntityReference($entity, $fields);
foreach ($parents as $parent) {
if (isset($context['ancestors'][$parent->id()])) {
Expand Down