Source for file Formagic.php
Documentation is available at Formagic.php
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at
* http://formagic.weasle.de/licence.txt
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to licence@weasle.de so we can send you a copy immediately.
* @author Florian Sonnenburg
* @copyright Copyright (c) 2007 Florian Sonnenburg
* @license http://formagic.weasle.de/licence.txt New BSD License
* @revision $Revision: 19 $
require_once 'Item/Item.php';
require_once 'Renderer/Renderer.php';
* Formagic main and interface class
* Highly extensible formgenerator with various rendering options, form
* validation and multipage support.
* @author Florian Sonnenburg
* @copyright Copyright (c) 2007 Florian Sonnenburg
* @version $Id: Formagic.php 19 2007-08-22 22:02:47Z meweasle $
* Form name, used for eg. form action tag in HTML renderer
public $name = 'undefined';
* Form submission method (POST or GET)
* Item values that are not effected by POST/GET
* Points to either $_POST or $_GET
* Array of predefined values for this Formagic object
* Type of renderer used to display form
* @see Formagic::setRenderer()
private $_renderer = null;
* Enables or disabled submission tracking. Contains string with variable
* name if enabled or FALSE if disabled
* @var mixed String or FALSE
private $_trackSubmission = '__fm';
* container item holding all items added to Formagic object
* Array of directories custom classes are searched for
* Caches result of method Formagic::validate()
* @see Formagic::validate();
private $_isValid = null;
* Flag that defines if FormagicItems contained by Formagic object can be
private $_isBlocked = false;
* Contains Formagic form messages (errors, notices, debugs)
private $_formMessages = array();
* Valid callback to be executed when form is submitted
private $_executeCallback;
* Name of currently active page
* @see Formagic::addItem();
private $_currentPage = 'default';
private $_formAction = null;
const VERSION = '0.2.3b';
const API_VERSION = '1.2';
const PAGE_TRACKING_KEY = '__fm_rp';
const PAGE_REQUEST_KEY = '__fm_sw';
* @throws Formagic_Exception
public function __construct($name= 'formagic', $options = null)
// set pointer to submission pool (GET or POST)
if ($this->method == 'post') {
} elseif ($this->method == 'get') {
// set item container of main Formagic object
$this->_itemHolder = $this->createItem('container', '__fm_itemholder');
// handle trackSubmission
if ($this->_trackSubmission) {
$this->_trackSubmission .= "_" . $this->name;
$tsi = $this->addItem('hidden',$this->_trackSubmission,array('default'=> 1));
$tsi->isExecuteItem = false;
// switch($this->_multipageStorage) {
// if (isset($this->submitValues['__fm_sv'])) {
// $this->savedValues =& $this->submitValues['__fm_sv'];
// // $this->savedValues =& $_SESSION['__fmsv'];
// throw new Formagic_Exception("Storage engine {$this->storage} for " .
// "multipaged forms not supported");
* Sets Formagic option $name to $value
* Triggers warning if option $name is not supported.
* @param string $name Formagic option name or array with name => value
* @param mixed $value value of option $name
* @throws Formagic_Exception
public function setOption($options, $value=null)
if (!is_array($options)) {
$options = array($options => $value);
foreach($options as $name => $value) {
$this->_formAction = $value;
throw new <a href="../Formagic/Formagic_Exception.html">Formagic_Exception</a>('Action has to be string value');
case 'FormagicPluginDir':
$this->_pluginDir = (array)$value;
// add hidden input for submission tracking if enabled
$this->_trackSubmission = $value;
// set storage engine for saved values
$this->_multipageStorage = $value;
throw new <a href="../Formagic/Formagic_Exception.html">Formagic_Exception</a>("Option $name not supported");
* Defines renderer for current Formagic object
* @param string $renderer FormagicRenderer object or string with name of
public function setRenderer($renderer)
if ($renderer instanceOf Formagic_Renderer) {
$this->_renderer = $renderer;
$class = 'Formagic_Renderer_' . $renderer;
} catch (<a href="../Formagic/Formagic_Exception.html">Formagic_Exception</a> $e) {
$this->_renderer = new $class();
* Formagic::setDefaultValues()
* $callback has to be a valid PHP callback variable.
$this->_executeCallback = $callback;
* Restores formerly manipulated include path.
* Returns result for string casting of Formagic object
"[items loaded: ' $numItems' ][isSubmitted: ' $submitted' ]" .
// $str = "<pre>". print_r($this->_items,true) ."</pre>";
// public function __call($method, $arguments)
* Returns number of items added to Formagic object
* Counts total number of items recursively
return $this->_itemHolder->countItems();
* Adds Formagic item object to array of first level form items
* Creates new item object and adds this or adds passed FormagicItem object
* @param mixed $type String with item type or FormagicItem object
* @param string $name String with item name. NULL if $type is FormagicItem
* @param array $args Array with additional item information. NULL if $type
* @return object FormagicItem object
public function addItem($type, $name, $args=null)
return $this->_itemHolder->addItem($type, $name, $args);
* Creates and returns FormagicItem object
* Tries to load correct object class and creates new object. Returns object
* if successfull, false if not.
public function &createItem($type, $name, $args=null)
$class = 'Formagic_Item_' . ucFirst($type);
$obj = new $class($type, $name, $args, $this);
if ($obj->_execEvent('onCreate')) {
throw new <a href="../Formagic/Formagic_Exception.html">Formagic_Exception</a>('Event onCreate of item object returned error');
* Returns pointer to Formagic items array
return $this->_itemHolder;
* Returns current form action
if (!$this->_formAction) {
$this->_formAction = $_SERVER['PHP_SELF'];
return $this->_formAction;
* Checks if form is submitted and all rules apply
* Iterates through all items added to the form. If any rule is violated,
* iteration is stopped. Returns true if no rules are violated.
* The result of validate() is cached.
// return cached validation result if present
return $this->_isValid = false;
// Assume that validation is negative if form is not submitted
return $this->_isValid = false;
$items = $this->_itemHolder->getItems();
foreach($items as $item) {
$res = $item->validate();
if ($res instanceOf <a href="../Rule/Formagic_Rule.html">Formagic_Rule</a>) {
$this->setMessage('Bitte markierte Eingabefelder prüfen', self::ERROR);
} elseif($res == false) {
return $this->_isValid = false;
* Returns output generated by renderer
* Loads renderer class and calls renderer::fetch()
* @return string Renderer result
$this->_itemHolder->_execEvent('onFetch');
if (!($this->_renderer instanceOf <a href="../Renderer/Formagic_Renderer.html">Formagic_Renderer</a>)) {
return $this->_renderer->fetch($this);
* @throws Formagic_Exception
if (!isset($this->_executeCallback)) {
throw new <a href="../Formagic/Formagic_Exception.html">Formagic_Exception</a>('No valid callback to execute');
|| (is_array($this->_executeCallback) &&
!method_exists($this->_executeCallback[0], $this->_executeCallback[1]))
throw new <a href="../Formagic/Formagic_Exception.html">Formagic_Exception</a>('Method or function does not exist');
* Returns item value from Formagic value pool
// if (isset($this->savedValues[$name])) {
// return $this->savedValues[$name];
* Returns array with values from all added items
$items = $this->_itemHolder->getItems();
$this->_getValueFromItemRecursive($items, $values);
* Recursively iterates through $items and fills $values
private function _getValueFromItemRecursive($items, &$values)
foreach($items as $item) {
if ($item instanceOf <a href="../Item/Formagic_Item_Container.html">Formagic_Item_Container</a>) {
$this->_getValueFromItemRecursive($item->getItems(), $values);
if ($item->isPostItem && strpos($item->name, '__fm') === false) {
$values[$item->name] = $this->getValue($item->name);
* Checks if HTML form is submitted
* Check result is true for following rules:
* - if submission tracking is enabled in Formagic options and the
* submission variable is present
* - if submission tracking is disabled, but either GET or POST values
* (dependent on chosen submission method) are present
// Return value of trackSubmission variable if tracking enabled
if ($this->_trackSubmission) {
return !empty($this->submitValues[$this->_trackSubmission]);
// If tracking disabled, guess submission status from $_POST/$_GET
$this->_isBlocked = true;
$items =& $this->_itemHolder->getItems();
foreach($items as &$item) {
* Adds $message to Formagic message stack
* Other levels can be used if neccessary. Corresponding level has to be
* used in Formagic::getMessages()
* @see Formagic::getMessages()
$this->_formMessages[$level][] = $message;
* Returns Formagic messages of level $level or empty array if no messages
* @throws Formagic_Exception
return $this->_formMessages;
if (isset($this->_formMessages[$level])) {
return $this->_formMessages[$level];
throw new <a href="../Formagic/Formagic_Exception.html">Formagic_Exception</a>('No such message level as "' . $level . '"');
* Includes Formagic extension class
* Skipped if class is already loaded. loadClass() tries to load from any
* extension directories defined. Returns true if successful, false if not.
* @param string $class Class name. File name is $class.php
* @throws Formagic_Exception
$file = '.'.DIRECTORY_SEPARATOR.$chunks[1].DIRECTORY_SEPARATOR.$chunks[2].'.php';
throw new <a href="../Formagic/Formagic_Exception.html">Formagic_Exception</a>("Formagic item class \" $class\" could not be loaded");
* Formagic event dispatcher
* @param string $event Event to be triggered
protected function _execEvent($event)
case 'onValidationComplete':
throw new <a href="../Formagic/Formagic_Exception.html">Formagic_Exception</a>("Event $event not supported");
* Generic Formagic Exception class
* @author Florian Sonnenburg
* @copyright Copyright (c) 2007 Florian Sonnenburg
* @version $Id: Formagic.php 19 2007-08-22 22:02:47Z meweasle $
class Formagic_Exception extends Exception
|