Jump to content

Bug: Languages with users roles, translations


Soma
 Share

Recommended Posts

A co-worker is desperate building a front-end project tool with 3 languages.

1.

Now there a problem with new users and roles etc, that are saved as pages.

They only have a name field with non language page names as normal pages. Now creating a new user, the status for each langauge isn't set to 1. Means it's not active! Now if I query a user with its name it doesn't get found from a alternative language.

When in default language (front-end)

$users->get("xyz"); // returns user correct

When in a alternative language

$users->get("xyz"); // returns nothing

2. 

Sometimes the translation in the front-end using the PW translator sometimes doesn't output the correct language even though the $user->language is "fr" the output is in some part is the german (default) text. This happens a lot on after a form submission. It makes no sense and we are lost how to find the issue. After outputting the $user->language in various parts of the code where it happens, it suddenly is "default" instead of  "fr". Any ideas what could cause it?

Link to comment
Share on other sites

To problem 2.

After testing we found that in where the language suddenly changes from "fr" to "default" is where we in API modify a user (not current) and save it. Afterwards the $user->language is set to "default" of the current user. THe culprit seems to be that after $page->save() there's a uncacheAll called which cleans out the $user->language set on runtime. 

We have now a workaround to save language before to a var, and give it back to the $user after the save. But it looks like when saving a user in front-end the $user->language set by the language system is reset.

  • Like 3
Link to comment
Share on other sites

Soma thanks for the troubleshooting here. I think we can solve both issues by having the LanguageSupportPageNames module hook into both $pages->saveReady() and $pages->saved(). It'll set an active status for all users/roles/permissions before one is saved, as well as record the current language setting. Then the $pages->saved() hook will restore that language setting. I will implement these updates later today. 

  • Like 3
Link to comment
Share on other sites

I haven't had enough bandwidth to give it enough testing to commit to dev just yet, but attached are the changes I implemented earlier this week in an attempt to fix these issues. I don't yet know if they actually fix them or not. But if you have a chance to test it out, please let me know what you find. 

LanguageSupportPageNames.module

  • Like 1
Link to comment
Share on other sites

The saving of the status[LangID] is now working with your fix for user, permissions, roles pages.

But I'm having issue to solve the problem when saving/creating a new page in front-end on a alternative language. The user language set by language page names module is lost and reset to default after saving.

I was getting strange errors when trying:

Error: Exception: Unable to save to 'field_title' for page that doesn't exist in pages table (in /Applications/XAMPP/xamppfiles/htdocs/pw2-dev/wire/core/Fieldtype.php line 506)

#0 [internal function]: Fieldtype->___savePageField(Object(Page), Object(Field))
#1 /Applications/XAMPP/xamppfiles/htdocs/pw2-dev/wire/core/Wire.php(359): call_user_func_array(Array, Array)
#2 /Applications/XAMPP/xamppfiles/htdocs/pw2-dev/wire/core/Wire.php(317): Wire->runHooks('savePageField', Array)
#3 [internal function]: Wire->__call('savePageField', Array)
#4 /Applications/XAMPP/xamppfiles/htdocs/pw2-dev/wire/core/Pages.php(718): FieldtypePageTitleLanguage->savePageField(Object(Page), Object(Field))
#5 /Applications/XAMPP/xamppfiles/htdocs/pw2-dev/wire/core/Pages.php(605): Pages->savePageFinish(Object(Page), true, Array)
#6 [internal function]: Pages->___save(Object(Page))
#7 /Applications/XAMPP/xamppfiles/htdocs/pw2-dev/wire/core/Wire.php(359): call_user_func_array(Array, Array)
#8 /Applications/XAMPP/xamppfiles/htdocs/pw2-dev/wire/cor
 

Which means the page has no id at some point in save routine. The fieldtype throws this error.

A few hours later I found by outputting "page field" infos in various methods of the pages save process I tracked it down to being an issue with repeater field. As soon as I remove repeater it works! And the language is correct again after saving.

