- π³πΏNew Zealand quietone
There have been no further reports of this. Perhaps this is outdated?
For Commerce, I provided an override to the `getRelated` route for `commerce_product--{type}.variations.related`. This allows us to follow internal API logic for filtering valid variations. I have added here: https://github.com/mglaman/commerce_demo_jsonapi/blob/master/src/Control....
This does not filter values from the actual variations
reference field, that's a "to figure out." Ideally, I could filter out what is returned by referencedEntities
on the field level. But, due to earlier limitations in Drupal core variations
is not a base field (yet) and you can't provide a custom field list class per field definition -- only field type.
For instance, a product could have twenty variations. The store has logic which filters out some variations based on the user's country, selected store, or preferred currency. This is why we have the ProductEvents::FILTER_VARIATIONS
event, which is fired from the variation storage loadEnabled
method. This is the method used to determine valid variations for the add to cart form.
I don't see any way to filter out access for the entities returned on a relationship route unless all logic lived in `view` which still returned `Access denied` entries in the list (bad DX in my opinion.) I would rather see the unavailable product variations removed rather than the response contain "sorry, this isn't accessible."
----
Here is the normal code for getRelated:
// Remove the entities pointing to a resource that may be disabled. Even
// though the normalizer skips disabled references, we can avoid unnecessary
// work by checking here too.
/* @var \Drupal\Core\Entity\EntityInterface[] $referenced_entities */
$referenced_entities = array_filter(
$field_list->referencedEntities(),
function (EntityInterface $entity) {
return (bool) $this->resourceTypeRepository->get(
$entity->getEntityTypeId(),
$entity->bundle()
);
}
);
$collection_data = [];
foreach ($referenced_entities as $referenced_entity) {
$collection_data[] = $this->entityAccessChecker->getAccessCheckedResourceObject($referenced_entity);
}
In my override,
$referenced_entities = array_filter($field_list->referencedEntities(),
function (ProductVariationInterface $entity) {
return (bool) $this->resourceTypeRepository->get($entity->getEntityTypeId(), $entity->bundle());
}
);
# START COMMERCE LOGIC from variation storage.
// Remove entities which cannot be viewed.
$referenced_entities = array_filter($referenced_entities,
function (ProductVariationInterface $variation) {
return $variation->access('view');
});
// Allow modules to apply own filtering (based on date, stock, etc).
$event = new FilterVariationsEvent($entity, $referenced_entities);
$this->eventDispatcher->dispatch(ProductEvents::FILTER_VARIATIONS, $event);
$referenced_entities = $event->getVariations();
# END COMMERCE LOGIC
$collection_data = array_map([$this->entityAccessChecker, 'getAccessCheckedResourceObject'], $referenced_entities);
---
I am not sure of any way to easily alter the variations returned from this route. Or the field in general. Ideally, this would only run during JSON:API calls, so we can preserve any BC for working in normal PHP code.
---
Adding examples of the loadEnabled
usage.
Cart Flyout: fetching variations to serialize and embed as JSON on the page
http://cgit.drupalcode.org/commerce_cart_flyout/tree/src/Plugin/Field/Fi...
protected function loadVariations(ProductInterface $product) {
return array_reduce(
$this->variationStorage->loadEnabled($product),
function ($carry, ProductVariationInterface $variation) {
$carry[$variation->uuid()] = $variation;
return $carry;
}, []);
}
Add to cart: attributes widget
http://cgit.drupalcode.org/commerce/tree/modules/product/src/Plugin/Fiel...
protected function loadEnabledVariations(ProductInterface $product) {
$langcode = $product->language()->getId();
$variations = $this->variationStorage->loadEnabled($product);
foreach ($variations as $key => $variation) {
$variations[$key] = $this->entityRepository->getTranslationFromContext($variation, $langcode);
}
return $variations;
}
Best example is the TitleWidget, which takes the variations and renders a select list.
http://cgit.drupalcode.org/commerce/tree/modules/product/src/Plugin/Fiel...
$variations = $this->loadEnabledVariations($product);
if (count($variations) === 0) {
// Nothing to purchase, tell the parent form to hide itself.
$form_state->set('hide_form', TRUE);
$element['variation'] = [
'#type' => 'value',
'#value' => 0,
];
return $element;
}
elseif (count($variations) === 1) {
/** @var \Drupal\commerce_product\Entity\ProductVariationInterface $selected_variation */
$selected_variation = reset($variations);
$element['variation'] = [
'#type' => 'value',
'#value' => $selected_variation->id(),
];
return $element;
}
....
$variation_options = [];
foreach ($variations as $option) {
$variation_options[$option->id()] = $option->label();
}
$element['variation'] = [
'#type' => 'select',
// Widget settings can't be translated in D8 yet, t() is a workaround.
'#title' => $this->t($this->getSetting('label_text')),
'#options' => $variation_options,
'#required' => TRUE,
'#default_value' => $selected_variation->id(),
'#ajax' => [
'callback' => [get_class($this), 'ajaxRefresh'],
'wrapper' => $form['#wrapper_id'],
],
];
Active
11.0 π₯
jsonapi.module
Not all content is available!
It's likely this issue predates Contrib.social: some issue and comment data are missing.
There have been no further reports of this. Perhaps this is outdated?