Jump to content

Best Practice to determine if admin from init method?


Noel Boss
 Share

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
Link to comment
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
Link to comment
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;
		}
}

 

Link to comment
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

 

Link to comment
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…

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

Link to comment
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 🙂

Link to comment
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
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

×
×
  • Create New...