Currently, the QueryInterface::getFields() method documentation states that the return value will always be an array of strings (field IDs). However, if the method is called before preExecute() is run on the query (for whatever reason), the return value is actually NULL, thus violating the method contract.

There would be two fixes possible for this, as far as I can see:

  1. Just allow the method to also return NULL and leave backends to call $index->getFulltextFields() themselves if they still need the fields.
  2. Move the fallback code for unspecified fields from preExecute() to getFields() to make sure we always return an array.

I'm leaning towards the former option, but I'd be open to both. (The latter would have the advantage, e.g., that backends wouldn't have to adapt to the change.)

In any case, while implementing this we could also fix the following for fields():

  // @todo Allow calling with NULL, and maybe rename to setFulltextFields().
  public function fields(array $fields);

Comments

drunken monkey created an issue. See original summary.

sdstyles’s picture

Status: Active » Needs review
StatusFileSize
new4.83 KB

Added fallback code for getField() method, also changed field() method.

Status: Needs review » Needs work

The last submitted patch, 2: 2559255-2.patch, failed testing.

sdstyles’s picture

Status: Needs work » Needs review

sdstyles queued 2: 2559255-2.patch for re-testing.

drunken monkey’s picture

Status: Needs review » Needs work

Thanks a lot for creating the patch, it's definitely a good start!

However, there's some problems with it currently:

  1. +++ b/src/Entity/Index.php
    @@ -582,6 +582,11 @@ class Index extends ConfigEntityBase implements IndexInterface {
    +    // Add fulltext fields, unless set.
    +    if ($this->fields === NULL) {
    +      $this->fields = $this->index->getFulltextFields();
    +    }
    

    Any particular reason you chose the second way of fixing this?
    As said, I think I'd have preferred the former one (allowing a NULL return value).

    Oh, also this is in the completely wrong method. It should, if at all, be in the query class's getFulltextFields() method, not in the index class. (And should then be removed from the query class's preExecute() method.)

  2. +++ b/src/Plugin/views/query/SearchApiQuery.php
    @@ -566,12 +566,11 @@ class SearchApiQuery extends QueryPluginBase {
    -  // @todo Allow calling with NULL, and maybe rename to setFulltextFields().
    -  public function fields(array $fields) {
    +  public function setFulltextFields($fields = array()) {
    

    array $fields = NULL is the argument list I had in mind. (Also in the two other method definitions.)

sdstyles’s picture

Status: Needs work » Needs review
StatusFileSize
new4.59 KB
new2.19 KB

Hi, I've used first proposed fix.

drunken monkey’s picture

Status: Needs review » Needs work

Great work, thanks! Looks pretty good now already. Some more nit-picking, though:

  1. +++ b/src/Plugin/views/query/SearchApiQuery.php
    @@ -566,12 +566,11 @@ class SearchApiQuery extends QueryPluginBase {
    -  public function fields(array $fields) {
    +  public function setFulltextFields($fields = NULL) {
    

    This can still use the array type hint if the default value is NULL – a perhaps little-known but very handy feature of PHP (same for class/interface type hints).

  2. +++ b/src/Query/QueryInterface.php
    @@ -231,9 +230,9 @@ interface QueryInterface {
    -   * @return string[]
    +   * @return NULL|string[]
        *   An array containing the fields that should be searched for the search
    -   *   keys.
    +   *   keys or null.
    

    Exactly the other way round – "null" next to the @return tag but then "NULL" in the description.

    Also, the description should say in which situation NULL is returned. And I'd list the return types as string[]|null, since that's the "main" type. (I usually put "null" last in such lists – but of course purely a matter of taste.)

Also, now that NULL is an allowed return value for getFulltextFields(), we don't have to explicitly set them to anything in Query::preProcess() – so, please remove that code, too.

Otherwise, this is fine, I can probably commit it once these are fixed.
Thanks again!

sdstyles’s picture

Status: Needs work » Needs review
StatusFileSize
new5.02 KB
new1.67 KB

Changed.

Status: Needs review » Needs work

The last submitted patch, 9: 2559255-9.patch, failed testing.

sdstyles’s picture

Status: Needs work » Needs review
StatusFileSize
new4.66 KB
new428 bytes

Reverted.

drunken monkey’s picture

Yes, when we change the contract for getFields(), we of course also need to change the backend plugin accordingly.
(Interdiff based on #9.)

Status: Needs review » Needs work

The last submitted patch, 12: 2559255-12--null_fulltext_fields.patch, failed testing.

drunken monkey’s picture

Status: Needs work » Needs review
StatusFileSize
new10.39 KB
new601 bytes
drunken monkey’s picture

Status: Needs review » Fixed

Committed.
Thanks again for your great work on this!

Status: Fixed » Closed (fixed)

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