processwire-issues icon indicating copy to clipboard operation
processwire-issues copied to clipboard

findRaw() paths do not account for user language

Open Toutouwai opened this issue 1 year ago • 3 comments

Short description of the issue

When getting page paths via $page->findRaw(), only the path for the default language is returned, regardless of the $user language.

2024-09-03_103702

Paths for each language are in the pages_paths table but I don't see a way to tell findRaw() which language path is wanted. Is there support for multi-language paths in findRaw()? Is there a way to have findRaw() return all the language paths that exist for pages in the results?

Setup/Environment

  • ProcessWire version: 3.0.241

Toutouwai avatar Sep 02 '24 22:09 Toutouwai

@Toutouwai It doesn't look like PagesRaw supports multi-language path properties at present. I'm not sure to what extent it can, as those are supplied to Page objects via hooks. And there are no Page objects when using findRaw(). I suppose it could use pages_paths for some cases, but those aren't guaranteed to be present, so would not be a complete solution.

ryancramerdesign avatar Sep 06 '24 19:09 ryancramerdesign

I suppose it could use pages_paths for some cases, but those aren't guaranteed to be present, so would not be a complete solution.

@ryancramerdesign, not sure what you mean about not guaranteed to be present as the PagePaths module has to be installed for path to work.

Could there perhaps be new options for the plurals paths and urls, which would return all the values in pages_paths with a matching value in pages_id, in a similar way to how FieldtypeMulti values are returned now in findRaw()?

For a temporary solution I'm doing this:

// Get some data from findRaw()
$data = $pages->findRaw("template=basic-page", ['title']);

// Find paths that match the IDs
$ids = array_keys($data);
$sql = "SELECT pages_id, language_id, path FROM `pages_paths` WHERE pages_id IN(" . implode(',', $ids) . ")";
$query = $database->query($sql);
$paths_data = $query->fetchAll(\PDO::FETCH_GROUP|\PDO::FETCH_ASSOC);

// Merge in the paths indexed by language ID
foreach($data as $id => $item) {
    foreach($paths_data[$id] as $path) {
        $data[$id]['paths'][$path['language_id']] = '/' . $path['path'] . '/';
    }
}

Toutouwai avatar Sep 07 '24 07:09 Toutouwai

@ryancramerdesign, as a test I added the code below at line 1676 of PageFinder.php

$paths_join = 'pages_paths ON pages_paths.pages_id=pages.id';
$user = $this->wire()->user;
if($user->language && !$user->language->isDefault()) {
    $paths_join .= " AND pages_paths.language_id=" . $user->language->id;
}
$query->leftjoin($paths_join);

And now it returns paths for the user's language.

2024-09-07_195146

Could an option for something like this be added too? Perhaps rather than based off the user language there would be an option to pass in a language and findRaw() would adapt all its results automatically so field values for non-default languages can be retrieved without having to specify .data$lang_id https://github.com/processwire/processwire-issues/issues/1609#issuecomment-1206689482

Toutouwai avatar Sep 07 '24 07:09 Toutouwai