Also it is a little strange what is happening, even after the hook saved() get's called the page isn't really saved yet, as the repeater also has pages that needs to get saved. So a hook on Pages::saved() is called multiple times. As soon after saving the repeater page(s) (FieldtypeRepeater::savePageField()) it calls the parent savePageField() again and there it somehow fails as suddenly the page id is zero! 

Looks like this:

Pages::savePageFinish(): pid:2257 -> hide_de 
Fieldtype::savePageField() : pid:2257 -> field : hide_de
Pages::savePageFinish(): pid:2257 -> state 
Fieldtype::savePageField() : pid:2257 -> field : state
Pages::savePageFinish(): pid:2257 -> myrepeater 
FieldtypeRepeater::savePageField() : 2257 -> myrepeater
Pages::savePageFinish(): pid:2258 -> title 
Fieldtype::savePageField() : pid:2258 -> field : title
Pages::savePageFinish(): pid:2258 -> process 
Fieldtype::savePageField() : pid:2258 -> field : process
Fieldtype::savePageField() : pid:2257 -> field : myrepeater
Pages::savePageFinish(): pid:0 -> title 
Fieldtype::savePageField() : pid:0 -> field : title
page : 0 (error) no page id!

  • Like 1
Link to comment
Share on other sites

Thanks for your help debugging this Soma. Did this issue seem to be introduced or worsened by the LanguageSupportPageNames.module that I posted earlier? I'm having to leave the house right now so can't look closer at the moment, but need setup an environment where I can repeat it and then fix it. 

Link to comment
Share on other sites

In my tests (although a little long session with forth and back) it was not working even without any modification to current page names module. The problem really is the repeater here. Without any repeater it works.

But I tried and came of with a much simpler solution to yours, but not sure it would be really the way. You were using a temp property set to the page before saving and reading it after which I think is strange as I would think this value would may introduce other effects? Also you used $user instead of $this->user, however I removed you code and commented. Here's the current version I have.

LanguageSupportPageNames.module

And I tested in template with something like this:

echo "user lang before: $user->language<br/>";

/* to create a page */
$p = new Page();
$p->template = "basic-page";
$p->parent = "/";
$p->of(false);

/* to edit a page */
// $p = $pages->get(2179);
// echo "page title: $p->title<br/>";

$p->of(false);
$n = rand(1,100);
foreach($languages as $lang) {
  // $id = $lang->isDefault() ? '' : $lang->id;
  // $p->set("status$id",1);
  $user->language = $lang;
  $p->set("title", "{$n}_titleofpage_lang_{$lang->id}");
}
$pages->save($p);

echo "page saved '$p->name'<br/>";
echo "user lang after: $user->language<br/>";
 
  • Like 1
Link to comment
Share on other sites

Soma, I like the direct simplicity of your solution here. The $user instead of $this->user was a typo on my part, not intended. PHP usually gives me an "undefined variable" notice to let me know about those things. But to explain the purpose of the temporary variable _language_tmp, that is so that the original setting could be restored. It's possible that $user->language is something different than $this->setLanguage, perhaps due to something changing it in the site's templates during the course of program execution. The only way to capture that is to store it in some temporary place before save and then restore it after save (which is what I was attempting to do). Though it's probably a rare thing, so if the new solution you've tested is working, then I'd rather just stick with it and approach the other issue if it ever comes up (I don't think it will). Thanks for debugging this and coming up with a nice simple and working solution. Just to confirm, this solves it? Or are there still things that aren't working still?

Link to comment
Share on other sites

Soma, I like the direct simplicity of your solution here. The $user instead of $this->user was a typo on my part, not intended. PHP usually gives me an "undefined variable" notice to let me know about those things. But to explain the purpose of the temporary variable _language_tmp, that is so that the original setting could be restored. It's possible that $user->language is something different than $this->setLanguage, perhaps due to something changing it in the site's templates during the course of program execution. The only way to capture that is to store it in some temporary place before save and then restore it after save (which is what I was attempting to do). Though it's probably a rare thing, so if the new solution you've tested is working, then I'd rather just stick with it and approach the other issue if it ever comes up (I don't think it will). Thanks for debugging this and coming up with a nice simple and working solution. Just to confirm, this solves it? Or are there still things that aren't working still?

