Perforce Chronicle 2012.2/486814
API Documentation
|
Extends Zend_Form to provide support for an id prefix and show errors by default. More...
Public Member Functions | |
__construct ($options=null) | |
Extend Zend_Dojo_Form's constructor to provide our own decorators. | |
addElement ($element, $name=null, $options=null) | |
Add a new element. | |
getElementValidator ($element, $validator) | |
Helper method to get the validator of an element. | |
getFlattenedValues () | |
Get the values of the form flattened with array notation for keys. | |
getIdPrefix () | |
Get the string used to prefix element ids. | |
getMessages ($name=null, $suppressArrayNotation=false) | |
Retrieve error messages from elements failing validations. | |
getStorageAdapter () | |
Get the storage adapter used by this form to access records. | |
getValues ($suppressArrayNotation=false) | |
Retrieve all form element values. | |
hasCsrfProtection () | |
Returns whether or not this form has csrf protection enabled. | |
isValid ($data) | |
Validate the form, including csrf check. | |
loadDefaultDecorators () | |
Add "Errors" and "CsrfForm" to the default set of decorators. | |
populate ($values) | |
Populate form. | |
render (Zend_View_Interface $view=null) | |
Add id prefixes, then render the form. | |
setCsrfProtection ($csrf) | |
Enables or disables the csrf protection for this form; defaults to enabled. | |
setDefaults ($defaults) | |
Set element values. | |
setIdPrefix ($prefix) | |
Set a string to prefix element ids with. | |
setStorageAdapter (P4Cms_Record_Adapter $adapter) | |
Set the storage adapter to use to access records. | |
Static Public Member Functions | |
static | clearPrefixPathRegistry () |
Remove any registered form plugin prefix paths. | |
static | getCsrfToken () |
For authenticated users, returns the current session value or generate a new value (and set on the session) if none is present. | |
static | getLibraryPathRegistry () |
Get any library prefix paths that are statically registered. | |
static | getPrefixPathRegistry () |
Get any plugin prefix paths that are statically registered. | |
static | moveCheckboxLabel (Zend_Form_Element $element) |
Helper function to adjust decorators on checkbox element to position the checkbox label to the right of the checkbox, instead of on the left hand side. | |
static | normalizeSubForm ($form, $name=null) |
Ensure consistent presentation of sub-forms. | |
static | prefixFormIds (Zend_Form $form, $prefix) |
Prefix the ids of all elements, fieldsets and sub-forms within a form. | |
static | registerPrefixPath ($prefix, $path, $type) |
Add a form plugin path to be used whenever a form is instantiated. | |
Public Attributes | |
const | CSRF_TOKEN_NAME = '_csrfToken' |
const | UTF8_NBSP = "\xc2\xa0" |
Useful for indenting items (e.g. | |
Static Protected Member Functions | |
static | _applyIdPrefix ($element, $prefix) |
Add prefix to id attribute of given element. | |
static | _getSession () |
Return the static session object, initializing if necessary. | |
Protected Attributes | |
$_csrfProtection = true | |
$_idPrefix = null | |
$_populatedCsrfToken = '' | |
$_storageAdapter = null | |
Static Protected Attributes | |
static | $_libraryPaths |
static | $_prefixPaths = array() |
static | $_session = null |
Extends Zend_Form to provide support for an id prefix and show errors by default.
P4Cms_Form::__construct | ( | $ | options = null | ) |
Extend Zend_Dojo_Form's constructor to provide our own decorators.
array | Zend_Config | null | $options | Zend provides no documentation for this param. |
Reimplemented in User_Form_Add, and User_Form_Edit.
{ // combine library prefix paths with // paths from the static registry. $prefixPaths = static::$_libraryPaths + static::$_prefixPaths; // add prefix paths to form instance. foreach ($prefixPaths as $prefixPath) { extract($prefixPath); // add element and decorator paths to form. if ($type === static::ELEMENT || $type === static::DECORATOR) { $this->addPrefixPath($prefix, $path, $type); } // add decorator, validator and filter paths to elements. if ($type !== static::ELEMENT) { $this->addElementPrefixPath($prefix, $path, $type); } // add decorator paths to display groups. if ($type === static::DECORATOR) { $this->addDisplayGroupPrefixPath($prefix, $path); } } // if no storage adapter specified, use default where available if (!isset($options['storageAdapter']) && P4Cms_Record::hasDefaultAdapter() ) { $this->_storageAdapter = P4Cms_Record::getDefaultAdapter(); } parent::__construct($options); }
static P4Cms_Form::_applyIdPrefix | ( | $ | element, |
$ | prefix | ||
) | [static, protected] |
Add prefix to id attribute of given element.
mixed | $element | the element to prefix the id of - can be a form, fieldset or standard element. |
string | $prefix | the prefix to apply |
{ // ensure prefix ends with a dash. $prefix = rtrim($prefix, '-') . '-'; // prefix if id is not blank and not already prefixed. if (strlen($element->getId()) && strpos($element->getId(), $prefix) !== 0) { $id = $prefix . $element->getId(); $element->setAttrib('id', $id); } }
static P4Cms_Form::_getSession | ( | ) | [static, protected] |
Return the static session object, initializing if necessary.
{ if (!static::$_session instanceof Zend_Session_Namespace) { static::$_session = new Zend_Session_Namespace('Forms'); } return static::$_session; }
P4Cms_Form::addElement | ( | $ | element, |
$ | name = null , |
||
$ | options = null |
||
) |
Add a new element.
This is a wrapper around the parent function that provides more palatable error messages for end users.
string | Zend_Form_Element | $element | The element to add. |
string | $name | The name of the element. |
array | Zend_Config | $options | The options for the element. |
{ try { parent::addElement($element, $name, $options); } catch (Exception $e) { P4Cms_Log::log( 'P4Cms_Form->addElement exception ('. get_class($e) .') - '. $e->getMessage(), P4Cms_Log::DEBUG ); if (preg_match("/^Plugin by name '(.+)' was not found in the registry;/", $e->getMessage(), $matches)) { throw new Zend_Form_Exception('Element plugin "'. $matches[1] .'" not found.'); } else { throw $e; } } return $this; }
static P4Cms_Form::clearPrefixPathRegistry | ( | ) | [static] |
Remove any registered form plugin prefix paths.
{ static::$_prefixPaths = array(); }
static P4Cms_Form::getCsrfToken | ( | ) | [static] |
For authenticated users, returns the current session value or generate a new value (and set on the session) if none is present.
For anonymous users this method simply returns null as they don't receive CSRF protection
{ // skip starting a session for anonymous users and simply return null if (!P4Cms_User::hasActive() || P4Cms_User::fetchActive()->isAnonymous()) { return null; } $session = static::_getSession(); if (!$session->csrfToken) { $session->csrfToken = (string) new P4Cms_Uuid; // Don't let the presence of a CSRF token in the session // prevent caching of future unrelated requests. if (P4Cms_Cache::canCache('page')) { P4Cms_Cache::getCache('page')->addIgnoredSessionVariable('Forms[csrfToken]'); } } return $session->csrfToken; }
P4Cms_Form::getElementValidator | ( | $ | element, |
$ | validator | ||
) |
Helper method to get the validator of an element.
Calls isValid on the element to load the correct validators. Attempts to preserve original errors and value.
string | $element | the name of the element to get the validator for. |
string | $validator | the name of the validator to get. |
{ // create a copy of element (to avoid polluting the element) // and call isValid to load the validators. $temp = clone $this->getElement($element); $temp->isValid(true); return $this->getElement($element) ->setValidators($temp->getValidators()) ->getValidator($validator); }
P4Cms_Form::getFlattenedValues | ( | ) |
Get the values of the form flattened with array notation for keys.
{ $filter = new P4Cms_Filter_FlattenArray; return $filter->filter($this->getValues()); }
P4Cms_Form::getIdPrefix | ( | ) |
Get the string used to prefix element ids.
{
return $this->_idPrefix;
}
static P4Cms_Form::getLibraryPathRegistry | ( | ) | [static] |
Get any library prefix paths that are statically registered.
{ return static::$_libraryPaths; }
P4Cms_Form::getMessages | ( | $ | name = null , |
$ | suppressArrayNotation = false |
||
) |
Retrieve error messages from elements failing validations.
Fix for an issue where output from parent method is not consistent with the form structure when form contains nested sub-forms with 'isArray' flag set to false. See description for getValues() method where we fix the same issue.
string | $name | a element or sub-form to get messages for. |
bool | $suppressArrayNotation | zend provides no description for this param. |
{ if (null !== $name) { if (isset($this->_elements[$name])) { return $this->getElement($name)->getMessages(); } else if (isset($this->_subForms[$name])) { return $this->getSubForm($name)->getMessages(null, true); } foreach ($this->getSubForms() as $key => $subForm) { if ($subForm->isArray()) { $belongTo = $subForm->getElementsBelongTo(); if ($name == $this->_getArrayName($belongTo)) { return $subForm->getMessages(null, true); } } } } $customMessages = $this->_getErrorMessages(); if ($this->isErrors() && !empty($customMessages)) { return $customMessages; } $messages = array(); foreach ($this->getElements() as $name => $element) { $eMessages = $element->getMessages(); if (!empty($eMessages)) { $messages[$name] = $eMessages; } } foreach ($this->getSubForms() as $key => $subForm) { $merge = $subForm->getMessages(null, true); if (!empty($merge)) { if ($subForm->isArray()) { $merge = $this->_attachToArray( $merge, $subForm->getElementsBelongTo() ); } $messages = $this->_array_replace_recursive($messages, $merge); } } if (!$suppressArrayNotation && $this->isArray() && !$this->_getIsRendered()) { $messages = $this->_attachToArray($messages, $this->getElementsBelongTo()); } return $messages; }
static P4Cms_Form::getPrefixPathRegistry | ( | ) | [static] |
Get any plugin prefix paths that are statically registered.
{ return static::$_prefixPaths; }
P4Cms_Form::getStorageAdapter | ( | ) |
Get the storage adapter used by this form to access records.
{ if ($this->_storageAdapter instanceof P4Cms_Record_Adapter) { return $this->_storageAdapter; } throw new P4Cms_Form_Exception( "Cannot get storage adapter. Adapter has not been set." ); }
P4Cms_Form::getValues | ( | $ | suppressArrayNotation = false | ) |
Retrieve all form element values.
Override parent to fix an issue where form structure and form->getValues() are inconsistent if form has a sub-form with 'isArray' property set to false.
See: http://framework.zend.com/issues/browse/ZF-12027
bool | $suppressArrayNotation | zend provides no description for this param. |
Reimplemented in Menu_Form_MenuItem, and Menu_Form_MenuItemMvc.
{ $values = array(); $eBelongTo = null; if ($this->isArray()) { $eBelongTo = $this->getElementsBelongTo(); } foreach ($this->getElements() as $key => $element) { if (!$element->getIgnore()) { $merge = array(); if (($belongsTo = $element->getBelongsTo()) !== $eBelongTo) { if ('' !== (string)$belongsTo) { $key = $belongsTo . '[' . $key . ']'; } } $merge = $this->_attachToArray($element->getValue(), $key); $values = $this->_array_replace_recursive($values, $merge); } } foreach ($this->getSubForms() as $key => $subForm) { $merge = array(); if (!$subForm->isArray()) { $merge = $subForm->getValues(); } else { $merge = $this->_attachToArray( $subForm->getValues(true), $subForm->getElementsBelongTo() ); } $values = $this->_array_replace_recursive($values, $merge); } if (!$suppressArrayNotation && $this->isArray() && !$this->_getIsRendered()) { $values = $this->_attachToArray($values, $this->getElementsBelongTo()); } return $values; }
P4Cms_Form::hasCsrfProtection | ( | ) |
Returns whether or not this form has csrf protection enabled.
Protection is always turned off for anonymous users. For authenticated users protection is on by default but can optionally be disabled.
{ return $this->_csrfProtection && P4Cms_User::hasActive() && !P4Cms_User::fetchActive()->isAnonymous(); }
P4Cms_Form::isValid | ( | $ | data | ) |
Validate the form, including csrf check.
array | $data | the data to validate. |
Reimplemented in Category_Form_Manage, Content_Form_Type, Menu_Form_MenuItem, Menu_Form_MenuItemContentQuick, Menu_Form_MenuItemMvc, Setup_Form_Administrator, Setup_Form_Site, Setup_Form_Storage, Site_Form_Branch, User_Form_Add, User_Form_AddRole, User_Form_Edit, Workflow_Form_Workflow, P4Cms_Form_PubSubForm, Analytics_Form_Configure, and Flickr_Form_Configure.
{ $isValid = parent::isValid($data); // validate the CSRF token if protection is enabled if ($this->hasCsrfProtection()) { if (array_key_exists(static::CSRF_TOKEN_NAME, $data)) { $this->_populatedCsrfToken = $data[static::CSRF_TOKEN_NAME]; } if ($this->getPopulatedCsrfToken() != static::getCsrfToken()) { $isValid = false; $this->addError('Form failed security validation.'); } } return $isValid; }
P4Cms_Form::loadDefaultDecorators | ( | ) |
Add "Errors" and "CsrfForm" to the default set of decorators.
{ if ($this->loadDefaultDecoratorsIsDisabled()) { return; } $decorators = $this->getDecorators(); $prepend = Zend_Form_Decorator_Abstract::PREPEND; if (empty($decorators)) { $this->addDecorator('FormElements') ->addDecorator('HtmlTag', array('tag' => 'dl', 'class' => 'zend_form_dojo')) ->addDecorator('Errors', array('placement' => $prepend)) ->addDecorator('Csrf', array('placement' => $prepend)) ->addDecorator('DijitForm'); } }
static P4Cms_Form::moveCheckboxLabel | ( | Zend_Form_Element $ | element | ) | [static] |
Helper function to adjust decorators on checkbox element to position the checkbox label to the right of the checkbox, instead of on the left hand side.
Zend_Form_Element | $element | the element to adjust decorators on. |
{ // adjust how the auto-label element is decorated // to put the label immediately after the checkbox. $decorators = array( 'Zend_Form_Decorator_ViewHelper' => null, 'P4Cms_Form_Decorator_Label' => null ); $element->setDecorators(array_merge($decorators, $element->getDecorators())); $element->getDecorator('label') ->setOption('placement', 'append') ->setOption('tag', null); return $element; }
static P4Cms_Form::normalizeSubForm | ( | $ | form, |
$ | name = null |
||
) | [static] |
Ensure consistent presentation of sub-forms.
Zend_Form | $form | the sub-form to normalize. |
string | $name | the name of the sub-form. |
{ $name = $name ?: $form->getName(); $form->setDecorators( array( 'FormElements', array( 'decorator' => 'HtmlTag', 'options' => array('tag' => 'dl') ), 'Fieldset', array( 'decorator' => array('DdTag' => 'HtmlTag'), 'options' => array('tag' => 'dd') ), ) ); // ensure form is identified with a css class. $class = $name ? $name . '-sub-form' : ''; if (!preg_match("/(^| )$class( |$)/", $form->getAttrib('class'))) { $form->setAttrib('class', trim($class . ' ' . $form->getAttrib('class'))); } // normalized sub-forms should always put values in an array. $form->setIsArray(true); return $form; }
P4Cms_Form::populate | ( | $ | values | ) |
Populate form.
Records CSRF token, if enabled and present, for later use, then calls the parent populate method.
P4Cms_Record | array | $values | the values to populate from |
Reimplemented in Content_Form_Content, and P4Cms_Form_PubSubForm.
{ if ($this->hasCsrfProtection() && array_key_exists(static::CSRF_TOKEN_NAME, $values)) { $this->_populatedCsrfToken = $values[static::CSRF_TOKEN_NAME]; } return $this->setDefaults($values); }
static P4Cms_Form::prefixFormIds | ( | Zend_Form $ | form, |
$ | prefix | ||
) | [static] |
Prefix the ids of all elements, fieldsets and sub-forms within a form.
Zend_Form | $form | a specific form to prefix the ids of. |
string | $prefix | the prefix to use |
{ // prefix id of form itself. static::_applyIdPrefix($form, $prefix); // prefix elements in form. foreach ($form->getElements() as $element) { static::_applyIdPrefix($element, $prefix); } // prefix display groups. foreach ($form->getDisplayGroups() as $displayGroup) { static::_applyIdPrefix($displayGroup, $prefix); } // prefix sub-forms. foreach ($form->getSubForms() as $subForm) { $subForm->setIdPrefix($prefix); } }
static P4Cms_Form::registerPrefixPath | ( | $ | prefix, |
$ | path, | ||
$ | type | ||
) | [static] |
Add a form plugin path to be used whenever a form is instantiated.
string | $prefix | the class prefix (e.g. Foo_Form_Element) |
string | $path | the path containing the classes |
string | $type | the type of plugin (e.g. element, decorator validator, filter) |
{ static::$_prefixPaths[$prefix] = array( 'prefix' => $prefix, 'path' => $path, 'type' => strtoupper($type) ); }
P4Cms_Form::render | ( | Zend_View_Interface $ | view = null | ) |
Add id prefixes, then render the form.
Zend_View_Interface | $view | The Zend View Interface to render. |
{ // prefix form element ids if id prefix is set. if ($this->getIdPrefix()) { static::prefixFormIds($this, $this->getIdPrefix()); } return parent::render($view); }
P4Cms_Form::setCsrfProtection | ( | $ | csrf | ) |
Enables or disables the csrf protection for this form; defaults to enabled.
boolean | $csrf | Whether or not to enable csrf protection |
{
$this->_csrfProtection = (boolean)$csrf;
return $this;
}
P4Cms_Form::setDefaults | ( | $ | defaults | ) |
Set element values.
Extended here to support setting values from a record object. Accepting a record object allows 'enhanced' elements to look at other aspects of the record and make decisions accordingly.
P4Cms_Record | array | $defaults | the default values to set on elements |
Reimplemented in Menu_Form_MenuItem, Menu_Form_MenuItemContent, Menu_Form_MenuItemContentQuick, Menu_Form_MenuItemMvc, Setup_Form_Site, and Site_Form_Branch.
{ // handle record input. if ($defaults instanceof P4Cms_Record) { $record = $defaults; $defaults = $record->getValues(); // handle enhanced elements. foreach ($defaults as $field => $value) { $element = $this->getElement($field); if ($element instanceof P4Cms_Record_EnhancedElementInterface) { $element->populateFromRecord($record); unset($defaults[$field]); } } } // Zend form has a strange behavior where sub-forms will populate // from the entire values array, rather than their designated portion // of the values array if there is no matching key in defaults for // the sub-form (e.g. from $defaults instead of $defaults['subForm']) // and parent form has no element matching the key. // // This can have some unfortunate side-effects (top-level values // polluting the sub-forms) - to avoid this problem we ensure that // there is an entry in the defaults array for every sub-form. // // Example: // assuming we have a $form with element [foo] and a sub-form 'subForm' // with elements [foo] and [bar], then // $form->setDefaults(array('foo' => 'foo_value')) // will populate only [foo] element, whereas // $form->setDefaults(array('bar' => 'bar_value')) // will populate [subForm][bar] element. This fix is to prevent the // second case above (i.e. [subForm][bar] will be populated only if // defaults array contains 'subForm' => array('bar' => 'bar_value'). foreach ($this->getSubForms() as $subForm) { $key = $subForm->getElementsBelongTo(); if ($subForm->isArray() && !isset($defaults[$key])) { $defaults[$key] = array(); } } return parent::setDefaults($defaults); }
P4Cms_Form::setIdPrefix | ( | $ | prefix | ) |
Set a string to prefix element ids with.
string | $prefix | the string to prefix element ids with. |
{
$this->_idPrefix = (string) $prefix;
return $this;
}
P4Cms_Form::setStorageAdapter | ( | P4Cms_Record_Adapter $ | adapter | ) |
Set the storage adapter to use to access records.
P4Cms_Record_Adapter | $adapter | the adapter to use for record access |
{
$this->_storageAdapter = $adapter;
return $this;
}
P4Cms_Form::$_csrfProtection = true [protected] |
P4Cms_Form::$_idPrefix = null [protected] |
P4Cms_Form::$_libraryPaths [static, protected] |
P4Cms_Form::$_populatedCsrfToken = '' [protected] |
P4Cms_Form::$_prefixPaths = array() [static, protected] |
P4Cms_Form::$_session = null [static, protected] |
P4Cms_Form::$_storageAdapter = null [protected] |
const P4Cms_Form::CSRF_TOKEN_NAME = '_csrfToken' |
const P4Cms_Form::UTF8_NBSP = "\xc2\xa0" |
Useful for indenting items (e.g.
in select elements)