/**
  * @test
  */
 public function testGetAuditEntryFieldClass()
 {
     $user = $this->getDiamanteUser();
     $this->auditEntityMapper->addAuditEntryFieldClass('Diamante\\UserBundle\\Entity\\DiamanteUser', 'Diamante\\DeskBundle\\Entity\\AuditField');
     $result = $this->auditEntityMapper->getAuditEntryFieldClass($user);
     $this->assertEquals('Diamante\\DeskBundle\\Entity\\AuditField', $result);
 }
 /**
  * @param string $action
  * @param mixed  $entity
  *
  * @throws \Doctrine\ORM\Mapping\MappingException
  * @throws \ReflectionException
  */
 protected function createLogEntity($action, $entity)
 {
     $entityClassName = $this->getEntityClassName($entity);
     if (!$this->checkAuditable($entityClassName)) {
         return;
     }
     $uow = $this->em->getUnitOfWork();
     $meta = $this->getConfig($entityClassName);
     $entityMeta = $this->em->getClassMetadata($entityClassName);
     $loggedUser = $this->container->get('oro_security.security_facade')->getLoggedUser();
     $user = $this->container->get('diamante.user.service')->getUserFromApiUser($loggedUser);
     $organization = current($this->em->getRepository('OroOrganizationBundle:Organization')->getEnabled());
     $logEntryMeta = $this->em->getClassMetadata($this->getLogClass($user));
     /** @var AbstractAudit $logEntry */
     $logEntry = $logEntryMeta->newInstance();
     $logEntry->setAction($action);
     $logEntry->setObjectClass($meta->name);
     $logEntry->setLoggedAt();
     $logEntry->setUser($user);
     $logEntry->setOrganization($organization);
     $logEntry->setObjectName(method_exists($entity, '__toString') ? (string) $entity : $meta->name);
     $entityId = $this->getIdentifier($entity);
     if (!$entityId && $action === self::ACTION_CREATE) {
         $this->pendingLogEntityInserts[spl_object_hash($entity)] = $logEntry;
     }
     $logEntry->setObjectId($entityId);
     $newValues = [];
     if ($action !== self::ACTION_REMOVE && count($meta->propertyMetadata)) {
         foreach ($uow->getEntityChangeSet($entity) as $field => $changes) {
             if (!isset($meta->propertyMetadata[$field])) {
                 continue;
             }
             $old = $changes[0];
             $new = $changes[1];
             if ($old == $new) {
                 continue;
             }
             $fieldMapping = null;
             if ($entityMeta->hasField($field)) {
                 $fieldMapping = $entityMeta->getFieldMapping($field);
                 if ($fieldMapping['type'] === 'date') {
                     // leave only date
                     $utc = new \DateTimeZone('UTC');
                     if ($old && $old instanceof \DateTime) {
                         $old->setTimezone($utc);
                         $old = new \DateTime($old->format('Y-m-d'), $utc);
                     }
                     if ($new && $new instanceof \DateTime) {
                         $new->setTimezone($utc);
                         $new = new \DateTime($new->format('Y-m-d'), $utc);
                     }
                 }
             }
             if ($old instanceof \DateTime && $new instanceof \DateTime && $old->getTimestamp() == $new->getTimestamp()) {
                 continue;
             }
             if ($entityMeta->isSingleValuedAssociation($field) && $new) {
                 $oid = spl_object_hash($new);
                 $value = $this->getIdentifier($new);
                 if (!is_array($value) && !$value) {
                     $this->pendingRelatedEntities[$oid][] = ['log' => $logEntry, 'field' => $field];
                 }
                 $method = $meta->propertyMetadata[$field]->method;
                 if ($old !== null) {
                     // check if an object has the required method to avoid a fatal error
                     if (!method_exists($old, $method)) {
                         throw new \ReflectionException(sprintf('Try to call to undefined method %s::%s', get_class($old), $method));
                     }
                     $old = $old->{$method}();
                 }
                 if ($new !== null) {
                     // check if an object has the required method to avoid a fatal error
                     if (!method_exists($new, $method)) {
                         throw new \ReflectionException(sprintf('Try to call to undefined method %s::%s', get_class($new), $method));
                     }
                     $new = $new->{$method}();
                 }
             }
             $newValues[$field] = ['old' => $old, 'new' => $new, 'type' => $this->getFieldType($entityMeta, $field)];
         }
         $entityIdentifier = $this->getEntityIdentifierString($entity);
         if (!empty($this->collectionLogData[$entityClassName][$entityIdentifier])) {
             $collectionData = $this->collectionLogData[$entityClassName][$entityIdentifier];
             foreach ($collectionData as $field => $changes) {
                 if (!isset($meta->propertyMetadata[$field])) {
                     continue;
                 }
                 if ($changes['old'] != $changes['new']) {
                     $newValues[$field] = $changes;
                     $newValues[$field]['type'] = $this->getFieldType($entityMeta, $field);
                 }
             }
             unset($this->collectionLogData[$entityClassName][$entityIdentifier]);
             if (!$this->collectionLogData[$entityClassName]) {
                 unset($this->collectionLogData[$entityClassName]);
             }
         }
         foreach ($newValues as $field => $newValue) {
             $logEntry->createField($field, $newValue['type'], $newValue['new'], $newValue['old']);
         }
     }
     if ($action === self::ACTION_UPDATE && 0 === count($newValues)) {
         return;
     }
     $version = 1;
     if ($action !== self::ACTION_CREATE) {
         $version = $this->getNewVersion($logEntryMeta, $entity);
         if (empty($version)) {
             // was versioned later
             $version = 1;
         }
     }
     $logEntry->setVersion($version);
     $this->em->persist($logEntry);
     $uow->computeChangeSet($logEntryMeta, $logEntry);
     $logEntryFieldMeta = $this->em->getClassMetadata($this->diamanteAuditEntityMapper->getAuditEntryFieldClass($user));
     foreach ($logEntry->getFields() as $field) {
         $this->em->persist($field);
         $uow->computeChangeSet($logEntryFieldMeta, $field);
     }
 }