/**
  * @param string $entityName
  * @param bool $fullData
  * @param int $singleRelationDeepLevel
  * @param int $multipleRelationDeepLevel
  * @return array
  */
 protected function getEntityRulesAndBackendHeaders($entityName, $fullData = false, $singleRelationDeepLevel = 0, $multipleRelationDeepLevel = 0)
 {
     // get fields data
     $fields = $this->fieldHelper->getFields($entityName, true);
     $rules = array();
     $backendHeaders = array();
     $defaultOrder = 10000;
     // generate conversion rules and backend header
     foreach ($fields as $field) {
         $fieldName = $field['name'];
         if ($this->fieldHelper->getConfigValue($entityName, $fieldName, 'excluded')) {
             continue;
         }
         // get import/export config parameters
         $fieldHeader = $this->fieldHelper->getConfigValue($entityName, $fieldName, 'header', $field['label']);
         $fieldOrder = $this->fieldHelper->getConfigValue($entityName, $fieldName, 'order');
         if ($fieldOrder === null || $fieldOrder === '') {
             $fieldOrder = $defaultOrder;
             $defaultOrder++;
         }
         $fieldOrder = (int) $fieldOrder;
         // process relations
         if ($this->fieldHelper->isRelation($field) && !$this->fieldHelper->processRelationAsScalar($entityName, $fieldName)) {
             $isSingleRelation = $this->fieldHelper->isSingleRelation($field) && $singleRelationDeepLevel > 0;
             $isMultipleRelation = $this->fieldHelper->isMultipleRelation($field) && $multipleRelationDeepLevel > 0;
             // if relation must be included
             if ($fullData && ($isSingleRelation || $isMultipleRelation)) {
                 $relatedEntityName = $field['related_entity_name'];
                 $fieldFullData = $this->fieldHelper->getConfigValue($entityName, $fieldName, 'full', false);
                 // process and merge relation rules and backend header for relation
                 list($relationRules, $relationBackendHeaders) = $this->getEntityRulesAndBackendHeaders($relatedEntityName, $fieldFullData, $singleRelationDeepLevel - 1, $multipleRelationDeepLevel - 1);
                 $relationRules = $this->buildRelationRules($relationRules, $isSingleRelation, $isMultipleRelation, $fieldName, $fieldHeader, $fieldOrder);
                 $rules = array_merge($rules, $relationRules);
                 $relationBackendHeaders = $this->buildBackendHeaders($relationBackendHeaders, $isSingleRelation, $isMultipleRelation, $entityName, $fieldName, $fieldOrder);
                 $backendHeaders = array_merge($backendHeaders, $relationBackendHeaders);
             }
         } else {
             // process scalars
             if ($fullData || $this->fieldHelper->getConfigValue($entityName, $fieldName, 'identity')) {
                 $rules[$fieldHeader] = array('value' => $fieldName, 'order' => $fieldOrder);
                 $backendHeaders[] = $rules[$fieldHeader];
             }
         }
     }
     return array($this->sortData($rules), $this->sortData($backendHeaders));
 }
 /**
  * {@inheritdoc}
  */
 public function normalize($object, $format = null, array $context = array())
 {
     $entityName = ClassUtils::getClass($object);
     $fields = $this->fieldHelper->getFields($entityName, true);
     $result = array();
     $propertyAccessor = PropertyAccess::createPropertyAccessor();
     foreach ($fields as $field) {
         $fieldName = $field['name'];
         // Do not normalize excluded fields
         if ($this->fieldHelper->getConfigValue($entityName, $fieldName, 'excluded')) {
             continue;
         }
         // Do not normalize non identity fields for short mode
         if ($this->getMode($context) == self::SHORT_MODE && !$this->fieldHelper->getConfigValue($entityName, $fieldName, 'identity')) {
             continue;
         }
         $fieldValue = $propertyAccessor->getValue($object, $fieldName);
         if (is_object($fieldValue)) {
             $fieldContext = $context;
             $fieldContext['fieldName'] = $fieldName;
             if (method_exists($object, 'getId')) {
                 $fieldContext['entityId'] = $object->getId();
             }
             $isFullMode = $this->fieldHelper->getConfigValue($entityName, $fieldName, 'full');
             // Do not export relation in short mode if it does not contain identity fields
             if (!$isFullMode && isset($field['related_entity_type']) && $this->fieldHelper->hasConfig($field['related_entity_type']) && !$this->hasIdentityFields($field['related_entity_type'])) {
                 continue;
             }
             if ($this->fieldHelper->isRelation($field)) {
                 if ($isFullMode) {
                     $fieldContext['mode'] = self::FULL_MODE;
                 } else {
                     $fieldContext['mode'] = self::SHORT_MODE;
                 }
             }
             $fieldValue = $this->serializer->normalize($fieldValue, $format, $fieldContext);
         }
         $result[$fieldName] = $fieldValue;
     }
     return $result;
 }
 /**
  * {@inheritdoc}
  */
 public function normalize($object, $format = null, array $context = [])
 {
     $entityName = ClassUtils::getClass($object);
     $fields = $this->fieldHelper->getFields($entityName, true);
     $result = [];
     foreach ($fields as $field) {
         $fieldName = $field['name'];
         if ($this->isFieldSkippedForNormalization($entityName, $fieldName, $context)) {
             continue;
         }
         $fieldValue = $this->fieldHelper->getObjectValue($object, $fieldName);
         if (is_object($fieldValue)) {
             $fieldContext = $context;
             $fieldContext['fieldName'] = $fieldName;
             if (method_exists($object, 'getId')) {
                 $fieldContext['entityId'] = $object->getId();
             }
             $isFullMode = $this->fieldHelper->getConfigValue($entityName, $fieldName, 'full');
             // Do not export relation in short mode if it does not contain identity fields
             if (!$isFullMode && isset($field['related_entity_name']) && $this->fieldHelper->hasConfig($field['related_entity_name']) && !$this->hasIdentityFields($field['related_entity_name'])) {
                 continue;
             }
             if ($this->fieldHelper->isRelation($field)) {
                 if ($isFullMode) {
                     $fieldContext['mode'] = self::FULL_MODE;
                 } else {
                     $fieldContext['mode'] = self::SHORT_MODE;
                 }
             }
             if ($this->fieldHelper->isDateTimeField($field)) {
                 $fieldContext['type'] = $field['type'];
             }
             $fieldValue = $this->serializer->normalize($fieldValue, $format, $fieldContext);
         }
         $result[$fieldName] = $fieldValue;
     }
     return $result;
 }
 /**
  * @param string $entityName
  * @param bool $fullData
  * @param int $singleRelationDeepLevel
  * @param int $multipleRelationDeepLevel
  * @return array
  */
 protected function getEntityRulesAndBackendHeaders($entityName, $fullData = false, $singleRelationDeepLevel = 0, $multipleRelationDeepLevel = 0)
 {
     // get fields data
     $fields = $this->fieldHelper->getFields($entityName, true);
     $rules = [];
     $backendHeaders = [];
     $defaultOrder = self::DEFAULT_ORDER;
     // generate conversion rules and backend header
     foreach ($fields as $field) {
         $fieldName = $field['name'];
         if ($this->fieldHelper->getConfigValue($entityName, $fieldName, 'excluded')) {
             continue;
         }
         // get import/export config parameters
         $fieldHeader = $this->getFieldHeader($entityName, $field);
         $fieldOrder = $this->fieldHelper->getConfigValue($entityName, $fieldName, 'order');
         if ($fieldOrder === null || $fieldOrder === '') {
             $fieldOrder = $defaultOrder;
             $defaultOrder++;
         }
         $fieldOrder = (int) $fieldOrder;
         // process relations
         if ($this->fieldHelper->isRelation($field) && !$this->fieldHelper->processRelationAsScalar($entityName, $fieldName)) {
             list($relationRules, $relationBackendHeaders) = $this->getRelatedEntityRulesAndBackendHeaders($entityName, $fullData, $singleRelationDeepLevel, $multipleRelationDeepLevel, $field, $fieldHeader, $fieldOrder);
             $rules = array_merge($rules, $relationRules);
             $backendHeaders = array_merge($backendHeaders, $relationBackendHeaders);
         } else {
             // process scalars
             if ($fullData || $this->fieldHelper->getConfigValue($entityName, $fieldName, 'identity')) {
                 $rules[$fieldHeader] = ['value' => $fieldName, 'order' => $fieldOrder];
                 $backendHeaders[] = $rules[$fieldHeader];
             }
         }
     }
     return [$this->sortData($rules), $this->sortData($backendHeaders)];
 }
 /**
  * @param boolean $expected
  * @param array $field
  * @dataProvider relationDataProvider
  */
 public function testIsRelation($expected, array $field)
 {
     $this->assertSame($expected, $this->helper->isRelation($field));
 }