knowledge-8.x-1.x-dev/src/Plugin/EntityReferenceSelection/KnowledgeSelection.php
src/Plugin/EntityReferenceSelection/KnowledgeSelection.php
<?php
namespace Drupal\knowledge\Plugin\EntityReferenceSelection;
use Drupal\Core\Database\Query\SelectInterface;
use Drupal\Core\Entity\Plugin\EntityReferenceSelection\DefaultSelection;
use Drupal\knowledge\KnowledgeInterface;
/**
* Provides specific access control for the knowledge entity type.
*
* @EntityReferenceSelection(
* id = "default:knowledge",
* label = @Translation("Knowledge selection"),
* entity_types = {"knowledge"},
* group = "default",
* weight = 1
* )
*/
class KnowledgeSelection extends DefaultSelection {
/**
* {@inheritdoc}
*/
protected function buildEntityQuery($match = NULL, $match_operator = 'CONTAINS') {
$query = parent::buildEntityQuery($match, $match_operator);
// Adding the 'knowledge_access' tag is sadly insufficient for knowledge:
// core requires us to also know about the concept of 'published' and
// 'unpublished'.
if (!$this->currentUser->hasPermission('administer knowledge')) {
$query->condition('status', KnowledgeInterface::PUBLISHED);
}
return $query;
}
/**
* {@inheritdoc}
*/
public function createNewEntity($entity_type_id, $bundle, $label, $uid) {
$knowledge = parent::createNewEntity($entity_type_id, $bundle, $label, $uid);
// In order to create a referenceable knowledge, it needs to published.
/** @var \Drupal\knowledge\KnowledgeInterface $knowledge */
$knowledge->setPublished();
return $knowledge;
}
/**
* {@inheritdoc}
*/
public function validateReferenceableNewEntities(array $entities) {
$entities = parent::validateReferenceableNewEntities($entities);
// Mirror the conditions checked in buildEntityQuery().
if (!$this->currentUser->hasPermission('administer knowledge')) {
$entities = array_filter($entities, function ($knowledge) {
/** @var \Drupal\knowledge\KnowledgeInterface $knowledge */
return $knowledge->isPublished();
});
}
return $entities;
}
/**
* {@inheritdoc}
*/
public function entityQueryAlter(SelectInterface $query) {
parent::entityQueryAlter($query);
$tables = $query->getTables();
$data_table = 'knowledge';
if (!isset($tables['knowledge']['alias'])) {
// If no conditions join against the knowledge data table, it should be
// joined manually to allow node access processing.
$query->innerJoin($data_table, NULL, "[base_table].[kid] = [$data_table].[kid]");
}
// The Knowledge module doesn't implement any proper knowledge access,
// and as a consequence doesn't make sure that knowledge cannot be viewed
// when the user doesn't have access to the node.
$node_alias = $query->innerJoin('node_field_data', 'n', "[%alias].[nid] = [$data_table].[entity_id] AND [$data_table].[entity_type] = 'node'");
// Pass the query to the node access control.
$this->reAlterQuery($query, 'node_access', $node_alias);
// Passing the query to node_query_node_access_alter() is sadly
// insufficient for nodes.
// @see \Drupal\node\Plugin\EntityReferenceSelection\NodeSelection::buildEntityQuery()
if (!$this->currentUser->hasPermission('bypass node access') && !$this->moduleHandler->hasImplementations('node_grants')) {
$query->condition($node_alias . '.status', 1);
}
}
}
