PubSubForm.php #1

  • //
  • guest/
  • perforce_software/
  • chronicle/
  • main/
  • library/
  • P4Cms/
  • Form/
  • PubSubForm.php
  • View
  • Commits
  • Open Download .zip Download (6 KB)
<?php
/**
 * A 'pub-sub' form is a form that can be modified via pub/sub.
 * Topics published:
 *
 *  <form-topic>           -  general form manipulation at init time
 *  <form-topic>.subForms  -  provide sub forms (via return) at init time
 *  <form-topic>.validate  -  validate form data (true for valid, false otherwise)
 *  <form-topic>.populate  -  populate form from data
 *
 * @copyright   2011 Perforce Software. All rights reserved.
 * @license     Please see LICENSE.txt in top-level folder of this distribution.
 * @version     <release>/<patch>
 */
class P4Cms_Form_PubSubForm extends P4Cms_Form
{
    protected   $_topic = null;

    /**
     * If this form has a topic set, automatically publish to collect
     * any sub-forms and allow arbitrary modification of the form itself.
     */
    public function init()
    {
        if (!$this->hasTopic()) {
            return;
        }

        // collect any sub-forms.
        $this->publishSubForms();

        // allow arbitrary modification of this form.
        $this->publish();
    }

    /**
     * Specify the topic to use when publishing this form.
     *
     * @param   string  $topic              the topic to use when publishing this form.
     * @return  P4Cms_Form_PubSubForm       provides fluent interface
     * @throws  InvalidArgumentException    if topic is not a string or null
     */
    public function setTopic($topic)
    {
        if (!is_string($topic) && !is_null($topic)) {
            throw new InvalidArgumentException("Form topic must be a string or null");
        }
        
        $this->_topic = $topic;
        
        return $this;
    }

    /**
     * Get the topic for publishing this form.
     *
     * @return  string  the topic for publishing this form.
     * @throws  InvalidArgumentException    if no topic is set.
     */
    public function getTopic()
    {
        if ($this->_topic === null) {
            throw new P4Cms_Form_Exception("No topic set for this form");
        }

        return $this->_topic;
    }

    /**
     * Check if a topic has been set for this form.
     * 
     * @return  bool    true if a topic has been set, false otherwise.
     */
    public function hasTopic()
    {
        return !is_null($this->_topic);
    }

    /**
     * Collect sub-forms for this form by publishing to the
     * form topic + '/sub-forms'. Sub-forms are automatically
     * normalized for consistent presentation and added.
     *
     * @return  P4Cms_Form_PubSubForm   provides fluent interface
     */
    public function publishSubForms()
    {
        $feedback = $this->publish('subForms');

        // process sub-form feedback.
        foreach ($feedback as $subForms) {

            if (!is_array($subForms)) {
                $subForms = array($subForms);
            }

            foreach ($subForms as $subForm) {
                // skip cases where the subscriber decided not to return a form
                if (!isset($subForm)) {
                    continue;
                }
                if (!$subForm instanceof Zend_Form || !$subForm->getName()) {
                    P4Cms_Log::log(
                        "Encountered invalid pub-sub sub-form.",
                        P4Cms_Log::ERR
                    );
                    P4Cms_Log::log(print_r($subForm, true), P4Cms_Log::DEBUG);

                    // skip form.
                    continue;
                }

                $name = $subForm->getName();

                // ensure consistent sub-form markup.
                static::normalizeSubForm($subForm, $name);

                // add it.
                $this->addSubForm($subForm, $name);
            }
        }

        return $this;
    }

    /**
     * Validate the form - publish to the form topic + '/validate'
     * to allow third-party involvement in validation.
     *
     * Subscribers should return true if the data is valid and false
     * otherwise. Errors can be added directly to the form object.
     *
     * @param  array    $data   the data to validate.
     * @return boolean
     */
    public function isValid($data)
    {
        // allow third-parties to make adjustments to the 
        // form and influence the outcome of the validation.
        $this->publish('preValidate', $data);

        $isValid = parent::isValid($data);

        // allow third-parties to validate the form
        $feedback = $this->publish('validate', $data);

        // any false feedback means the form is invalid.
        foreach ($feedback as $valid) {
            if (!$valid) {
                $isValid            = false;
                $this->_errorsExist = true;
            }
        }

        return $isValid;
    }

    /**
     * Populate the form from key-value array. Extended to publish to form
     * topic + '/populate' so that third-parties can participate.
     *
     * @param   P4Cms_Record|array      $values     the values to populate the form from.
     * @return  P4Cms_Form_PubSubForm   provides fluent interface.
     */
    public function populate($values)
    {
        parent::populate($values);

        // turn records into arrays before publishing so that
        // subscribers consistently get array input.
        if ($values instanceof P4Cms_Record) {
            $values = $values->getValues();
        }
        
        $this->publish('populate', $values);

        return $this;
    }

    /**
     * Publish this form. Happens automatically on init() if the topic has been set.
     * Pass subTopic to append a suffix to the topic. Pass additional args to be
     * included in the publish call (always includes the form instance by default).
     * 
     * @param   string  $subTopic   optional - suffix to add to the form topic.
     * @param   mixed   $args       optional - all arguments besides the topic
     *                              are passed as arguments to the handler
     * @return  array   the return values of all subscribers.
     */
    public function publish($subTopic = null, $args = null)
    {
        $topic = $subTopic
            ? $this->getTopic() . P4Cms_PubSub::TOPIC_DELIMITER . $subTopic
            : $this->getTopic();

        // inject topic and form into args.
        $args = func_get_args();
        array_splice($args, 0, 1, array($topic, $this));

        return call_user_func_array(
            array('P4Cms_PubSub', 'publish'),
            $args
        );
    }
}
# Change User Description Committed
#1 16170 perforce_software Move Chronicle files to follow new path scheme for branching.
//guest/perforce_software/chronicle/library/P4Cms/Form/PubSubForm.php
#1 8972 Matt Attaway Initial add of the Chronicle source code