If I use Entity argument validator with custom entity without bundles I got the following warning:

Warning: count(): Parameter must be an array or an object that implements Countable in Drupal\views\Plugin\views\argument_validator\Entity->validateEntity() (line 203 of core/modules/views/src/Plugin/views/argument_validator/Entity.php).

Drupal\views\Plugin\views\argument_validator\Entity->validateEntity(Object) (Line: 180)
Drupal\views\Plugin\views\argument_validator\Entity->validateArgument('22522') (Line: 999)
Drupal\views\Plugin\views\argument\ArgumentPluginBase->validateArgument('22522') (Line: 1034)
Drupal\views\Plugin\views\argument\ArgumentPluginBase->setArgument('22522') (Line: 1100)
Drupal\views\ViewExecutable->_buildArguments() (Line: 1264)
Drupal\views\ViewExecutable->build() (Line: 390)
Drupal\views\Plugin\views\display\PathPluginBase->execute() (Line: 180)
Drupal\views\Plugin\views\display\Page->execute() (Line: 1627)
Drupal\views\ViewExecutable->executeDisplay('page_users', Array) (Line: 77)
Drupal\views\Element\View::preRenderViewElement(Array)
call_user_func(Array, Array) (Line: 378)
Drupal\Core\Render\Renderer->doRender(Array, ) (Line: 195)
Drupal\Core\Render\Renderer->render(Array, ) (Line: 226)
Drupal\Core\Render\MainContent\HtmlRenderer->Drupal\Core\Render\MainContent\{closure}() (Line: 582)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 227)
Drupal\Core\Render\MainContent\HtmlRenderer->prepare(Array, Object, Object) (Line: 117)
Drupal\Core\Render\MainContent\HtmlRenderer->renderResponse(Array, Object, Object) (Line: 90)
Drupal\Core\EventSubscriber\MainContentViewSubscriber->onViewRenderArray(Object, 'kernel.view', Object)
call_user_func(Array, Object, 'kernel.view', Object) (Line: 111)
Drupal\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch('kernel.view', Object) (Line: 156)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 68)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 57)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 47)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 99)
Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1) (Line: 78)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 47)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 50)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 664)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

BlacKICEUA created an issue. See original summary.

BlacKICEUA’s picture

Proposed solution.

cilefen’s picture

dawehner’s picture

I'm curious how it was possible that this value is empty in the first place? It feels like just adding some checks here might hide an underlying bug.

Once we do understand the underlying bug, maybe this patch is exactly though the right solution.

BlacKICEUA’s picture

As I think, this piece of code produce this behavior (Drupal\views\Plugin\views\argument_validator\Entity):

    // If the entity has bundles, allow option to restrict to bundle(s).
    if ($entity_type->hasKey('bundle')) {
      $bundle_options = [];
      foreach ($this->entityManager->getBundleInfo($entity_type_id) as $bundle_id => $bundle_info) {
        $bundle_options[$bundle_id] = $bundle_info['label'];
      }

      $form['bundles'] = [
        '#title' => $entity_type->getBundleLabel() ?: $this->t('Bundles'),
        '#default_value' => $this->options['bundles'],
        '#type' => 'checkboxes',
        '#options' => $bundle_options,
        '#description' => $this->t('If none are selected, all are allowed.'),
      ];
    }

So we haven't element and that's why we haven't any values in the 'submitOptionsForm' for 'bundles' form element.

dawehner’s picture

Issue tags: +Needs tests

I fear some level of tests are needed here to resolve the issue.

bkosborne’s picture

I ran into this when testing an upgrade to PHP 7.2 as well. This is indeed a minor bug in the views argument validator for entities. This validator works by allowing you to validate that an argument provided is an entity of a specific type. Additionally, if the entity type you're validating has bundles, it allows you to validate that the passed in argument matches one of the bundles.

The problem occurs when you add the validator for an entity type that doesn't have bundles. In that case, the "bundles" form option is not used, and when the form is submitted, it has no value. But the submit handler still tries to set a value:

  /**
   * {@inheritdoc}
   */
  public function submitOptionsForm(&$form, FormStateInterface $form_state, &$options = []) {
    // Filter out unused options so we don't store giant unnecessary arrays.
    $options['bundles'] = array_filter($options['bundles']);
  }

In this case, $options['bundles'] is NULL (key does not exist), so array_filter also returns NULL, so it saves NULL for the option.

