I am using a .php page as my holding page and use the date() function and $_SERVER["HTTP_HOST"] variable within this page. When I access this page directly example.com/holding.php the variables display fine. However from within this module the variables are ignored.

I am guesing that the page is parsed by the module and not through PHP. Is there an alternative way to access this information?

Cheers,

Roy

Comments

joachim’s picture

I don't think any PHP is parsed at all -- try a print statement.

The code in the module just slurps up the file and outputs it:

drupal_page_header();
$output = file_get_contents($holding_page);
print $output;
Corneloues’s picture

This is what I thought, but it is a real shame as there is potential here.

I might have to look in the module myself to see if the code could be wrapped with a simple parser that could look for simple tokens such as {domainname}, {day}, {month}, {year} so that it could be adapted in this way.

I'm thinking something along the lines of:

drupal_page_header();
$output = file_get_contents(holding_parser($holding_page), $holding_state);
print $output;

This would require adding a checkbox to the admin page to enable/disable parsing and one additional function parse the &holding_page.

Being really, really new to Drupal (and a php novice) I could have a stab at this, but not really sure at this stage how I would update all the admin side of things etc.

Cheers,

Roy

joachim’s picture

I'm wondering whether the way would be to use http://api.drupal.org/api/function/drupal_goto -- that should cause the whole thing to go to the indicated URL.

Alternatively, if that's not viable and we need to parse and add tokens, the right way to do it (TM) is with Token module.

joachim’s picture

Category: support » feature
Corneloues’s picture

Ok,

I've had a play with the module I have installed and its working well.

First I added this code to the holding_admin() function:

$form['holding_parse_state'] = array(
    '#type' => 'checkbox',
    '#title' => t('Parse holding page for tokens'),
    '#description' => t("Tick to parse the holding page for the tokens {domainname}, {day}, {month}, {year}, {hour}, {minute}, {second}"),
    '#default_value' => variable_get('holding_parse_state', 0),
  );

The admin page shows the new field correctly and stores the value in the variable table as i:1; or i:0;

Then I changed the following in the holding_boot() function:

if (is_array($holding_sites) && in_array($site, $holding_sites)) {
    $holding_page = variable_get('holding_page', '');
    $holding_parse_state = variable_get('holding_parse_state', 0);

    if (!$holding_page) {
      drupal_set_message(t('No holding page has been set.'), 'warning');
      return;
    }

    drupal_page_header();
    $output = holding_parser(file_get_contents($holding_page), $holding_parse_state);
    print $output;

Finally I added the new holding_parser() function beneath holding_boot():

/**
 * holding_parser().
 */
function holding_parser($page, $parse_state) {
  if ($parse_state) {
    while (substr_count($page, "{domainname}") > 0) {
      $page= str_replace("{domainname}", $_SERVER["HTTP_HOST"], $page);
    }

    while (substr_count($page, "{year}") > 0) {
      $page= str_replace("{year}", date('Y'), $page);
    }
  };
  return $page;
}

As you can see so far I have only added support for {domainname} and {year} and I have not attempted to optimise the routine in any way - simply using a separate while for each token.

I'm interested to know what you think.

Cheers,

Roy

joachim’s picture

Version: 6.x-1.2 » 6.x-1.x-dev

Interesting...

I think I see what you're getting at now.

Just having the holding page's PHP get parsed is good, but not *that* good as you don't get any values from Drupal.

Parsing it for tokens on the other hand means you can get things like site name, logo, email, and so on, and yes, as I think you said in your email, then have one single holding.php file which does duty for all multisites on an installation. If that can be made to work, then that is rather cool :)

A few things about the work you've done so far though:

- All changes to modules is done with patches. If you're not used to patching it's a bit daunting but there are very good docs starting here http://drupal.org/patch and folk on IRC are usually happy to help.
- Read up on http://drupal.org/coding-standards
- Look at http://drupal.org/project/token. Anything to do with token replacement should be done via that module's API: it does a huge amount of work for you and presents users with a consistent interface.

Corneloues’s picture

I'll look in to that. However in the mean time I have developed the module as follows.

/**
 * holding_parser().
 */
