That was fast! Glad it's working. For the next step (keeping it modal), I pushed a couple updates to GitHub today to aid in doing that (made a few more things hookable). So make sure you've got the latest commit.
Now we want to hook into a couple more things to modify the form URL and redirect URL, like you did by editing ProcessPageEdit, but we want to do it in a way that doesn't require changing anything in the core. So here is the full skeleton module code from before, but with the addition of two new hooks. Note that I didn't add as many comments to the new stuff, because I have to go pick up my daughter from school, so please reply with any questions:
<?php
class AdminBar extends WireData implements Module {
/**
* This is where you define some basic info about your module.
*
* See /wire/core/Module.php for definitions of all these.
*
*/
public static function getModuleInfo() {
return array(
'title' => 'Admin Bar',
'summary' => '[Summary of your module], by apeisa',
'href' => 'http://processwire.com/talk/index.php/topic,56.0.html',
'version' => 100,
'permanent' => false,
'autoload' => true,
'singular' => true,
);
}
/**
* Initialize the module and setup hooks
*
* The init method of a module is called right after ProcessWire is bootstrapped, when all
* API vars are ready. Whereas the __construct() is called DURING bootstrap, so the init()
* method is a better place to attach hooks to API vars.
*
* In this method, we'll use an 'after' hook since we want to modify the output of the
* rendered page template.
*
* Note also that the 'Class::method' syntax means it hooks into ALL Page instances.
* The syntax for hooking to a single instance would be:
* $page->addHookAfter('render', $this, 'pageRender');
*
* Also note that there isn't actually a Page::render method, it was instead added by
* another module (wire/modules/PageRender.module). Not that it matters here, but just
* wanted to mention in case you look in the Page class and don't see a render method.
*
*/
public function init() {
// modify the output of a page render, adding some markup to support the adminbar
$this->addHookAfter('Page::render', $this, 'pageRender');
// hook before forms are rendered, so that we can modify the form's "action" attribute
$this->addHookBefore('InputfieldForm::render', $this, 'formRender');
// hook before a redirect occurs, os we can modify the redirect URL
$this->session->addHookBefore('redirect', $this, 'sessionRedirect');
}
/**
* Hook called when a page is rendered
*
* The method name used here does not matter, it just has to be consistent with the name you provided
* when creating the hook.
*
* This method is given an $event object of type HookEvent. To see what's in that, see this file:
* /wire/core/HookEvent.php (it's very short and simple)
*
*/
public function pageRender($event) {
// $event->object always has the object instance that resulted in this call
$page = $event->object;
// if the page isn't editable, or if it's using the admin template, abort.
if(!$page->editable() || $page->template == 'admin') return;
// find the location of this module for linking css and js files
$url = $this->config->urls->AdminBar . "AdminBar";
// the css and js links we're going to add
$out = "\n\t<link rel='stylesheet' type='text/css' href='$url.css' />" .
"\n\t<script type='text/javascript' src='$url.js'></script>" .
"\n</head>";
// modify the value returned by $page->render() to include our css and js files
$event->return = str_ireplace('</head>', $out, $event->return);
}
/**
* Hook to take place before forms are rendered
*
* We check if there is a 'modal' get var set, and if so, we add it to the form's action attribute
*
*/
public function formRender($event) {
if(!$this->input->get->modal) return;
$form = $event->object;
$action = $form->attr('action');
$action .= (strpos($action, '?') !== false ? '&' : '?') . "modal=1";
$form->attr('action', $action);
}
/**
* Hook to take place right before a redirect occurs
*
* We intercept the redirect URL and modify it to add 'modal=1' to the query string
*
*/
public function sessionRedirect($event) {
if(!$this->page || $this->page->template != 'admin') return;
if(!$this->input->get->modal) return;
$url = $event->arguments(0);
if(preg_match('/[?&]modal=/', $url)) return;
$url .= (count($this->input->get) ? '&' : '?') . "modal=1";
$event->arguments(0, $url);
}
}
Lastly, I should probably have the core look for a modal attribute and keep it going when it finds it (because this has use elsewhere), but I thought this was a really good example of how to implement a module, so figured we would start here.