No, this does only solve the language issue after saving when not having any repeaters on the page edited/created. Error below still exists and even without any changes to page names module.

Error: Exception: Unable to save to 'field_title' for page that doesn't exist in pages table (in /Applications/XAMPP/xamppfiles/htdocs/pw2-dev/wire/core/Fieldtype.php line 506)
 
Link to comment
Share on other sites

I'm trying to reproduce this issue–no luck yet, but not sure I understand it in full.

Does it occur editing a page in the admin, or just from the API side? If from the API side, does your API code create a new page or modify an existing page? Does your code populate the repeater? If so, does it populate it before or after the page is initially saved?

How may 'ready items' does your repeater field have?

Is there more than 1 repeater field?

Other then removing the repeater from the template, has anything else changed the behavior?

Link to comment
Share on other sites

I'm trying to reproduce this issue–no luck yet, but not sure I understand it in full.

Does it occur editing a page in the admin, or just from the API side? If from the API side, does your API code create a new page or modify an existing page? Does your code populate the repeater? If so, does it populate it before or after the page is initially saved?

How may 'ready items' does your repeater field have?

Is there more than 1 repeater field?

Other then removing the repeater from the template, has anything else changed the behavior?

Hmm.

Just from API side (see code examples I posted) when editing or creating a page with repeater. Repeater isn't populated (see my code) and the repeater has title language field. The repeater has 3 items ready.

I think I provided all informations in above posts and I don't know what else I can give without repeating. :/

No, I don't know if other factors than removing repeater change behaviour. As soon as I remove repeater it works fine, add it back and it throws error.

Link to comment
Share on other sites

Ok I tested again with another install.

When viewing page on default language (/de/about/), and in template create or edit a page (always with API):

1. creating page works fine, language is same before and after

2. editing the page and modifying the title of each language, I get the famous error

3. when removing repeater from template, it works, no error

When viewing page on alternative language (/en/about/), and in template create or edit a page

1. creating fails, error

2. editing fails, error

3. when removing repeater, it works fine

Hope this help you reproduce

  • Like 1
Link to comment
Share on other sites

Thanks for the description, this may help me to reproduce. I don't yet have a good test case setup–I want to debug it now, but still have 3 pages of messages to get through, so may not get time today. But this week I was experiencing the same error you were, though  in an entirely different situation. But it did reveal a problem where $pages->save() was catching an Exception that it shouldn't have, and this was leading to fieldtypes trying to save, presenting the familiar "Unable to save to 'field_title' for page that doesn't exist...". This is now corrected on dev, as of yesterday. I don't think it will fix the problem you are experiencing, but the result of the exception might very well reveal what the problem is. If you have a moment to try the latest dev sometime with the same situation, please let me know what you find. Otherwise, I will work to duplicate the issue here soon.

Link to comment
Share on other sites

Ryan, I'm back again withe the user language again when saving a page. I'm currently working on importing a large site in 3 languages.

Now I scripting a bootstrap to import the data and create pages. Now when doing the second language I recognized that the user language is set back to default after saving a page. I figured the LanguageSupportPageNames wouldn't even get loaded (eventhough it's autoload) and the code to set the user language after save doesn't get called. I put code in there (exit()) to see and nothing. Maybe just the after save hook doesn't get called but it's strange. So I have to again manually set the language back to the alternative after every save.

Link to comment
Share on other sites

Hello it's me again! :P

Ok, I now maybe lost already days with this... and loosing my mind slowly... :) and seen so many problems and error that I think has to do with the language support in general. It shows there definately some hard to track and explain "bugs" or miss-behaviors of the system. I thought it is all very easy but turns out it is not at all, or I am just not made for this.

As I'm said I'm trying to import many data from another system to multilanguage pages in PW in step by step each language. Newest thing was that images got added twice to fields, when there's only one and only one save happens before and after. After long time I found it has to do with language and user somehow again! I then found that by $pages->uncacheAll() after the save it works again. That's cool but I have no idea why. A test on a simple script to create a page and add an image works fine, just not in the script I build which is quite complex already. I have to manually set the user language after each save and somehow it screws up a lot due to not understanding what's happening. Depending on if you're on default or alternative language the behaviour is different as we already found out.

