diff --git a/bibcite_footnotes.module b/bibcite_footnotes.module
index 39c617e..bdbd215 100644
--- a/bibcite_footnotes.module
+++ b/bibcite_footnotes.module
@@ -10,8 +10,31 @@ use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Url;
use Drupal\Core\Link;
use Drupal\bibcite_footnotes\CitationTools;
+use Drupal\bibcite_footnotes\Plugin\Filter\ReferenceFootnotesFilter;
-/**_bibcite_foot
+/**
+ * Implements hook_theme().
+ */
+function bibcite_footnotes_theme() {
+ return [
+ 'bibcite_footnote_link' => [
+ 'render element' => 'fn',
+ 'template' => 'bibcite-footnote-link',
+ ],
+ 'bibcite_footnote_list' => [
+ 'render element' => 'footnotes',
+ 'path' => drupal_get_path('module', 'bibcite_footnotes') . '/templates',
+ 'template' => 'bibcite-footnote-list',
+ 'variables' => [
+ 'notes' => [],
+ 'note_type' => [],
+ 'config' => [],
+ ],
+ ],
+ ];
+}
+
+/**
* Implements hook_help().
*/
function bibcite_footnotes_help($route_name, RouteMatchInterface $route_match) {
@@ -28,7 +51,7 @@ function bibcite_footnotes_help($route_name, RouteMatchInterface $route_match) {
}
/**
- * Implementation of hook_preprocess_footnote_list().
+ * Implementation of hook_preprocess_bibcite_footnote_list().
*
* Gatehrs all notes and prints out Notes and References as separate lists.
*
@@ -37,29 +60,21 @@ function bibcite_footnotes_help($route_name, RouteMatchInterface $route_match) {
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
*/
-function bibcite_footnotes_preprocess_footnote_list(&$variables) {
- $config = \Drupal::config('filter.format.rich_text_references');//filters.filter_reference_footnotes.settings');
- $footnotes = $variables['footnotes'];
+function bibcite_footnotes_preprocess_bibcite_footnote_list(&$variables) {
+ $config = $variables['config'];
+ $footnotes = $variables['notes'];
$notes = [
'#theme' => 'item_list',
'#list_type' => 'ul',
- '#title' => $config->get('filters.filter_reference_footnotes.settings.notes_section_label'),
+ '#title' => $variables['note_type'] == ReferenceFootnotesFilter::ENDNOTE ? $config['notes_section_label'] : $config['references_section_label'],
'#attributes' => ['class' => 'footnotes'],
'#wrapper_attributes' => ['class' => 'container'],
];
- $references= [
- '#theme' => 'item_list',
- '#list_type' => 'ul',
- '#title' => $config->get('filters.filter_reference_footnotes.settings.references_section_label'),
- '#attributes' => ['class' => 'footnotes'],
- '#wrapper_attributes' => ['class' => 'container'],
-
- ];
- $references['#attached']['library'][] = 'bibcite_footnotes/reference_footnote';
- $dont_show_backlink_text = $config->get('filters.filter_reference_footnotes.settings.reference_dont_show_backlink_text');
- $sort_references_by = $config->get('filters.filter_reference_footnotes.settings.reference_sort_by');
+ $notes['#attached']['library'][] = 'bibcite_footnotes/reference_footnote';
+ $dont_show_backlink_text = $config['reference_dont_show_backlink_text'];
+ $sort_references_by = $config['reference_sort_by'];
$citation_tools = new CitationTools();
foreach ($footnotes as $fn) {
$item = [
@@ -97,53 +112,66 @@ function bibcite_footnotes_preprocess_footnote_list(&$variables) {
$override_page_in_citation = FALSE;
}
- if (!empty($fn['text'])) {
- // Handle the case where an endnote contains text and a reference.
- // It will appear in both lists. But the link text for the endnote should
- // always be the title of the note. So make a copy of the biuld arrray
- // and change the link text.
- $note_build = $build + ['#type' => 'markup', '#markup' => ' ' . $fn['text'] . ''];
- $note_build['footnote-link'] = Link::fromTextAndUrl($fn['value'], $url)->toRenderable();
- if (!empty($reference_entity_id)) {
- $citation_build = $citation_tools->getRenderableReference($reference_entity_id);
- $note_build[] = $citation_build;
- }
- $note_item = [] + $item;
- $note_item['#markup'] = render($note_build);
-
- $notes['#items'][] = $note_item;
+ if ($fn['ibid']) {
+ $build['#type'] = 'markup';
+ $build['#markup'] = ' '
+ . t('Ibid') . '.'
+ . (!empty($fn['page']) ? ', ' . $fn['page'] : '')
+ . '';
+ }
+ else if (!empty($fn['text']) && $variables['note_type'] == ReferenceFootnotesFilter::ENDNOTE) {
+ $build['#type'] = 'markup';
+ $build['#markup'] = ' ' . $fn['text'] . '';
+ $build['footnote-link'] = Link::fromTextAndUrl($fn['value'], $url)->toRenderable();
}
if (!empty($reference_entity_id)) {
- $citation_build = $citation_tools->getRenderableReference($reference_entity_id);
- if ($override_page_in_citation) {
- $citation_build['#data']['page'] = $override_page_in_citation;
+ if (!$fn['ibid']) {
+ $citation_build = $citation_tools->getRenderableReference($reference_entity_id);
+ if ($override_page_in_citation) {
+ $citation_build['#data']['page'] = $override_page_in_citation;
+ }
+
+ $build[] = $citation_build;
}
- $build[] = $citation_build;
+
$render = render($build);
- $item['#markup'] = $render;
$item['sort'] = trim(strip_tags(render($citation_build)));
- $references['#items'][] = $item;
-
}
+ $item['#markup'] = $render;
+ $notes['#items'][] = $item;
+ $reference_entity_id = FALSE;
+ $render = FALSE;
}
- $variables['notes'] = $notes;
-
- if ($sort_references_by == 'alphabetical') {
- usort($references['#items'], '_bibcite_footnotes_reference_array_cmp');
+ if ($sort_references_by == 'alphabetical' && $variables['note_type'] == ReferenceFootnotesFilter::REFERENCE) {
+ usort($notes['#items'], '_bibcite_footnotes_reference_array_cmp');
}
- $variables['references'] = $references;
+ $variables['notes'] = $notes;
}
+/**
+ * Comparator function for sorting lists of references.
+ *
+ * @param $a First item to compare
+ * @param $b Second item to compare
+ * @return int Result of the comparison.
+ */
function _bibcite_footnotes_reference_array_cmp($a, $b) {
$a1 = (!empty($a['sort']) ? strtolower($a['sort']) : '');
$b1 = (!empty($b['sort']) ? strtolower($b['sort']) : '');
return strcmp($a1, $b1);
}
-function bibcite_footnotes_preprocess_footnote_link(&$variables) {
+/**
+ * Implementation of hook_preprocess_bibcite_footnote_link().
+ *
+ * Construct a link inside a block of text so that it points to the reference list.
+ *
+ * @param $variables
+ */
+function bibcite_footnotes_preprocess_bibcite_footnote_link(&$variables) {
// $variables['fn']['fn']['#type'] = 'markeup';
// $variables['fn']['fn']['#markup'] = '
Hello!
';
$fn = $variables['fn']['fn'];
@@ -169,17 +197,3 @@ function bibcite_footnotes_preprocess_footnote_link(&$variables) {
$link = Link::fromTextAndUrl($fn['value'], $url)->toRenderable();
$variables['fn']['fn'][] = $link;
}
-
-function bibcite_footnotes_theme_registry_alter(&$theme_registry) {
- unset($theme_registry['footnote_list']['function']);
- $theme_registry['footnote_list']['path'] = drupal_get_path('module', 'bibcite_footnotes') . '/templates';
- $theme_registry['footnote_list']['template'] = 'footnote-list';
- $theme_registry['footnote_list']['variables']['notes'] = [];
- $theme_registry['footnote_list']['variables']['references'] = [];
- $theme_registry['footnote_list']['variables']['footnotes'] = [];
-
- unset($theme_registry['footnote_link']['function']);
- $theme_registry['footnote_link']['path'] = drupal_get_path('module', 'bibcite_footnotes') . '/templates';
- $theme_registry['footnote_link']['template'] = 'footnote-link';
-}
-
diff --git a/src/Plugin/Filter/ReferenceFootnotesFilter.php b/src/Plugin/Filter/ReferenceFootnotesFilter.php
index 3b24eed..032d386 100644
--- a/src/Plugin/Filter/ReferenceFootnotesFilter.php
+++ b/src/Plugin/Filter/ReferenceFootnotesFilter.php
@@ -7,7 +7,7 @@ use Drupal\Core\Form\FormStateInterface;
use Drupal\footnotes\Plugin\Filter\FootnotesFilter;
/**
- * Provides a base filter for Reference Footnotes filter.
+ * Reference Footnotes filter.
*
* @Filter(
* id = "filter_reference_footnotes",
@@ -17,7 +17,8 @@ use Drupal\footnotes\Plugin\Filter\FootnotesFilter;
* type = \Drupal\filter\Plugin\FilterInterface::TYPE_TRANSFORM_IRREVERSIBLE,
* cache = FALSE,
* settings = {
- * "footnotes_collapse" = FALSE,
+ * "footnotes_footnotefootnote_linkcollapse" = FALSE,
+ * "footnotes_ibid" = FALSE,
* "notes_section_label" = "Notes",
* "references_section_label" = "References"
* },
@@ -25,6 +26,8 @@ use Drupal\footnotes\Plugin\Filter\FootnotesFilter;
* )
*/
class ReferenceFootnotesFilter extends FootnotesFilter {
+ const ENDNOTE = 0;
+ const REFERENCE = 1;
/**
* Object with configuration for reference footnotes.
@@ -66,10 +69,15 @@ class ReferenceFootnotesFilter extends FootnotesFilter {
public function settingsForm(array $form, FormStateInterface $form_state) {
$settings['footnotes_collapse'] = [
'#type' => 'checkbox',
- '#title' => t('Collapse reference footnotes with identical content'),
+ '#title' => $this->t('Collapse reference footnotes with identical content'),
'#default_value' => $this->settings['footnotes_collapse'],
'#description' => t('If two reference footnotes have the exact same content, they will be collapsed into one as if using the same value="" attribute.'),
];
+ $settings['footnotes_ibid'] = [
+ '#type' => 'checkbox',
+ '#title' => $this->t('Display subsequent instances of multiple references with \'Ibid.\''),
+ '#default_value' => $this->settings['footnotes_ibid'],
+ ];
$settings['notes_section_label'] = [
'#type' => 'textfield',
'#title' => t('Notes section label'),
@@ -133,21 +141,33 @@ class ReferenceFootnotesFilter extends FootnotesFilter {
}
if ($op == 'output footer') {
+
+
if (count($store_matches) > 0) {
+ // Separate out endontes and reference notes.
+ $notes = $this->extractNotesByType(self::ENDNOTE, $store_matches);
+ $references = $this->extractNotesByType(self::REFERENCE, $store_matches);
+
+ if ($this->settings['footnotes_ibid']) {
+ $this->ibidemify($references);
+ }
// Only if there are stored fn matches, pass the array of fns to be
- // themed as a list Drupal 7 requires we use "render element" which
- // just introduces a wrapper around the old array.
- // @FIXME
- // theme() has been renamed to _theme() and should NEVER be called
- // directly. Calling _theme() directly can alter the expected output and
- // potentially introduce security issues
- // (see https://www.drupal.org/node/2195739). You should use renderable
- // arrays instead. @see https://www.drupal.org/node/2195739
+ // themed as a list
$markup = [
- '#theme' => 'footnote_list',
- '#footnotes' => $store_matches,
+ '#theme' => 'bibcite_footnote_list',
+ '#notes' => $notes,
+ '#note_type' => self::ENDNOTE,
+ '#config' => $this->settings,
];
$str = \Drupal::service('renderer')->render($markup, FALSE);
+
+ $markup = [
+ '#theme' => 'bibcite_footnote_list',
+ '#notes' => $references,
+ '#note_type' => self::REFERENCE,
+ '#config' => $this->settings,
+ ];
+ $str .= \Drupal::service('renderer')->render($markup, FALSE);
}
// Reset the static variables so they can be used again next time.
$n = 0;
@@ -246,30 +266,18 @@ class ReferenceFootnotesFilter extends FootnotesFilter {
// Drupal 7 requires we use "render element" which just introduces a wrapper
// around the old array.
$fn = [
- '#theme' => 'footnote_link',
+ '#theme' => 'bibcite_footnote_link',
'fn' => $fn,
];
+
+
$result = \Drupal::service('renderer')->render($fn, FALSE);
return $result;
}
/**
- * Search the $store_matches array for footnote text that matches.
- *
- * Note: This does a linear search on the $store_matches array. For a large
- * list of footnotes it would be more efficient to maintain a separate array
- * with the footnote content as key, in order to do a hash lookup at this
- * stage. Since you typically only have a handful of footnotes, this simple
- * search is assumed to be more efficient, but was not tested.
- *
- * @param string $text
- * The footnote text.
- * @param array $store_matches
- * The matches array.
- *
- * @return string|false
- * The value of the existing footnote, FALSE otherwise.
+ * @inheritdoc
*/
private function findFootnote($text, &$store_matches) {
if (!empty($store_matches)) {
@@ -304,4 +312,42 @@ class ReferenceFootnotesFilter extends FootnotesFilter {
}
return $value;
}
+
+ /**
+ * Determine references that are the same as one above it
+ * to be replaced with the string 'Ibid'.
+ *
+ * @param array $footnotes
+ */
+ protected function ibidemify(&$footnotes) {
+ $prev_reference_id = FALSE;
+ foreach ($footnotes as $index => $fn) {
+ if ($prev_reference_id) {
+ if ($fn['reference'] == $prev_reference_id) {
+ $footnotes[$index]['ibid'] = TRUE;
+ continue;
+ }
+ }
+ $prev_reference_id = $fn['reference'];
+ }
+ }
+
+ protected function extractNotesByType($type, $footnotes) {
+ $notes = [];
+ foreach ($footnotes as $fn) {
+ switch ($type) {
+ case self::ENDNOTE:
+ if (!empty($fn['text'])) {
+ $notes[] = $fn;
+ }
+ break;
+ case self::REFERENCE:
+ if (!empty($fn['reference'])) {
+ $notes[] = $fn;
+ }
+ break;
+ }
+ }
+ return $notes;
+ }
}
diff --git a/templates/footnote-link.html.twig b/templates/bibcite-footnote-link.html.twig
similarity index 100%
rename from templates/footnote-link.html.twig
rename to templates/bibcite-footnote-link.html.twig
diff --git a/templates/footnote-list.html.twig b/templates/bibcite-footnote-list.html.twig
similarity index 100%
rename from templates/footnote-list.html.twig
rename to templates/bibcite-footnote-list.html.twig