function holding_parser($page, $parse_state) {
  if ($parse_state) {
    while (substr_count($page, "{server:") > 0) {
    	$token = holding_token($page, "{server:");
    	$value = holding_token_value($token);
    	$page = str_replace($token, $_SERVER[$value], $page);
    }

    while (substr_count($page, "{date:") > 0) {
    	$token = holding_token($page, "{date:");
    	$value = holding_token_value($token);
    	$page = str_replace($token, date($value), $page);
    }

    while (substr_count($page, "{time:") > 0) {
    	$token = holding_token($page, "{time:");
    	$value = holding_token_value($token);
    	$page = str_replace($token, date($value), $page);
    }
  };
  return $page;
}

2 additional function for my own token parser. These I guess will be replaced once I understand the other project.

/**
 * holding_token().
 */
function holding_token($page, $tokenname) {
  $startpos = stripos($page, $tokenname);
  $endpos = stripos($page, "}", $startpos);
  $token = substr($page, $startpos, $endpos - $startpos + 1);
  
  return $token;
}

/**
 * holding_token().
 */
function holding_token_value($token) {
  $startpos = stripos($token, ":");
  $endpos = stripos($token, "}", $startpos);
  $token = substr($token, $startpos + 1, $endpos - $startpos - 1);
  
  return $token;
}

Finally the admin page changes:

$form['holding_parse_state'] = array(
    '#type' => 'checkbox',
    '#title' => t('Parse holding page for tokens'),
    '#description' => t("Tick to parse the holding page for the tokens {server:value}, {date:value} and (time:value}."),
    '#default_value' => variable_get('holding_parse_state', 0),
  );

I will look at the token stuff and work out how to integrate. That may take it bit longer though. But for now this will do for me ;-)

Cheers,

Roy

Corneloues’s picture

FYI... I have taken your advice on board and have now started the token integration. I am having a few issues getting token to parse and replace at the moment but have narrowed the changes down to the following.

All other code has been removed.

holding.info
dependencies[] = token

holding.module: holding_boot()

  ...
// Load token module functions
drupal_load('module', 'token');
  ...
  ...
$output = file_get_contents($holding_page);

if (module_exists('token') and $holding_parse_state) {
  $output = token_replace($output, 'global');
}

drupal_page_header();
print $output;

holding.module: holding_admin()

$form['holding_parse_state'] = array(
  '#type' => 'checkbox',
  '#title' => t('Parse holding page for tokens'),
  '#description' => t("Tick to parse the holding page for the tokens. The token module is required for this."),
  '#default_value' => variable_get('holding_parse_state', 0),
  );

holding.install:

/**
 * Implementation of hook_uninstall().
 */
function holding_uninstall() {
  variable_del('holding_sites');
  variable_del('holding_page');
  variable_del('holding_parse_state');
}

The next step will be to see if I can do this via a proper patch.

Cheers,

Roy

joachim’s picture

Looks good but would be much easier to follow as a patch :)

Also, if you've set a dependency in a .info file, there is no need to do module_exists('token'). However, it would be best not to require token as some users may not need its features at all.

Corneloues’s picture

Yeah I know... Need to understsnd the patch system next...

So how do you go about "depending" but not "depending" ;-)

Also I'm having issues getting toekn to actually do anything.If I start a patch will you be able to help?

Cheers,

Roy

Corneloues’s picture

StatusFileSize
new1.32 KB

OK, I've created a patch file. Let me know if I have done this correctly. I used diff to create a patch file for the three files I touched individually and then tar'd them together.

Cheers,

Roy

joachim’s picture

Status: Active » Needs work

> So how do you go about "depending" but not "depending" ;-)

Do only one of the two things you did to depend on token...

If you set a dependency if the info file, then you absolutely need token; Drupal will not let a user enable your module without token.
If you wrap some code in a check to module_exists() then you code that will run if token is present, but your users are not forced to install it.

Patch file.... nope, a patch file is text; something that can be read at a glance. Instructions are at http://drupal.org/patch/create

Another thing:

