/ */ class Content_Form_Element_ContentSelect extends Zend_Dojo_Form_Element_Dijit implements P4Cms_Content_EnhancedElementInterface { public $helper = 'ContentSelect'; protected $_contentRecord = null; /** * Get the associated content record (if set). * * @return null|P4Cms_Content the associated content record or null if none set. */ public function getContentRecord() { return $this->_contentRecord; } /** * Set the associated content record for this element. * * @param P4Cms_Content $content the associated content record for this element. */ public function setContentRecord($content) { $this->_contentRecord = $content; } /** * Get the default display decorators to use when rendering * content elements of this type. Renders using the purpose * built display selected content decorator (which is a wrapper * of the content list view helper). * * Configures it not to display a message when no content is * selected. This allows placeholder values to work. * * @return array decorators configuration array suitable for passing * to element setDecorators(). */ public function getDefaultDisplayDecorators() { return array( array( 'decorator' => 'DisplaySelectedContent', 'options' => array( 'emptyMessage' => '' ) ) ); } /** * Extends validate to ensure that value is not an array when * multiple select is disabled (and vice-versa) and to verify * that selected content ids exist. * * @param string|array $value the selected content id(s). * @param mixed $context optional context * @return bool */ public function isValid($value, $context = null) { if (!$this->getValidator('P4Cms_Validate_Callback')) { $element = $this; $validator = new P4Cms_Validate_Callback; $validator->setCallback( function ($value) use ($element, $validator) { $multiple = $element->getAttrib('multiple'); $validTypes = (array) $element->getAttrib('validTypes'); // set value to list of ids to simplify validation. $value = $element::extractIds($value); // ensure single select is enforced. if (count($value) > 1 && !$multiple) { $validator->setMessage( "You may only select one content entry.", $validator::INVALID_VALUE ); return false; } // validate the content id(s). $invalidIds = array(); $idValidator = new P4Cms_Validate_ContentId; $idValidator->setAllowNonExistent(false)->setAllowEmpty(true); foreach ($value as $id) { if (!$idValidator->isValid($id)) { $invalidIds[] = $id; } } if ($invalidIds) { $validator->setMessage( "One or more of the selected entries could not be found. " . "Please review and clear these selections.", $validator::INVALID_VALUE ); return false; } // ensure that entries have valid content types if ($validTypes) { $entries = P4Cms_Content::fetchAll( array( 'ids' => $value, 'limitFields' => array('contentType') ) ); foreach ($entries as $entry) { if (!in_array($entry->getContentTypeId(), $validTypes)) { $validator->setMessage( "One or more entries have an invalid content type" . " (allowed types: " . implode(', ', $validTypes) . ').', $validator::INVALID_VALUE ); return false; } } } return true; } ); $this->addValidator($validator); } return parent::isValid($value, $context); } /** * Normalize value to an array of arrays with id elements. * Content select values take several forms in storage: * - a single string * - an array of strings * - an array of arrays * * @param mixed $value the value from storage to normalize. * @return array the value normalized to an array of arrays. */ public static function normalizeValue($value) { $normalized = array(); foreach ((array) $value as $element) { if (!is_array($element)) { $element = array('id' => $element); } if (isset($element['id']) && is_string($element['id']) && strlen($element['id'])) { $normalized[] = $element; } } return $normalized; } /** * Extract a list of ids from the given content select value. * * @param mixed $value the content select value * @return array a list of selected ids. */ public static function extractIds($value) { $ids = array(); foreach (static::normalizeValue($value) as $element) { $ids[] = $element['id']; } return $ids; } }