Vanilla 1 is no longer supported or maintained. If you need a copy, you can get it here.
HackerOne users: Testing against this community violates our program's Terms of Service and will result in your bounty being denied.

Extension Problem

edited August 2005 in Vanilla 1.0 Help
Further to my needs of altering the header HTML of Vanilla, I set about writing myself an extension to help me. I read the documentation, I understood it. I wrote my code. It didn't work.

As far as I'm aware, the problem lies in something that I'm doing wrong with the

$Context->ObjectFactory->SetReference("MyNeatClass", "AnotherClass");

For outputting HTML head content, the class 'Head' in ./controls/Common.Controls.php is used, around line 322.
This class loops through scripts, stylesheets and strings added to the header, and then the function Render() is used to render the page, outputting the HTML header.

Excellent, I thought. I'll just Set a reference (using the above code) so that Vanilla asks for my version of the Head class (which i called ManualHead) and uses my Render() function instead of its own. So I wrote this:

$Context->ObjectFactory->SetReference("Head", "ManualHead");

With the class ManualHead being:

class ManualHead extends Head { function Render(){ $this->Context->Writer->Add("test"); } }

Which should, with the SetReference method just write the entire head to 'test'.
This didn't work.

I tried it with $this->Context->Writer->Write("test"); instead. Nope.

So I tried copying the entire Head class to ManualHead. I even changed the

function Head(&$Context) { $this->Context = &$Context; }


function ManualHead(&$Context) { $this->Context = &$Context; }

I set a class var$Context. I even tried making ManualHead a new object, and a new ContextObject. Nothing worked.

So, after much playing, and getting annoyed...i've decided to ask the forums. Maybe a php whizz can lend a hand (Mark?) as i've tried my best.

Here's the code in the simplest format I think should work:

class ManualHead extends Head { function Render(){ $this->Context->Writer->Add("test"); } } $Context->ObjectFactory->SetReference("Head", "ManualHead");