function holding_parser($page, $parse_state) {
  if ($parse_state) {

If the whole function body is wrapped in an if, check the value before calling rather than handing it around.

Corneloues’s picture

StatusFileSize
new1.97 KB
new383 bytes

I've removed the dependency and simply gone with the module_exists() option as you suggested.

The tar file I attached had the individual .patch files inside. I've now attached the two .patch files directly. The .info file has been reverted as I have removed the dependency.

Finally the holding_parser() function no longer exists as I am now using token. All in all a much simpler solution. If only I could get it to work!!!

Cheers,

Roy

Corneloues’s picture

OK, I'm hoping you can now help me crack this with the patch info I have sent you...

If I remove the drupal_load('module', 'token') line from the holding_boot() function. I get errors when trying to call the token_replace() or token_replace_multiple() functions.

If I leave the drupal_load('module', 'token') line in place, the errors go away but token_replace() doesn't replace the tokens. If I change the function for token_replace_multiple() then I get error messages from the function - due to invalid parameters, so I know the functions are being called.

Even if I hard code a call like this print token_replace_multiple('[yyyy]', 'node') all I get back is [yyyy].

Any help would be appreciated.

Cheers,

Roy

joachim’s picture

It looks like we're too early in the bootstrap process for token_get_values() to actually have anything.

I guess your options are either:

a) go through the token flow and figure out why it's not getting anything (you'd think at least its own token hook gets called?)
b) if the option to use token is set, defer the whole process to hook_init() which happens later.

Corneloues’s picture

I see you've made a feature request on the token page (didn't know there was a "site logo" - where is that exactly), I've also updated my issue on there as I think it maybe because we are in offline mode...

Let's see if we can get the token guys involved in this.

Cheers,

Roy

Corneloues’s picture

Confirmed by the token guys that replace_token() can't be called in _boot(). What would happen if we moved the display functionality to _init()?

Cheers,

Roy

Corneloues’s picture

Update:

renaming holding_boot() to holding_init() still works and I am able to get the 'global' tokens to work. For some reason the 'node' tokens still will not update.

Also, as to your request for the site-logo, we can add two hooks to the holding module which will allow the introduction of new tokens. So, I believe this means we can create a 'holding' object and have our own tokens such as:

[site-domain] - without the 'http://'
[site-image] - As you asked for

and so on...

I'll provide another patch update later once I've worked out the token hooks.

Cheers,

Roy

joachim’s picture

> the 'node' tokens still will not update.

Because there is no node!

> Also, as to your request for the site-logo, we can add two hooks to the holding module which will allow the introduction of new tokens

We can, but they don't belong here: they belong in Token module so anything can use them.

Corneloues’s picture

StatusFileSize
new4 KB
new224 bytes
new243 bytes

OK,

I think I've cracked it. Attached you will find patches for the module files.

High level overview:

All files - Version updated to 1.3 and added my username

.install
Added the removal of the new 'holding_parse-state' variable

.module
_boot() is now _init() - There was no effect on the modules behaviour with this change
Added wrap for parsing

_admin()
Added 'holding_parse_state' to the admin page

_token_values()
Added new hook for the Token module. Specifically added a new 'type' called 'server' which adds all the values for the $_SERVER variable

For an example of this holding page with replaced tokens try www.soundchaser.me.uk.

Not sure what happens next...

Cheers,

Roy

joachim’s picture

Can you check that page I linked to on the finer details of how to make a patch?

This really needs to be a single file and in the unified format, which makes it all much easier to read. Sorry to be a stickler, but I review patches in my free time and so I'd like them in the commonly-agreed format.

> // $Id: holding.module,v 1.3 2010/06/17 16:40:00 joachim,corneloues Exp $

No need to change this line: it's automatic.

>  * New For v1.3 - Replaces the hook_boot() with hook_init()

Don't record history in files. That's what CVS is for.

