Search

I know we’re all looking forward to Symphony 3.0 which seems like it builds this capability in a little better. But I’m wondering about the present. I’d love to be able to update two separate sections from a front-end form.

Is this possible via a custom event? Does anyone have an example they’ve created that they could show me?

Try searching the forum for EventEx. I haven’t used it for ages but it should still be compatible with the latest Symphony version.

Hmmm, I guess that’s the only option, huh? I experimented with it a bit and especially combined with the Members Extension it seemed buggy and I would have to change all of my forms.

It seems that it can be done — at least in the very simple case I tested. I created two new sections, each with only one text box field, and named them “Name1” and “Name2” (It’s critical that the field names be unique between the two sections.) I created a new event called “Save Dual” and added it to a page. I then added this form to the page:

<form method="post" action="" enctype="multipart/form-data">
    <input name="MAX_FILE_SIZE" type="hidden" value="5242880" />
    <label>Name1
        <input name="fields[name1]" type="text" />
    </label>
    <label>Name2
        <input name="fields[name2]" type="text" />
    </label>
    <input name="action[save-dual]" type="submit" value="Submit" />
</form>

I modified the trigger function like this:

require_once(TOOLKIT . '/class.event.php');
Class eventsave_dual extends Event{
    const ROOTELEMENT = 'save-dual';
    private static $source = 15; //section1 id
    public $eParamFILTERS = array();
    public static function about(){return array('name' => 'Save Dual');}
    public static function getSource(){
        return self::$source;
    }
    public static function allowEditorToParse(){
        return false;
    }
    public static function documentation(){}
    public function load(){
        if(isset($_POST['action']['save-dual'])) return $this->__trigger();
    }
    protected function __trigger(){
        include(TOOLKIT . '/events/event.section.php');
        self::$source = 16; //section2 id
        include(TOOLKIT . '/events/event.section.php');
        return $result;
    }       
}

$source is initially set to one section and then changed to the other in the __trigger function between the two includes. This saves the name1 input in section1 and the name2 input in section2. I assume that you can have as many fields as you want in each of the two sections as long as their names are unique across both sections.

That is all EventEx does too: it looks at different POST arrays, determines which ones are sections, then includes the event.section.php file for each.

Either way you’ll need to customise the original event.

Under the premise that all field handles are unique it should be possible to achieve the same without customizing the events. Create two events, one for each section, and trigger the one action with you submit button and the other one with a hidden input, like

<form method="post" action="" enctype="multipart/form-data">
    <input name="MAX_FILE_SIZE" type="hidden" value="5242880" />
    <label>Name1
        <input name="fields[name1]" type="text" />
    </label>
    <label>Name2
        <input name="fields[name2]" type="text" />
    </label>
    <input name="action[save-section1]" type="hidden" value="Submit" />
    <input name="action[save-section2]" type="submit" value="Submit" />
</form>

I haven’t tested it, but I think it should work.

I’m wanting to do a wizard interface for a client that needs to do forms and events. This will need to post to multiple sections…

I hope that does work Jonas, it will make my life easier, I’ve been really concerned about how to do it…

I have confirmed that klaftertief’s approach does work. While it requires two events instead of one, it is much cleaner.

Brilliant! I’m looking forward to trying the wizard approach now!

Good points, all. Much simpler.

I’ll just add that EventEx is useful when you need the events to be chained i.e. when the entry ID (or result) of the first needs to be used in the second. This could be when you need to create a parent entry and attach a child entry (with a Select Box Link) at the same time.

But! TheJester12 did say that he wanted to be able to update two sections at the same time in the frontend. The only way I see to do this is to add two more lines to the form:

<input name="id1" type="hidden" value="{$id1}" />
<input name="id2" type="hidden" value="{$id2}" />

Where $id1 and $id2 are the ids of the entries being edited.

And add this line to the save_section1 event as the first line in the __trigger function:

if (isset($_POST['id1']) && is_numeric($_POST['id1'])) $_POST['id'] = $_POST['id1'];

Do the same in the save_section2 event, substituting id2 for id1.

So I’m back to customizing the events. klaftertief?

So I’m back to customizing the events. klaftertief?

Yep :-)

So it’s a matter of taste and requirements if you want to create a combined event, separate events or use EventEx. A combined event seems to be the easiest, in separate events it’s easier to do further separate customizations and EventEx probably is the most powerful.

