/**
  * (non-PHPdoc)
  * @see lib/form/data/collection/phDataCollection::validate()
  */
 public function validate(phFormViewElement $element, phNameInfo $name, phCompositeDataCollection $collection)
 {
     if ($element instanceof phForm) {
         $data = $collection->find($name->getFullName());
         if ($data !== null) {
             throw new phFormException("There is already a data item registered with the name {$name->getFullName()}");
         }
     }
 }
 /**
  * Changed behavior so if an element with the same name has already been registered then that
  * same data item created last time is bound to this element
  * @see lib/form/data/collection/phSimpleDataCollection::registerNormal()
  */
 protected function registerNormal(phFormViewElement $element, phNameInfo $name, phCompositeDataCollection $collection)
 {
     if (!array_key_exists($name->getName(), $this->_dataItems)) {
         $item = $this->createNormalDataItem($name->getName(), $element);
         $this->_dataItems[$name->getName()] = $item;
     }
     $item = $this->_dataItems[$name->getName()];
     $element->bindDataItem($item);
 }
 public function testInvalidNames()
 {
     $info = new phNameInfo('ids[');
     // unclosed array
     $this->assertFalse($info->isValid(), 'ids[ is not valid');
     $info = new phNameInfo('ids[][name]');
     // auto keys must be at the very end of the name
     $this->assertFalse($info->isValid(), 'ids[][name] is not valid');
     $info = new phNameInfo('ids$%');
     // invalid characters
     $this->assertFalse($info->isValid(), 'ids$% is not valid');
 }
 /**
  * (non-PHPdoc)
  * @see lib/form/data/collection/phDataCollection::find()
  */
 public function find($name)
 {
     $info = new phNameInfo($name);
     if ($info->isArray()) {
         // if the $name specifies any auto keys then they will not be able to be found
         $keys = $info->getArrayInfo()->getKeys();
         foreach ($keys as $k) {
             if ($k->isAutoKey()) {
                 throw new phFormException("{$name} is ambiguous as it specifies an auto key ([])");
             }
         }
     }
     if (!array_key_exists($info->getName(), $this->_dataItems)) {
         return null;
     }
     $dataItem = $this->_dataItems[$info->getName()];
     if ($info->isArray() && !$dataItem instanceof phArrayFormDataItem) {
         /*
          * name is an array but the data type registered there is not
          * an array type
          */
         return null;
     }
     if ($info->isArray()) {
         $dataItem = $this->recurseArray($dataItem, $info->getArrayInfo()->getKeys());
     }
     return $dataItem;
 }
 /**
  * (non-PHPdoc)
  * @see lib/form/data/collection/phSimpleDataCollection::validate()
  */
 public function validate(phFormViewElement $element, phNameInfo $name, phCompositeDataCollection $collection)
 {
     /*
      * go through the name and, if it's an array, build it back up, BUT - skip
      * the last key if it's an auto key.  We do this because checkboxes with auto 
      * key's cannot be mixed with any other data type.
      */
     $nameString = $name->getName();
     $hasAutoKey = false;
     if ($name->isArray()) {
         $keys = $name->getArrayInfo()->getKeys();
         foreach ($keys as $k) {
             if ($k->isAutoKey()) {
                 $hasAutoKey = true;
                 break;
             }
             $nameString .= "[{$k->getKey()}]";
         }
     }
     $item = $collection->find($nameString);
     if ($hasAutoKey && $item !== null) {
         if (!$element instanceof phCheckboxElement && $item instanceof phSimpleArrayDataItem) {
             // not ok - checkbox registered here previously and someone is trying to add another datatype to the same array
             throw new phFormException("Trying to mix checkboxes with auto keys with another type of element at {$name}");
         }
         if ($element instanceof phCheckboxElement && !$item instanceof phSimpleArrayDataItem) {
             // not ok - checkbox with auto key trying to be registered to a normal array type
             throw new phFormException("Trying to mix checkboxes with auto keys with another type of element at {$name}");
         }
     }
     if (!$element instanceof phCheckboxElement) {
         return;
         // not interested at this point if it's not a checkbox
     }
     /*
      * check unique values
      */
     if (array_key_exists($name->getFullName(), $this->_checkboxValues) && in_array($element->getRawValue(), $this->_checkboxValues[$name->getFullName()])) {
         // value is not unique
         throw new phFormException("Duplicate value for checkbox with name {$name->getFullName()}");
     }
     if (!$name->isArray() && $item !== null) {
         throw new phFormException("Cannot register checkbox with name {$name->getFullName()}, an item of data with the same name already exists.  If you are trying to use multiple checkboxes with the same name then please note that these must have array names e.g. \"ids[]\"");
     }
 }
 /**
  * (non-PHPdoc)
  * @see lib/form/data/collection/phSimpleDataCollection::validate()
  */
 public function validate(phFormViewElement $element, phNameInfo $name, phCompositeDataCollection $collection)
 {
     /*
      * go through the name and, if it's an array, build it back up, BUT - skip
      * the last key if it's an auto key.  We do this because checkboxes with auto 
      * key's cannot be mixed with any other data type.
      */
     $nameString = $name->getName();
     $hasAutoKey = false;
     if ($name->isArray()) {
         $keys = $name->getArrayInfo()->getKeys();
         foreach ($keys as $k) {
             if ($k->isAutoKey()) {
                 $hasAutoKey = true;
                 break;
             }
             $nameString .= "[{$k->getKey()}]";
         }
     }
     if ($element instanceof phSelectListElement && $element->isMultiple()) {
         if (!$hasAutoKey) {
             throw new phFormException("Invalid name \"{$name->getFullName()}\" - Multi select list elements must use a name with an auto key");
         } else {
             $data = $collection->find($nameString);
             if ($data !== null) {
                 throw new phFormException("Cannot register multi-select list at {$name->getFullName()} another data item exists there");
             }
         }
     }
     if (array_key_exists($name->getFullName(), $this->_multipleElements)) {
         throw new phFormException("There is a multi-select list registered at \"{$name->getFullName()}\", you cannot register any other types of data here");
     }
     if ($element instanceof phSelectListElement) {
         /*
          * also do uniqueness checks if we are registering a select element
          */
         parent::validate($element, $name, $collection);
     }
 }
 protected function registerNormal(phFormViewElement $element, phNameInfo $name, phCompositeDataCollection $collection)
 {
     $data = $this->createNormalDataItem($name->getName(), $element);
     $this->_dataItems[$name->getName()] = $data;
     $element->bindDataItem($data);
 }
 /**
  * Gets a rewritten name that will be unique and relate to the form
  * that the element belongs to
  * 
  * @param string $name
  */
 public function name($name)
 {
     /*
      * valid names can only start with alpha characters
      * following the first letter can be alpha, numeric or underscores (but need'nt be present, a valid name can be 1 character)
      * the second parahenthises check, if an array is present that it is valid
      */
     $nameInfo = new phNameInfo($name);
     if (!$nameInfo->isValid()) {
         throw new phFormException("'{$name}' is not valid, names must be a-z0-9 or '_' only and contain no spaces and must not start with an '_' (underscore) or number");
     }
     $nameOnly = $nameInfo->getName();
     /*
      * check if someone is trying to specify 2 names where one is an array and the other isn't
      * e.g. name="address" and name="address[zip]"
      */
     if (array_key_exists($nameOnly, $this->_types) && $nameInfo->isArray() != $this->_types[$nameOnly]) {
         throw new phFormException("Invalid name {$name}, trying to mix array's and normal types");
     }
     $key = array_search($name, $this->_names);
     if ($key !== false) {
         return $key;
     } else {
         $this->_types[$nameOnly] = $nameInfo->isArray();
         $newName = sprintf($this->_form->getNameFormat(), $nameOnly);
         if ($nameInfo->isArray()) {
             $newName .= $nameInfo->getArrayKeyString();
         }
         $this->_names[$newName] = $name;
         return $newName;
     }
 }
 /**
  * Registers an element with this collection
  * 
  * @param phFormViewElement $element
  * @param phNameInfo $name
  */
 public function register(phFormViewElement $element, phNameInfo $name, phCompositeDataCollection $collection)
 {
     $item = new phFormDataItem($name->getName());
     $this->_dataItems[$name->getName()] = $item;
     $element->bindDataItem($item);
 }