Here is code for a sample filter based on our source. I've tried to simplify it as much as possible, but it probably does not work as a drop-in somewhere. But it shows how we create the relationship to the node tables. Hope this helps.
namespace Drupal\example_mod\Plugin\views\filter;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Session\AccountProxyInterface;
use Drupal\views\Views;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* @ingroup views_filter_handlers
*
* @ViewsFilter("example_mod_write_access_filter")
*/
class ExampleFilter extends LogeAccessFilterBase implements ContainerFactoryPluginInterface {
protected EntityStorageInterface $logeStorage;
/**
*
*/
public function __construct(array $configuration,
$plugin_id,
$plugin_definition,
AccountProxyInterface $current_user,
EntityTypeManagerInterface $entity_type_manager) {
parent::__construct($configuration, $plugin_id, $plugin_definition, $current_user);
$this->logeStorage = $entity_type_manager->getStorage('loge');
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
// @see \Drupal\Core\Field\FormatterPluginManager::createInstance().
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('current_user'),
$container->get('entity_type.manager'),
);
}
/**
*
*/
public function query() {
$roles = $this->currentUser->getRoles();
if ($this->hasDefaultWriteAccess($roles)) {
return;
}
$readWrites = $this->normalizeReadWriteByRoom($this->extractReadWriteRolePrefix($roles));
if (empty($readWrites)) {
$readWrites = ['DenyAccessRole'];
}
// Join from event unit reference to daily availability entity.
$configuration = [
'table' => 'node__field_availability_daily',
'field' => 'field_availability_daily_target_id',
'left_table' => 'unit_bat_event__event_bat_unit_reference',
'left_field' => 'id',
];
$join = Views::pluginManager('join')->createInstance('standard', $configuration);
$rel = $this->query->addRelationship('node__field_availability_daily', $join, 'unit');
// Join from daily availability entity to bookable entity (the actual room).
$configuration = [
'table' => 'node__field_loger',
'field' => 'entity_id',
'left_table' => 'node__field_availability_daily',
'left_field' => 'entity_id',
];
$join = Views::pluginManager('join')->createInstance('standard', $configuration);
$rel = $this->query->addRelationship('node__field_loger', $join, 'node');
// Join from bookable entity to loge entity.
$configuration = [
'table' => 'loge',
'field' => 'id',
'left_table' => 'node__field_loger',
'left_field' => 'field_loger_target_id',
];
$join = Views::pluginManager('join')->createInstance('standard', $configuration);
$rel = $this->query->addRelationship('loge', $join, 'loge');
$this->ensureMyTable();
// Join to Loge entity, check IN on ad_prefix and readWrites.
$this->operator = 'in';
$group = $this->options['group'];
$this->query->addWhere($group, 'loge.ad_prefix', $readWrites, $this->operator);
}
/**
*
*/
protected function normalizeReadWriteByRoom(array $readWrites) :array {
$loges = $this->logeStorage->loadByProperties(['ad_prefix' => $readWrites]);
$rtn = [];
$lastRoom = NULL;
foreach ($loges as $loge) {
if (empty($loge->get('field_standard_room')->entity)) {
continue;
}
$roomId = $loge->get('field_standard_room')->entity->id();
if ($roomId === $lastRoom) {
continue;
}
$lastRoom = $roomId;
if (!in_array($loge->getADPrefix(), $rtn)) {
$rtn[] = $loge->getADPrefix();
}
}
return $rtn;
}
}
I'm going to have to re-open this issue, because I think there is still a problem, though perhaps not quite related to my original assumption. Based on the description in comment #3, this module should only look at deleted
columns in base field definitions? So in the case of a node content type, it should only be looking at node_field_data.deleted
, which is the column that has been added by trash_entity_base_field_info()
? It should not be looking at deleted
columns in any fields connected to the content entity, e.g. node__field_image
. Am I correct?
If my above understanding is correct, then if the view query already contains a relationship to a node__field*, in my case for instance because of a custom filter that adds a relationship to a field__xx table, then ViewsQueryAlter will also process that table as if it's a base field definition. So to me it looks like ViewsQueryAlter is processing field__*
-tables when it shouldn't. But I don't have a good enough understanding of how view queries work to be sure, or have an idea of how to fix it...
Basically my problem is that I have a custom view filter which adds a relationship to another table to the view query. This table is a field definition table for nodes, called node__field_loger. node__field_loger
contains a deleted
column as defined by Drupal core's SQL schema (which is how I understand it based on comment #3). When I enable the Trash module and run the query, it adds a check for null values against node__field_loger.deleted:
... AND ("node__field_loger"."deleted" IS NULL) ...
But since this field is not actually the field that trash adds to the base definition and it contains the integer 0, not a NULL value, the check will always fail and thus no results are returned. So based on this, I think the way in which the Trash module determines which tables it should take into account when adding the NULL check is wrong. I guess it should somehow resolve the base field definition to which it has added the "deleted" column, and not just scan for all tables in the query relationships that have a "deleted" column (which is what it seems to be doing in alterQueryForEntityType
). But again, my understanding of view queries and also the code of this module is not quite good enough to be sure...
jwwj → created an issue.
Patch attached in #2 should fix the issue in my case at least by creating an OR-condition group comparing both NULL and 0 values.
I have a similar issue when I try to force the bat module to be a newer version:
composer require 'drupal/bat:^10.1@RC'
Problem 1
- Root composer.json requires drupal/bat ^10.1@RC, found drupal/bat[10.1.0-rc1, 10.1.0-rc2, 10.1.0-rc3] but these were not loaded, likely because it conflicts with another require.
Problem 2
- drupal/bat_booking 2.1.0 requires drupal/bat ^2 -> found drupal/bat[2.1.0] but it conflicts with your root composer.json require (^10.1@RC).
- drupal/bee 3.0.0-rc1 requires drupal/bat_booking * -> satisfiable by drupal/bat_booking[2.1.0].
- drupal/bee is locked to version 3.0.0-rc1 and an update of this package was not requested.
This could potentially be because there is no stable version of drupal/bat 10.x yet, so composer falls back to the minimum stable version of 2.1.0 (I'm not sure of the inner workings of composer and how it resolves dependencies, but this is my guess).
I was able to work around the issue by aliasing the module in my composer require (only downside I'm now on the dev branch instead of the RC, couldn't figure out how to alias an RC version):
composer require 'drupal/bat:10.x-dev as 2.1.0'
But I think the more stable solution would be for drupal/bee to explicitly require a specific version of drupal/bat_booking and any other dependencies it has in it's composer.json. But I leave that for the maintainers to decide...
Here is one use case: In our project the customer has rooms that they allow their members to book, and we have implemented this feature using bee. There is no need for any payment to use these rooms, so there is no need for a commerce integration. Thus, in this case having a dependency on modules from the Drupal Commerce ecosystem is unnecessary and would just add unnecessary complexity to the maintenance of the site and potentials for bugs / security vulnerabilities to creep in.
Basically, any use case where there is a need to book something, but NOT a need to ask for payment would be a use case for NOT having an integration to the Drupal Commerce ecosystem. Another such example could be lending of equipment within a company or a neighbourhood (sharing economy).
Patch in #16 seems to apply OK for me on Drupal 10 and 2.1 version
The patch in issue https://www.drupal.org/project/bat/issues/3404353 🐛 bat_fullcalendar_timeline.js?v=10.1.6:251 Uncaught TypeError: Cannot set properties of undefined (setting 'url') Needs review also addresses the same issues as my patch, and since that one also fixes some other issues I suggest using it instead.
Seems to solve the issue on my installation. +1 for RTBC
The patch worked on my installation. +1 for RTBC
Aaand patch in #2 didn't apply after all due to whitespace issues, so re-rolled
Attached patch should fix issue with boolean and null in javascript file.
jwwj → created an issue.
Fixed import statement (forgot in previous patch)
jwwj → created an issue.
I get the same error as Nchase when applying patch from #10 against the release version, however that patch did state that it was a re-roll against the dev branch. I guess there is a difference between the dev version and the latest release (1.6) on that part. Applying the rector patch in this issue against the release branch worked for me (or at least everything is green now in upgrade status).
Here is a patch that should fix the problem against the 2.x branch.
jwwj → created an issue.
Are there still issues that need to be resolved around this, and is there anything that can be done to help move them along without deep knowledge of Solr and it's configs? Just ran in to this error also when trying to set up a Solr 9 instance for a site.
We're also in a pickle in one project where we use this module. We added the feature last spring based on this module as it looked like there was activity around the module back then. But now with the Drupal 10 update arriving this module would require updates to be compatible.
If the maintainers don't respond and taking ownership does not work, would one option be to fork the module into a new namespace/module? I guess that would require some trickery to migrate the configuration/namespaces at least, but if the first release would be a 1-1 copy of the current latest official release, then existing patches should be appliable and it should be fairly easy for users to switch over?