Jump to content

Inconsistent Search Results - Language-Specific False Positives and False Negatives


froot
 Share

Recommended Posts

Hello everyone,

I'm currently facing a perplexing issue with the search functionality on my PW website. The search results are exhibiting inconsistency, producing both false positives and false negatives, depending on the code approach and if-condition used.

Problem Description:
When performing a search for a specific term, the condition used to determine if a search result matches the query seems to act binary, leading to two distinct issues:

False Positives: At times, matches are found in languages other than the one specified, leading to incorrect results. For example, English words may appear in search results on the German site, and vice versa.

False Negatives: Conversely, in some cases, no matches are found even when they should be present, i.e. the condition I set is never met, regardless of the site's language.

Approaches Tried:

isTranslatable() Method: Initially, I attempted to check if the field was translatable and, if so, used the getLanguageValue() method to fetch content in the user's language. Unfortunately, this approach introduced the aforementioned false positives and false negatives.

getUnformatted() Method: In an effort to mitigate the inconsistency, I explored using the getUnformatted() method, which should return all language versions of the field value. However, this approach also resulted in the same issues.

protected function filterCurrentLanguage($items, $q) {
	$language = $this->wire('user')->language; // always seems to return the same ID, logged in and incognito :(
    $filteredItems = new PageArray;

    foreach ($items as $item) {
        $fields = $this->getUniqueFieldsFromTemplate($item->template);
        $foundInCurrentLanguage = false;

        foreach ($fields as $field) {
            // Here lies the condition that seems to behave inconsistently
            $fieldValue = $item->getLanguageValue($language, $field);
            if (stripos($fieldValue, $q) !== false) {
                $foundInCurrentLanguage = true;
                break;
            }
        }

        if ($foundInCurrentLanguage) {
            $filteredItems->add($item);
        }
    }

    return $filteredItems;
}

Unfortunately, I cannot utilise a selector for my language-specific queries, which may have limited the available solutions. I am open to exploring other possible approaches or features that might be added to the ProcessWire API in future versions, if any, to facilitate better language-specific search filtering.

I am seeking insights from the ProcessWire community to understand why the condition behaves in this inconsistent manner. Additionally, I would greatly appreciate any guidance or alternative approaches that can help me improve the search functionality, ensuring that it provides accurate and language-specific search results.

If anyone has faced a similar challenge or possesses expertise in handling language-specific search and filtering in ProcessWire, I humbly request your assistance and valuable input.

Thanks a lot!

Link to comment
Share on other sites

OK, after further investigation, I think the real and more technical question I should ask is, how do I access the current $page from inside the module? Do I need to pass it? like:

// on Test Page
$MyModule = $modules->get('MyModule');
$MyModule->renderPageTitle($page); // Test Page

// inside the module
class MyModule extends WireData implements Module, ConfigurableModule {
  ...
  public function renderPageTitle($page) {
	  echo $page->title;
  }
  ...
}

I am extending class WireData, don't know if that makes a difference.

Link to comment
Share on other sites

1 hour ago, fruid said:

OK, after further investigation, I think the real and more technical question I should ask is, how do I access the current $page from inside the module? Do I need to pass it? like:

This page in the docs helps, but basically inside a module you can use:

$this->page;
$this->wire('page'); // preferred in Wire-derived classes (i.e. modules)

However, for the example you gave above (renderPageTitle()), it might be easier to create a new method for the $page class with a hook.

For example:

/**
 * NOTE: the module will need to be set to be 'autoload' => true in the Module Info
 */
class MyModule extends WireData implements Module, ConfigurableModule {
	/**
	 * Run when PW is "ready" (like ready.php file) - so it's where you place you ready hooks.
	 */
	public function ready() {
		// Add a hook to define the "renderPageTitle" for the $page class.
		// Called in your templates with with $page->renderPageTitle()
		$this->addHook('Page::renderPageTitle', $this, 'renderPageTitleHook');
	}

	/**
	 * The hook code itself (could have been an enclosure on the hook if simple enough)
	 */
	public function renderPageTitleHook(HookEvent $event) {
		$page = $event->object; // the $page class *instance* calling the method
		$event->return = $page->title;
	}
}

Alternatively, this is a good case for using Custom Page Classes (look at the most recent 'site-blank' profile for an example).

  • Like 1
Link to comment
Share on other sites

I think it had to do with when the page loads. Running the above function later than in init() workes as expected, there doesn't even seem to be a need for the API calls that target the specific language value, PW does that automatically with the selector after all ^^

However, here's a very similar requirement, therefor I use the same thread to discuss it.

class MyModuleConfig extends ModuleConfig {

    public function getInputfields() {
        $inputfields = parent::getInputfields();

        $f = $this->modules->get('InputfieldText');
        $f->attr('name', 'foo');
        $f->useLanguages = true; // This enables multilingual support
        $f->columnWidth = 100;
        $inputfields->add($f);

        return $inputfields;
    }

}


class MyModule extends WireData implements Module, ConfigurableModule {

    public function bar() {
        $foo = $this->foo;
        echo $foo; // always returns the default language of the page, not even
    }

}

I'm able to create a multilanguage field in the module's settings but I am not able to return the page language specific value in the frontend.

What am I doing wrong? Thanks for your help again.

P.S. I hope you're enjoying your summer so far.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...