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.

Delegates doubt

edited January 2007 in Vanilla 1.0 Help
I'm starting to grasp a little bit of the delegation or at least I think so... the question: so when I saw a $this->CallDelegate('whatever') in a control I can attach it to my function and get all the references of the control right? if I attach to a delegate that his "post" that means that everything above is what I will get? I'm still a bit confused... for instance this part from the discussion form control: $this->CallDelegate('PostLoadData'); // If saving a discussion if ($this->PostBackAction == 'SaveDiscussion') { $this->Discussion->Clear(); $this->Discussion->GetPropertiesFromForm($this->Context); // If we are editing a discussion, the following line // will make sure we save the proper discussion topic & message $this->Discussion->DiscussionID = $this->EditDiscussionID; $this->DelegateParameters['SaveDiscussion'] = &$this->Discussion; $this->CallDelegate('PreSaveDiscussion'); $ResultDiscussion = $dm->SaveDiscussion($this->Discussion); $this->DelegateParameters['ResultDiscussion'] = &$ResultDiscussion; $this->CallDelegate('PostSaveDiscussion'); is the PostLoadData or the PostSaveDiscussion that delegate this chunk of code?


  • Delegation term is a bit confusing in Vanilla implementation of the paradigm.
    CallDelegate() is rather a call to any function attached to this particular object/delegate pair.
    In your function you get the calling object as first parameter and then have access to all its public variables. But not to local ones, which in many places raise difficulties. That's a limitation.
    You can't "replace" any processing of the calling object by your own, you can add to, possibly undoing or redoing something. That's a second limitation.
  • edited January 2007
    Max is right. Delegation isn't so much as replacing functionality with your own code, instead it's a point where you can inject your code. You can grab some variables or objects from inside Vanilla with the delegate parameters.

    Best way to learn how it works is to see it in action.

    For example, I wanted a way to auto-fill a whisper value in a discussion form:function PreFillWhisperTo(&$DiscussionForm) { // The DiscusisonForm control fills its form fields with values in a discussion object. //Retrieve its reference to that object from its DelegateParameters: $Discussion = &$DiscussionForm->DelegateParameters['Discussion']; // Set the whisper user name to the value passed in the URL query string $Discussion->WhisperUsername = urldecode(ForceIncomingString('WhisperTo', '')); } $Context->AddToDelegate('DiscussionForm', 'DiscussionForm_PreRender', 'PreFillWhisperTo');

    Would be glad to help explain if you say what you are trying to accomplish.
  • edited January 2007
    Thx Max and Wallphone for your answer :D I want to merge the start new discussion(only the category select and the topic txt title not the comment body) with the comment grid. so for instance: //I create my controller class saveDiscussionForm extends Control { function saveDiscussionForm (&$Context) { $this->Name = 'saveDiscussionForm'; $this->Control($Context); } function Render () { $this->CallDelegate('PreRender'); //here I include moderation_form.php that is a copy of discussion_form.php include(dirname(__FILE__) . '/moderation_form.php'); $this->CallDelegate('PostRender'); } } some lines later.... // Instantiate data managers to be used in this page $saveDiscussionForm = $Context->ObjectFactory->NewContextObject($Context,"saveDiscussionForm"); then I add the control to the page $Page->AddRenderControl($saveDiscussionForm, $Configuration["CONTROL_POSITION_PANEL"] + 9); I guess that I've to tweak the discussion_form.php to display something but I was wondering If I could just take some part of it just with delegation... for example to render the category selector I could use the delegate DiscussionForm_PreCategoryRender? no? and how I will do that?
  • I did not dig into your specific problem, but wanted to add that, when it come to rendering some part, it's often simpler to create your own theme by copying a file or two and tweak those as needed. Use of delegate from theme files is not straightforward if you want to render something wich does not fit well in the current design.
    Theming does not break the core and is another customization tool beside delegation.
  • I see thx Max, but I need also the functionalities of the function savediscussion that are attached to that form so how I could use them? or the easiest way is just to make my own function copying from the library and modifying to suite my needs? I mean wich is the cleanest way? I thought that delegation and extending controls where the cleanest ways as said in the lussumo docs...
  • edited January 2007
    I think you are misunderstanding delegation. It serves as a point where you can insert code. You don't access the existing code with delegates, merely change variables or add your own bits of code to the existing code. Have a look at the extensions I listed here: . They add a field or control to a comment or discussion form, (one delegate to insert the controls, probably using a PreRender or PostRender) and do different things with that data (probably by using a Pre/PostSaveData delegate).
  • edited January 2007
    Oh yes there's a lot of misunderstanding... but hopefully the understanding will take place.... ;) and the delegate parameters? I can't access object and variables with that? Thx Wallphone for your help! :D the vote example should do it... it's kind of what I want to do... let's experiment! lol and see if I can do that mod tools extension ;)
  • Ok so to keep it simple: AddToDelegate for inject your code and DelegateParameters for access some of the objects and variables am I right?
  • DelegateParameters gives you access to local variables of the object that Mark thought might be useful for the delegate.
    You can also acces all the calling object properties ($callingObject->property). But no access to local variables not added to DelegateParameters.
  • Thx Max ;) but what you mean exactly for "But no access to local variables not added to DelegateParameters" did you mean "But no access to local variables added to DelegateParameters" maybe??
  • I mean just what I wrote, probably unclear...
    Given this code snip from DiscussionManager class: function GetDiscussionList($RowsPerPage, $CurrentPage, $CategoryID) { $CategoryID = ForceInt($CategoryID, 0); $TotalNumberOfRecords = 0; if ($RowsPerPage > 0) { $CurrentPage = ForceInt($CurrentPage, 1); if ($CurrentPage < 1) $CurrentPage == 1; $RowsPerPage = ForceInt($RowsPerPage, 50); $FirstRecord = ($CurrentPage * $RowsPerPage) - $RowsPerPage; } $s = $this->GetDiscussionBuilder(); $this->DelegateParameters["SqlBuilder"] = &$s; $this->CallDelegate('PreGetDiscussionList'); ...
    If you attach a function to the 'PreGetDiscussionList' delegate, you get the DiscussionManager object as a parameter. Then you can access this object properties. One of these is the array DelegateParameters. Trough this one you got the SqlBuilder object. But you can't acess $RowsPerPage or $CategoryID because these are local variables of the DiscussionManager object and were not added to the DelegateParameters array.
    There are a few case where this is a true limitation to extension writing.
    The ultimate tool in this case is to overload the class through the ObjectFactory paradigm.
    I did not use this last tool yet because Mark advice to keep it as a last resort.
  • ok, thx Max ;) for your clarificated explanation I get the point....
This discussion has been closed.