I'd be most pleased if someone could help me out :-)




  • Options
    lechlech Chicagoland
    edited August 2005
    It might help to know EXACTLY what you're trying to modify in the head area there. Just part of it, the whole thing or inserting something in between it all? Because I want to say if it's replacing the utf-8 and encoding and other general header info, it might not be possible yet because I'm fairly certain mark didn't consider that as necessary to being modified. Maybe in the next revision it should be extension compatible.
  • Options
    edited August 2005
    Hokay - here's the code:

    function Render() { $this->Context->Writer->Add("<".chr(63)."xml version=\"1.0\" encoding=\"utf-8\"".chr(63)."> <!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"\"> <html xmlns=\"\" xml:lang=\"en-ca\"> <head> <title>".agAPPLICATION_TITLE." - ".$this->Context->PageTitle."</title> <link rel=\"shortcut icon\" href=\"/favicon.ico\" />"); if (is_array($this->StyleSheets)) { $StyleSheetCount = count($this->StyleSheets); for ($i = 0; $i < $StyleSheetCount; $i++) { $this->Context->Writer->Add("\r\n<link rel=\"stylesheet\" type=\"text/css\" href=\"".$this->StyleSheets[$i]["Sheet"]."\"".($this->StyleSheets[$i]["Media"] == ""?"":" media=\"".$this->StyleSheets[$i]["Media"]."\"")." />"); } } if (is_array($this->Scripts)) { $ScriptCount = count($this->Scripts); for ($i = 0; $i < $ScriptCount; $i++) { $this->Context->Writer->Add("\r\n<script type=\"text/javascript\" src=\"".$this->Scripts[$i]."\"></script>"); } } if (is_array($this->Strings)) { $StringCount = count($this->Strings); for ($i = 0; $i < $StringCount; $i++) { $this->Context->Writer->Add($this->Strings[$i]); } } $this->Context->Writer->Write("</head> <body".$this->Context->BodyAttributes."><div id=\"header\"><!-- A menu, a few divs etc --></div> "); }
    if it's not an essential feature and I can't do it, then how am I to add my own header etc?
  • Options
    lechlech Chicagoland
    edited August 2005
    Well, if you just want to change the DTD, then all you really need to change is

    $this->Context->Writer->Add("<".chr(63)."xml version=\"1.0\" encoding=\"utf-8\"".chr(63)."> <!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"\"> <html xmlns=\"\" xml:lang=\"en-ca\">

    To my knowledge, mark hasn't yet added support to change this yet. However it would be wise in the future for Arabic languages and such.

    For adding just a script, you shouldn't be hacking away directly at the header and core files, instead look at this discussion on how to add a header script as an extension.
  • Options
    edited August 2005
    That's not really what i'm after doing...I don't want to change the DTD; I want to add in the bit of HTML near the bottom after the body tag.

    I'm not not planning on hacking away at the header and core files; i'm writing an extension to do it for me so that it's lifespan extends across upgrades.

    I suspect that the order of execution sees the Common.Control.php script being executed after the extensions, which makes my attempt to change the 'Head' class not do anything.
    It's just that I thought I would be able to do this...either that or I'm doing something wrong. Perhaps a php whizz could shed some light on this, or perhaps Mark himself?

  • Options
    MarkMark Vanilla Staff
    Sorry it took me so long to get to this discussion - I've been really busy. The problem is that the Head control is instantiated before the extensions are loaded. So by the time you're setting your new reference in the ObjectFactory, the object has already been created and your reference does nothing. Now, there *is* an "AddString" method in the Head control that allows you to add *anything you want* to the head. Would that allow you to do what it is you're trying to do?
  • Options
    MarkMark Vanilla Staff
    Oh, and by the way, please feel free to send me an email if you've got a pressing code-related question that isn't being answered: support [at] lussumo [dot] com
  • Options
    Ah ha! As I thought, except the wrong way around! It made sense in my head, just not translated properly into text!

    The AddString method is dandy, but I want to add code outside of the head, before the rest of the Vanilla forum code - so that I can add my own block of 'stuff' - everything which fits in with the rest of the site that I'm making.

    If needs be, I'll just hack about with the core files. Is there any reason why the control classes can't be instantiated after the extensions?

  • Options
    MarkMark Vanilla Staff
    edited August 2005
    Those five control classes are instantiated before the extensions are loaded so that extension writers can take advantage of their various utility methods like adding things to the head, adding things to the panel, adding things to the body, etc.

    You can always just create your own control and add it to the Head_Render event of the page object if you just want to add something *after* the head.

    $MyObj = $Context->ObjectFactory->NewContextObject($Context, "MyClass"); $Page->AddControl("Head_Render", $MyObj);

    To be honest, I've never even tried it, but theoretically it should be fine.

    The only thing you might stumble across is that your control gets added before the head control and therefore is rendered before the head control. If that is the case, the quick fix is to add your control to the next event in the page, which is the Menu_Render event.

    If that happens, though - please let me know. I want to make sure that things get executed in the correct order, and I may have to change the page object a bit for the next release to ensure that happens.
  • Options
    edited August 2005
    You're an absolute star!

    sweeney kisses Mark on the forehead, Mafia Stylee.

    I had to use the Menu_Render event as you said...
    Extension Name: Change the header
    Extension Url:
    Description: Allows you to manually edit the header of Vanilla forums
    Version: 1.0
    Author: Martin Sweeney
    Author Url:
    class ManualHead  {
            var $Context;
            function ManualHead (&$Context) {
                    $this->Context = &$Context;
            function Render() {
                    $this->Context->Writer->Write("Hello :-)");
    $ManualHead = $Context->ObjectFactory->NewContextObject($Context, "ManualHead");
    $Page->AddControl("Menu_Render", $ManualHead);
  • Options
    MarkMark Vanilla Staff
    Cool - thanks for the heads-up. I'll be sure to fix that order-of-events bug for the next release. :)
This discussion has been closed.