Jump to content

Connect Page Fields


Robin S

Recommended Posts

  • 1 year later...

to set all the "backlinks" programmatically, i.e. set all the referenced pages to point back, shouldn't something like this work too?

$projects = $pages("template=project");

foreach ($projects as $project) {
    // related_pages being the name of the page reference field
    // I store the value of the page reference field temporarily in a variable 
    $temp = $project->related_pages;
    $idle = new WireArray;
    
    // populate the page reference field with an empty WireArray object and save it
    $project->of(false);
    $project->related_pages = $idle;
    $project->save('related_pages');
    $project->of(true);

    // populate the page reference field with the value we stored in $idle
    $project->of(false);
    $project->related_pages = $temp;
    $project->save('related_pages');
    $project->of(true);

}

Because as I understand it, the value needs to change and the page needs to be saved for the module to do what it does.

Doesn't work though…

Link to comment
Share on other sites

19 hours ago, fruid said:

Because as I understand it, the value needs to change and the page needs to be saved for the module to do what it does.

Correct.

19 hours ago, fruid said:

Doesn't work though…

Don't know, similar code works for me here. Trying to set a plain WireArray to a Page Reference field looks wrong to me. The acceptable value to set to a Page Reference field is a Page or PageArray.

There is some example code in the post below that can help deal with Page Reference field values from before the module was installed:

 

 

  • Like 1
Link to comment
Share on other sites

Hello,
Is it possible that this doesn't work with a Repeater?

I have a template "album" with a Repeater for the tracks of an album. In this Repeater there is a field with type "Page" (lyric_sel / Single page Page or boolean false / Template: lyric).
And I also have a Template "lyric" with a field with the type "Page" field with type "Page" (album_sel / Multiple pages PageArray / Template: album).

I selected them in the settings of this module. See Screenshots

Now I can select a lyric in the repeater from the template "album" thats works fine. But it will not update the album_sel field in the "lyric" page.

I hope you can help me with that. Greetings

Test Album - Repeater.png

Edit Page Test Song.png

Module Connect Page Fields.png

album_sel.png

lyric_sel.png

Link to comment
Share on other sites

@ShadowByte first let me say welcome to the PW forums 🙂

13 hours ago, ShadowByte said:

Is it possible that this doesn't work with a Repeater?

The module does work with repeaters, but perhaps not in the way you are expecting. If you are relatively new to PW you may not be aware that every repeater item is a page, and those repeater pages have their own template. Repeater template names take the form "repeater_[field name]" and to see them in the templates list you have to enable "Show system templates" in the Filters section.

image.png.1d047678c6fc55a899360a48d17d5ffe.png

The Connect Page Fields readme says:

Quote

Make sure you have set the "Selectable Pages" settings for each Page field correctly:

  • The settings for Page field A should allow pages using the template(s) that Page field B has been added to.
  • The settings for Page field B should allow pages using the template(s) that Page field A has been added to.

The way you have configured the module you have connected the fields "Track lyric" and "Albums". But the Albums field allows pages using the album template, and the album template doesn't contain the lyric field. Instead the lyric field is used on the repeater template (if the repeater field is named "tracks" then the template will be "repeater_tracks").

So for Connect Page Fields to work you would need to have a Page Reference field that defines its selectable pages as those using the repeater_tracks template and then connect that field to the lyric field in the Connect Page Fields config.

As a side note, it's redundant to double up the connections like this in the module config:

13 hours ago, ShadowByte said:

Module Connect Page Fields.png

The connections are two-way so you only need to link a Page Reference field to its partner once.

Assuming you actually want to connect albums to lyrics and not repeater_tracks items to lyrics, and you want to still use Connect Page Fields to avoid writing your own API code to synchonise the Page Reference fields, here's how I would do it...

1. Create a new Page Reference field (multiple pages) named "track_lyrics" that allows pages with the lyric template.

2. Add this field to the album template. Later on you might set its visibility to "Hidden (not shown in editor)" but for now leave it visible so you can check that everything works as expected.

3. In the Connect Page Fields config, connect the albums field to the track_lyrics field. 

4. Add a Pages::saveReady() hook to /site/ready.php that will populate the track_lyrics field with all the lyrics that have been selected inside the repeater items on the page, every time an album page is saved. It might look something like this (update the template/field names if needed):

$pages->addHookAfter('saveReady', function(HookEvent $event) {
	/** @var Page $page */
	$page = $event->arguments(0);

	// Album: populate the track_lyrics field from the "tracks" repeater items
	if($page->template == 'album') {
		$lyrics = new PageArray();
		foreach($page->tracks as $track) {
			$lyrics->add($track->lyric);
		}
		$page->track_lyrics = $lyrics;
	}
});

