Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PER-26: Rework querying. #31

Merged
merged 19 commits into from
Mar 14, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Functional.
adam-vessey committed Mar 9, 2024

Verified

This commit was signed with the committer’s verified signature.
mostafa Mostafa Moradian
commit 7507e6ba37144c1328014e7fb78c58c64c87ac65
29 changes: 1 addition & 28 deletions src/Access/QueryTagger.php
Original file line number Diff line number Diff line change
@@ -70,34 +70,7 @@ public function tagNode(SelectInterface $query) : void {
}

$query->addMetaData('embargo_tagged_table_aliases', $tagged_table_aliases);
$existence_query = $query->getMetaData('embargo_tagged_existence_query');

if (!$existence_query) {
$existence_query = $this->database->select('node', 'existence_node');
$existence_query->fields('existence_node', ['nid']);
$query->addMetaData('embargo_tagged_existence_query', $existence_query);

$query->exists($existence_query);
}

$existence_query->where(strtr('!field IN (!targets)', [
'!field' => 'existence_node.nid',
'!targets' => implode(', ', $target_aliases),
]));

if (!$query->hasTag('embargo_access')) {
$query->addTag('embargo_access');

$existence_query->condition($existence_condition = $existence_query->andConditionGroup())
->addMetaData('embargo_existence_condition', $existence_condition);

$this->applyExistenceQuery(
$existence_query,
$existence_condition,
'existence_node',
[EmbargoInterface::EMBARGO_TYPE_NODE],
);
}
$this->applyExistenceQuery($query, $target_aliases, [EmbargoInterface::EMBARGO_TYPE_NODE]);
}

}
97 changes: 65 additions & 32 deletions src/EmbargoExistenceQueryTrait.php
Original file line number Diff line number Diff line change
@@ -61,67 +61,100 @@ trait EmbargoExistenceQueryTrait {
/**
* Helper; apply existence checks to a node(-like) table.
*
* @param \Drupal\Core\Database\Query\SelectInterface $existence_query
* The query to which to add.
* @param string $target_alias
* @param string[] $target_aliases
* The alias of the node-like table in the query to which to attach things.
* @param array $embargo_types
* The types of embargo to deal with.
*/
protected function applyExistenceQuery(
SelectInterface $existence_query,
ConditionInterface $existence_condition,
string $target_alias,
array $target_aliases,
array $embargo_types,
) {
$embargo_alias = $existence_query->leftJoin('embargo', 'e', "%alias.embargoed_node = {$target_alias}.nid");
$user_alias = $existence_query->leftJoin('embargo__exempt_users', 'u', "%alias.entity_id = {$embargo_alias}.id");


) : void {
$existence_condition->condition(
$existence_or = $existence_condition->orConditionGroup()
$existence_condition->orConditionGroup()
->notExists($this->getNullQuery($target_aliases, $embargo_types))
->exists($this->getAccessibleEmbargoesQuery($target_aliases, $embargo_types))
);
}

protected function getNullQuery(array $target_aliases, array $embargo_types) : SelectInterface {
$embargo_alias = 'embargo_null';
$query = $this->database->select('embargo', $embargo_alias);
$query->addExpression(1, 'embargo_null_e');

$query->where(strtr('!field IN (!targets)', [
'!field' => "{$embargo_alias}.embargoed_node",
'!targets' => implode(', ', $target_aliases),
]));
$query->condition("{$embargo_alias}.embargo_type", $embargo_types, 'IN');

return $query;
}

// No embargo.
// XXX: Might have to change to examine one of the fields outside the join
// condition?
$existence_or->isNull("{$embargo_alias}.embargoed_node");
protected function getAccessibleEmbargoesQuery(array $target_aliases, array $embargo_types) : SelectInterface {
// Embargo exists for the entity, where:
$embargo_alias = 'embargo_existence';
$embargo_existence = $this->database->select('embargo', $embargo_alias);
$embargo_existence->addExpression(1, 'embargo_allowed');

$embargo_existence->addMetaData('embargo_alias', $embargo_alias);

$replacements = [
'!field' => "{$embargo_alias}.embargoed_node",
'!targets' => implode(', ', $target_aliases),
];
$embargo_existence->condition(
$embargo_existence->orConditionGroup()
->condition($existence_condition = $embargo_existence->andConditionGroup()
->where(strtr('!field IN (!targets)', $replacements))
->condition($embargo_or = $embargo_existence->orConditionGroup())
)
);

// The user is exempt from the embargo.
$existence_or->condition("{$user_alias}.exempt_users_target_id", $this->user->id());
$embargo_existence->addMetaData('embargo_existence_condition', $existence_condition);

// ... the incoming IP is in an exempt range; or...
// - The request IP is exempt.
/** @var \Drupal\embargo\IpRangeStorageInterface $storage */
$storage = $this->entityTypeManager->getStorage('embargo_ip_range');
$applicable_ip_ranges = $storage->getApplicableIpRanges($this->currentIp);
if (!empty($applicable_ip_ranges)) {
$existence_or->condition("{$embargo_alias}.exempt_ips", array_keys($applicable_ip_ranges), 'IN');
if ($applicable_ip_ranges) {
$embargo_or->condition("{$embargo_alias}.exempt_ips", array_keys($applicable_ip_ranges), 'IN');
}

// With embargo, without exemption.
$embargo_and = $existence_or->andConditionGroup();

// Has an embargo of a relevant type.
$embargo_and->condition("{$embargo_alias}.embargo_type", $embargo_types, 'IN');
// - The user is exempt.
// @todo Should the IP range constraint(s) take precedence?
$user_existence = $this->database->select('embargo__exempt_users', 'eeu');
$user_existence->addExpression(1, 'user_existence');
$user_existence->where("eeu.entity_id = {$embargo_alias}.id")
->condition('eeu.exempt_users_target_id', $this->user->id());
$embargo_or->exists($user_existence);

// - There's a scheduled embargo of an appropriate type and no other
// overriding embargo.
$current_date = $this->dateFormatter->format($this->time->getRequestTime(), 'custom', DateTimeItemInterface::DATE_STORAGE_FORMAT);
// No indefinite embargoes or embargoes expiring in the future.
$unexpired_embargo_subquery = $this->database->select('embargo', 'ue')
->fields('ue', ['embargoed_node'])
->where("ue.embargoed_node = {$embargo_alias}.embargoed_node");
->where("ue.embargoed_node = {$embargo_alias}.embargoed_node")
->condition('ue.embargo_type', $embargo_types, 'IN');
$unexpired_embargo_subquery->addExpression(1, 'ueee');
$unexpired_embargo_subquery->condition($unexpired_embargo_subquery->orConditionGroup()
->condition('ue.expiration_type', EmbargoInterface::EXPIRATION_TYPE_INDEFINITE)
->condition($unexpired_embargo_subquery->andConditionGroup()
->condition('ue.expiration_type', EmbargoInterface::EXPIRATION_TYPE_SCHEDULED)
->condition('ue.expiration_date', $current_date, '>')
)
);
$embargo_and
->notExists($unexpired_embargo_subquery)
->condition("{$embargo_alias}.expiration_type", EmbargoInterface::EXPIRATION_TYPE_SCHEDULED)
->condition("{$embargo_alias}.expiration_date", $current_date, '<=');

$existence_or->condition($embargo_and);
$embargo_or->condition(
$embargo_or->andConditionGroup()
->condition("{$embargo_alias}.embargo_type", $embargo_types, 'IN')
->condition("{$embargo_alias}.expiration_type", EmbargoInterface::EXPIRATION_TYPE_SCHEDULED)
->condition("{$embargo_alias}.expiration_date", $current_date, '<=')
->notExists($unexpired_embargo_subquery)
);

return $embargo_existence;
}

}
Original file line number Diff line number Diff line change
@@ -79,14 +79,11 @@ public function processEvent(Event $event) : void {
return;
}

/** @var \Drupal\Core\Database\Query\SelectInterface $existence_query */
$existence_query = $query->getMetaData('islandora_hierarchical_access_tagged_existence_query');
/** @var \Drupal\Core\Database\Query\ConditionInterface $existence_condition */
$existence_condition = $existence_query->getMetaData('islandora_hierarchical_access_tagged_existence_condition');
$existence_condition = $query->getMetaData('islandora_hierarchical_access_tagged_existence_condition');
$this->applyExistenceQuery(
$existence_query,
$existence_condition,
'lut',
['lut_exist.nid'],
match ($event->getType()) {
'file', 'media' => [
EmbargoInterface::EMBARGO_TYPE_FILE,