It’s always good to see that you can achieve a lot with little customizations. It shows the flexibility of Symphony beyond its standard functionality.

Thanks so much guys for explaining the options and giving me some examples. I’m trying to build a sort of Member Activity Tracker into my Issue Tracker, but admittedly it sounds like EventEx is my only option if i want to be able to update the Activity Stream as someone creates a new issue.

I guess I need to give this some more thought.

In my attempt to rebuild the Forum ensemble without the old Forum extension, I was trying to figure out how to use @wisolman's custom event to pass an entry ID of the parent section entry to a Select Box Link in the child entry. I modified the event:

<?php

    require_once(TOOLKIT . '/class.event.php');

    Class eventsave_discussion extends Event{

        const ROOTELEMENT = 'save-discussion';

        // Set the section ID of first section
        private static $source = 1;

        public $eParamFILTERS = array(

        );

        public static function about(){
            return array(
                'name' => 'Save Discussion',
                'author' => array(
                    'name' => 'Stephen Bau',
                    'website' => 'http://home/tmp/dual',
                    'email' => 'bauhouse@gmail.com'),
                'version' => '1.0',
                'release-date' => '2011-04-09T17:47:10+00:00',
                'trigger-condition' => 'action[save-discussion]'
            );
        }

        public static function getSource(){
            return self::$source;
        }

        public static function allowEditorToParse(){
            return false;
        }

        public static function documentation(){
            return 'Save to two sections: Discussions and Comments';
        }

        public function load(){
            if(isset($_POST['action']['save-discussion'])) return $this->__trigger();
        }

        protected function __trigger(){
            include(TOOLKIT . '/events/event.section.php');

            // Set the entry ID of the Select Box Link field
            if(isset($_POST['section-link-field'])) {
                $section_link_handle = $_POST['section-link-field'];
                $entry_id = $result->getAttribute('id');
                $_POST['fields'][$section_link_handle] = $entry_id;
            }

            // Set the section ID of the second section
            self::$source = 2;
            include(TOOLKIT . '/events/event.section.php');

            return $result;
        }

    }

And created a form like this, which adds a field to specify the section link field handle:

<?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" action="" enctype="multipart/form-data">
        <input name="MAX_FILE_SIZE" type="hidden" value="5242880" />
        <div><label>Topic
            <input name="fields[topic]" type="text" />
        </label></div>
        <div><label>Comment
            <textarea name="fields[comment]" rows="30" cols="80"></textarea>
        </label></div>
        <input name="fields[discussion]" type="hidden" value="" />
        <input name="section-link-field" type="hidden" value="discussion" />
        <input name="action[save-discussion]" type="submit" value="Submit" />
    </form>
</xsl:template>

</xsl:stylesheet>

This seems to be working quite well to create two entries linked by a Select Box Link field with a single event.

I was going to use the Dynamic Event Redirect extension with my custom event, but I realized that the redirect would be triggered by the successful creation of the first entry and bypass the creation of the second entry, so I had to create my own redirect logic:

<?php

    require_once(TOOLKIT . '/class.event.php');

    Class eventforum_new_discussion extends Event{

        const ROOTELEMENT = 'forum-new-discussion';

        // Set the section ID of first section
        private static $source = 2;

        public $eParamFILTERS = array(

        );

        public static function about(){
            return array(
                'name' => 'Forum: New Discussion',
                'author' => array(
                    'name' => 'Stephen Bau',
                    'website' => 'http://home/domain7/team-members',
                    'email' => 'stephen@domain7.com'),
                'version' => '1.0',
                'release-date' => '2011-04-09T21:50:40+00:00',
                'trigger-condition' => 'action[forum-new-discussion]'
            );
        }

        public static function getSource(){
            return self::$source;
        }

        public static function allowEditorToParse(){
            return false;
        }

        public static function documentation(){
            return '
        <h3>Save Parent and Child Entries</h3>
        <p>This custom event will save a parent section entry and a child section entry that
        is linked to the parent section entry with a Select Box Link field. Specify the handle
        of the Select Box Link field as the value of a hidden text input field in the front end form
        to save the parent entry ID as the value of the Select Box Link field in the child entry.</p>
        <pre class="XML"><code>&lt;input name="section-link-field" type="hidden" value="parent-id" /></code></pre>
        <p>The section ID for each section must be set manually in the event. (See lines 10 and 110
        of this event, where the value of the static <code>$source</code> variable is set.)
        <h3>Redirect ID</h3>
        <p>After successfully creating the entries, the event will redirect to the new parent entry,
        where <code>/id/</code> will be replaced with the actual ID: e.g. <code>/123/</code>.</p>
        <pre class="XML"><code>&lt;input type="hidden" name="redirect-id" value="{$root}/forum/discussions/id/"/></code></pre>
        <h3>Success and Failure XML Examples</h3>
        <p>When saved successfully, the following XML will be returned:</p>
        <pre class="XML"><code>&lt;forum-new-discussion result="success" type="create | edit">
  &lt;message>Entry [created | edited] successfully.&lt;/message>
&lt;/forum-new-discussion></code></pre>
        <p>When an error occurs during saving, due to either missing or invalid fields, the following XML will be returned:</p>
        <pre class="XML"><code>&lt;forum-new-discussion result="error">
  &lt;message>Entry encountered errors when saving.&lt;/message>
  &lt;field-name type="invalid | missing" />
  ...
&lt;/forum-new-discussion></code></pre>
        <h3>Example Front-end Form Markup</h3>
        <p>This is an example of the form markup you can use on your frontend:</p>
        <pre class="XML"><code>&lt;form method="post" action="" enctype="multipart/form-data">
  &lt;input name="MAX_FILE_SIZE" type="hidden" value="5242880" />
  &lt;label>Topic
    &lt;input name="fields[topic]" type="text" />
  &lt;/label>
  &lt;input name="fields[created-by]" type="hidden" value="..." />
  &lt;label>Creation Date
    &lt;input name="fields[creation-date]" type="text" />
  &lt;/label>
  &lt;input name="fields[last-post]" type="hidden" value="..." />
  &lt;label>Last Active
    &lt;input name="fields[last-active]" type="text" />
  &lt;/label>
  &lt;label>Pinned
    &lt;input name="fields[pinned]" type="checkbox" />
  &lt;/label>
  &lt;label>Closed
    &lt;input name="fields[closed]" type="checkbox" />
  &lt;/label>
  &lt;input name="redirect-id" type="hidden" value="{$root}/forum/discussions/id/"/>
  &lt;input name="section-link-field" type="hidden" value="parent-id" />
  &lt;input name="action[forum-new-discussion]" type="submit" value="Submit" />
&lt;/form></code></pre>';
        }

        public function load(){
            if(isset($_POST['action']['forum-new-discussion'])) return $this->__trigger();
        }

        protected function __trigger(){
            include(TOOLKIT . '/events/event.section.php');

            $entry_id = $result->getAttribute('id');

            // Set the entry ID of the Select Box Link field
            if(isset($_POST['section-link-field'])) {
                $section_link_handle = $_POST['section-link-field'];
                $_POST['fields'][$section_link_handle] = $entry_id;
            }

            // Set the redirect URL to the parent entry ID
            if(isset($_POST['redirect-id'])) {
                $redirect_url = str_replace('/id/', '/' . $entry_id . '/', $_POST['redirect-id']);
            }

            // Set the section ID of the second section
            self::$source = 3;
            include(TOOLKIT . '/events/event.section.php');

            if($redirect_url) {
                redirect($redirect_url);
            }

            return $result;
        }

    }

Works beautifully.

Looks like Brendo is working on a tutorial!

Thanks for pointing that out, michael-e! I'm really looking forward to the finished tutorial.

Heh, bleeding edge tutorials. I can't promise a release date on it as I'm usually occupied by other things, but it should be before May.

Would it be possible to trigger the second event from the __trigger() function of the primary event, whithout the second event being referenced in the frontend form?

This will be useful when the second event uses values submitted by the primary event in the first section, manipulates them and updates the second section.

The logic would be to first test the result of the primary event and if success, post the values from the first section that need to be manipulated, then perform the manipulation and finally trigger the second event to update the second section with the new values.

So, do you think this is doable? I am a beginner with PHP and I'd hate to start working on a custom event by trying to achieve something impossible...

Create an account or sign in to comment.

Symphony • Open Source XSLT CMS

Server Requirements

  • PHP 5.3-5.6 or 7.0-7.3
  • PHP's LibXML module, with the XSLT extension enabled (--with-xsl)
  • MySQL 5.5 or above
  • An Apache or Litespeed webserver
  • Apache's mod_rewrite module or equivalent

Compatible Hosts

Sign in

Login details