View source
<?php
namespace Drupal\nopremium\Plugin\search_api\processor;
use Drupal\Core\Database\Connection;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\node\Entity\NodeType;
use Drupal\search_api\IndexInterface;
use Drupal\search_api\LoggerTrait;
use Drupal\search_api\Processor\ProcessorPluginBase;
use Drupal\search_api\Query\QueryInterface;
use Drupal\search_api\SearchApiException;
use Drupal\user\Entity\User;
use Symfony\Component\DependencyInjection\ContainerInterface;
class PremiumContent extends ProcessorPluginBase {
use LoggerTrait;
protected $database;
protected $currentUser;
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
$processor = parent::create($container, $configuration, $plugin_id, $plugin_definition);
$processor
->setLogger($container
->get('logger.channel.search_api'));
$processor
->setDatabase($container
->get('database'));
$processor
->setCurrentUser($container
->get('current_user'));
return $processor;
}
public function getDatabase() {
return $this->database ?: \Drupal::database();
}
public function setDatabase(Connection $database) {
$this->database = $database;
return $this;
}
public function getCurrentUser() {
return $this->currentUser ?: \Drupal::currentUser();
}
public function setCurrentUser(AccountProxyInterface $current_user) {
$this->currentUser = $current_user;
return $this;
}
public static function supportsIndex(IndexInterface $index) {
foreach ($index
->getDatasources() as $datasource) {
if ($datasource
->getEntityTypeId() === 'node') {
return TRUE;
}
}
return FALSE;
}
public function preIndexSave() {
foreach ($this->index
->getDatasources() as $datasource_id => $datasource) {
if ($datasource
->getEntityTypeId() == 'node') {
$this
->ensureField($datasource_id, 'premium', 'boolean');
$this
->ensureField($datasource_id, 'type', 'string');
$this
->ensureField($datasource_id, 'uid', 'integer');
}
}
}
public function preprocessSearchQuery(QueryInterface $query) {
if (!$query
->getOption('search_api_bypass_access')) {
$account = $query
->getOption('search_api_access_account', $this
->getCurrentUser());
if (is_numeric($account)) {
$account = User::load($account);
}
if ($account instanceof AccountInterface) {
try {
$this
->addPremiumAccess($query, $account);
} catch (SearchApiException $e) {
$this
->logException($e);
}
}
else {
$account = $query
->getOption('search_api_access_account', $this
->getCurrentUser());
if ($account instanceof AccountInterface) {
$account = $account
->id();
}
if (!is_scalar($account)) {
$account = var_export($account, TRUE);
}
$this
->getLogger()
->warning('An illegal user UID was given for node access: @uid.', [
'@uid' => $account,
]);
}
}
}
protected function addPremiumAccess(QueryInterface $query, AccountInterface $account) {
if ($account
->hasPermission('view full premium content of any type')) {
return;
}
$affected_datasources = [];
$unaffected_datasources = [];
foreach ($this->index
->getDatasources() as $datasource_id => $datasource) {
if ($datasource
->getEntityTypeId() === 'node') {
$affected_datasources['node'][] = $datasource_id;
}
else {
$unaffected_datasources[] = $datasource_id;
}
}
if ($unaffected_datasources) {
$outer_conditions = $query
->createConditionGroup('OR', [
'content_access',
]);
$query
->addConditionGroup($outer_conditions);
foreach ($unaffected_datasources as $datasource_id) {
$outer_conditions
->addCondition('search_api_datasource', $datasource_id);
}
$access_conditions = $query
->createConditionGroup('AND');
$outer_conditions
->addConditionGroup($access_conditions);
}
else {
$access_conditions = $query;
}
if (!$affected_datasources) {
if (!$unaffected_datasources) {
$query
->abort($this
->t('You have no access to any results in this search.'));
}
return;
}
$premium_conditions = $query
->createConditionGroup('OR');
if ($account
->isAuthenticated()) {
$author_conditions = $query
->createConditionGroup('OR');
foreach ($affected_datasources as $entity_type => $datasources) {
foreach ($datasources as $datasource_id) {
if ($entity_type == 'node') {
$author_field = $this
->findField($datasource_id, 'uid', 'integer');
if ($author_field) {
$author_conditions
->addCondition($author_field
->getFieldIdentifier(), $account
->id());
}
}
}
}
$premium_conditions
->addConditionGroup($author_conditions);
}
foreach (NodeType::loadMultiple() as $type) {
$type_id = $type
->id();
if (!$account
->hasPermission("view full {$type_id} premium content")) {
$node_type_conditions = $query
->createConditionGroup('AND');
$node_type_conditions
->addCondition('type', $type_id);
$node_type_conditions
->addCondition('premium', FALSE);
$premium_conditions
->addConditionGroup($node_type_conditions);
}
else {
$premium_conditions
->addCondition('type', $type_id);
}
}
$access_conditions
->addConditionGroup($premium_conditions);
}
}