We can fix that submit callback so that it doesn't save a NULL value and instead saves an empty array. That will fix it for people that re-save the argument config form or create a new argument, but doesn't help existing argument plugin configs. For that we could write a database update hook, but that's seriously overkill IMO. We can just handle the NULL case gracefully.

The previous patch works, but we can combine is_array() and count() > 0 into just a simple !empty().

bkosborne’s picture

bkosborne’s picture

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.6 was released on August 1, 2018 and is the final bugfix release for the Drupal 8.5.x series. Drupal 8.5.x will not receive any further development aside from security fixes. Sites should prepare to update to 8.6.0 on September 5, 2018. (Drupal 8.6.0-rc1 is available for testing.)

Bug reports should be targeted against the 8.6.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.7.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

joelpittet’s picture

Status: Needs review » Needs work
  1. +++ b/core/modules/views/src/Plugin/views/argument_validator/Entity.php
    @@ -148,7 +148,15 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) {
    +    // entity type doens't support bundles, so the option may not be set.
    

    doesn't is spelled as doens't

  2. +++ b/core/modules/views/src/Plugin/views/argument_validator/Entity.php
    @@ -148,7 +148,15 @@ public function buildOptionsForm(&$form, FormStateInterface $form_state) {
    +    if (array_key_exists('bundles', $options)) {
    

    array_key_exists() can have a null value.

    $ php -r '$a["test"] = NULL; var_dump(array_key_exists("test", $a));'
    bool(true)

    Consider !empty($options['bundles']) because it's faster than array_key_exists(), but maybe cleaner just to cast it to an (array)?

bkosborne’s picture

oriol_e9g’s picture

Status: Needs review » Reviewed & tested by the community

All feedback addressed.

alexpott’s picture

Status: Reviewed & tested by the community » Needs work

We must be missing test coverage as we run nightly tests on PHP 7.2 (and 7.3 now). Given this is now causing warnings we need to add that test coverage here. As per @dawehner / #6.

FeyP’s picture

Attached is a patch against 8.8.x, which extends the existing unit test for the argument validator to cover this issue. No interdiff, since it's trivial.

Status: Needs review » Needs work
FeyP’s picture

Status: Needs work » Needs review

Test results as expected on PHP7.2. The test fail in PHP 7.1 looks suspiciously like another random unrelated test fail in ManageGitIgnoreTest, so let's try again.

FeyP’s picture

bkosborne’s picture

Version: 8.6.x-dev » 8.8.x-dev
Status: Needs review » Reviewed & tested by the community

Looks good

Status: Reviewed & tested by the community » Needs work
FeyP’s picture

Status: Needs work » Reviewed & tested by the community

The test fail was most likely caused by #3085697-31: Allow scaffold plugin to append to non-scaffolded files. Retest came back green. Setting back to RTBC per #19.

Version: 8.8.x-dev » 8.9.x-dev

Drupal 8.8.0-alpha1 will be released the week of October 14th, 2019, which means new developments and disruptive changes should now be targeted against the 8.9.x-dev branch. (Any changes to 8.9.x will also be committed to 9.0.x in preparation for Drupal 9’s release, but some changes like significant feature additions will be deferred to 9.1.x.). For more information see the Drupal 8 and 9 minor version schedule and the Allowed changes during the Drupal 8 and 9 release cycles.

siva01’s picture

Patch for Drupal 8.8 with PHP 7.3 doesn't work.

Status: Reviewed & tested by the community » Needs work
Spokje’s picture

Status: Needs work » Reviewed & tested by the community

Random test fail, retest was green, back to RTBC per #19

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

Committed and pushed 73b8d10170 to 9.0.x and 9ade85c270 to 8.9.x and 74a79f60aa to 8.8.x. Thanks!

Backported to 8.8.x as a low risk bugfix.

  • alexpott committed 73b8d10 on 9.0.x
    Issue #2969262 by bkosborne, FeyP, BlacKICEUA, dawehner, joelpittet: PHP...

  • alexpott committed 9ade85c on 8.9.x
    Issue #2969262 by bkosborne, FeyP, BlacKICEUA, dawehner, joelpittet: PHP...

  • alexpott committed 74a79f6 on 8.8.x
    Issue #2969262 by bkosborne, FeyP, BlacKICEUA, dawehner, joelpittet: PHP...

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

quietone’s picture