Hope this helps!

  • Like 3
Link to comment
Share on other sites

  • 8 months later...

Hi @Robin S, I just had the following error message:

869452606_Screenshot2024-04-05224737.thumb.png.3b0312d47b32ff97cf817a04feebfd8f.png

I'm not sure exactly what caused it, but changing line 144 to

if(!$item->fields || !$item->fields->get($other_fname)) continue;

seemed to do the trick

  • Like 1
Link to comment
Share on other sites

Thanks @Robin S. I also got this error (after the fix), which might be related:

325420606_Screenshot2024-04-06113914.thumb.png.f907979ea9eaebd9e75d07db56858756.png

As you can see, it seems to be caused by a null item being included in an implode. I'm seeing if I can fix that too.

Update:

Added this after line 125, which seems to fix it:

			// Remove any null pages and continue if the new value is empty
			if(!$new_value) continue;
			if($new_value instanceof PageArray) {
				foreach ($new_value as $valueItem) {
					if ($valueItem instanceof NullPage) {
						$new_value->remove($valueItem);
					}
				}
				if($new_value->count() == 0) continue;
				if($new_value->count() == 1) {
					$new_value = $new_value->first();
					$this_is_multi = false;
				}
			} else {
				if($new_value instanceof NullPage) continue;
			}

I'm not sure how the null pages were getting in there - probably something specific to my set-up - but hopefully the above code doesn't have any side-effects.

Edited by MarkE
Possible solution
Link to comment
Share on other sites

10 hours ago, MarkE said:

Added this after line 125, which seems to fix it:

Hmmm, I'm not keen to add that. A NullPage has an ID of 0, and it shouldn't be possible to have a Page object that lacks an ID. Therefore when a PageArray is cast to a string it should never be possible to get something that looks like "|20896|20897" where there is clearly a missing ID for the first item.

If your code is somehow producing a Page object that lacks an ID then I think that's a core issue that should be reported, because in general it ought to be safe to use a PageArray in a selector without needing to check for missing IDs. But for Ryan to fix I expect you'll need to create a reproducible test case.

Link to comment
Share on other sites

1 hour ago, Robin S said:

If your code is somehow producing a Page object that lacks an ID then I think that's a core issue

I'll investigate. I suspect it may be connected with an export method that never seemed to have been completely finished although part of the core.

Link to comment
Share on other sites

Hi @Robin S. I'm still investigating this. However, in the course of my investigations, I discovered another problem I was having with the ConnectPageFields::updateConnectedFields($page, $field) method. What I understand happens is that the entire array of connected fields which pair with the field on the page is run through and an update occurs if the page passes the 'isValidPage' test for the other field.

Unfortunately, 'isValidPage' also sets an _isValidPage attribute (error message) which then seems to 'stick' on the page. In my particular usage, this seemed to prevent the valid 'other field' (which occurred later in the connected fields array) from updating.

I'm probably being a bit thick (it is a bit late here) but I don't see why fields are attempted to be updated when they don't exist on the page. I added 

if(!$page->hasField($other_fname)) continue;

after line 

$other_fname = $other_field->name;

and everything seemed to update fine.

I can provide more background to the situation if required.

EDIT: Actually that last bit is not the right solution, but I need to sleep on it!

Edited by MarkE
Link to comment
Share on other sites

@MarkE, not sure I understand the issue but I've removed the InputfieldPage::isValidPage() check in v0.3.7 because it seems unnecessary seeing as FieldtypePage will itself do this validation before it saves a value.

  • Like 1
Link to comment
Share on other sites

On 4/11/2024 at 2:37 AM, Robin S said:

I've removed the InputfieldPage::isValidPage() check in v0.3.7 because it seems unnecessary

Thanks @Robin S - I think that's an improvement (although I'm not sure if it may be slightly less efficient). However, it doesn't really solve my problem: I realise after sleeping on it that my code is actually setting both sides of the pair anyway and so may be conflicting with ConnectPageFields. I changed my code to save the page with 'noHooks' => true and it all works fine. It also fixes the earlier problem, so I'll update your issue for that as it was proving difficult to tie down the source of the null page. 'noHooks' may have side effects, however, and I'm wondering if I can just temporarily turn off ConnectPageFields.

EDIT: not updated issue as the issue description perfectly explains the problem outside my context

Edited by MarkE
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
  • Recently Browsing   0 members

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