Jump to content
Noel Boss

Best Practice to determine if admin from init method?

Recommended Posts

👋 PW Pros…

I have some hooks that I need to bind at the init phase (or even __construct) and I was wondering, and I couldn't find a good and simple way to determine if I'm in the admin. Would be nice if there is a reliable short option to do so, but I can't seem to find one… Is there a coherent way to tell this no matter where I am?

Right now, I use the following method inside one of my modules:

public function isAdmin($page = null)
	{

		if (
			strpos($this->input->url, $this->urls->admin) !== false
			|| $this->process instanceof ProcessPageList
			|| $this->process instanceof ProcessPageEdit
			|| ($page instanceof Page && $page->rootParent->id == $this->config->adminRootPageID)
		) {
			return true;
		}
		return false;
	}

@ryan wouldn't it be nice to have something like wire()->isAdmin(); like wire()->user->isLoggedin(); to tell if we are in admin – very early on (probably even in __construct() phase of modules?

  • Like 1

Share this post


Link to post
Share on other sites

Doesn't this work?

if ($this->page->template == 'admin') {
    echo "in admin";
} else {
    echo "not in admin";
}

It surely works in ready.php. (Maybe you'd have to alter the syntax a bit... wire instead of this)

Just tried this inside one of my modules, and it works as expected:

    public function init() {
        parent::init();
        if ($this->page->template == 'admin') {
            $this->wire->message("in admin");
        } else {
            $this->wire->message("not in admin");
        }
    }

 

Edited by dragan
added module example code
  • Like 2

Share this post


Link to post
Share on other sites

@Noel Boss

I'm using this code in hooks to Templatefile::render and didn't have any issues with it. 

	if (strpos($_SERVER['REQUEST_URI'], $this->wire('config')->urls->admin) === 0 || $this->wire('page')->template->name == 'admin') return;

 

  • Like 2

Share this post


Link to post
Share on other sites

Thanks four your suggestions… However, I'm talking about the init() method inside a module, not ready and not render (for render, the page needs to be there, so ready is already fired) – this is early in the boot process, no page and no template is available at that stage… sometimes not even a process… (at least wherever I tested it) – also parent::init throws an error.I am also not talking about the init.php – this might be different…

4 hours ago, dragan said:

Doesn't this work?

Nope 😉 

2115815220_Screenshot2019-09-29at18_30_08.png.ca4999d379d12ea053ffe88c44de71b8.png

 

@Zeka – thats about what I do with the first and the last test from my example, but it feels very much like a hack for my taste…

I currently use a Hook to extend wire that looks the following:

public function __construct() {
		$this->addHookMethod('Wire::isAdmin', $this, 'isAdminHook');
}


public function isAdminHook(HookEvent $event) {
		$event->return = false;

		if (
			$this->process instanceof ProcessPageList // Admin Page List
			|| $this->process instanceof ProcessPageEdit // Edit Screen
			|| strpos($this->input->url, $this->urls->admin) !== false // determine from Admin url…
			|| ($event->arguments(0) instanceof Page && $event->arguments(0)->rootParent->id == $this->config->adminRootPageID) // if a page is passed…
		) {
			$event->return = true;
		}
}

 

Share this post


Link to post
Share on other sites

Hi @Noel Boss, - I haven't understand why you need init() and why you are not able to use ready(). (Maybe, because you haven't told 😉

But what about testing with prioritizing your hook(s)? Maybe with init() it may run lately, or in ready() (as one of the early birds), will do what you are after??

Links:

https://processwire.com/docs/modules/hooks/#hook-priority

and

 

Share this post


Link to post
Share on other sites

@horst – I need init to bind hooks that can only be bound before ready fires – for example render, or viewable … Therefore, hook priorities don’t help me. I could just bind the hooks anyway, but I only want to bind the hooks, when I really need them… My goal is to not bloat the system with hooks … I use tons of them, but I only wan’t to invoke them wenn really needed.

For example. some of the hooks are access related and since PW does not provide a robust and native way to hook into page access features [viewable about the only option, or filtering find queries, both not great options but it's what you get…] I have to be very early in to boot process, sometimes earlier than init ( __construct() ) … These hooks are costly since I have to check for all pages with related pages and then get a blacklist from ID’s that I can then later use filter my results so I don’t get wrong page counts when requesting pages…

@ryan it would really be great to be able to hook into the access system on a lower api level… (not directly on sql…) you’ve built some nice modules, but they all are on top of the current system and don’t work for find queries…

Share this post


Link to post
Share on other sites
2 hours ago, Noel Boss said:

 @ryan it would really be great to be able to hook into the access system on a lower api level… (not directly on sql…) you’ve built some nice modules, but they all are on top of the current system and don’t work for find queries…

That's not really true. Ryan's Dynamic Roles module does add additional sql clauses to ensure dynamic roles are fully resolved at the database level. Sadly is the module is not very well maintained and it could also be build a bit more flexible (e.g. matching on calculated values instead of just "membership"), but it is possible.

2 hours ago, Noel Boss said:

For example. some of the hooks are access related and since PW does not provide a robust and native way to hook into page access features [viewable about the only option, or filtering find queries, both not great options but it's what you get…] I have to be very early in to boot process, sometimes earlier than init ( __construct() ) … These hooks are costly since I have to check for all pages with related pages and then get a blacklist from ID’s that I can then later use filter my results so I don’t get wrong page counts when requesting pages…

This to me sounds like a very hacky workaround. You initially said you don't want to bloat the system with hooks. Blacklisting IDs and filtering them at runtime is very likely to be way worse for performance than a handful or two more hooks.

Share this post


Link to post
Share on other sites

Hi @LostKobrakai – we are diverting from the subject 😉

My business logic is a bit complicated. I have many organisations, and an organisation have different memberships and depending on these memberships, the users assigned to the organusation can view different pages … and the users themselves have different roles inside the organisation and some pages are blocked or unlocked based on the role in the organisation. I could not find any module or core functionality that let me handle this use case with elegance. So what I do is i get all the pages blocked by a specific selector based on language, membership and role (and sometimes login state etc.) and cache the resulting ids based on these attributes [so they are only fetched once per membership-role combo-language until a page matching relevant template or the user or the organisation changes … complicated eh 😉], this needs to happen very early so I don't miss any query operations later on. I then filter using a hook by appending the id's as a id!=1|2|3 selector … thats the most efficient way I found. – I tried most of the modules out there, not sure if I found this one you mentioned @LostKobrakai – I'll have a look at it, thanks!

Also, I just recently found the ___getQueryAllowedTemplatesWhere() hook in PageFinder.php … I might investigate this one a bit more… (thats the one Dynamic Roles uses as well)

So, back to the topic, I use hooks here, and elsewhere for other purposes inside the init() method and it would be nice to have a consistent and simple way to check if we are in admin or not 🙂

Share this post


Link to post
Share on other sites
2 hours ago, Noel Boss said:

So, back to the topic, I use hooks here, and elsewhere for other purposes inside the init() method and it would be nice to have a consistent and simple way to check if we are in admin or not

I guess this is a bit of a chicken and egg problem. The admin in processwire is hardly anything special based on what the core knows about it. It's a bunch of pages, which just happens to be tightly access controlled and forwarding their handling to process modules instead of rendering templates. So before knowing the page you're on there's not really a good way to know if the request is going to serve an "admin page" or not. To query the current page a lot of things already need to be started, and I guess you want to hook into those before any pages are queried, at best by already knowing the context, which is not going to work.

A good example is the function you've shown in your initial post. It's a good heuristic for determining if the user is in the admin, but also not bullet prove, as there can be normal pages as children of $this->config->adminRootPageID as well. It might rarely happen, but it's possible. The only way to be sure is actually having $page queried.

  • Like 1

Share this post


Link to post
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.

  • Similar Content

    • By codevark
      The Minimal Site works fine, but if I try to login as admin, I have no idea what the credentials are.
      I did not do the "install" process myself. The OVA came with everything set up, but there's no mention of the PW admin credentials being set to some initial value.
      Wondering if anyone else has tried the Bitnami OVA and if there's a simple answer.
      --Pete
    • By vwatson
      I don't have any fontawesome icons in the admin section. Not sure what's wrong. They used to appear. I've tried all the user profiles and they're gone in all of them.
      Using the browser inspector tool, I see this message:
      Access to font at 'https://www.domain.com/wire/templates-admin/styles/font-awesome/fonts/fontawesome-webfont.ttf?v=4.7.0' from origin 'http://domain.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
      I'm not sure why this is occurring or how to fix it. Any help would be greatly appreciated. 
    • By Andi
      Continuing my journey into PW hooks, I'm trying to find a way to retrieve all images from a page that explicitly *do not* have a certain tag (or tags) attached to them.
      Found this post from 2015
      But I'm wondering if there's a more elegant way to go about this.
      Let's say I have a multi-image field called "images_header" and instead of
      $page->images_header->findTag('mytag'); I would like to do this:
      $page->images_header->excludeTag('mytag'); So I'd be able to do
      // find images that don't have the tag "mytag" $images = $page->images_header->excludeTag('mytag'); // check if there's any images if (count($images)>0) { // do something.. } Would this be possible by hooking into Pagefiles somehow?
      There's this bit in /wire/core/Pagefiles.php Line 626 that I'd basically just need to reverse (or at least in my mind 😄 )
      public function findTag($tag) { $items = $this->makeNew(); foreach($this as $pagefile) { if($pagefile->hasTag($tag)) $items->add($pagefile); } return $items; } Any ideas on how this could be done in a graceful manner?
      Thanks in advance!
    • By Andi
      Getting a little deeper into the ProcessWire state-of-mind here. I seriously think I wouldn't have come back to webdev if it wasn't for this wonderful little gem of a CMS.
      I have an "Options" field added to all users on a site. If the user has anything other then "default" selected, I would like to show a permanent message in the admin like the one in the screenshot, only so that the user can't close it. As a friendly reminder that he changed that option from default to something crazy 🙂
      I've read up on how to send messages to users, but where would I hook into to make this show up all the time in the backend?
      https://processwire.com/api/ref/wire/message/
      Thanks in advance!

×
×
  • Create New...