class NodeTypeAccessService in Nodetype access 8
Hierarchy
- class \Drupal\nodetype_access\NodeTypeAccessService
Expanded class hierarchy of NodeTypeAccessService
1 string reference to 'NodeTypeAccessService'
1 service uses NodeTypeAccessService
File
- src/
NodeTypeAccessService.php, line 12
Namespace
Drupal\nodetype_accessView source
class NodeTypeAccessService {
/**
* @var \Drupal\Core\Entity\EntityTypeBundleInfoInterface
*/
protected $entityTypeBundleInfo;
/**
* NodetypeAccessService constructor.
*
* @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $entityTypeBundleInfo
*/
public function __construct(EntityTypeBundleInfoInterface $entityTypeBundleInfo) {
$this->entityTypeBundleInfo = $entityTypeBundleInfo;
}
/**
* Get permission ID for bundle
*/
protected function makeViewAnyPermissionId($bundleId) {
return "view any {$bundleId} content";
}
/**
* Permissions callback.
*
* Defines a 'view any $type content' permission.
*/
public function permissions() {
$permissions = array();
foreach ($this->entityTypeBundleInfo
->getBundleInfo('node') as $bundleId => $info) {
$permissions[$this
->makeViewAnyPermissionId($bundleId)] = [
'title' => t('View published %bundle_label content', array(
'%bundle_label' => $info['label'],
)),
];
}
return $permissions;
}
protected function permittedBundleIds(AccountInterface $account) {
$bundleIds = [];
foreach ($this->entityTypeBundleInfo
->getAllBundleInfo()['node'] as $bundleId => $info) {
if ($account
->hasPermission($this
->makeViewAnyPermissionId($bundleId))) {
$bundleIds[$bundleId] = $bundleId;
}
}
return $bundleIds;
}
/**
* Implements hook_node_access().
*
* Why does this use forbiddenIf()? The main controller uses allowedIf() so
* if we want an AND conjunction we must use the stronger forbiddenIf().
* (Which also means: If we want to OR this result with something else like
* OG access, we can not use independent node access hooks, but somehow must
* consolidate both results first.)
*
* @see \Drupal\Core\Entity\EntityAccessControlHandler::access
* @see \Drupal\Core\Entity\EntityAccessControlHandler::checkAccess
* @see \Drupal\node\NodeAccessControlHandler::access
* @see \Drupal\node\NodeAccessControlHandler::checkAccess
* @see \Drupal\node\NodeGrantDatabaseStorage::access
*
* @param \Drupal\node\NodeInterface $node
* @param string $op
* @param \Drupal\Core\Session\AccountInterface $account
*
* @return \Drupal\Core\Access\AccessResultInterface
*/
public function hookNodeAccess(NodeInterface $node, $op, AccountInterface $account) {
if ($op === 'view') {
$bundleIsPermitted = in_array($node
->bundle(), $this
->permittedBundleIds($account));
return AccessResult::forbiddenIf(!$bundleIsPermitted)
->cachePerPermissions();
}
}
public function hookQueryNodeAccessAlter(AlterableInterface $query) {
$account = $query
->getMetaData('account') ?? \Drupal::currentUser();
$op = $query
->getMetaData('op') ?? 'view';
if ($query instanceof SelectInterface && $op === 'view') {
$nodeTableAlias = $this
->extractBaseTableAlias($query);
// Bail out if the base table is missing.
if (!$nodeTableAlias) {
throw new \Exception('Query tagged for node access but there is no node table, specify the base_table using meta data.');
}
$permittedBundleIds = $this
->permittedBundleIds($account);
if ($permittedBundleIds) {
$query
->condition("{$nodeTableAlias}.type", $permittedBundleIds, 'IN');
}
else {
$query
->alwaysFalse();
}
}
}
/**
* Extract base table alias.
*
* @param \Drupal\Core\Database\Query\AlterableInterface $query
*
* @return string|null
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
* @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
* @throws \Exception
*/
private function extractBaseTableAlias(AlterableInterface $query) {
// Copied from @see \node_query_node_access_alter
$tables = $query
->getTables();
$base_table = $query
->getMetaData('base_table');
// If the base table is not given, default to one of the node base tables.
if (!$base_table) {
/** @var \Drupal\Core\Entity\Sql\DefaultTableMapping $table_mapping */
$table_mapping = \Drupal::entityTypeManager()
->getStorage('node')
->getTableMapping();
$node_base_tables = $table_mapping
->getTableNames();
foreach ($tables as $table_info) {
if (!$table_info instanceof SelectInterface) {
$table = $table_info['table'];
// Ensure that 'node' and 'node_field_data' are always preferred over
// 'node_revision' and 'node_field_revision'.
if ($table == 'node' || $table == 'node_field_data') {
$base_table = $table;
break;
}
// If one of the node base tables are in the query, add it to the list
// of possible base tables to join against.
if (in_array($table, $node_base_tables)) {
$base_table = $table;
}
}
}
}
if (isset($base_table)) {
// Copied from @see \Drupal\node\NodeGrantDatabaseStorage::alterQuery
foreach ($tables as $table_alias => $tableinfo) {
$table = $tableinfo['table'];
if (!$table instanceof SelectInterface && $table == $base_table) {
return $table_alias;
}
}
}
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
NodeTypeAccessService:: |
protected | property | ||
NodeTypeAccessService:: |
private | function | Extract base table alias. | |
NodeTypeAccessService:: |
public | function | Implements hook_node_access(). | |
NodeTypeAccessService:: |
public | function | ||
NodeTypeAccessService:: |
protected | function | Get permission ID for bundle | |
NodeTypeAccessService:: |
public | function | Permissions callback. | |
NodeTypeAccessService:: |
protected | function | ||
NodeTypeAccessService:: |
public | function | NodetypeAccessService constructor. |