public function postGenerateSchema(GenerateSchemaEventArgs $eventArgs)
 {
     $schema = $eventArgs->getSchema();
     $revisionsTable = $schema->createTable($this->config->getRevisionTableName());
     $revisionsTable->addColumn('id', $this->config->getRevisionIdFieldType(), array('autoincrement' => true));
     $revisionsTable->addColumn('timestamp', 'datetime');
     $revisionsTable->addColumn('username', 'string');
     $revisionsTable->setPrimaryKey(array('id'));
 }
 public function postFlush(PostFlushEventArgs $eventArgs)
 {
     $em = $eventArgs->getEntityManager();
     $uow = $em->getUnitOfWork();
     foreach ($this->extraUpdates as $entity) {
         $className = get_class($entity);
         $meta = $em->getClassMetadata($className);
         $persister = $uow->getEntityPersister($className);
         $updateData = $this->prepareUpdateData($persister, $entity);
         if (!isset($updateData[$meta->table['name']]) || !$updateData[$meta->table['name']]) {
             continue;
         }
         foreach ($updateData[$meta->table['name']] as $field => $value) {
             $sql = 'UPDATE ' . $this->config->getTableName($meta) . ' ' . 'SET ' . $field . ' = ? ' . 'WHERE ' . $this->config->getRevisionFieldName() . ' = ? ';
             $params = array($value, $this->getRevisionId());
             $types = array();
             if (in_array($field, $meta->columnNames)) {
                 $types[] = $meta->fieldMappings[$meta->getFieldForColumn($field)]['type'];
             } else {
                 //try to find column in association mappings
                 $type = null;
                 foreach ($meta->associationMappings as $mapping) {
                     if (isset($mapping['joinColumns'])) {
                         foreach ($mapping['joinColumns'] as $definition) {
                             if ($definition['name'] == $field) {
                                 $targetTable = $em->getClassMetadata($mapping['targetEntity']);
                                 $type = $targetTable->getTypeOfColumn($definition['referencedColumnName']);
                             }
                         }
                     }
                 }
                 if (is_null($type)) {
                     throw new \Exception(sprintf('Could not resolve database type for column "%s" during extra updates', $field));
                 }
             }
             $types[] = $this->config->getRevisionIdFieldType();
             foreach ($meta->identifier as $idField) {
                 if (isset($meta->fieldMappings[$idField])) {
                     $columnName = $meta->fieldMappings[$idField]['columnName'];
                     $types[] = $meta->fieldMappings[$idField]['type'];
                 } elseif (isset($meta->associationMappings[$idField])) {
                     $columnName = $meta->associationMappings[$idField]['joinColumns'][0];
                     $types[] = $meta->associationMappings[$idField]['type'];
                 }
                 $params[] = $meta->reflFields[$idField]->getValue($entity);
                 $sql .= 'AND ' . $columnName . ' = ?';
             }
             $this->em->getConnection()->executeQuery($sql, $params, $types);
         }
     }
 }
 public function postFlush(PostFlushEventArgs $eventArgs)
 {
     $em = $eventArgs->getEntityManager();
     $uow = $em->getUnitOfWork();
     //well, this is awkward, it's a reflection again
     $uowR = new \ReflectionClass($uow);
     $extraUpdatesR = $uowR->getProperty('extraUpdates');
     $extraUpdatesR->setAccessible(true);
     $extraUpdates = $extraUpdatesR->getValue($uow);
     foreach ($extraUpdates as $update) {
         list($entity, $changeset) = $update;
         if (!$this->metadataFactory->isAudited(get_class($entity))) {
             continue;
         }
         $meta = $em->getClassMetadata(get_class($entity));
         $persister = new BasicEntityPersister($em, $meta);
         $persisterR = new \ReflectionClass($persister);
         if ($persisterR->hasMethod('prepareUpdateData')) {
             //doctrine 2.4+
             $prepareUpdateDataR = $persisterR->getMethod('prepareUpdateData');
         } elseif ($persisterR->hasMethod('_prepareUpdateData')) {
             //doctrine < 2.4
             $prepareUpdateDataR = $persisterR->getMethod('_prepareUpdateData');
         } else {
             throw new \Exception('Can not resolve prepareUpdateData method of BasicPersister, probably a doctrine regression');
         }
         $prepareUpdateDataR->setAccessible(true);
         $updateData = $prepareUpdateDataR->invoke($persister, $entity);
         if (!isset($updateData[$meta->table['name']]) || !$updateData[$meta->table['name']]) {
             continue;
         }
         foreach ($updateData[$meta->table['name']] as $field => $value) {
             $sql = 'UPDATE ' . $this->config->getTablePrefix() . $meta->table['name'] . $this->config->getTableSuffix() . ' ' . 'SET ' . $field . ' = ? ' . 'WHERE ' . $this->config->getRevisionFieldName() . ' = ? ';
             $params = array($value, $this->getRevisionId());
             $types = array();
             if (in_array($field, $meta->columnNames)) {
                 $types[] = $meta->fieldMappings[$meta->getFieldForColumn($field)]['type'];
             } else {
                 //try to find column in association mappings
                 $type = null;
                 foreach ($meta->associationMappings as $mapping) {
                     if (isset($mapping['joinColumns'])) {
                         foreach ($mapping['joinColumns'] as $definition) {
                             if ($definition['name'] == $field) {
                                 $targetTable = $em->getClassMetadata($mapping['targetEntity']);
                                 $type = $targetTable->getTypeOfColumn($definition['referencedColumnName']);
                             }
                         }
                     }
                 }
                 if (is_null($type)) {
                     throw new \Exception(sprintf('Could not resolve database type for column "%s" during extra updates', $field));
                 }
             }
             $types[] = $this->config->getRevisionIdFieldType();
             foreach ($meta->identifier as $idField) {
                 if (isset($meta->fieldMappings[$idField])) {
                     $columnName = $meta->fieldMappings[$idField]['columnName'];
                     $types[] = $meta->fieldMappings[$idField]['type'];
                 } else {
                     if (isset($meta->associationMappings[$idField])) {
                         $columnName = $meta->associationMappings[$idField]['joinColumns'][0];
                         $types[] = $meta->associationMappings[$idField]['type'];
                     }
                 }
                 $params[] = $meta->reflFields[$idField]->getValue($entity);
                 $sql .= 'AND ' . $columnName . ' = ?';
             }
             $this->em->getConnection()->executeQuery($sql, $params, $types);
         }
     }
 }