public function tearDown() { // Replace entity manager $moduleOptions = \SoliantEntityAudit\Module::getModuleOptions(); $moduleOptions->setEntityManager($this->_oldEntityManager); \SoliantEntityAudit\Module::getModuleOptions()->setAuditedClassNames($this->_oldAuditedClassNames); }
public function testDoesNotReturnRevisionEntity() { $sm = Bootstrap::getApplication()->getServiceManager(); $em = \SoliantEntityAudit\Module::getModuleOptions()->getEntityManager(); $helper = $sm->get('viewhelpermanager')->get('auditCurrentRevisionEntity'); $entity = new Album(); $revisionEntity = $helper($entity); $this->assertEquals(null, $revisionEntity); }
public function testGettersAndSetters() { $entity = new Revision(); $this->assertLessThanOrEqual(new \DateTime(), $entity->getTimestamp()); $userClass = \SoliantEntityAudit\Module::getModuleOptions()->getUserEntityClassName(); $user = new $userClass(); $this->assertEquals($entity, $entity->setUser($user)); $this->assertEquals($user, $entity->getUser()); $entity->setComment('Test revision entity setter and getter'); $this->assertEquals('Test revision entity setter and getter', $entity->getComment()); }
public function testGetRevisionEntitiesByEntityClass() { // Inserting data insures we will have a result > 0 $em = \SoliantEntityAudit\Module::getModuleOptions()->getEntityManager(); $service = \SoliantEntityAudit\Module::getModuleOptions()->getAuditService(); $service->setComment('test 2'); $entity = new Album(); $entity->setTitle('Test 1'); $em->persist($entity); $em->flush(); $entity->setTitle('Test 2'); $em->flush(); $serviceEntities = $service->getRevisionEntities($entity); $this->assertGreaterThan(1, sizeof($service->getRevisionEntities(get_class($entity)))); }
public function testSetUser() { $serviceManager = Bootstrap::getApplication()->getServiceManager(); $em = Bootstrap::getApplication()->getServiceManager()->get("doctrine.entitymanager.orm_default"); $moduleOptions = clone $serviceManager->get('auditModuleOptions'); $moduleOptions->setDefaults(array()); $userClass = \SoliantEntityAudit\Module::getModuleOptions()->getUserEntityClassName(); $user = new $userClass(); $user->setEmail('test'); $user->setPassword('test'); $em->persist($user); $em->flush(); $moduleOptions->setUser($user); $this->assertEquals($user, $moduleOptions->getUser()); }
public function testPaginatorCanAcceptAuditedClassName() { $sm = Bootstrap::getApplication()->getServiceManager(); $em = \SoliantEntityAudit\Module::getModuleOptions()->getEntityManager(); $helper = $sm->get('viewhelpermanager')->get('auditRevisionEntityPaginator'); $revisionEntities = $em->getRepository('SoliantEntityAudit\\Entity\\RevisionEntity')->findAll(); $count = sizeof($revisionEntities); $paginator = $helper($page = 0, get_class(array_shift($revisionEntities)->getTargetEntity())); $paginatedcount = 0; foreach ($paginator as $row) { $paginatedcount++; } $this->assertGreaterThan(0, $count); $this->assertEquals($count, $paginatedcount); }
public function getTargetEntity() { $entityManager = \SoliantEntityAudit\Module::getModuleOptions()->getEntityManager(); return $entityManager->getRepository($entityManager->getRepository($this->getAuditEntityClass())->findOneBy($this->getEntityKeys())->getAuditedEntityClass())->findOneBy($this->getEntityKeys()); }
/** * Gets the names of all mapped classes known to this driver. * * @return array The names of all mapped classes known to this driver. */ function getAllClassNames() { $moduleOptions = \SoliantEntityAudit\Module::getModuleOptions(); $entityManager = $moduleOptions->getEntityManager(); $metadataFactory = $entityManager->getMetadataFactory(); $auditEntities = array(); foreach ($moduleOptions->getAuditedClassNames() as $name => $targetClassOptions) { $auditClassName = "SoliantEntityAudit\\Entity\\" . str_replace('\\', '_', $name); $auditEntities[] = $auditClassName; $auditedClassMetadata = $metadataFactory->getMetadataFor($name); // FIXME: done in autoloader foreach ($auditedClassMetadata->getAssociationMappings() as $mapping) { if (isset($mapping['joinTable']['name'])) { $auditJoinTableClassName = "SoliantEntityAudit\\Entity\\" . str_replace('\\', '_', $mapping['joinTable']['name']); $auditEntities[] = $auditJoinTableClassName; $moduleOptions->addJoinClass($auditJoinTableClassName, $mapping); } } } // Add revision (manage here rather than separate namespace) $auditEntities[] = 'SoliantEntityAudit\\Entity\\Revision'; $auditEntities[] = 'SoliantEntityAudit\\Entity\\RevisionEntity'; return $auditEntities; }
/** * Dynamically scope an audit class * * @param string $className * @return false|string */ public function loadClass($className, $type) { $moduleOptions = \SoliantEntityAudit\Module::getModuleOptions(); if (!$moduleOptions) { return; } $entityManager = $moduleOptions->getEntityManager(); $auditClass = new ClassGenerator(); // Build a discovered many to many join class $joinClasses = $moduleOptions->getJoinClasses(); if (in_array($className, array_keys($joinClasses))) { $auditClass->setNamespaceName("SoliantEntityAudit\\Entity"); $auditClass->setName($className); $auditClass->setExtendedClass('AbstractAudit'); $auditClass->addProperty('id', null, PropertyGenerator::FLAG_PROTECTED); $auditClass->addProperty('targetRevisionEntity', null, PropertyGenerator::FLAG_PROTECTED); $auditClass->addProperty('sourceRevisionEntity', null, PropertyGenerator::FLAG_PROTECTED); $auditClass->addMethod('getTargetRevisionEntity', array(), MethodGenerator::FLAG_PUBLIC, 'return $this->targetRevisionEntity;'); $auditClass->addMethod('getSourceRevisionEntity', array(), MethodGenerator::FLAG_PUBLIC, 'return $this->sourceRevisionEntity;'); $auditClass->addMethod('getId', array(), MethodGenerator::FLAG_PUBLIC, 'return $this->id;'); $auditClass->addMethod('setTargetRevisionEntity', array(ParameterGenerator::fromArray(array('name' => 'value', 'type' => '\\SoliantEntityAudit\\Entity\\RevisionEntity'))), MethodGenerator::FLAG_PUBLIC, '$this->targetRevisionEntity = $value;' . "\n" . 'return $this;'); $auditClass->addMethod('setSourceRevisionEntity', array(ParameterGenerator::fromArray(array('name' => 'value', 'type' => '\\SoliantEntityAudit\\Entity\\RevisionEntity'))), MethodGenerator::FLAG_PUBLIC, '$this->sourceRevisionEntity = $value;' . "\n" . 'return $this;'); # print_r($auditClass->generate()); # die(); eval($auditClass->generate()); return; } // Add revision reference getter and setter $auditClass->addProperty($moduleOptions->getRevisionEntityFieldName(), null, PropertyGenerator::FLAG_PROTECTED); $auditClass->addMethod('get' . $moduleOptions->getRevisionEntityFieldName(), array(), MethodGenerator::FLAG_PUBLIC, " return \$this->" . $moduleOptions->getRevisionEntityFieldName() . ";"); $auditClass->addMethod('set' . $moduleOptions->getRevisionEntityFieldName(), array('value'), MethodGenerator::FLAG_PUBLIC, " \$this->" . $moduleOptions->getRevisionEntityFieldName() . " = \$value;\nreturn \$this;\r\n "); // Verify this autoloader is used for target class #FIXME: why is this sent work outside the set namespace? foreach ($moduleOptions->getAuditedClassNames() as $targetClass => $targetClassOptions) { $auditClassName = 'SoliantEntityAudit\\Entity\\' . str_replace('\\', '_', $targetClass); if ($auditClassName == $className) { $currentClass = $targetClass; } $autoloadClasses[] = $auditClassName; } if (!in_array($className, $autoloadClasses)) { return; } // Get fields from target entity $metadataFactory = $entityManager->getMetadataFactory(); $auditedClassMetadata = $metadataFactory->getMetadataFor($currentClass); $fields = $auditedClassMetadata->getFieldNames(); $identifiers = $auditedClassMetadata->getFieldNames(); $service = \SoliantEntityAudit\Module::getModuleOptions()->getAuditService(); // Generate audit entity foreach ($fields as $field) { $auditClass->addProperty($field, null, PropertyGenerator::FLAG_PROTECTED); } foreach ($auditedClassMetadata->getAssociationNames() as $associationName) { $auditClass->addProperty($associationName, null, PropertyGenerator::FLAG_PROTECTED); $fields[] = $associationName; } $auditClass->addMethod('getAssociationMappings', array(), MethodGenerator::FLAG_PUBLIC, "return unserialize('" . serialize($auditedClassMetadata->getAssociationMappings()) . "');"); // Add exchange array method $setters = array(); foreach ($fields as $fieldName) { $setters[] = '$this->' . $fieldName . ' = (isset($data["' . $fieldName . '"])) ? $data["' . $fieldName . '"]: null;'; $arrayCopy[] = " \"{$fieldName}\"" . ' => $this->' . $fieldName; } $auditClass->addMethod('getArrayCopy', array(), MethodGenerator::FLAG_PUBLIC, "return array(\n" . implode(",\n", $arrayCopy) . "\n);"); $auditClass->addMethod('exchangeArray', array('data'), MethodGenerator::FLAG_PUBLIC, implode("\n", $setters)); // Add function to return the entity class this entity audits $auditClass->addMethod('getAuditedEntityClass', array(), MethodGenerator::FLAG_PUBLIC, " return '" . addslashes($currentClass) . "';"); $auditClass->setNamespaceName("SoliantEntityAudit\\Entity"); $auditClass->setName(str_replace('\\', '_', $currentClass)); // $auditedClassMetadata = $metadataFactory->getMetadataFor($currentClass); if ($auditedClassMetadata->parentClasses) { $auditClass->setExtendedClass(str_replace('\\', '_', array_pop($auditedClassMetadata->parentClasses))); } else { $auditClass->setExtendedClass('AbstractAudit'); } foreach ($auditedClassMetadata->getAssociationMappings() as $mapping) { if (isset($mapping['joinTable']['name'])) { $auditJoinTableClassName = "SoliantEntityAudit\\Entity\\" . str_replace('\\', '_', $mapping['joinTable']['name']); $auditEntities[] = $auditJoinTableClassName; $moduleOptions->addJoinClass($auditJoinTableClassName, $mapping); } } # if ($auditClass->getName() == 'AppleConnect_Entity_UserAuthenticationLog') { # echo '<pre>'; # echo($auditClass->generate()); # die(); # } eval($auditClass->generate()); # die(); return true; }
public function associationTargetAction() { // When an association is requested all audit metadata must // be loaded in order to create the necessary join table // information $moduleOptions = $this->getServiceLocator()->get('auditModuleOptions'); $this->mapAllAuditedClasses(); foreach ($moduleOptions->getAuditedClassNames() as $className => $route) { $auditClassName = 'SoliantEntityAudit\\Entity\\' . str_replace('\\', '_', $className); $x = new $auditClassName(); } $joinClasses = $moduleOptions->getJoinClasses(); $page = (int) $this->getEvent()->getRouteMatch()->getParam('page'); $joinTable = $this->getEvent()->getRouteMatch()->getParam('joinTable'); $revisionEntityId = $this->getEvent()->getRouteMatch()->getParam('revisionEntityId'); $auditService = $this->getServiceLocator()->get('auditService'); $revisionEntity = \SoliantEntityAudit\Module::getModuleOptions()->getEntityManager()->getRepository('SoliantEntityAudit\\Entity\\RevisionEntity')->find($revisionEntityId); if (!$revisionEntity) { return $this->plugin('redirect')->toRoute('audit'); } return array('revisionEntity' => $revisionEntity, 'page' => $page, 'joinTable' => $joinTable); }
public function postFlush(PostFlushEventArgs $args) { if ($this->getEntities() and !$this->getInAuditTransaction()) { $this->setInAuditTransaction(true); $moduleOptions = Module::getModuleOptions(); $entityManager = $moduleOptions->getEntityManager(); $entityManager->beginTransaction(); // Insert entites will trigger key generation and must be // re-exchanged (delete entites go out of scope) foreach ($this->getReexchangeEntities() as $entityMap) { $entityMap['auditEntity']->exchangeArray($this->getClassProperties($entityMap['entity'])); $entityMap['revisionEntity']->setAuditEntity($entityMap['auditEntity']); } // Flush revision and revisionEntities $entityManager->persist($this->getRevision()); foreach ($this->getRevisionEntities() as $entity) { $entityManager->persist($entity); } $entityManager->flush(); foreach ($this->getEntities() as $entity) { $entityManager->persist($entity); } // Persist many to many collections foreach ($this->getCollections() as $value) { $mapping = $value->getMapping(); if (!$mapping['isOwningSide']) { continue; } $joinClassName = "SoliantEntityAudit\\Entity\\" . str_replace('\\', '_', $mapping['joinTable']['name']); $moduleOptions->addJoinClass($joinClassName, $mapping); $revisionEntity = null; foreach ($this->many2many as $map) { if ($map['collection'] == $value) { $revisionEntity = $map['revisionEntity']; break; } } if (!$revisionEntity) { continue; } foreach ($value->getSnapshot() as $element) { $audit = new $joinClassName(); // Get current inverse revision entity $revisionEntities = $entityManager->getRepository('SoliantEntityAudit\\Entity\\RevisionEntity')->findBy(array('targetEntityClass' => $this->getEntityClass($element), 'entityKeys' => serialize(array('id' => $element->getId()))), array('id' => 'DESC'), 1); $inverseRevisionEntity = reset($revisionEntities); if (!$inverseRevisionEntity) { // No inverse revision entity found continue; } $audit->setTargetRevisionEntity($revisionEntity); $audit->setSourceRevisionEntity($inverseRevisionEntity); $entityManager->persist($audit); } } $entityManager->flush(); $entityManager->commit(); $this->resetEntities(); $this->resetReexchangeEntities(); $this->resetRevision(); $this->resetRevisionEntities(); $this->setInAuditTransaction(false); } }
/** * Pass an audited entity or the audit entity * and return a collection of RevisionEntity s * for that record */ public function getRevisionEntities($entity) { $entityManager = \SoliantEntityAudit\Module::getModuleOptions()->getEntityManager(); if (gettype($entity) != 'string' and in_array(get_class($entity), array_keys(\SoliantEntityAudit\Module::getModuleOptions()->getAuditedClassNames()))) { $auditEntityClass = 'SoliantEntityAudit\\Entity\\' . str_replace('\\', '_', get_class($entity)); $identifiers = $this->getEntityIdentifierValues($entity); } elseif ($entity instanceof AbstractAudit) { $auditEntityClass = get_class($entity); $identifiers = $this->getEntityIdentifierValues($entity, true); } else { $auditEntityClass = 'SoliantEntityAudit\\Entity\\' . str_replace('\\', '_', $entity); } $search = array('auditEntityClass' => $auditEntityClass); if (isset($identifiers)) { $search['entityKeys'] = serialize($identifiers); } return $entityManager->getRepository('SoliantEntityAudit\\Entity\\RevisionEntity')->findBy($search, array('id' => 'DESC')); }