Skip to content
Snippets Groups Projects
Commit ff92005b authored by Marcos Cano's avatar Marcos Cano :speech_balloon: Committed by Daniele Piaggesi
Browse files

Issue #2734749 by marcoscano: Port to D8

parent 194f8c22
No related branches found
No related tags found
No related merge requests found
{
"name": "drupal/prevnext",
"type": "drupal-module",
"description": "Add a 'Previous - Next' links to the node display.",
"keywords": ["Drupal"],
"license": "GPL-2.0+",
"homepage": "https://www.drupal.org/project/prevnext",
"minimum-stability": "dev",
"support": {
"issues": "http://drupal.org/project/issues/prevnext",
"source": "http://cgit.drupalcode.org/prevnext"
},
"require": { }
}
<?php
/**
* @file
* prevnext.admin.inc
*/
/**
* Previous/Next Settings Form Callback
*/
function prevnext_settings($form, &$form_state) {
$form['prevnext_enabled_nodetypes'] = array(
'#title' => t('Enabled Node Types'),
'#description' => t('Check node types enabled for Previous/Next'),
'#type' => 'checkboxes',
'#options' => _prevnext_types_as_options(),
'#default_value' => variable_get('prevnext_enabled_nodetypes', array())
);
$form['#submit'][] = 'prevnext_settings_submit';
return system_settings_form($form);
}
/**
* Previous/Next form settings submit
* Needs to clear cache :)
*
* @see prevnext_settings
*/
function prevnext_settings_submit(&$form, $form_state) {
drupal_flush_all_caches();
}
/**
* Helper: Retrieve all node types and create an option list with them.
*/
function _prevnext_types_as_options() {
$node_types = node_type_get_types();
$options = array();
foreach ($node_types as $type => $info) {
$options[$type] = $info->name;
}
asort($options);
return $options;
}
\ No newline at end of file
name = Previous Next
description = Add a "Previous/Next" variables to a node
core = 7.x
version = 7.x-1.0
configure = admin/config/user-interface/prevnext
\ No newline at end of file
name: Previous & Next
type: module
description: Add a "Previous/Next" links to the node display.
core: 8.x
package: Other
configure: prevnext.admin_settings
prevnext.settings:
title: 'Prev / Next settings'
description: 'Configure which content types will have the Prev/Next links on the node display.'
parent: system.admin_config_ui
route_name: prevnext.admin_settings
prevnext.module 100644 → 100755
......@@ -2,74 +2,26 @@
/**
* @file
*
* prevnext.module
*/
/**
* Implements hook_permission().
* Contains prevnext.module.
*/
function prevnext_permission() {
return array(
'access prevnext settings' => array(
'title' => t('Access to Previous/Next Settings page')
),
);
}
/**
* Implements hook_menu().
*/
function prevnext_menu() {
$items = array();
$items['admin/config/user-interface/prevnext'] = array(
'title' => 'Previous/Next',
'description' => 'Enable bundles that will use previous/next',
'page callback' => 'drupal_get_form',
'page arguments' => array('prevnext_settings'),
'access arguments' => array('access prevnext settings'),
'file' => 'prevnext.admin.inc',
'file path' => drupal_get_path('module', 'prevnext') . '/include',
'type' => MENU_NORMAL_ITEM
);
return $items;
}
use Drupal\Core\Routing\RouteMatchInterface;
use \Drupal\Core\Url;
use \Drupal\Core\Cache\Cache;
/**
* Implements hook_node_view().
* Implements hook_help().
*/
function prevnext_node_view($node, $view_mode, $langcode) {
$enabled_nodetypes = array_filter(variable_get('prevnext_enabled_nodetypes', array()));
if (in_array($node->type, $enabled_nodetypes)) {
$extrafields = field_extra_fields_get_display('node', $node->type, $view_mode);
$language = NULL;
if (module_exists(array('i18n_node'))) {
$mode = variable_get('language_content_type_' . $node->type, 0);
$language = ($mode != 0) ? $langcode : NULL;
}
$prevnext = _prevnext_get_prevnext($node, $language);
// @todo: Change theme() with a renderable array.
if (isset($extrafields['prevnext_previous']) && !empty($extrafields['prevnext_previous']['visible']) && !empty($prevnext['prev'])) {
$node->content['prevnext_previous'] = array(
'#markup' => theme('prevnext_previous', array(
'previous' => 'node/' . $prevnext['prev'],
))
);
}
if (isset($extrafields['prevnext_next']) && !empty($extrafields['prevnext_next']['visible']) && !empty($prevnext['next'])) {
$node->content['prevnext_next'] = array(
'#markup' => theme('prevnext_next', array(
'next' => 'node/' . $prevnext['next'],
))
);
}
function prevnext_help($route_name, RouteMatchInterface $route_match) {
switch ($route_name) {
// Main module help for the prevnext module.
case 'help.page.prevnext':
$output = '';
$output .= '<h3>' . t('About') . '</h3>';
$output .= '<p>' . t('Add a &quot;Previous/Next&quot; links to the node display.') . '</p>';
return $output;
default:
}
}
......@@ -77,77 +29,121 @@ function prevnext_node_view($node, $view_mode, $langcode) {
* Implements hook_theme().
*/
function prevnext_theme($existing, $type, $theme, $path) {
return array(
'prevnext_previous' => array(
'variables' => array(
'previous' => NULL
),
'template' => 'prevnext-previous',
'path' => $path . '/templates'
),
'prevnext_next' => array(
'variables' => array(
'next' => NULL
),
'template' => 'prevnext-next',
'path' => $path . '/templates'
)
);
$themes = [];
$themes['prevnext'] = [
'variables' => [
'direction' => '',
'text' => '',
'nid' => '',
'url' => '',
'void' => TRUE,
],
// Note that there is no need to indicate the template name, in absence of
// it the system will assume "prevnext.html.twig", inside "templates" dir.
];
return $themes;
}
/**
* Implements hook_field_extra_fields().
* Implements hook_entity_extra_field_info().
*/
function prevnext_field_extra_fields() {
$enabled_nodetypes = array_filter(variable_get('prevnext_enabled_nodetypes', array()));
function prevnext_entity_extra_field_info() {
$extra = [];
if (!empty($enabled_nodetypes)) {
$extra = array();
foreach ($enabled_nodetypes as $key => $value) {
$config = \Drupal::config('prevnext.settings');
$enabled_nodetypes = $config->get('prevnext_enabled_nodetypes');
$extra['node'][$key]['display']['prevnext_previous'] = array(
if (!empty($enabled_nodetypes)) {
foreach ($enabled_nodetypes as $bundle_key => $bundle_name) {
$extra['node'][$bundle_key]['display']['prevnext_previous'] = [
'label' => t('Previous'),
'description' => t('Previous node indicator'),
'weight' => 50
);
$extra['node'][$key]['display']['prevnext_next'] = array(
'weight' => 50,
];
$extra['node'][$bundle_key]['display']['prevnext_next'] = [
'label' => t('Next'),
'description' => t('Next node indicator'),
'weight' => 50
);
'weight' => 50,
];
}
return $extra;
}
return $extra;
}
/**
* Helper: Retrieve previous/next nodes
* Implements hook_ENTITY_TYPE_view().
*/
function _prevnext_get_prevnext($node, $language = NULL) {
$query = new EntityFieldQuery();
$query->entityCondition('entity_type', 'node')
->propertyCondition('type', $node->type)
->propertyCondition('status', 1);
if (!is_null($language)) {
$query->propertyCondition('language', $language);
function prevnext_node_view(array &$build, \Drupal\Core\Entity\EntityInterface $entity, \Drupal\Core\Entity\Display\EntityViewDisplayInterface $display, $view_mode) {
if ($display->getComponent('prevnext_previous')) {
$nids = _prevnext_get_prev_and_next_nids($entity);
$build['prevnext_previous'] = [
'#theme' => 'prevnext',
'#direction' => 'previous',
'#text' => t('Previous'),
'#nid' => $nids['prev'],
'#url' => Url::fromUserInput('/node/' . $nids['prev'], ['absolute' => TRUE])->toString(),
'#void' => empty($nids['prev']),
];
$build['prevnext_next'] = [
'#theme' => 'prevnext',
'#direction' => 'next',
'#text' => t('Next'),
'#nid' => $nids['next'],
'#url' => Url::fromUserInput('/node/' . $nids['next'], ['absolute' => TRUE])->toString(),
'#void' => empty($nids['next']),
];
// Once these links will be cached inside the node rendered output, we will
// add a custom cache tag to allow invalidation of all these cached info
// later (for example when a new node of this type is created).
$build['#cache']['tags'][] = 'prevnext-' . $entity->bundle();
}
$result = $query->execute();
}
$nids = array();
foreach ($result['node'] as $result_nids) {
$nids[$result_nids->nid] = $result_nids->nid;
/**
* Implements hook_ENTITY_TYPE_presave().
*/
function prevnext_node_presave(Drupal\Core\Entity\EntityInterface $entity) {
$config = \Drupal::config('prevnext.settings');
$enabled_nodetypes = $config->get('prevnext_enabled_nodetypes');
if (in_array($entity->bundle(), $enabled_nodetypes)) {
// We are saving a node of a type with prevnext enabled, so invalidate
// all cached rendered output of other nodes of this type with our tag.
Cache::invalidateTags(['prevnext-' . $entity->bundle()]);
}
}
$key = array_search($node->nid, $nids);
return array(
'prev' => !empty($nids[$key-1]) ? $nids[$key-1] : '',
'next' => !empty($nids[$key+1]) ? $nids[$key+1] : '',
);
/**
* Query the database and fetch the previous and next nids, if they exist.
*
* @param \Drupal\Core\Entity\EntityInterface $entity
* The node being viewed.
*
* @return array
* An array with keys "prev" and "next", and the values are the NIDs of the
* corresponding previous and next nodes. The values may be empty, if the
* node is the first or last nodes of this type.
*/
function _prevnext_get_prev_and_next_nids(\Drupal\Core\Entity\EntityInterface $entity) {
// @TODO: isn't there a better way to get the query object?
$entity_query = \Drupal::entityQuery('node');
$nodes = $entity_query->condition('status', NODE_PUBLISHED)
->condition('type', $entity->bundle())
->condition('langcode', $entity->language()->getId())
->execute();
// @TODO: improve the logic to allow defining the sort criteria.
$current_nid = $entity->id();
// Reset the array to have numerically indexed keys.
$nodes = array_values($nodes);
$current_key = array_search($current_nid, $nodes);
$nids['prev'] = ($current_key == 0) ? '' : $nodes[$current_key - 1];
$nids['next'] = ($current_key == count($nodes) - 1) ? '' : $nodes[$current_key + 1];
return $nids;
}
administer prevnext:
title: 'Administer the PrevNext module.'
description: 'Administer the settings for the PrevNext module.'
restrict access: TRUE
\ No newline at end of file
prevnext.admin_settings:
path: '/admin/config/user-interface/prevnext'
defaults:
_form: '\Drupal\prevnext\Form\PrevnextSettingsForm'
_title: 'Previous - Next Settings'
requirements:
_permission: 'administer prevnext'
<?php
/**
* @file
* Contains \Drupal\prevnext\Form\PrevnextSettingsForm.
*/
namespace Drupal\prevnext\Form;
use Drupal\Core\Form\ConfigFormBase;
use Drupal\Core\Form\FormStateInterface;
/**
* Class PrevnextSettingsForm.
*
* @package Drupal\prevnext\Form
*/
class PrevnextSettingsForm extends ConfigFormBase {
/**
* {@inheritdoc}
*/
public function getFormId() {
return 'prevnext_settings_form';
}
/**
* {@inheritdoc}
*/
protected function getEditableConfigNames() {
return ['prevnext.settings'];
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
$config = $this->config('prevnext.settings');
$form['prevnext_enabled_nodetypes'] = array(
'#title' => $this->t('Enabled Node Types'),
'#description' => $this->t('Check node types enabled for Previous/Next'),
'#type' => 'checkboxes',
'#options' => node_type_get_names(),
'#default_value' => $config->get('prevnext_enabled_nodetypes'),
);
return parent::buildForm($form, $form_state);
}
// /**
// * {@inheritdoc}
// */
// public function validateForm(array &$form, FormStateInterface $form_state) {
// if ('foo') {
// $form_state->setErrorByName('foo_element_name', t("Bar error message"));
// }
// }
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
// Save the config values.
$this->config('prevnext.settings')
->set('prevnext_enabled_nodetypes', $form_state->getValue('prevnext_enabled_nodetypes'))
->save();
parent::submitForm($form, $form_state);
}
}
<div id="prevnext-next" class="prevnext">
<?php print l(t('Next'), $next); ?>
</div>
\ No newline at end of file
<div id="prevnext-previous" class="prevnext">
<?php print l(t('Previous'), $previous); ?>
</div>
\ No newline at end of file
{#
/**
* @file prevnext.html.twig
* Default theme implementation to the prevnext indicator.
*
* Available variables:
* - direction: "previous" or "next"
* - text: The translated text for "Previous" or "Next"
* - nid: The node NID of the destination link
* - url: A formatted absolute URL for the path /node/$nid
* - void: A flag indicating wether this element should be completelly skipped. TRUE means there is no available $nid.
*
*/
#}
{% if not void %}
<div id="prevnext-{{ direction }}" class="prevnext-element {{ direction }}">
<a href="{{ url }}">{{ text }}</a>
</div>
{% endif %}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment