Jump to content

[solved] page reference field - unpublished pages not visible by non-superuser roles/users


formulate
 Share

Recommended Posts

I have a page reference field with the "include unpublished" checked. Non-superuser accounts still can't see unpublished pages. I went through the permissions for the role and couldn't see anything related. Do I need to create some kind of custom permission to get this working?

Link to comment
Share on other sites

Is this an autocomplete inputfield? I just ran into the same problem (a page field not finding unpublished pages for non-superusers, even though Include unpublished is checked).

I managed to isolate the issue to ProcessWire's internal admin search that is used behind the scenes of autocomplete fields. Not sure if anything from the last major search update in 3.0.108 might play a role here.

 

This is what's worked for me:

Copy the core search module folder from /wire/modules/Process/ProcessPageSearch to /site/modules/Process/ProcessPageSearch/

After lines 422–425 in ProcessPageSearch.module…

if(!$status && !$hasInclude && $superuser) {
    // superuser only
    $selectors[] = "include=all, status<" . Page::statusTrash;
}

…insert this:

// FIX: include unpublished pages for non-superusers
else if(!$status && !$hasInclude && !$superuser) {
    $selectors[] = "include=all, status<" . Page::statusTrash;
}

Back in the admin, refresh the module cache (Navigation » Modules » Refresh). ProcessWire will then ask you which version to use for the search module. Pick the one you modified in the /site/ folder.

This will basically make it work the same for superusers and non-superusers.

I can't report any negative side effects at this point, but in my case it beats promoting all content editors to superusers.

  • Like 2
Link to comment
Share on other sites

2 minutes ago, adrian said:

Sorry guys, in a rush but perhaps including "check_access=0" in the selector for the page field will do the trick here. I might be totally off track and it might be a bug, but worth a shot.

From my cursory reading of the source, check_access also seems limited to superusers:

// don't allow setting of check_access property, except for superuser
if($lowerName == 'check_access' && !$superuser) continue; 

 

Link to comment
Share on other sites

2 minutes ago, formulate said:

I am having a separate issue at the moment where my custom selector isn't working (either in the Input or ready.php). Once I get that hashed out I'll try the two above solutions and report back.

I'm pretty sure that anything beyond basic template selection will not work in autocomplete inputs. I found this comment in the InputfieldPage source regarding custom PHP selectors: Not compatible with PageListSelect or Autocomplete input field types.

Also, the field for adding custom code is disabled for autocomplete and page list selects:

$field->showIf = 'inputfield!=InputfieldPageAutocomplete|InputfieldPageListSelect|InputfieldPageListSelectMultiple';

 

Link to comment
Share on other sites

 

15 minutes ago, d'Hinnisdaël said:

I'm pretty sure that anything beyond basic template selection will not work in autocomplete inputs. I found this comment in the InputfieldPage source regarding custom PHP selectors: Not compatible with PageListSelect or Autocomplete input field types.

 

 

Well, that would explain my custom selector not working. Problem is that the page reference is pulling several thousand pages. Very impractical for anything but the autocomplete search from a usability standpoint. Not sure what I'll do for a solution - will put on my thinking cap.

Link to comment
Share on other sites

Strange, any custom selector I try and specify doesn't work. Even when using standard select vs auto complete. Running a clean install of 3.0.108. I'll try a different version PW install and see what happens. Once I get my selector working I can then test check_access.

EDIT: Turns out using a standard selector works after all, but using page list or auto complete doesn't seem to use custom selectors. My experience here confirms what d'Hinnisdael has said above.

Link to comment
Share on other sites

11 minutes ago, adrian said:

Not sure if this helps, but this works for me

Unfortunately, this doesn't seem to work for non-superusers. I've been up and down the source of ProcessWire's internal admin search (which powers the page autocomplete input) and it really seems to limit the selection of unpublished pages to superusers.

Would be great to have autocomplete inputs respect the Include unpublished setting of a Page field.

Link to comment
Share on other sites

Ok, I can confirm the following:

1. Adrian's advice above about check_access=0 works, provided you're doing #2 below.

2. Custom Selectors and therefore the solution from #1 above, will NOT work using page list or auto complete. You need to use good old fashioned select drop down.

Adrian, in your example above, how do you think you were able to circumvent issue #2 that myself and d'Hinnisdael seem to be experiencing? Was your screen shot from a superuser or non-superuser role?

Link to comment
Share on other sites

I put this in my ready.php file:

// hack to overcome this: https://github.com/processwire/processwire-issues/issues/550
$this->addHookBefore('Pages::find', function(HookEvent $event) {
    $selector = $event->arguments(0);
    if(is_string($selector) && strpos($selector, 'template=user') !== false && strpos($selector, 'name|first_name|last_name%=') !== false) {
        $selector .= ', check_access=0';
    }
    $event->arguments(0, $selector);
});

You'll need to adjust to suit the needs of your selector, but this is how I got around it and make it work for non-superusers. Sorry I forgot about this above.

Definitely worth a read through that github issue as well: https://github.com/processwire/processwire-issues/issues/550

  • Like 2
Link to comment
Share on other sites

14 minutes ago, adrian said:

I put this in my ready.php file:


// hack to overcome this: https://github.com/processwire/processwire-issues/issues/550
$this->addHookBefore('Pages::find', function(HookEvent $event) {
    $selector = $event->arguments(0);
    if(is_string($selector) && strpos($selector, 'template=user') !== false && strpos($selector, 'name|first_name|last_name%=') !== false) {
        $selector .= ', check_access=0';
    }
    $event->arguments(0, $selector);
});

You'll need to adjust to suit the needs of your selector, but this is how I got around it and make it work for non-superusers. Sorry I forgot about this above.

Definitely worth a read through that github issue as well: https://github.com/processwire/processwire-issues/issues/550

Couldn't get this to work on my first attempt. Out of time tonight, but will try another crack at it in the morning. Thanks for the github link as well.

Link to comment
Share on other sites

3 minutes ago, formulate said:

Couldn't get this to work on my first attempt. Out of time tonight, but will try another crack at it in the morning. Thanks for the github link as well.

Start by removing the $selector check stuff so that it just appends the , check_access=0 bit and once it's working build back up to protect other instances of Pages::find

Link to comment
Share on other sites

13 minutes ago, adrian said:

Start by removing the $selector check stuff so that it just appends the , check_access=0 bit and once it's working build back up to protect other instances of Pages::find

Yeah, first thing I did was strip the conditional back. It appears that if I'm logged in as a superuser, your ready.php code works (as expected). If I'm logged in as any other role, a generic error is thrown and pages in the admin don't work. Below is the code I'm using. Note, I also tried removing the appending of check_access=0 line and it still throws an error (some issue with re-assigning the event arguments, which makes no sense to me).

$this->addHookBefore('Pages::find', function(HookEvent $event) {
    $selector = $event->arguments(0);
    $selector = ', check_access=0';
    $event->arguments(0, $selector);
});

Will look again tomorrow. Thanks Adrian.

Link to comment
Share on other sites

7 hours ago, adrian said:

I put this in my ready.php file:


// hack to overcome this: https://github.com/processwire/processwire-issues/issues/550
$this->addHookBefore('Pages::find', function(HookEvent $event) {
    $selector = $event->arguments(0);
    if(is_string($selector) && strpos($selector, 'template=user') !== false && strpos($selector, 'name|first_name|last_name%=') !== false) {
        $selector .= ', check_access=0';
    }
    $event->arguments(0, $selector);
});

Hooking ProcessPageSearch::findReady might be better because it's more specific to autocomplete and the method looks like it exists for just this sort of purpose.

$wire->addHookAfter('ProcessPageSearch::findReady', function(HookEvent $event) {
    $selector = $event->arguments(0);
    // Manipulate $selector as needed...
});
/**
 * Hookable function to optionally modify selector before it is sent to $pages->find()
 * 
 * Not applicable when Lister is handling the search/render. 
 * 
 * #pw-hooker
 *
 * @param string $selector Selector that will be used to find pages
 * @return string Must return the selector (optionally modified)
 *
 */
public function ___findReady($selector) {
	return $selector;
}

 

Edited by Robin S
Corrected to addHookAfter
  • Like 2
  • Thanks 1
Link to comment
Share on other sites

2 hours ago, Robin S said:

Hooking ProcessPageSearch::findReady might be better because it's more specific to autocomplete and the method looks like it exists for just this sort of purpose.


$wire->addHookAfter('ProcessPageSearch::findReady', function(HookEvent $event) {
    $selector = $event->arguments(0);
    // Manipulate $selector as needed...
});

 

Beautiful, that did the trick. Thanks! Much better than modifying the core search module, and it won't spill over into generic find() calls in the front-end.

No idea how I missed the findReady hook in the first place…

Final working implementation:

// Include unpublished participants in page fields for non-superusers

wire()->addHookAfter('ProcessPageSearch::findReady', function(HookEvent $event) {
    $selector = $event->arguments(0);
    if(strpos($selector, 'template=participant') !== false || strpos($selector, 'templates_id=76') !== false) {
        $selector .= ", check_access=0, include=all, status<" . Page::statusTrash;
    }
    $event->return = $selector;
});

 

  • Like 5
Link to comment
Share on other sites

  • 4 years later...

Coming here 4 years later because the problem still seems to appear in PW3.0.208 dev and the proposed workarounds are not working for me. I tried both hooks in Pages::find and ProcessPageSearch::findReady.

Even if I uncomment the if statements in https://github.com/processwire/processwire/blob/6018c1fbc41c5aab4aceedf1d4a9c610de34aff3/wire/modules/Process/ProcessPageSearch/ProcessPageSearch.module#L378 and https://github.com/processwire/processwire/blob/6018c1fbc41c5aab4aceedf1d4a9c610de34aff3/wire/modules/Process/ProcessPageSearch/ProcessPageSearch.module#L390 

Unpublished pages are still not selectable from autocomplete fields for non superusers. Kind of frustrating. And no idea how else to tackle this. Any help would be much appreciated.

Need to switch to InputfieldSelectMultiple InputfieldAsmSelect which is not so nice since there will be ~50 pages from which to select.

Link to comment
Share on other sites

@gebeer, the findReady method is working for me:

$wire->addHookAfter('ProcessPageSearch::findReady', function(HookEvent $event) {
	$selector = $event->return;
	if($event->wire()->user->isSuperuser()) return;
	// If the selector looks like it comes from a particular autocomplete Page Reference field
	// (I wish this method provided a better way of working out where the selector is coming from)
	if(strpos($selector, 'parent_id=1329, templates_id=62,') === 0) {
		$selector .= ", include=all";
		$event->return = $selector;
	}
});

 

  • Like 1
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...