View source
<?php
namespace Drupal\prev_next;
use Drupal\Core\Database\Driver\mysql\Connection;
use Drupal\Core\Extension\ModuleHandler;
use Drupal\node\Entity\NodeType;
class PrevNextApi implements PrevNextApiInterface {
protected $moduleHandler;
protected $database;
protected $prevnextHelper;
public function __construct(ModuleHandler $module_handler, Connection $database, PrevNextHelperInterface $prevnext_helper) {
$this->moduleHandler = $module_handler;
$this->database = $database;
$this->prevnextHelper = $prevnext_helper;
}
public function add($entity_id, $bundle_name) {
$prevnext_bundle = $this->prevnextHelper
->loadBundle($bundle_name);
$search_criteria = $prevnext_bundle
->get('indexing_criteria');
$cond = $this
->bundlesSql($bundle_name, $prevnext_bundle);
if ($search_criteria != 'nid') {
$criteria_value = $this->database
->queryRange("SELECT {$search_criteria} FROM {node_field_data} WHERE nid = :nid", 0, 1, [
':nid' => $entity_id,
])
->fetchField();
$next_nid = $this->database
->queryRange("SELECT nid FROM {node_field_data} WHERE (({$search_criteria} = :value AND nid > :nid) OR {$search_criteria} > :value) AND status = 1 {$cond} ORDER BY {$search_criteria} ASC,nid ASC", 0, 1, [
':value' => $criteria_value,
':nid' => $entity_id,
])
->fetchField();
$prev_nid = $this->database
->queryRange("SELECT nid FROM {node_field_data} WHERE (({$search_criteria} = :value AND nid < :nid) OR {$search_criteria} < :value) AND status = 1 {$cond} ORDER BY {$search_criteria} DESC,nid DESC", 0, 1, [
':value' => $criteria_value,
':nid' => $entity_id,
])
->fetchField();
}
else {
$next_nid = $this->database
->queryRange("SELECT nid FROM {node_field_data} WHERE nid > :nid AND status = 1 {$cond} ORDER BY nid ASC", 0, 1, [
':nid' => $entity_id,
])
->fetchField();
$prev_nid = $this->database
->queryRange("SELECT nid FROM {node_field_data} WHERE nid < :nid AND status = 1 {$cond} ORDER BY nid DESC", 0, 1, [
':nid' => $entity_id,
])
->fetchField();
}
$exists = (bool) $this->database
->queryRange('SELECT 1 FROM {prev_next_node} WHERE nid = :nid', 0, 1, [
':nid' => $entity_id,
])
->fetchField();
if (!empty($exists)) {
$this->database
->update('prev_next_node')
->fields([
'prev_nid' => $prev_nid ? $prev_nid : 0,
'next_nid' => $next_nid ? $next_nid : 0,
'changed' => REQUEST_TIME,
])
->condition('nid', $entity_id)
->execute();
}
else {
$id = $this->database
->insert('prev_next_node')
->fields([
'prev_nid' => $prev_nid ? $prev_nid : 0,
'next_nid' => $next_nid ? $next_nid : 0,
'changed' => REQUEST_TIME,
'nid' => $entity_id,
])
->execute();
}
foreach (NodeType::loadMultiple() as $type => $name) {
$prevnext_bundles = $this->prevnextHelper
->getBundleNames();
if (in_array($type, $prevnext_bundles)) {
$prevnext_bundle = $this->prevnextHelper
->loadBundle($type);
$search_criteria = $prevnext_bundle
->get('indexing_criteria');
$cond = $this
->bundlesSql($bundle_name, $prevnext_bundle);
if ($search_criteria != 'nid') {
$criteria_value = $this->database
->queryRange("SELECT {$search_criteria} FROM {node_field_data} WHERE nid = :nid", 0, 1, [
':nid' => $entity_id,
])
->fetchField();
$prev_nid = $this->database
->queryRange("SELECT nid FROM {node_field_data} WHERE (({$search_criteria} = :value AND nid > :nid) OR {$search_criteria} > :value) AND status = 1 {$cond} ORDER BY {$search_criteria} ASC,nid ASC", 0, 1, [
':value' => $criteria_value,
':nid' => $entity_id,
])
->fetchField();
$next_nid = $this->database
->queryRange("SELECT nid FROM {node_field_data} WHERE (({$search_criteria} = :value AND nid < :nid) OR {$search_criteria} < :value) AND status = 1 {$cond} ORDER BY {$search_criteria} DESC,nid DESC", 0, 1, [
':value' => $criteria_value,
':nid' => $entity_id,
])
->fetchField();
}
else {
$prev_nid = $this->database
->queryRange("SELECT nid FROM {node_field_data} WHERE nid > :nid AND status = 1 {$cond} ORDER BY nid ASC", 0, 1, [
':nid' => $entity_id,
])
->fetchField();
$next_nid = $this->database
->queryRange("SELECT nid FROM {node_field_data} WHERE nid < :nid AND status = 1 {$cond} ORDER BY nid DESC", 0, 1, [
':nid' => $entity_id,
])
->fetchField();
}
}
if ($next_nid) {
$this->database
->update('prev_next_node')
->fields([
'next_nid' => $entity_id,
])
->condition('nid', $next_nid)
->execute();
}
if ($prev_nid) {
$this->database
->update('prev_next_node')
->fields([
'prev_nid' => $entity_id,
])
->condition('nid', $prev_nid)
->execute();
}
}
}
public function update($entity_id, $bundle_name) {
$this
->modifyPointingEntities($entity_id, $bundle_name);
$this
->add($entity_id, $bundle_name);
}
public function remove($entity_id, $bundle_name) {
$this->database
->delete('prev_next_node')
->condition('nid', $entity_id)
->execute();
$this
->modifyPointingEntities($entity_id, $bundle_name);
}
public function bundlesSql($bundle_name, $bundle) {
$same_type = $bundle
->get('same_type');
if (!$same_type) {
$types = $this->prevnextHelper
->getBundleNames();
$quoted_types = [];
foreach ($this->prevnextHelper
->getBundleNames() as $type) {
$quoted_types[] = "'" . $type . "'";
}
$cond = '';
if (count($types)) {
$cond = 'AND type IN (' . implode(',', $quoted_types) . ')';
}
}
else {
$cond = "AND type = '" . $bundle_name . "'";
}
return $cond;
}
public function modifyPointingEntities($entity_id, $bundle_name) {
$prev = $this->database
->query("SELECT nid FROM {prev_next_node} WHERE prev_nid = :prev_nid", array(
':prev_nid' => $entity_id,
))
->fetchField();
if ($prev) {
$this
->add($prev, $bundle_name);
}
$next = $this->database
->query("SELECT nid FROM {prev_next_node} WHERE next_nid = :next_nid", array(
':next_nid' => $entity_id,
))
->fetchField();
if ($next) {
$this
->add($next, $bundle_name);
}
}
}