/**
  * (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/phDataCollection::validate()
  */
 public function validate(phFormViewElement $element, phNameInfo $name, phCompositeDataCollection $collection)
 {
     /*
      * check uniqueness of name
      */
     if (!$name->hasAutoKey()) {
         $elementsCollection = $element->createDataCollection();
         $ourItem = $this->find($name->getFullName());
         if ($ourItem) {
             // we already have an item registered in this collection with this name
             throw new phFormException("The element with name {$name->getFullName()} is not unique");
         } else {
             if (get_class($elementsCollection) == get_class($this)) {
                 // the item will be stored in this collection - check uniqueness of name
                 $item = $collection->find($name->getFullName());
                 if ($item) {
                     throw new phFormException("The element with name {$name->getFullName()} is not unique");
                 }
             }
         }
     }
     /*
      * make sure we are not mixing arrays and normal types
      */
     $rootItem = $collection->find($name->getName());
     if ($rootItem && $name->isArray() && !$rootItem instanceof phArrayFormDataItem) {
         throw new phFormException("There is already a data item registered at {$name->getFullName()} and it is not an array data type so I cannot add to it!");
     }
 }
 /**
  * (non-PHPdoc)
  * @see lib/form/data/collection/phSimpleDataCollection::register()
  */
 public function register(phFormViewElement $element, phNameInfo $name, phCompositeDataCollection $collection)
 {
     if (!$element instanceof phForm) {
         throw new phFormException('This collection can only store phForm instances');
     }
     if ($name->isArray()) {
         throw new phFormException("The name {$name} is invalid, you cannot use array names with forms");
     }
     $this->_dataItems[$name->getName()] = $element;
 }
 /**
  * (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[]\"");
     }
 }
 public function testParseName()
 {
     $info = new phNameInfo('ids[1]');
     $this->assertTrue($info->isValid(), 'ids[1] is valid');
     $this->assertTrue($info->isArray(), 'ids[1] has been identified as an array');
     $this->assertEquals($info->getArrayKeyString(), '[1]', 'Array parts is [1]');
     $this->assertEquals($info->getName(), 'ids', 'Name is ids');
     $info = new phNameInfo('ids[]');
     $this->assertTrue($info->isValid(), 'ids[] is valid');
     $this->assertTrue($info->isArray(), 'ids[] has been identified as an array');
     $this->assertEquals($info->getArrayKeyString(), '[]', 'Array parts is []');
     $this->assertEquals($info->getName(), 'ids', 'Name is ids');
     $info = new phNameInfo('ids[1][moo]');
     $this->assertTrue($info->isValid(), 'ids[1][moo] is valid');
     $this->assertTrue($info->isArray(), 'ids[1][moo] has been identified as an array');
     $this->assertEquals($info->getArrayKeyString(), '[1][moo]', 'Array parts is [1][moo]');
     $this->assertEquals($info->getName(), 'ids', 'Name is ids');
 }
 /**
  * (non-PHPdoc)
  * @see lib/form/data/collection/phSimpleDataCollection::validate()
  */
 public function validate(phFormViewElement $element, phNameInfo $name, phCompositeDataCollection $collection)
 {
     if ($name->isArray()) {
         $arrayInfo = $name->getArrayInfo();
         $keys = $arrayInfo->getKeys();
         $lastKey = array_pop($keys);
         if ($lastKey->isAutoKey()) {
             throw new phFormException("The name {$name->getFullName()} is invalid, you cannot use an auto key with a radio button");
         }
     }
     if (!$element instanceof phRadioButtonElement) {
         return;
         // not interested from here on
     }
     if (array_key_exists($name->getFullName(), $this->_radioValues)) {
         if (in_array($element->getRawValue(), $this->_radioValues[$name->getFullName()])) {
             throw new phFormException("Non unique value for radio button with name \"{$name->getFullName()}\"");
         }
     }
 }
 /**
  * (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);
     }
 }
 /**
  * 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;
     }
 }