< function holding_boot() {
---
> function holding_init() {

I'd actually like to keep hook_boot() for speed -- delay operation to hook_init() only if token module's involvement is requested.

Powered by Dreditor.

Corneloues’s picture

OK, I'll look in to delaying... and will sort out the patching stuff

Cheers,

Roy

joachim’s picture

> I'll look in to delaying.

I can do that bit once there's a patch to work from :)

Corneloues’s picture

Ok, I've managed to create a single patch file. The changes now include updates to the readme file and I have reverted the version changes I made plus removed the unecessary comments.

I'm glad you've said you'd work on the _boot()/_init() changes as I failed miserably...

However, I cannot make head nor tail out of how to apply a patch to the module. The documentation seems to skirt around the process but actually how to do it.

I've attached the patch so hopefully you can apply.

Cheers,

Roy

Corneloues’s picture

joachim’s picture

Title: Accessing variables & functions variables from a PHP holding page » Add token support to the holding page
Status: Needs work » Needs review
StatusFileSize
new3.87 KB

Okay I've taken this and worked on it, but for future reference:

- roll the patch from the actual module directory. this patch does not apply properly.
- don't change the CVS $Id$ line. That is automatically set by CVS.
- don't change anything beyond the essentials of what you are doing. I appreciate your updating the README file, that's great, but don't embellish it by changing the number of '===='s or that kind of thing. Likewise, don't change the title of the module in the info file or the title of the admin page -- it has nothing to do with this issue. As you can see from the patch file, it means there is more to take in and read and it means I have to manually edit your patch to remove the bits I don't want. Good explanation of this here: http://www.webchick.net/please-stop-eating-baby-kittens
- don't put in comments like "// New for v1.3". Code should not contain its history.

More specifically for this patch:

- this won't work: $output = token_replace($output, 'node') -- there is no node as I said above. Even if you try to go to a path like /node/1, if you're being shown the holding page then Drupal has bailed long before a node is loaded. Ditto the user tokens, as the holding page is only ever shown to anonymous users -- anything of interest such as the 'Anonymous' username is available in the global token set.
- I'm taking out the token hooks: it is not this module's responsibility to add support for tokens for all the server variables: either token should do it or another module -- you should file a patch on Token module with this. This is because any module might feasibly want to use server variable tokens and yet not want a holding page, so these should be implemented centrally rather than repeatedly in each module. It's one of the principles of Drupal: reuse.
- there's no need to pass the value of $parse around. This is something you won't know as you're new to Drupal: the variable table is cached, so calls to variable_get() are cheap: you can certainly call it again in another function.

If you're able to apply this, give it a spin, otherwise I'll commit it in a few days :)

Corneloues’s picture

Would appreciate understanding how to apply the patch. But I'm obviously missing something as I cannot see how to do it - and I've read the docs.

I really would like to understand, as I would like to offer the 'server' variables to Token, but don;t want to have to go through all this again.

Just need to understand, learn and do it... Can it really be that difficult?

Cheers,

Roy

joachim’s picture

Start here: http://drupal.org/patch/apply

If anything is not clear to a beginner, then this is a flaw in the documentation: please file bugs in the issue tracker on the Documentation component explaining what you don't understand and someone will fix them.

Corneloues’s picture

OK, here;s what I don't understand. I can apply a patch on my side, but how does that help you/the module? I was kind of expecting it to patch something here...

I thought 'I' was patching 'your' module. Or was I just providing a patch for 'you' to review.

I am guessing now that the patch you have sent me is simply to align it your holding module I have installed locally and that this will bring our code in to line with each other?

Cheers,

Roy

Corneloues’s picture

Right... Finally... I think I've got it... (sorry for being so slow with this!!!)

Applied you patch here and can see what you've changed and how you've changed it. I also like the way the parse option doesn't show unless Token is enabled and how you've pulled the tokens through to the admin page as well.

Obviously I've lost my [http_host] token that I need at the moment, but now I'll go and patch Token, now that I know what I'm doing and submit it over there.

So is this now going to make it in to a formal update?

Cheers,

Roy

joachim’s picture

Ah okay. Conceptual stuff.

A patch is just a file that says 'Make these changes to these files'. If you and I both have the same files to start with -- in this case either a checkout from CVS or a development download -- then this is what happens: I change my files and make a patch. The patch shows what I have changed from the starting point to where I am now.
I give you the patch file. You have the same starting point (this is the important bit) and so you can apply the patch. You are making the same changes I have made, so after applying the patch your files are now the same as mine with my changes. This means you can see what I have changed and try it out.

It helps the module and the maintainer because it means you're testing the patch and you may find things that the person who made the patch has missed -- this is peer review.

*Committing* a patch is the action of applying it and then updating the CVS repository with the changes. Once that has happened the new version of the code can be released.

You really should be asking this on the documentation issue queue -- perhaps you can add a bit of background explanation to one of the handbook pages?

Corneloues’s picture

Good point... I'll certainly think about that and see where best to place my comments/experiences...

Thanks for your help, look forward to the official update coming out in the near future.

Cheers,

Roy

joachim’s picture

Status: Needs review » Fixed

#821484 by Corneloues, joachim: Added token support to the holding page.

I've gone ahead and committed this.

The 6.x-1.x-dev release will be updated in the next 24 hours with this -- give that a try. If I don't hear from you about any problems I'll roll a new release in a few days.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.