/**
  * Evaluates the data value at the specified field.
  * - If the data is an array, then the field is treated as an array index
  *   and the corresponding element value is returned; the field name can also include
  *   dots to access subarrays. For example a field named 'MyField.MySubField' will
  *   first try to access $data['MyField.MySubField'], then try $data['MyField']['MySubField'].
  * - If the data is a TMap or TList object, then the field is treated as a key
  *   into the map or list, and the corresponding value is returned.
  * - If the data is an object, the field is treated as a property or sub-property
  *   defined with getter methods. For example, if the object has a method called
  *   getMyValue(), then field 'MyValue' will retrieve the result of this method call.
  *   If getMyValue() returns an object which contains a method getMySubValue(),
  *   then field 'MyValue.MySubValue' will return that method call result.
  * @param mixed data containing the field value, can be an array, TMap, TList or object.
  * @param mixed field value
  * @return mixed value at the specified field
  * @throws TInvalidDataValueException if field or data is invalid
  */
 public static function getDataFieldValue($data, $field)
 {
     try {
         if (is_array($data) || $data instanceof ArrayAccess) {
             if (isset($data[$field])) {
                 return $data[$field];
             }
             $tmp = $data;
             foreach (explode(".", $field) as $f) {
                 $tmp = $tmp[$f];
             }
             return $tmp;
         } else {
             if (is_object($data)) {
                 if (strpos($field, '.') === false) {
                     if (method_exists($data, 'get' . $field)) {
                         return call_user_func(array($data, 'get' . $field));
                     } else {
                         return $data->{$field};
                     }
                 } else {
                     $object = $data;
                     foreach (explode('.', $field) as $f) {
                         $object = TDataFieldAccessor::getDataFieldValue($object, $f);
                     }
                     return $object;
                 }
             }
         }
     } catch (Exception $e) {
         throw new TInvalidDataValueException('datafieldaccessor_datafield_invalid', $field, $e->getMessage());
     }
     throw new TInvalidDataValueException('datafieldaccessor_data_invalid', $field);
 }
 /**
  * Fetches the value of the data at the specified field.
  * If the data is an array, the field is used as an array key.
  * If the data is an of {@link TMap}, {@link TList} or their derived class,
  * the field is used as a key value.
  * If the data is a component, the field is used as the name of a property.
  * @param mixed data containing the field of value
  * @param string the data field
  * @return mixed data value at the specified field
  * @throws TInvalidDataValueException if the data or the field is invalid.
  */
 protected function getDataFieldValue($data, $field)
 {
     return TDataFieldAccessor::getDataFieldValue($data, $field);
 }
 /**
  * Performs databinding to populate list items from data source.
  * This method is invoked by dataBind().
  * You may override this function to provide your own way of data population.
  * @param Traversable the data
  */
 protected function performDataBinding($data)
 {
     $items = $this->getItems();
     if (!$this->getAppendDataBoundItems()) {
         $items->clear();
     }
     $textField = $this->getDataTextField();
     if ($textField === '') {
         $textField = 0;
     }
     $valueField = $this->getDataValueField();
     if ($valueField === '') {
         $valueField = 1;
     }
     $textFormat = $this->getDataTextFormatString();
     $groupField = $this->getDataGroupField();
     foreach ($data as $key => $object) {
         $item = $items->createListItem();
         if (is_array($object) || is_object($object)) {
             $text = TDataFieldAccessor::getDataFieldValue($object, $textField);
             $value = TDataFieldAccessor::getDataFieldValue($object, $valueField);
             $item->setValue($value);
             if ($groupField !== '') {
                 $item->setAttribute('Group', TDataFieldAccessor::getDataFieldValue($object, $groupField));
             }
         } else {
             $text = $object;
             $item->setValue("{$key}");
         }
         $item->setText($this->formatDataValue($textFormat, $text));
     }
     // SelectedValue or SelectedIndex may be set before databinding
     // so we make them be effective now
     if ($this->_cachedSelectedValue !== null) {
         $this->setSelectedValue($this->_cachedSelectedValue);
         $this->resetCachedSelections();
     } else {
         if ($this->_cachedSelectedIndex !== -1) {
             $this->setSelectedIndex($this->_cachedSelectedIndex);
             $this->resetCachedSelections();
         } else {
             if ($this->_cachedSelectedValues !== null) {
                 $this->setSelectedValues($this->_cachedSelectedValues);
                 $this->resetCachedSelections();
             } else {
                 if ($this->_cachedSelectedIndices !== null) {
                     $this->setSelectedIndices($this->_cachedSelectedIndices);
                     $this->resetCachedSelections();
                 }
             }
         }
     }
 }