public function getEntityHistory($className, $id) { if (!$this->metadataFactory->isAudited($className)) { throw new NotAuditedException($className); } /** @var ClassMetadataInfo|ClassMetadata $class */ $class = $this->em->getClassMetadata($className); $tableName = $this->config->getTableName($class); if (!is_array($id)) { $id = array($class->identifier[0] => $id); } $whereId = array(); foreach ($class->identifier as $idField) { if (isset($class->fieldMappings[$idField])) { $columnName = $class->fieldMappings[$idField]['columnName']; } else { if (isset($class->associationMappings[$idField])) { $columnName = $class->associationMappings[$idField]['joinColumns'][0]; } else { continue; } } $whereId[] = "{$columnName} = ?"; } $whereSQL = implode(' AND ', $whereId); $columnList = array($this->config->getRevisionFieldName()); $columnMap = array(); foreach ($class->fieldNames as $columnName => $field) { $type = Type::getType($class->fieldMappings[$field]['type']); $columnList[] = $type->convertToPHPValueSQL($class->getQuotedColumnName($field, $this->platform), $this->platform) . ' AS ' . $this->platform->quoteSingleIdentifier($field); $columnMap[$field] = $this->platform->getSQLResultCasing($columnName); } foreach ($class->associationMappings as $assoc) { if (($assoc['type'] & ClassMetadata::TO_ONE) == 0 || !$assoc['isOwningSide']) { continue; } foreach ($assoc['targetToSourceKeyColumns'] as $sourceCol) { $columnList[] = $sourceCol; $columnMap[$sourceCol] = $this->platform->getSQLResultCasing($sourceCol); } } $values = array_values($id); $query = "SELECT " . implode(', ', $columnList) . " FROM " . $tableName . " e WHERE " . $whereSQL . " ORDER BY e.rev DESC"; $stmt = $this->em->getConnection()->executeQuery($query, $values); $result = array(); while ($row = $stmt->fetch(Query::HYDRATE_ARRAY)) { $rev = $row[$this->config->getRevisionFieldName()]; unset($row[$this->config->getRevisionFieldName()]); $result[] = $this->createEntity($class->name, $row, $rev); } return $result; }
/** * @param ClassMetadata $class * * @return string * @throws \Doctrine\DBAL\DBALException */ private function getInsertRevisionSQL($class) { if (!isset($this->insertRevisionSQL[$class->name])) { $placeholders = array('?', '?'); $tableName = $this->config->getTableName($class); $sql = "INSERT INTO " . $tableName . " (" . $this->config->getRevisionFieldName() . ", " . $this->config->getRevisionTypeFieldName(); $fields = array(); foreach ($class->associationMappings as $field => $assoc) { if ($class->isInheritanceTypeJoined() && $class->isInheritedAssociation($field)) { continue; } if (($assoc['type'] & ClassMetadata::TO_ONE) > 0 && $assoc['isOwningSide']) { foreach ($assoc['targetToSourceKeyColumns'] as $sourceCol) { $fields[$sourceCol] = true; $sql .= ', ' . $sourceCol; $placeholders[] = '?'; } } } foreach ($class->fieldNames as $field) { if (array_key_exists($field, $fields)) { continue; } if ($class->isInheritanceTypeJoined() && $class->isInheritedField($field) && !$class->isIdentifier($field)) { continue; } $type = Type::getType($class->fieldMappings[$field]['type']); $placeholders[] = !empty($class->fieldMappings[$field]['requireSQLConversion']) ? $type->convertToDatabaseValueSQL('?', $this->platform) : '?'; $sql .= ', ' . $this->quoteStrategy->getColumnName($field, $class, $this->platform); } if ($class->isInheritanceTypeJoined() && $class->rootEntityName == $class->name || $class->isInheritanceTypeSingleTable()) { $sql .= ', ' . $class->discriminatorColumn['name']; $placeholders[] = '?'; } $sql .= ") VALUES (" . implode(", ", $placeholders) . ")"; $this->insertRevisionSQL[$class->name] = $sql; } return $this->insertRevisionSQL[$class->name]; }
protected function initialize() { if (!$this->initialized) { $params = array(); $sql = 'SELECT MAX(' . $this->configuration->getRevisionFieldName() . ') as rev, '; $sql .= implode(', ', $this->metadata->getIdentifierColumnNames()) . ' '; if (isset($this->associationDefinition['indexBy'])) { $sql .= ', ' . $this->associationDefinition['indexBy'] . ' '; } $sql .= 'FROM ' . $this->configuration->getTableName($this->metadata) . ' t '; $sql .= 'WHERE ' . $this->configuration->getRevisionFieldName() . ' <= ' . $this->revision . ' '; foreach ($this->foreignKeys as $column => $value) { $sql .= 'AND ' . $column . ' = ? '; $params[] = $value; } //we check for revisions greater than current belonging to other entities $sql .= 'AND NOT EXISTS (SELECT * FROM ' . $this->configuration->getTableName($this->metadata) . ' st WHERE'; //ids foreach ($this->metadata->getIdentifierColumnNames() as $name) { $sql .= ' st.' . $name . ' = t.' . $name . ' AND'; } //foreigns $sql .= ' (('; //master entity query, not equals $notEqualParts = $nullParts = array(); foreach ($this->foreignKeys as $column => $value) { $notEqualParts[] = $column . ' <> ?'; $nullParts[] = $column . ' IS NULL'; $params[] = $value; } $sql .= implode(' AND ', $notEqualParts) . ') OR (' . implode(' AND ', $nullParts) . '))'; //revision $sql .= ' AND st.' . $this->configuration->getRevisionFieldName() . ' <= ' . $this->revision; $sql .= ' AND st.' . $this->configuration->getRevisionFieldName() . ' > t.' . $this->configuration->getRevisionFieldName(); $sql .= ') '; //end of check for for belonging to other entities //check for deleted revisions older than requested $sql .= 'AND NOT EXISTS (SELECT * FROM ' . $this->configuration->getTableName($this->metadata) . ' sd WHERE'; //ids foreach ($this->metadata->getIdentifierColumnNames() as $name) { $sql .= ' sd.' . $name . ' = t.' . $name . ' AND'; } //revision $sql .= ' sd.' . $this->configuration->getRevisionFieldName() . ' <= ' . $this->revision; $sql .= ' AND sd.' . $this->configuration->getRevisionFieldName() . ' > t.' . $this->configuration->getRevisionFieldName(); $sql .= ' AND sd.' . $this->configuration->getRevisionTypeFieldName() . ' = ?'; $params[] = 'DEL'; $sql .= ') '; //end check for deleted revisions older than requested $sql .= 'AND ' . $this->configuration->getRevisionTypeFieldName() . ' <> ? '; $params[] = 'DEL'; $groupBy = $this->metadata->getIdentifierColumnNames(); if (isset($this->associationDefinition['indexBy'])) { $groupBy[] = $this->associationDefinition['indexBy']; } $sql .= ' GROUP BY ' . implode(', ', $groupBy); $sql .= ' ORDER BY ' . implode(' ASC, ', $this->metadata->getIdentifierColumnNames()) . ' ASC'; $rows = $this->auditReader->getConnection()->fetchAll($sql, $params); foreach ($rows as $row) { $entity = array('rev' => $row['rev']); unset($row['rev']); $entity['keys'] = $row; if (isset($this->associationDefinition['indexBy'])) { $key = $row[$this->associationDefinition['indexBy']]; unset($entity['keys'][$this->associationDefinition['indexBy']]); $this->entities[$key] = $entity; } else { $this->entities[] = $entity; } } $this->initialized = true; } }