- Issue created by @roman_pro
- π§πͺBelgium borisson_ Mechelen, π§πͺ
The indexing in search api happens on a field basis, and it is usually indexed as the anonymous user. This will need a custom processor to translate the node grants into something useful. I'll keep this open to see if there is more interest in this, but I don't think this should be something we include in facets.
- π¨πΏCzech Republic roman_pro
Thanks borrison_
I don't mind creating a custom processor myself, just looking for some hints really. Taking some inspiration from flag_search_api, where they index data per user but I'd rather use already indexed node_grants field if at all possible? - πΊπΈUnited States somebodysysop
Did anyone ever figure out a path to this? I have created a group facet and only want groups to show that the user has access to. Right now, it is not listing the nodes in the private groups, but still showing the private group facets.
Any suggestions?
If it helps, the facet source I am using is a datasource I created:
Using this processor:
namespace Drupal\sbn\Plugin\search_api\processor; use Drupal\search_api\Datasource\DatasourceInterface; use Drupal\search_api\Item\ItemInterface; use Drupal\search_api\Processor\ProcessorPluginBase; use Drupal\search_api\Processor\ProcessorProperty; /** * Adds the item's Node Group to the indexed data. * * @SearchApiProcessor( * id = "sbn_add_nodegroup_str", * label = @Translation("NodeGroup String field"), * description = @Translation("Adds the item's (or item's parent's) node group field to the indexed data (as string)."), * stages = { * "add_properties" = 0, * }, * locked = true, * hidden = true, * ) */ class AddNodeGroupStr extends ProcessorPluginBase { /** * {@inheritdoc} */ public function getPropertyDefinitions(DatasourceInterface $datasource = NULL) { $properties = []; if (!$datasource) { $definition = [ 'label' => $this->t('NodeGroup String'), 'description' => $this->t('The node group for this item or its parent (string)'), 'type' => 'string', 'is_list' => TRUE, // Add this option to the definition 'processor_id' => $this->getPluginId(), ]; $properties['sbn_add_nodegroup_str'] = new ProcessorProperty($definition); } return $properties; } /** * {@inheritdoc} */ public function addFieldValues(ItemInterface $item) { $user_id = \Drupal::currentUser()->id(); $account = \Drupal::entityTypeManager()->getStorage('user')->load($user_id); $bundle = $item->getDatasource()->getItemBundle($item->getOriginalObject()); $label = $item->getDatasource()->getItemLabel($item->getOriginalObject()); $id = $item->getDatasource()->getItemId($item->getOriginalObject()); # dpm($bundle); # dpm($label); # dpm($id); $nodegroup = []; $needle = 'group_content'; $needle01 = 'node'; $haystack = $bundle; if ($bundle == 'file') { // Process file $fid = $id; $data = sbn_get_file_group($fid, $account); $group = $data['group']; $node = $data['node']; if (!empty($node)) { $nid = $node->id(); $nodegroup = sbn_get_node_group_labels($nid); // return array of group labels for $nid } } elseif (str_contains($haystack, $needle) || str_contains($haystack, $needle01)) { // Group content type $nid = sbn_get_group_content_entity_id($id); $nodegroup = sbn_get_node_group_labels($nid); // return array of grouplabels for $nid } elseif ($bundle == 'comment') { // Comment entity type $nid = sbn_get_comment_entity_id($id); $nodegroup = sbn_get_node_group_labels($nid); // return array of grouplabels for $nid } else { // Process node/paragraph entity // If this is not a file or group_content, it is a node $nodegroup = sbn_get_node_group_labels($id); // return array of group labels for this $id (which should be a node id) } if ($nodegroup) { $fields = $item->getFields(FALSE); $fields = $this->getFieldsHelper() ->filterForPropertyPath($fields, NULL, 'sbn_add_nodegroup_str'); foreach ($fields as $field) { foreach ($nodegroup as $label) { $field->addValue($label); // add this label to group list for this $item } } } } }
Should I somehow add a permissions check to this code?
- πΊπΈUnited States somebodysysop
Instead of using a search_api processor, I used hook_preprocess_facets_item_list()
It works for group facets. However, if I want to implement group facet restrictions using content from the search resultset (like node id or file id), there doesn't appear to be a way to do it. Or is there?
function sbn_preprocess_facets_item_list(&$variables) { // Only process the NodeGroup facet. if (isset($variables['facet']) && ($variables['facet']->getFieldIdentifier() === 'sbn_add_nodegroup_str' || $variables['facet']->getFieldIdentifier() === 'sbn_add_nodegroup') ) { $current_user = \Drupal::currentUser(); // For administrators or users with bypass permissions, show all facets. if ($current_user->hasPermission('administer group') || $current_user->hasPermission('bypass group access')) { return; } \Drupal::logger('sbn_debug')->info('PREPROCESS: Processing NodeGroup facet - Original count: @count', [ '@count' => count($variables['items']), ]); // Loop through facet items to extract the group label and filter based on access. $items = &$variables['items']; $count = 0; foreach ($items as $key => $item) { $count++; # Debug Tests # https://x.com/i/grok?conversation=1927938543172866301 # \Drupal::logger('sbn_debug')->info('ITEM @count: Item keys = @item_keys, Value keys = @value_keys', [ # '@count' => $count, # '@item_keys' => implode(', ', array_keys($item)), # '@value_keys' => isset($item['value']) && is_array($item['value']) ? implode(', ', array_keys($item['value'])) : 'N/A', # ]); # \Drupal::logger('sbn_debug')->info('ITEM @count: Value #attributes keys = @attr_keys', [ # '@count' => $key + 1, # '@attr_keys' => isset($item['value']['#attributes']) && is_array($item['value']['#attributes']) ? implode(', ', array_keys($item['value']['#attributes'])) : 'N/A', # ]); # \Drupal::logger('sbn_debug')->info('ITEM @count: Attributes = [data-drupal-facet-item-id: @id, data-drupal-facet-item-value: @value, data-drupal-facet-item-count: @count_value, data-drupal-facet-filter-value: @filter_value, data-drupal-facet-widget-element-class: @widget_class], #type = @type, #url = @url', [ # '@count' => $key + 1, # '@id' => isset($item['value']['#attributes']['data-drupal-facet-item-id']) ? $item['value']['#attributes']['data-drupal-facet-item-id'] : 'N/A', # '@value' => isset($item['value']['#attributes']['data-drupal-facet-item-value']) ? $item['value']['#attributes']['data-drupal-facet-item-value'] : 'N/A', # '@count_value' => isset($item['value']['#attributes']['data-drupal-facet-item-count']) ? $item['value']['#attributes']['data-drupal-facet-item-count'] : 'N/A', # '@filter_value' => isset($item['value']['#attributes']['data-drupal-facet-filter-value']) ? $item['value']['#attributes']['data-drupal-facet-filter-value'] : 'N/A', # '@widget_class' => isset($item['value']['#attributes']['data-drupal-facet-widget-element-class']) ? $item['value']['#attributes']['data-drupal-facet-widget-element-class'] : 'N/A', # '@type' => isset($item['value']['#type']) ? $item['value']['#type'] : 'N/A', # '@url' => isset($item['value']['#url']) && $item['value']['#url'] instanceof \Drupal\Core\Url ? $item['value']['#url']->toString() : 'N/A', # ]); # \Drupal::logger('sbn_debug')->info('Facet config keys: @keys', [ # '@keys' => implode(', ', array_keys($variables['facet']->toArray())), # ]); # \Drupal::logger('sbn_debug')->info('Facet source ID: @source', [ # '@source' => isset($variables['facet']) && method_exists($variables['facet'], 'get') ? $variables['facet']->get('facet_source_id') : 'N/A', # ]); // Extract the group label. $group_label = NULL; // Check if $item['value'] is a render array and look for the group label in #title. if (is_array($item['value']) && isset($item['value']['#title'])) { // If #title is a string, use it directly. if (is_string($item['value']['#title'])) { $group_label = $item['value']['#title']; } // If #title is a render array, check for #value or other common keys. elseif (is_array($item['value']['#title'])) { if (isset($item['value']['#title']['#value']) && is_string($item['value']['#title']['#value'])) { $group_label = $item['value']['#title']['#value']; } elseif (isset($item['value']['#title']['#markup']) && is_string($item['value']['#title']['#markup'])) { $group_label = $item['value']['#title']['#markup']; } // As a last resort, try rendering the #title array. else { $group_label = (string) \Drupal::service('renderer')->renderPlain($item['value']['#title']); } } } // Log the group label for debugging (for all items). if ($group_label) { \Drupal::logger('sbn_debug')->info('ITEM @count: GROUP LABEL = "@label"', [ '@count' => $count, '@label' => $group_label, ]); } else { \Drupal::logger('sbn_debug')->info('ITEM @count: GROUP LABEL not found, item[value] type = @type', [ '@count' => $count, '@type' => gettype($item['value']), ]); \Drupal::logger('sbn_debug')->info('ITEM @count: item[value] keys = @keys', [ '@count' => $count, '@keys' => implode(', ', array_keys($item['value'])), ]); // Log the structure of #title for further debugging. if (isset($item['value']['#title'])) { \Drupal::logger('sbn_debug')->info('ITEM @count: item[value][#title] type = @type, keys = @keys', [ '@count' => $count, '@type' => gettype($item['value']['#title']), '@keys' => is_array($item['value']['#title']) ? implode(', ', array_keys($item['value']['#title'])) : 'N/A', ]); \Drupal::logger('sbn_debug')->info('ITEM @count: item[value][#title] structure = @structure', [ '@count' => $count, '@structure' => print_r($item['value']['#title'], TRUE), ]); } } // Apply access control: remove the facet item if the user doesn't have access. if ($group_label && !sbn_group_label_access($group_label, $current_user)) { \Drupal::logger('sbn_debug')->info('ITEM @count: REMOVED GROUP LABEL = "@label" due to access restriction', [ '@count' => $count, '@label' => $group_label, ]); unset($items[$key]); } } // Reindex the array to avoid gaps in the keys. $variables['items'] = array_values($items); // Log the final count after filtering. \Drupal::logger('sbn_debug')->info('PREPROCESS: Processing NodeGroup facet - Final count after filtering: @count', [ '@count' => count($variables['items']), ]); } }