Skip to content

Instantly share code, notes, and snippets.

@andrewminton
Forked from brendo/EventTutorial.md
Created December 4, 2012 18:35
Show Gist options
  • Select an option

  • Save andrewminton/4207276 to your computer and use it in GitHub Desktop.

Select an option

Save andrewminton/4207276 to your computer and use it in GitHub Desktop.

Revisions

  1. @brendo brendo revised this gist May 16, 2011. 2 changed files with 5 additions and 5 deletions.
    8 changes: 4 additions & 4 deletions EventTutorial.md
    Original file line number Diff line number Diff line change
    @@ -35,13 +35,13 @@ Let's open up our Events in a text editor and take a look at something. There's

    Just before I made a right turn, we had created and attached two events and attached them to our page. We finished setting up our page XSL with one form containing all our fields with two actions. You'll pleasantly surprised that if you submit this form, a new entry will be created in the Cars and Dealers section. Victory!

    Or not quite... there is a couple of caveats here that I haven't mentioned. This worked well in this case because our field names were unique to each section, so there was no confusion as to what data should go where. In fact, if we had two name fields, the same input field would of populated both fields in either section. Depending on how you set up your section, you may of found that `Create Dealer` executed, even though there was an error with the other event, or vice versa, `Create Car` worked fine, `Create Dealer` did not.
    Or not quite... there is a couple of caveats here that I haven't mentioned. This worked well in this case because our field names were unique to each section, so there was no confusion as to what data should go where. In fact, if we had two name fields, the same input field would of populated both fields in either section. Depending on how you set up your section, you may have found that `Create Dealer` executed, even though there was an error with the other event, or vice versa, `Create Car` worked fine, `Create Dealer` did not.

    Let's tackle these one at a time.

    ### Unique field names

    Unique field names is never going to be a realistic situation for every project, so to prevent this from happening, lets prefix our fields by the event handle's `create-car` and `create-dealer`. So `<select name="fields[year]">` becomes `<select name="create-car[fields][year]">` or `<input name="fields[name]" type="text" />` becomes `<input name="create-dealer[fields][name]" type="text" />`.
    Unique field names are never going to be a realistic situation for every project, so to prevent this from happening, lets prefix our fields by the event handle's `create-car` and `create-dealer`. So `<select name="fields[year]">` becomes `<select name="create-car[fields][year]">` or `<input name="fields[name]" type="text" />` becomes `<input name="create-dealer[fields][name]" type="text" />`.

    There's another change we need to make now to our Event classes. Open these up in your text editor again (hey I did say we'd be getting dirty with some PHP ;) and find the `load` function and add `$this->post = $_POST;`:

    @@ -60,7 +60,7 @@ Now make your `__trigger()` function look like this:
    return $result;
    }

    What have we done? In the `load` function, we've saved a copy of the `$_POST` array to use later, remembering that `load` gets called for each event first, before execution, so every event will have a full copy of the `$_POST` array if it should be executed. If the `__trigger()` is called, we override the `$_POST['fields']` array with the fields that are specific to our current event. What is `self::ROOTELEMENT`? When your events are saved a `ROOTELEMENT` constant is created that is a handle of the event name. This is used by Symphony as the root node name when returning XML for your event. The benefit of using this constant is that if you change the name of your event, you only have to change it one location.
    What have we done? In the `load` function, we've saved a copy of the `$_POST` array to use later, remembering that `load` gets called for each event first, before execution, so every event will have a full copy of the `$_POST` array if it should be executed. If the `__trigger()` is called, we override the `$_POST['fields']` array with the fields that are specific to our current event. What is `self::ROOTELEMENT`? When your events are saved, a `ROOTELEMENT` constant is created as a handle of the event name. This is used by Symphony as the root node name when returning XML for your event. The benefit of using this constant is that if you change the name of your event, you only have to change it in one location.

    While we're at it, change the return value of each event's `allowEditorToParse` function to be `false`, instead of `true`, this will prevent you (or another developer) from overriding your changes should they try to resave the Event from the Symphony backend.

    @@ -135,7 +135,7 @@ In the attached [XSL](https://gist.github.com/raw/901476/new-car.xsl), I've gone

    ## Wrap up

    Well I hope that has been helpful and given you a little bit of insight into some of the more mysterious aspects of Events. If this all seems a little too difficult, I suggest checking out the [Event Ex](http://symphony-cms.com/download/extensions/view/22125/) extension, it quite old, but is maintained by Nick Dunn, who also happens to like juggling fire in his spare time.
    Well I hope that has been helpful and given you a little bit of insight into some of the more mysterious aspects of Events. If this all seems a little too difficult, I suggest checking out the [Event Ex](http://symphony-cms.com/download/extensions/view/22125/) extension, it's quite old, but is maintained by Nick Dunn, who also happens to like juggling fire in his spare time.

    ## But hey, what about Custom Events!?

    2 changes: 1 addition & 1 deletion increment-trigger.php
    Original file line number Diff line number Diff line change
    @@ -83,7 +83,7 @@ protected function __trigger(){
    }
    // If something goes wrong, lets save the Exception to the Email Response
    catch(EmailException $ex) {
    $email_send = false;
    $email_sent = false;
    $entry->setData(
    $email_response_field->get('id'),
    $email_response_field->processRawFieldData($ex->getMessage(), $status)
  2. @brendo brendo revised this gist May 16, 2011. 1 changed file with 4 additions and 6 deletions.
    10 changes: 4 additions & 6 deletions EventTutorial.md
    Original file line number Diff line number Diff line change
    @@ -1,12 +1,12 @@
    Forms have been an integral part of any interactive site since the dawn of time, they promote interactivity and is usually the most common way users interact with a site. It's commonplace that when a form is submitted, the website will take 'action' and do something with the data and then provide a user with the result. Symphony provides this logic layer via Events.
    Forms have been an integral part of any interactive site since the dawn of time, they promote interactivity and are usually the most common way users interact with a site. It's commonplace that when a form is submitted, the website will take 'action' and do something with the data and then provide a user with the result. Symphony provides this logic layer via Events.

    This tutorial assumes you have a basic understanding of how Events work in Symphony (if not, [this may be a good introduction](http://symphony-cms.com/learn/concepts/view/events/)) and are semi comfortable writing some PHP code. I'll be showing you some of the lesser known features of Symphony Events, including Priority, Event Chaining and a brief demonstration of how to write a custom Event. The difficulty level progresses as we go through, but with any luck you'll be able to learn a thing or two :)
    This tutorial assumes you have a basic understanding of how Events work in Symphony (if not, [this may be a good introduction](http://symphony-cms.com/learn/concepts/view/events/)) and are semi comfortable writing some PHP code. I'll be showing you some of the lesser known features of Symphony Events, including event priority, event chaining and a brief demonstration of how to write a custom Event. The difficulty level progresses as we go through, but with any luck you'll be able to learn a thing or two :)

    ### Getting Started

    ## The Scenario

    Lets say our client requires a form that allows a user to submit some details about their new car purchase. The information is particular to the car, but there's a couple of questions about where they purchased it from, so the data needs to post to two sections in Symphony, Car and Dealers.
    Our client requires a form that allows a user to submit some details about their new car purchase. The information is particular to the car, but there's a couple of questions about where they purchased it from, so the data needs to post to two sections in Symphony, Car and Dealers.

    ## Setup

    @@ -25,9 +25,7 @@ Name | Text Input
    Suburb | Text Input
    </pre>

    Now let's create two events, one for each section. I've called mine `Create Car` and `Create Dealer`. We'll next create a page (I've called mine 'New Car') and attach our two events to this page. To get us up and running quickly, lets copy the example form markup from the `Create Car` event into our . This now allows us to create a new Car in the Cars section, but we want to be able to create a new Dealer entry from the same form, so lets copy the field markup from the 'Create Dealer' event and we'll paste it just above the current submit button. Instead of having two 'submit' buttons, lets change the `Create Dealer` submit to be a hidden input field instead. This will just leave one Submit button, but to our Events, there is actually two triggers on this page.

    This is my [page XSL](https://gist.github.com/raw/901476/new-car.xsl), I've included some additional templates and markup to output the result of our event to make things a little clearer.
    Now let's create two events, one for each section. I've called mine `Create Car` and `Create Dealer`. We'll next create a page (I've called mine 'New Car') and attach our two events to this page. To get us up and running quickly, lets copy the example form markup from the `Create Car` event into our page XSL. This example form markup now allows us to create a new Car in the Cars section when a user submits the form, but we also want to be able to create a new Dealer entry from the same form so the experience is seamless. To do this, lets copy the field markup from the 'Create Dealer' event and paste it just above the current submit button. Instead of having two 'submit' buttons, lets change the `Create Dealer` submit to be a hidden input field instead. This will just leave one Submit button, but to our Events, there is actually two triggers on this page.

    ## A detour, a short note on `load` and `__trigger`

  3. @brendo brendo revised this gist May 13, 2011. 1 changed file with 4 additions and 4 deletions.
    8 changes: 4 additions & 4 deletions increment-trigger.php
    Original file line number Diff line number Diff line change
    @@ -56,7 +56,7 @@ protected function __trigger(){
    );

    // 3. If `count` now equals our `max`, send email an email
    if($current_count == $max_count) {
    if($new_count == $max_count) {
    // Get our Email field ID (readonly)
    $email_field_id = $field_manager->fetchFieldIDFromElementName('email');
    // Get our Email Response Field (writing)
    @@ -76,8 +76,8 @@ protected function __trigger(){
    $entry_data[$email_field_id]['value']
    );

    $email->text_plain = 'Surprise, our counter reached 10, now you can dance!';
    $email->subject = 'Our Counter reached 10!';
    $email->text_plain = 'Surprise, our counter reached ' . $new_count . ', now you can dance!';
    $email->subject = 'Our Counter reached ' . $new_count . '!';

    $email->send();
    }
    @@ -103,7 +103,7 @@ protected function __trigger(){
    if($entry->commit()) {
    $result->setAttribute('result', 'success');
    $result->appendChild(new XMLElement(
    'message', 'Count is at ' . $current_count
    'message', 'Count is at ' . $new_count
    ));
    }
    else {
  4. @brendo brendo revised this gist May 13, 2011. 1 changed file with 3 additions and 1 deletion.
    4 changes: 3 additions & 1 deletion increment-trigger.php
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,4 @@
    <?php
    protected function __trigger(){
    $result = new XMLElement(self::ROOTELEMENT);
    $entry_manager = new EntryManager(Symphony::Engine());
    @@ -111,4 +112,5 @@ protected function __trigger(){

    // This line is essential for the Event XML to appear in your `?debug`
    return $result;
    }
    }
    ?>
  5. @brendo brendo revised this gist May 13, 2011. 2 changed files with 127 additions and 5 deletions.
    18 changes: 13 additions & 5 deletions EventTutorial.md
    Original file line number Diff line number Diff line change
    @@ -165,6 +165,8 @@ I've added one entry, setting the count to 1, max to 10, added my email address
    <input name="action[increment]" type="submit" value="Submit" />
    </form>

    ### Our custom Increment event

    Now we'll jump to our `eventincrement` Class (inside `workspace/events/event.increment.php`). First things first, set the `allowEditorToParse` function to return `false`, then move to the `__trigger()` function and remove the `include` and we'll set the `$result` to be an empty `XMLElement` instance:

    protected function __trigger(){
    @@ -173,14 +175,20 @@ Now we'll jump to our `eventincrement` Class (inside `workspace/events/event.inc
    return $result;
    }

    If you click our Submit button, you should get an empty response in our Event XML, `<increment />`.
    If you click our Submit button, you should get an empty response in our Event XML, `<increment />`. Happy? Didn't think so. I've attached [the `__trigger()` function](https://gist.github.com/raw/901476/increment-trigger.php) with comments to guide you through the rest of the custom event. There's a couple of big omissions here, such as ensuring user input is [sanitized](https://github.com/symphonycms/xssfilter) and checking that the [data is correct](http://symphony-cms.com/learn/api/2.2.1/toolkit/field/#checkPostFieldData) which will need to be covered in a later tutorial, but hopefully this gives you a general idea of creating a custom event which involves reading an Entry's current data, updating Entry data and displaying a result to a user.

    One last touch, remember how we removed set `allowEditorToParse` to `false`? This will now show the Event's `documentation()` return value when you click on the Event in the backend. By default, Symphony generates this documentation to the default form needed to populate the fields of the Event and may include some additional information about the filters attached to your event. Because our event is custom, this information is irrelevant and it's considered best practice for you to update this to be a little more descriptive. It's helpful to your future self, who jumps back onto the project in 6 months and can't quite remember how the event works, and to whoever else may use your event (particularly if it's part of an Extension). The `documentation()` function returns either a string of HTML, or a `XMLElement` object

    **BLAH BLAH COMPLETE THIS**
    ## And that's that!

    That's the end of this long tutorial folks, hopefully that gives you a little more insight into Events and has given you some ideas about how you can use them to deliver a rich, interactive experience on your Symphony website.

    ## References
    ### References

    * [Event Concept](http://symphony-cms.com/learn/concepts/view/events/)
    * [Event API Documentation](http://symphony-cms.com/learn/api/2.2.1/toolkit/event/)
    * [Event Ex](http://symphony-cms.com/download/extensions/view/22125/)
    * [Event API](http://symphony-cms.com/learn/api/2.2.1/toolkit/event/)
    * [Field API](http://symphony-cms.com/learn/api/2.2.1/toolkit/field/)
    * [Entry API](http://symphony-cms.com/learn/api/2.2.1/toolkit/entry/)
    * [EntryManager API](http://symphony-cms.com/learn/api/2.2.1/toolkit/entrymanager/)
    * [Event Ex extension](http://symphony-cms.com/download/extensions/view/22125/)

    114 changes: 114 additions & 0 deletions increment-trigger.php
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,114 @@
    protected function __trigger(){
    $result = new XMLElement(self::ROOTELEMENT);
    $entry_manager = new EntryManager(Symphony::Engine());
    $field_manager = $entry_manager->fieldManager;
    $status = Field::__OK__;

    // Check that we have an `$entry_id` set otherwise fail
    $entry_id = (is_numeric($_POST['id'])) ? $_POST['id'] : null;
    if(is_null($entry_id)) {
    $result->setAttribute('result', 'error');
    $result->appendChild(new XMLElement(
    'message', 'No Entry ID specified'
    ));
    return $result;
    }

    // Retrieve our current Entry using the EntryManager
    // EntryManager returns an array of entries, so we'll want the first
    // one using `current()`.
    $entry = $entry_manager->fetch($entry_id);
    $entry = current($entry);

    // Get all the entry's data, which is an associative array of field ID => data
    $entry_data = $entry->getData();

    // Get a Field instance for the `count` field as we need to add data to it
    $count_field = $field_manager->fetch(
    $field_manager->fetchFieldIDFromElementName('count')
    );
    // We are using the `max` for readonly work, so just get the Field ID
    $max_field_id = $field_manager->fetchFieldIDFromElementName('max');

    // Get the current entry data
    $current_count = $entry_data[$count_field->get('id')]['value'];
    $max_count = $entry_data[$max_field_id]['value'];

    // 1. Check that `count` is less than our `max`, otherwise return
    if($current_count >= $max_count) {
    $result->setAttribute('result', 'error');
    $result->appendChild(new XMLElement(
    'message', 'Count has reached it\'s max'
    ));
    return $result;
    }

    // 2. If `count` is less, increment `count` by 1
    $new_count = $current_count + 1;
    $entry->setData(
    $count_field->get('id'),
    // I'm deliberately ignoring the `$status` result here for simplicity
    // and just assuming everything will be ok. This means that if your
    // data is coming from the user you should be running it against
    // `Field->checkPostFieldData` first
    $count_field->processRawFieldData($new_count, $status)
    );

    // 3. If `count` now equals our `max`, send email an email
    if($current_count == $max_count) {
    // Get our Email field ID (readonly)
    $email_field_id = $field_manager->fetchFieldIDFromElementName('email');
    // Get our Email Response Field (writing)
    $email_response_field = $field_manager->fetch(
    $field_manager->fetchFieldIDFromElementName('email-response')
    );

    // Create our Email instance from the Core Email API
    $email = Email::create();
    $email_sent = true;

    // Try to send our email
    // For more Core Email API information, check michael-e's guide
    // https://github.com/michael-e/core-email-api-docs/blob/master/developer-documentation.markdown
    try{
    $email->recipients = array(
    $entry_data[$email_field_id]['value']
    );

    $email->text_plain = 'Surprise, our counter reached 10, now you can dance!';
    $email->subject = 'Our Counter reached 10!';

    $email->send();
    }
    // If something goes wrong, lets save the Exception to the Email Response
    catch(EmailException $ex) {
    $email_send = false;
    $entry->setData(
    $email_response_field->get('id'),
    $email_response_field->processRawFieldData($ex->getMessage(), $status)
    );
    }

    // Everything went swell, save 'Email sent' to our Email Response field
    if($email_sent) {
    $entry->setData(
    $email_response_field->get('id'),
    $email_response_field->processRawFieldData('Email sent', $status)
    );
    }
    }

    // Update our Entry record, again keeping this very simple and not checking for errors
    if($entry->commit()) {
    $result->setAttribute('result', 'success');
    $result->appendChild(new XMLElement(
    'message', 'Count is at ' . $current_count
    ));
    }
    else {
    $result->setAttribute('result', 'error');
    }

    // This line is essential for the Event XML to appear in your `?debug`
    return $result;
    }
  6. @brendo brendo revised this gist May 12, 2011. 1 changed file with 44 additions and 2 deletions.
    46 changes: 44 additions & 2 deletions EventTutorial.md
    Original file line number Diff line number Diff line change
    @@ -133,12 +133,54 @@ In my example, both events were successful, but if something went wrong...
    </post-values>
    </create-dealer>

    I hope that helps
    In the attached [XSL](https://gist.github.com/raw/901476/new-car.xsl), I've gone with the approach that if the Create Car event is successful, it will display a summary to the user when an error occurs in the Create Dealer event, but with the Event XML it's possible to customise your frontend with XSLT to do whatever you like really.

    **blah blah todo finish this**
    ## Wrap up

    Well I hope that has been helpful and given you a little bit of insight into some of the more mysterious aspects of Events. If this all seems a little too difficult, I suggest checking out the [Event Ex](http://symphony-cms.com/download/extensions/view/22125/) extension, it quite old, but is maintained by Nick Dunn, who also happens to like juggling fire in his spare time.

    ## But hey, what about Custom Events!?

    The beauty of Symphony events is that they are really just a block of PHP that is called before your page renders, so it's possible to do almost anything your heart desires. To keep things simple, lets assume the following scenario. I have a button that upon each click, increments a Field's value one by one until it reaches 10. When it hits 10, we'll send an email to someone to let them know that this has happened. For tutorial purposes, we'll write this as a completely custom event.

    ### Setup

    Here's my test section

    Counter
    <pre>
    Count : Text Input
    Max : Text Input
    Email : Text Input
    Email Response : Text Input
    </pre>

    I've added one entry, setting the count to 1, max to 10, added my email address and left the Email Response empty. I've also created a new event, called Increment, and a new page with the following form XSL, where `213` is the entry ID of entry with my information in it

    <form method="post">
    <label>Count
    <input name="fields[count]" type="text" />
    </label>
    <input type="hidden" name="id" value="213" />
    <input name="action[increment]" type="submit" value="Submit" />
    </form>

    Now we'll jump to our `eventincrement` Class (inside `workspace/events/event.increment.php`). First things first, set the `allowEditorToParse` function to return `false`, then move to the `__trigger()` function and remove the `include` and we'll set the `$result` to be an empty `XMLElement` instance:

    protected function __trigger(){
    $result = new XMLElement(self::ROOTELEMENT);

    return $result;
    }

    If you click our Submit button, you should get an empty response in our Event XML, `<increment />`.

    **BLAH BLAH COMPLETE THIS**


    ## References

    * [Event Concept](http://symphony-cms.com/learn/concepts/view/events/)
    * [Event API Documentation](http://symphony-cms.com/learn/api/2.2.1/toolkit/event/)
    * [Event Ex](http://symphony-cms.com/download/extensions/view/22125/)

  7. @brendo brendo revised this gist May 10, 2011. 1 changed file with 52 additions and 23 deletions.
    75 changes: 52 additions & 23 deletions new-car.xsl
    Original file line number Diff line number Diff line change
    @@ -9,44 +9,73 @@
    encoding="UTF-8"
    indent="yes" />

    <xsl:variable name='create-car' select='/data/events/create-car' />
    <xsl:variable name='create-dealer' select='/data/events/create-dealer' />

    <xsl:template match="/">
    <h1><xsl:value-of select="$page-title"/></h1>

    <form method="post">
    <fieldset>
    <legend>Car</legend>
    <label>Manufacturer
    <input name="fields[manufacturer]" type="text" />
    </label>
    <label>Make
    <input name="fields[make]" type="text" />
    </label>
    <label>Year
    <select name="fields[year]">
    <option value="2008">2008</option>
    <option value="2009">2009</option>
    <option value="2010">2010</option>
    <option value="2011">2011</option>
    </select>
    </label>
    </fieldset>
    <xsl:choose>
    <xsl:when test='$create-car[@result = "success"]'>
    <xsl:value-of select='$create-car/message' />
    <dl>
    <dt>Manufacturer</dt>
    <dd>
    <xsl:value-of select='$create-car/manufacturer' />
    </dd>
    <dt>Car - Model</dt>
    <dd>
    <xsl:value-of select='concat($create-car/post-values/car, " ", $create-car/post-values/year)' />
    </dd>
    </dl>
    </xsl:when>
    <xsl:otherwise>
    <fieldset>
    <legend>Car</legend>
    <label>Manufacturer
    <input name="create-car[fields][manufacturer]" type="text" />
    </label>
    <label>Make
    <input name="create-car[fields][name]" type="text" />
    </label>
    <label>Year
    <select name="create-car[fields][year]">
    <option value="2008">2008</option>
    <option value="2009">2009</option>
    <option value="2010">2010</option>
    <option value="2011">2011</option>
    </select>
    </label>
    </fieldset>
    </xsl:otherwise>
    </xsl:choose>

    <fieldset>
    <legend>Dealer</legend>
    <label>Name
    <input name="fields[name]" type="text" />
    <input name="create-dealer[fields][name]" type="text" value='{$create-dealer/post-values/name}' />
    </label>
    <label>Suburb
    <input name="fields[suburb]" type="text" />
    <input name="create-dealer[fields][suburb]" type="text" value='{$create-dealer/post-values/suburb}' />
    </label>
    <input name="action[create-dealer]" type="hidden" value="Submit" />
    <xsl:if test='$create-car[@result = "success"]'>
    <input type='hidden' name="create-dealer[fields][related-car]" value='{$create-car/@id}' />
    </xsl:if>
    </fieldset>

    <input name="action[create-car]" type="submit" value="Submit" />
    <xsl:choose>
    <xsl:when test='$create-car[@result = "success"] and $create-dealer[@result != "success"]'>
    <input name="action[create-dealer]" type="submit" value="Submit" />
    </xsl:when>
    <xsl:otherwise>
    <input name="action[create-car]" type="submit" value="Submit" />
    </xsl:otherwise>
    </xsl:choose>
    </form>

    <xsl:apply-templates select='data/events/create-car' mode='event' />
    <xsl:apply-templates select='data/events/create-dealer' mode='event' />
    <xsl:apply-templates select='$create-car' mode='event' />
    <xsl:apply-templates select='$create-dealer' mode='event' />
    </xsl:template>

    <xsl:template match='*' mode='event'>
  8. @brendo brendo revised this gist May 10, 2011. 1 changed file with 2 additions and 7 deletions.
    9 changes: 2 additions & 7 deletions EventTutorial.md
    Original file line number Diff line number Diff line change
    @@ -49,12 +49,7 @@ There's another change we need to make now to our Event classes. Open these up i

    public function load(){
    $this->post = $_POST;
    if(isset($_POST['action']['create-car'])) return $this->__trigger();
    }

    public function load(){
    $this->post = $_POST;
    if(isset($_POST['action']['create-dealer'])) return $this->__trigger();
    if(isset($_POST['action'][self::ROOTELEMENT])) return $this->__trigger();
    }

    Now make your `__trigger()` function look like this:
    @@ -67,7 +62,7 @@ Now make your `__trigger()` function look like this:
    return $result;
    }

    What have we done? In the `load` function, we've saved a copy of the `$_POST` array to use later, remembering that `load` gets called for each event first, before execution, so every event will have a full copy of the `$_POST` array if it should be executed. If the `__trigger()` is called, we override the `$_POST['fields']` array with the fields that are specific to our current event.
    What have we done? In the `load` function, we've saved a copy of the `$_POST` array to use later, remembering that `load` gets called for each event first, before execution, so every event will have a full copy of the `$_POST` array if it should be executed. If the `__trigger()` is called, we override the `$_POST['fields']` array with the fields that are specific to our current event. What is `self::ROOTELEMENT`? When your events are saved a `ROOTELEMENT` constant is created that is a handle of the event name. This is used by Symphony as the root node name when returning XML for your event. The benefit of using this constant is that if you change the name of your event, you only have to change it one location.

    While we're at it, change the return value of each event's `allowEditorToParse` function to be `false`, instead of `true`, this will prevent you (or another developer) from overriding your changes should they try to resave the Event from the Symphony backend.

  9. @brendo brendo revised this gist May 10, 2011. 1 changed file with 62 additions and 12 deletions.
    74 changes: 62 additions & 12 deletions EventTutorial.md
    Original file line number Diff line number Diff line change
    @@ -37,7 +37,7 @@ Let's open up our Events in a text editor and take a look at something. There's

    Just before I made a right turn, we had created and attached two events and attached them to our page. We finished setting up our page XSL with one form containing all our fields with two actions. You'll pleasantly surprised that if you submit this form, a new entry will be created in the Cars and Dealers section. Victory!

    Or not quite.There's a couple of caveats here that I haven't mentioned. This worked well in this case because our field names were unique to each section, so there was no confusion as to what data should go where. In fact, if we had two name fields, the same input field would of populated both fields in either section. Depending on how you set up your section, you may of found that `Create Dealer` executed, even though there was an error with the other event, or vice versa, `Create Car` worked fine, `Create Dealer` did not.
    Or not quite... there is a couple of caveats here that I haven't mentioned. This worked well in this case because our field names were unique to each section, so there was no confusion as to what data should go where. In fact, if we had two name fields, the same input field would of populated both fields in either section. Depending on how you set up your section, you may of found that `Create Dealer` executed, even though there was an error with the other event, or vice versa, `Create Car` worked fine, `Create Dealer` did not.

    Let's tackle these one at a time.

    @@ -75,25 +75,75 @@ First limit solved, you can now have the same field names across multiple sectio

    ### I only want 'y' to execute if 'x' was successful!

    tbc.

    The other, while not important at the moment, is the order that the events are executed. All events have `priority`, which is a crude system of low, normal and high which determines what order events should be triggered. By default, all events are given the normal priority, and then are executed in alphabetical order. For the next part of this tutorial, let's add a Select Box Link field to our Dealers section called Related Cars and link it to the Cars: Make field.

    What we now want to happen is that when a user creates a Car and Dealer entry, that the Car entry is linked to the Dealer. Let's change the priority of the events to ensure that it will always fire in the correct order. This is really for tutorial purposes, as in this case, Create Dealer is alphabetically after Create Car, so will always be called after the Create Car event. Open up the Create Car event in your text editor and add:
    What we now want to happen is that when a user creates a Car and Dealer entry, that the Car entry is linked to the Dealer. Let's change the priority of the events to ensure that it will always fire in the correct order. This is really for tutorial purposes, as in this case, Create Dealer is alphabetically after Create Car, so will always be called after the Create Car event, but nevertheless, open up the Create Car event in your text editor and add the following:

    public function priority(){
    return self::kHIGH;
    }

    This current workflow always assumes that the Car entry is created successfully which isn't always the case. Users may enter some incorrect information which causes the entry not to save and instead the event will have some error information to show the user. In this case, we want the event to return before it even tries to create the Dealer entry. To do this, lets start by removing the hidden input field for the Create Dealer event for our form (`<input name="action[create-dealer]" type="hidden" value="Submit" />`). Just before the `return $result` of the Create Car event, lets check the status of the event by looking at the event XML result, what we are looking for is a status of 'success' and if so we want to replicate our hidden field in the `$_POST` data so the Create Dealer event will fire. The Select Box Link uses the Entry ID to maintain the link, so let's add the new Car's entry id into the `$_POST` array for the Create Dealer event, so our new Dealer entry will have a relationship.

    // Check that this event returned successfully, if it did,
    // inject the Create Dealer event and Car's entry ID
    if($result->getAttribute('result') == "success") {
    $_POST['action']['create-dealer'] = 'Submit';
    $_POST['create-dealer']['fields']['related-car'] = $result->getAttribute('id');
    }

    return $result;

    Tada! We now have two events chained together, with the second event only executing when the first one was successful.

    ### Executing 'y' only

    There is another case in that the Create Car event worked correctly, but the Create Dealer event did not. There's two different approaches you could employ here, both are based in XSLT and fortunately not in PHP. Our first option is to redisplay the entire form (including the Create Car) fields and instead add the ID of the Create Car entry as a hidden field. This will make the Event edit the entry, instead of creating a new one. It's a useful approach if you want users to have a second chance at updating the information. The second option is to not display any of the fields relating to the Create Car event, and instead just display those fields relating to the Create Dealer event.

    Symphony makes it easy to auto populate your forms with this information as it provides `post-values` in the Event response XML.

    `insert priority code`
    <create-car id="205" result="success" type="created">
    <message>Entry created successfully.</message>
    <post-values>
    <manufacturer>Nissan</manufacturer>
    <name>Pulsar</name>
    <year>2008</year>
    </post-values>
    </create-car>
    <create-dealer id="206" result="success" type="created">
    <message>Entry created successfully.</message>
    <post-values>
    <name>Tom Jones</name>
    <suburb>Burleigh Heads</suburb>
    <related-car>205</related-car>
    </post-values>
    </create-dealer>

    This current flow always assumes that the Car is entered successfully, this is something we'll need to change as we only want the Dealer entry to be created should the Car entry be saved successfully. To do this, lets start by removing the hidden input field for our form. Just before the `return $result` of the Create Car event, lets check the status of the event by looking at the event XML result, what we are looking for is a status of 'success' and if so, we want the newly created Entry ID. The SBL uses the Entry ID to maintain the link, so let's create it in the `$_POST` array for the Create Dealer event.
    In my example, both events were successful, but if something went wrong...

    `insert code for checking the result`
    <create-car id="208" result="success" type="created">
    <message>Entry created successfully.</message>
    <post-values>
    <manufacturer>Nissan</manufacturer>
    <name>Pulsar</name>
    <year>2008</year>
    </post-values>
    </create-car>
    <create-dealer result="error">
    <message>Entry encountered errors when saving.</message>
    <suburb label="Suburb" type="missing" message="'Suburb' is a required field." />
    <post-values>
    <name>Tom Jones</name>
    <related-car>208</related-car>
    </post-values>
    </create-dealer>

    `$_POST['create-dealer']['fields']['related-car'] = $id;`
    I hope that helps

    Now we'll also add our trigger back in so that the Create Dealer event runs:
    **blah blah todo finish this**

    `$_POST['action']['create-dealer'] = true;`

    Tada! We now have two events chained together
    ## References

    blah blah finish this.
    * [Event API Documentation](http://symphony-cms.com/learn/api/2.2.1/toolkit/event/)

  10. @brendo brendo revised this gist Apr 13, 2011. 2 changed files with 81 additions and 31 deletions.
    62 changes: 49 additions & 13 deletions EventTutorial.md
    Original file line number Diff line number Diff line change
    @@ -2,13 +2,14 @@ Forms have been an integral part of any interactive site since the dawn of time,

    This tutorial assumes you have a basic understanding of how Events work in Symphony (if not, [this may be a good introduction](http://symphony-cms.com/learn/concepts/view/events/)) and are semi comfortable writing some PHP code. I'll be showing you some of the lesser known features of Symphony Events, including Priority, Event Chaining and a brief demonstration of how to write a custom Event. The difficulty level progresses as we go through, but with any luck you'll be able to learn a thing or two :)


    ### Getting Started

    ## The Scenario

    Lets say our client requires a form that allows a user to submit some details about their new car purchase. The information is particular to the car, but there's a couple of questions about where they purchased it from, so the data needs to post to two sections in Symphony, Car and Dealers.

    ## Setup

    I've created the following test sections, kept really simple for the purposes of this tutorial.

    Cars
    @@ -24,31 +25,67 @@ Name | Text Input
    Suburb | Text Input
    </pre>

    Now let's create two events, one for each section. I've called mine 'Create Car' and 'Create Dealer'. We'll next create a page (I've called mine 'New Car') and attach our two events to this page. To get us up and running quickly, lets copy the example form markup from the 'Create Car' event into our page XSL
    Now let's create two events, one for each section. I've called mine `Create Car` and `Create Dealer`. We'll next create a page (I've called mine 'New Car') and attach our two events to this page. To get us up and running quickly, lets copy the example form markup from the `Create Car` event into our . This now allows us to create a new Car in the Cars section, but we want to be able to create a new Dealer entry from the same form, so lets copy the field markup from the 'Create Dealer' event and we'll paste it just above the current submit button. Instead of having two 'submit' buttons, lets change the `Create Dealer` submit to be a hidden input field instead. This will just leave one Submit button, but to our Events, there is actually two triggers on this page.

    This is my [page XSL](https://gist.github.com/raw/901476/new-car.xsl), I've included some additional templates and markup to output the result of our event to make things a little clearer.

    ## A detour, a short note on `load` and `__trigger`

    Let's open up our Events in a text editor and take a look at something. There's two functions are important here, `load` and `__trigger`. The `load` function acts as a condition, it runs on every page load that the event is attached to and checks to see if it should call the `__trigger` function, which is where the actual event logic takes place. For all Symphony's default events, this `load` checks that the action exists (eg. `isset($_POST['action']['create-car'])`), and if it does, it proceeds to call the `__trigger` function. This opens up a number of possibilities for a developer as your events don't necessarily have to be triggered by a form submit. For instance you could check if a particular value was in the `$_SESSION` array and then do `x`, or if the user came from a specific IP address range redirect them to a particular domain, perhaps for localisation.

    ## Back on the road

    Just before I made a right turn, we had created and attached two events and attached them to our page. We finished setting up our page XSL with one form containing all our fields with two actions. You'll pleasantly surprised that if you submit this form, a new entry will be created in the Cars and Dealers section. Victory!

    Or not quite.There's a couple of caveats here that I haven't mentioned. This worked well in this case because our field names were unique to each section, so there was no confusion as to what data should go where. In fact, if we had two name fields, the same input field would of populated both fields in either section. Depending on how you set up your section, you may of found that `Create Dealer` executed, even though there was an error with the other event, or vice versa, `Create Car` worked fine, `Create Dealer` did not.

    Let's tackle these one at a time.

    This now allow us to create a new Car in the Cars section. Now we want the user to be able to add the Dealer as well during the same event, so lets copy the field markup from the 'Create Dealer' event and we'll paste it just above the current submit button.
    ### Unique field names

    Instead of having two 'submit' buttons, lets change it to be a hidden field instead. This will just leave one Submit button, but to our Events, they're is actually two triggers here.
    Unique field names is never going to be a realistic situation for every project, so to prevent this from happening, lets prefix our fields by the event handle's `create-car` and `create-dealer`. So `<select name="fields[year]">` becomes `<select name="create-car[fields][year]">` or `<input name="fields[name]" type="text" />` becomes `<input name="create-dealer[fields][name]" type="text" />`.

    Let's open up our Events in a text editor and take a look at something. There's two functions are important here, `load` and `trigger`. The `load` function acts as a condition, it runs on every page load that the event is attached too and checks to see if it should call the `trigger` function, which is where the actual event logic takes place. For all Symphony's default events, this `load` checks that the action exists, and if it does, it proceeds to call the `trigger` function.
    There's another change we need to make now to our Event classes. Open these up in your text editor again (hey I did say we'd be getting dirty with some PHP ;) and find the `load` function and add `$this->post = $_POST;`:

    This opens up a number of possibilities for a developer, for instance you could check if a particular value was in the `$_SESSION` array, or if the user came from a specific IP address range, redirect them to a particular domain.
    public function load(){
    $this->post = $_POST;
    if(isset($_POST['action']['create-car'])) return $this->__trigger();
    }

    At the moment, we have one form, with two actions, and one set of fields, and you'll pleasantly surprised that if you submit this form, a new entry will be created in the Cars and Dealers section!
    public function load(){
    $this->post = $_POST;
    if(isset($_POST['action']['create-dealer'])) return $this->__trigger();
    }

    There's a couple of caveats here that I haven't mentioned. This worked well in this case because our field names were unique to each section, so there was no confusion as to what data should go where. In fact, if we had two name fields, the same input field would of populated both fields in either section.

    To prevent this from happening, lets prefix the fields by the event handle's `create-car` and `create-dealer`. To make this work again, we need to make a slight adjust to our event code. Inside the `trigger` function, there's a line that assigns `$_POST['fields']` to `$fields`. Change this to be `$fields = $_POST['create-car']['fields'];`. Ta da, our events work again.
    Now make your `__trigger()` function look like this:

    protected function __trigger(){
    unset($_POST['fields']);
    $_POST['fields'] = $this->post[self::ROOTELEMENT]['fields'];

    include(TOOLKIT . '/events/event.section.php');
    return $result;
    }

    What have we done? In the `load` function, we've saved a copy of the `$_POST` array to use later, remembering that `load` gets called for each event first, before execution, so every event will have a full copy of the `$_POST` array if it should be executed. If the `__trigger()` is called, we override the `$_POST['fields']` array with the fields that are specific to our current event.

    While we're at it, change the return value of each event's `allowEditorToParse` function to be `false`, instead of `true`, this will prevent you (or another developer) from overriding your changes should they try to resave the Event from the Symphony backend.

    First limit solved, you can now have the same field names across multiple sections and they will be added to their relevant section.

    ### I only want 'y' to execute if 'x' was successful!

    tbc.

    The other, while not important at the moment, is the order that the events are executed. All events have `priority`, which is a crude system of low, normal and high which determines what order events should be triggered. By default, all events are given the normal priority, and then are executed in alphabetical order. For the next part of this tutorial, let's add a Select Box Link field to our Dealers section called Related Cars and link it to the Cars: Make field.

    What we now want to happen is that when a user creates a Car and Dealer entry, that the Car entry is linked to the Dealer. Let's change the priority of the events to ensure that it will always fire in the correct order. This is really for tutorial purposes, as in this case, Create Dealer is alphabetically after Create Car, so will always be called after the Create Car event. Open up the Create Car event in your text editor and add:

    <insert priority code>
    `insert priority code`

    This current flow always assumes that the Car is entered successfully, this is something we'll need to change as we only want the Dealer entry to be created should the Car entry be saved successfully. To do this, lets start by removing the hidden input field for our form. Just before the `return $result` of the Create Car event, lets check the status of the event by looking at the event XML result, what we are looking for is a status of 'success' and if so, we want the newly created Entry ID. The SBL uses the Entry ID to maintain the link, so let's create it in the `$_POST` array for the Create Dealer event.

    <insert code for checking the result>
    `insert code for checking the result`

    `$_POST['create-dealer']['fields']['related-car'] = $id;`

    @@ -58,6 +95,5 @@ Now we'll also add our trigger back in so that the Create Dealer event runs:

    Tada! We now have two events chained together


    blah blah finish this.

    50 changes: 32 additions & 18 deletions new-car.xsl
    Original file line number Diff line number Diff line change
    @@ -13,26 +13,40 @@
    <h1><xsl:value-of select="$page-title"/></h1>

    <form method="post">
    <label>Manufacturer
    <input name="fields[manufacturer]" type="text" />
    </label>
    <label>Make
    <input name="fields[make]" type="text" />
    </label>
    <label>Year
    <select name="fields[year]">
    <option value="2008">2008</option>
    <option value="2009">2009</option>
    <option value="2010">2010</option>
    <option value="2011">2011</option>
    </select>
    </label>
    <input name="action[create-car]" type="submit" value="Submit" />
    <fieldset>
    <legend>Car</legend>
    <label>Manufacturer
    <input name="fields[manufacturer]" type="text" />
    </label>
    <label>Make
    <input name="fields[make]" type="text" />
    </label>
    <label>Year
    <select name="fields[year]">
    <option value="2008">2008</option>
    <option value="2009">2009</option>
    <option value="2010">2010</option>
    <option value="2011">2011</option>
    </select>
    </label>
    </fieldset>

    <fieldset>
    <legend>Dealer</legend>
    <label>Name
    <input name="fields[name]" type="text" />
    </label>
    <label>Suburb
    <input name="fields[suburb]" type="text" />
    </label>
    <input name="action[create-dealer]" type="hidden" value="Submit" />
    </fieldset>

    <input name="action[create-car]" type="submit" value="Submit" />
    </form>

    <div id='result'>
    <xsl:apply-templates select='data/events/create-car' mode='event' />
    </div>
    <xsl:apply-templates select='data/events/create-car' mode='event' />
    <xsl:apply-templates select='data/events/create-dealer' mode='event' />
    </xsl:template>

    <xsl:template match='*' mode='event'>
  11. @brendo brendo revised this gist Apr 13, 2011. 2 changed files with 64 additions and 4 deletions.
    5 changes: 1 addition & 4 deletions EventTutorial.md
    Original file line number Diff line number Diff line change
    @@ -24,10 +24,7 @@ Name | Text Input
    Suburb | Text Input
    </pre>


    Now let's create two events, one for each section. I've called mine 'Create Car' and 'Create Dealer'. We'll next create a page, and attach the two events to this page. To get us up and running quickly, lets copy the example form markup from the 'Create Car' event into our page XSL:

    <insert example>
    Now let's create two events, one for each section. I've called mine 'Create Car' and 'Create Dealer'. We'll next create a page (I've called mine 'New Car') and attach our two events to this page. To get us up and running quickly, lets copy the example form markup from the 'Create Car' event into our page XSL

    This now allow us to create a new Car in the Cars section. Now we want the user to be able to add the Dealer as well during the same event, so lets copy the field markup from the 'Create Dealer' event and we'll paste it just above the current submit button.

    63 changes: 63 additions & 0 deletions new-car.xsl
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,63 @@
    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet version="1.0"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="xml"
    doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
    doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
    omit-xml-declaration="yes"
    encoding="UTF-8"
    indent="yes" />

    <xsl:template match="/">
    <h1><xsl:value-of select="$page-title"/></h1>

    <form method="post">
    <label>Manufacturer
    <input name="fields[manufacturer]" type="text" />
    </label>
    <label>Make
    <input name="fields[make]" type="text" />
    </label>
    <label>Year
    <select name="fields[year]">
    <option value="2008">2008</option>
    <option value="2009">2009</option>
    <option value="2010">2010</option>
    <option value="2011">2011</option>
    </select>
    </label>
    <input name="action[create-car]" type="submit" value="Submit" />
    </form>

    <div id='result'>
    <xsl:apply-templates select='data/events/create-car' mode='event' />
    </div>
    </xsl:template>

    <xsl:template match='*' mode='event'>
    <div>
    <h3>
    <xsl:value-of select='local-name(.)' />
    <xsl:choose>
    <xsl:when test='@result = "error"'>
    <span style='color:red'> error</span>
    </xsl:when>
    <xsl:otherwise>
    <span style='color:green'> success</span>
    </xsl:otherwise>
    </xsl:choose>
    </h3>

    <xsl:copy-of select='message' />
    <ul>
    <xsl:apply-templates select='*[@message]' />
    </ul>
    </div>
    </xsl:template>

    <xsl:template match='*[@message]'>
    <li><xsl:value-of select='@message' /></li>
    </xsl:template>

    </xsl:stylesheet>
  12. @brendo brendo revised this gist Apr 9, 2011. 1 changed file with 43 additions and 2 deletions.
    45 changes: 43 additions & 2 deletions EventTutorial.md
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,4 @@
    HTML Forms are an integral part of any interactive site since, well, the dawn of time. It's commonplace that when a form is submitted, the website will taken 'action' and do something with the data and then provide a user with the result. Symphony provides this logic layer via Events.
    Forms have been an integral part of any interactive site since the dawn of time, they promote interactivity and is usually the most common way users interact with a site. It's commonplace that when a form is submitted, the website will take 'action' and do something with the data and then provide a user with the result. Symphony provides this logic layer via Events.

    This tutorial assumes you have a basic understanding of how Events work in Symphony (if not, [this may be a good introduction](http://symphony-cms.com/learn/concepts/view/events/)) and are semi comfortable writing some PHP code. I'll be showing you some of the lesser known features of Symphony Events, including Priority, Event Chaining and a brief demonstration of how to write a custom Event. The difficulty level progresses as we go through, but with any luck you'll be able to learn a thing or two :)

    @@ -22,4 +22,45 @@ Dealers
    <pre>
    Name | Text Input
    Suburb | Text Input
    </pre>
    </pre>


    Now let's create two events, one for each section. I've called mine 'Create Car' and 'Create Dealer'. We'll next create a page, and attach the two events to this page. To get us up and running quickly, lets copy the example form markup from the 'Create Car' event into our page XSL:

    <insert example>

    This now allow us to create a new Car in the Cars section. Now we want the user to be able to add the Dealer as well during the same event, so lets copy the field markup from the 'Create Dealer' event and we'll paste it just above the current submit button.

    Instead of having two 'submit' buttons, lets change it to be a hidden field instead. This will just leave one Submit button, but to our Events, they're is actually two triggers here.

    Let's open up our Events in a text editor and take a look at something. There's two functions are important here, `load` and `trigger`. The `load` function acts as a condition, it runs on every page load that the event is attached too and checks to see if it should call the `trigger` function, which is where the actual event logic takes place. For all Symphony's default events, this `load` checks that the action exists, and if it does, it proceeds to call the `trigger` function.

    This opens up a number of possibilities for a developer, for instance you could check if a particular value was in the `$_SESSION` array, or if the user came from a specific IP address range, redirect them to a particular domain.

    At the moment, we have one form, with two actions, and one set of fields, and you'll pleasantly surprised that if you submit this form, a new entry will be created in the Cars and Dealers section!

    There's a couple of caveats here that I haven't mentioned. This worked well in this case because our field names were unique to each section, so there was no confusion as to what data should go where. In fact, if we had two name fields, the same input field would of populated both fields in either section.

    To prevent this from happening, lets prefix the fields by the event handle's `create-car` and `create-dealer`. To make this work again, we need to make a slight adjust to our event code. Inside the `trigger` function, there's a line that assigns `$_POST['fields']` to `$fields`. Change this to be `$fields = $_POST['create-car']['fields'];`. Ta da, our events work again.

    The other, while not important at the moment, is the order that the events are executed. All events have `priority`, which is a crude system of low, normal and high which determines what order events should be triggered. By default, all events are given the normal priority, and then are executed in alphabetical order. For the next part of this tutorial, let's add a Select Box Link field to our Dealers section called Related Cars and link it to the Cars: Make field.

    What we now want to happen is that when a user creates a Car and Dealer entry, that the Car entry is linked to the Dealer. Let's change the priority of the events to ensure that it will always fire in the correct order. This is really for tutorial purposes, as in this case, Create Dealer is alphabetically after Create Car, so will always be called after the Create Car event. Open up the Create Car event in your text editor and add:

    <insert priority code>

    This current flow always assumes that the Car is entered successfully, this is something we'll need to change as we only want the Dealer entry to be created should the Car entry be saved successfully. To do this, lets start by removing the hidden input field for our form. Just before the `return $result` of the Create Car event, lets check the status of the event by looking at the event XML result, what we are looking for is a status of 'success' and if so, we want the newly created Entry ID. The SBL uses the Entry ID to maintain the link, so let's create it in the `$_POST` array for the Create Dealer event.

    <insert code for checking the result>

    `$_POST['create-dealer']['fields']['related-car'] = $id;`

    Now we'll also add our trigger back in so that the Create Dealer event runs:

    `$_POST['action']['create-dealer'] = true;`

    Tada! We now have two events chained together


    blah blah finish this.

  13. @brendo brendo revised this gist Apr 5, 2011. 1 changed file with 11 additions and 9 deletions.
    20 changes: 11 additions & 9 deletions EventTutorial.md
    Original file line number Diff line number Diff line change
    @@ -11,13 +11,15 @@ Lets say our client requires a form that allows a user to submit some details ab

    I've created the following test sections, kept really simple for the purposes of this tutorial.

    Cars |
    -------------
    Make | Text Input
    Year Model | Select Box [2008-2011]
    Manufacturer | Text Input

    Dealers |
    -------------
    Cars
    <pre>
    Make : Text Input
    Year Model : Select Box [2008-2011]
    Manufacturer : Text Input
    </pre>

    Dealers
    <pre>
    Name | Text Input
    Suburb | Text Input
    Suburb | Text Input
    </pre>
  14. @brendo brendo revised this gist Apr 5, 2011. 1 changed file with 16 additions and 0 deletions.
    16 changes: 16 additions & 0 deletions EventTutorial.md
    Original file line number Diff line number Diff line change
    @@ -5,3 +5,19 @@ This tutorial assumes you have a basic understanding of how Events work in Symph

    ### Getting Started

    ## The Scenario

    Lets say our client requires a form that allows a user to submit some details about their new car purchase. The information is particular to the car, but there's a couple of questions about where they purchased it from, so the data needs to post to two sections in Symphony, Car and Dealers.

    I've created the following test sections, kept really simple for the purposes of this tutorial.

    Cars |
    -------------
    Make | Text Input
    Year Model | Select Box [2008-2011]
    Manufacturer | Text Input

    Dealers |
    -------------
    Name | Text Input
    Suburb | Text Input
  15. @brendo brendo revised this gist Apr 4, 2011. 1 changed file with 5 additions and 1 deletion.
    6 changes: 5 additions & 1 deletion EventTutorial.md
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,7 @@
    HTML Forms are an integral part of any interactive site since, well, the dawn of time. It's commonplace that when a form is submitted, the website will taken 'action' and do something with the data and then provide a user with the result. Symphony provides this logic layer via Events.

    This tutorial assumes you have a basic understanding of how Events work in Symphony (if not, this may be a good introduction) and are semi comfortable writing some PHP code. I'll be showing you some of the lesser known features of Symphony Events, including Priority, Event Chaining and a brief demonstration of how to write a custom Event. The difficulty level progresses as we go through, but with any luck you'll be able to learn a thing or two :)
    This tutorial assumes you have a basic understanding of how Events work in Symphony (if not, [this may be a good introduction](http://symphony-cms.com/learn/concepts/view/events/)) and are semi comfortable writing some PHP code. I'll be showing you some of the lesser known features of Symphony Events, including Priority, Event Chaining and a brief demonstration of how to write a custom Event. The difficulty level progresses as we go through, but with any luck you'll be able to learn a thing or two :)


    ### Getting Started

  16. @brendo brendo created this gist Apr 4, 2011.
    3 changes: 3 additions & 0 deletions EventTutorial.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,3 @@
    HTML Forms are an integral part of any interactive site since, well, the dawn of time. It's commonplace that when a form is submitted, the website will taken 'action' and do something with the data and then provide a user with the result. Symphony provides this logic layer via Events.

    This tutorial assumes you have a basic understanding of how Events work in Symphony (if not, this may be a good introduction) and are semi comfortable writing some PHP code. I'll be showing you some of the lesser known features of Symphony Events, including Priority, Event Chaining and a brief demonstration of how to write a custom Event. The difficulty level progresses as we go through, but with any luck you'll be able to learn a thing or two :)