Now I was removing the workaround of setting user language after saving because I'm already working on default language, and suddenly I get this:

Fatal error: Uncaught exception 'PDOException' with message 'SQLSTATE[42S22]: Column not found: 1054 Unknown column 'field_title.data1011' in 'where clause'' in /Applications/XAMPP/xamppfiles/htdocs/blank.ch/wire/core/DatabaseQuery.php:86 Stack trace: #0 /Applications/XAMPP/xamppfiles/htdocs/blank.ch/wire/core/DatabaseQuery.php(86): PDOStatement->execute() #1 /Applications/XAMPP/xamppfiles/htdocs/blank.ch/wire/core/PageFinder.php(146): DatabaseQuery->execute() #2 /Applications/XAMPP/xamppfiles/htdocs/blank.ch/wire/core/Pages.php(143): PageFinder->find(Object(Selectors), Array) #3 [internal function]: Pages->___find('has_parent=4349...', Array) #4 /Applications/XAMPP/xamppfiles/htdocs/blank.ch/wire/core/Wire.php(359): call_user_func_array(Array, Array) #5 /Applications/XAMPP/xamppfiles/htdocs/blank.ch/wire/core/Wire.php(317): Wire->runHooks('find', Array) #6 [internal function]: Wire->__call('find', Array) #7 /Applications/XAMPP/xamppfiles/htdocs/blank.ch/wire/core/Page.php(862): Pages->find('has_parent=4349...', Array) #8 in /Applications/XAMPP/xamppfiles/htdocs/blank.ch/wire/core/DatabaseQuery.php on line 86

Seriously PW seems to now look to a title language field of the default data

field_title.data1011 : the default language is 1011 and the title in the default language is field_title.data and not field_title.data1011.

Just as a pointer to others maybe trying to create a multilanguage site imported and created via a script/bootstrap, DON'T as you will regret it as long as those bugs are still in there.

Ok ... breath slowly Soma ... :D

Link to comment
Share on other sites

Soma any chance I can get a copy of the site (or maybe online/FTP/SSH access to it) so that I can try and debug it? I'm jut not sure I have a good enough of a test case here. I have a multi-language site that imports from a giant XML feed every day, including numerous repeater fields. But have not run into these issues. Though in my case, I set language values using $page->field->setLanguageValue() rather than switching the user to different languages, so that may be the difference. But it definitely sounds like there is a bug in there somewhere if you are seeing data1011 and 1011 is the ID of the default language. I think I could track that one down pretty easily once I can reproduce it. The fastest way to that may be to just get access to your site. 

Link to comment
Share on other sites

I don't have a public install, so I just setup a test intall on my ISP. As it's nothing special to a install or project, it's a general things happening on all installs.

But meanwhile I get another error.... so even more confusing...

So this is still about the repeater thing and editing/saving pages on front-end on a alternative language.

I sent you a PM Ryan.

(The issue mentioned last, with "field_title.data1011" for default lang, is a completely different case, and no repeater involved there)

Link to comment
Share on other sites

  • 1 month later...

I have the same error on a site without Languages support enabled. 

Unable to save to 'field_title' for page that doesn't exist in pages table
/projects/app/wire/core/Fieldtype.php == Line: 503

I have a link that sends ajax request to create a page. When I click 2-3 times fast on this link and several ajax requests are fired to the backend I see the error above. The code for creating the page follows:

$title = 'item-' . time() . wire('user')->id;
$newPage = new Page();
$newPage->template = 'mytemplate';
$newPage->parent = $parentPage;
$newPage->name = $title;
$newPage->title = $title;
$newPage->save();

Still investigating.. 

Link to comment
Share on other sites

time() is not unique enough. By clicking the link fast, you are managing to get some pages with the same exact timestamped title. Since you are setting the 'name' to this as well, it's failing to create the page and resulting in the error you are getting. You can solve this by either using something more specific like microtime() or by just not setting the name and letting ProcessWire come up with it for you. 

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...