/** * @Remote */ public function suggestAction(array $params) { Toolkit::validateRequiredRequestParams($params, ['queryType', 'query']); /* @var FilterAutoSuggestService $service */ $service = $this->get('modera_backend_tools_activity_log.auto_suggest.filter_auto_suggest_service'); return $service->suggest($params['queryType'], $params['query']); }
/** * {@inheritdoc} */ public function create(array $params, array $config) { $entityClass = $config['entity']; // if __construct method doesn't have any mandatory parameters the we will use it $useConstructor = false; foreach (Toolkit::getReflectionMethods($entityClass) as $reflMethod) { /* @var \ReflectionMethod $reflMethod */ if ($reflMethod->getName() == '__construct' && $reflMethod->isPublic()) { if (count($reflMethod->getParameters()) == 0) { $useConstructor = true; } else { // if all parameters are optional we still can use constructor $allParametersOptional = true; foreach ($reflMethod->getParameters() as $reflParam) { /* @var \ReflectionParameter $reflParam */ if (!$reflParam->isOptional()) { $allParametersOptional = false; } } $useConstructor = $allParametersOptional; } } } if ($useConstructor) { return new $entityClass(); } else { $serialized = sprintf('O:%u:"%s":0:{}', strlen($entityClass), $entityClass); return unserialize($serialized); } }
public function testHowWellContainerIsInjected() { $repository = new Repository('test repo', array('filesystem' => '', 'storage_key_generator' => '')); self::$em->persist($repository); self::$em->flush(); self::$em->clear(); /* @var Repository $repository */ $repository = self::$em->getRepository(Repository::clazz())->find($repository->getId()); $this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\ContainerInterface', Toolkit::getPropertyValue($repository, 'container')); }
public function resolve($entityFqcn, $fieldName) { $metadata = $this->em->getClassMetadata($entityFqcn); if (!$metadata) { throw new \RuntimeException("Unable to load metadata for class '{$entityFqcn}'."); } $fieldMapping = $metadata->getAssociationMapping($fieldName); /* @var QueryOrder $ann */ $ann = $this->ar->getPropertyAnnotation(Tk::getReflectionProperty($entityFqcn, $fieldName), QueryOrder::clazz()); if (!$ann) { // no property annotation found $ann = $this->ar->getClassAnnotation(new \ReflectionClass($fieldMapping['targetEntity']), QueryOrder::clazz()); if (!$ann) { // no class annotation found return $this->getDefaultPropertyName($fieldMapping['targetEntity']); } else { return $ann->value; } } else { return $ann->value; } }
public function testHowWellItWorks() { /* @var FileRepository $fr */ $fr = self::$container->get('modera_file_repository.repository.file_repository'); $this->assertNull($fr->getRepository('dummy_repository')); $repositoryConfig = array('storage_key_generator' => 'modera_file_repository.repository.uniqid_key_generator', 'filesystem' => 'dummy_tmp_fs'); $this->assertFalse($fr->repositoryExists('dummy_repository')); $repository = $fr->createRepository('dummy_repository', $repositoryConfig, 'My dummy repository'); $this->assertTrue($fr->repositoryExists('dummy_repository')); $this->assertInstanceOf(Repository::clazz(), $repository); $this->assertNotNull($repository->getId()); $this->assertEquals('dummy_repository', $repository->getName()); $this->assertEquals('My dummy repository', $repository->getLabel()); $this->assertSame($repositoryConfig, $repository->getConfig()); $this->assertInstanceOf('Symfony\\Component\\DependencyInjection\\ContainerInterface', Toolkit::getPropertyValue($repository, 'container')); // --- $fileContents = 'foo contents'; $filePath = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'our-dummy-file.txt'; file_put_contents($filePath, $fileContents); $file = new File($filePath); $storedFile = $fr->put($repository->getName(), $file, array()); self::$em->clear(); // this way we will make sure that data is actually persisted in database /* @var StoredFile $storedFile */ $storedFile = self::$em->find(StoredFile::clazz(), $storedFile->getId()); $this->assertInstanceOf(StoredFile::clazz(), $storedFile); $this->assertNotNull($storedFile->getId()); $this->assertNotNull($storedFile->getStorageKey()); $this->assertEquals('our-dummy-file.txt', $storedFile->getFilename()); $this->assertNotNull($storedFile->getCreatedAt()); $this->assertEquals('txt', $storedFile->getExtension()); $this->assertEquals('text/plain', $storedFile->getMimeType()); $this->assertSame($repository->getId(), $storedFile->getRepository()->getId()); $this->assertEquals($fileContents, $storedFile->getContents()); $this->assertTrue('' != $storedFile->getChecksum()); $this->assertEquals($file->getSize(), $storedFile->getSize()); // --- $storedFileData = array('id' => $storedFile->getId(), 'storageKey' => $storedFile->getStorageKey(), 'filename' => $storedFile->getFilename()); $fileContents = 'bar contents'; $filePath = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'bar-dummy-file.txt'; file_put_contents($filePath, $fileContents); $file = new File($filePath); $storedFile = $fr->put($repository->getName(), $file, array()); self::$em->clear(); // this way we will make sure that data is actually persisted in database /* @var StoredFile $storedFile */ $storedFile = self::$em->find(StoredFile::clazz(), $storedFile->getId()); $this->assertNotEquals($storedFileData['id'], $storedFile->getId()); $this->assertNotEquals($storedFileData['storageKey'], $storedFile->getStorageKey()); $this->assertNotEquals($storedFileData['filename'], $storedFile->getFilename()); // --- $repositoryConfig['overwrite_files'] = true; $repository = $storedFile->getRepository(); $repository->setConfig($repositoryConfig); self::$em->persist($repository); self::$em->flush(); $storedFileData = array('id' => $storedFile->getId(), 'storageKey' => $storedFile->getStorageKey(), 'filename' => $storedFile->getFilename()); $storedFile = $fr->put($repository->getName(), $file, array()); self::$em->clear(); // this way we will make sure that data is actually persisted in database /* @var StoredFile $storedFile */ $storedFile = self::$em->find(StoredFile::clazz(), $storedFile->getId()); $this->assertEquals($storedFileData['id'], $storedFile->getId()); $this->assertEquals($storedFileData['storageKey'], $storedFile->getStorageKey()); $this->assertEquals($storedFileData['filename'], $storedFile->getFilename()); // --- $fs = $storedFile->getRepository()->getFilesystem(); $this->assertTrue($fs->has($storedFile->getStorageKey())); self::$em->remove($storedFile); self::$em->flush(); $this->assertFalse($fs->has($storedFile->getStorageKey())); }
/** * @Remote */ public function batchUpdateAction(array $params) { $config = $this->getPreparedConfig(); try { $persistenceHandler = $config['batch_update_entities_handler']; $dataMapper = $config['map_data_on_update']; $validator = $config['updated_entity_validator']; $this->interceptAction('batchUpdate', $params); if (isset($params['queries']) && is_array($params['queries']) && isset($params['record']) && is_array($params['record'])) { if (!isset($params['record'])) { $e = new BadRequestException("'/record' hasn't been provided"); $e->setParams($params); $e->setPath('/record'); throw $e; } $entities = array(); foreach ($params['queries'] as $query) { $entities = array_merge($entities, $this->getPersistenceHandler()->query($config['entity'], $query)); } $errors = array(); $operationResult = null; foreach ($entities as $entity) { $dataMapper($params['record'], $entity, $this->getDataMapper(), $this->container); if ($validator) { /* @var ValidationResult $validationResult */ $validationResult = $validator($params, $entity, $this->getEntityValidator(), $config, $this->container); if ($validationResult->hasErrors()) { $pkFields = $this->getPersistenceHandler()->resolveEntityPrimaryKeyFields($config['entity']); $ids = array(); foreach ($pkFields as $fieldName) { $ids[$fieldName] = Toolkit::getPropertyValue($entity, $fieldName); } $errors[] = array('id' => $ids, 'errors' => $validationResult->toArray()); } } } if (count($errors) == 0) { $operationResult = $persistenceHandler($entities, $params, $this->getPersistenceHandler(), $this->container); return array_merge($operationResult->toArray($this->getModelManager()), array('success' => true)); } else { return array('success' => false, 'errors' => $errors); } } elseif (isset($params['records']) && is_array($params['records'])) { $entities = array(); $errors = array(); foreach ($params['records'] as $recordParams) { $missingPkFields = array(); $query = array(); foreach ($this->getPersistenceHandler()->resolveEntityPrimaryKeyFields($config['entity']) as $fieldName) { if (isset($recordParams[$fieldName])) { $query[] = array('property' => $fieldName, 'value' => 'eq:' . $recordParams[$fieldName]); } else { $missingPkFields[] = $fieldName; } } if (count($missingPkFields) == 0) { $entity = $this->getPersistenceHandler()->query($config['entity'], array('filter' => $query)); $this->validateResultHasExactlyOneEntity($entity, $params); $entity = $entity[0]; $entities[] = $entity; $dataMapper($recordParams, $entity, $this->getDataMapper(), $this->container); if ($validator) { /* @var ValidationResult $validationResult */ $validationResult = $validator($params, $entity, $this->getEntityValidator(), $config, $this->container); if ($validationResult->hasErrors()) { $pkFields = $this->getPersistenceHandler()->resolveEntityPrimaryKeyFields($config['entity']); $ids = array(); foreach ($pkFields as $fieldName) { $ids[$fieldName] = Toolkit::getPropertyValue($entity, $fieldName); } $errors[] = array('id' => $ids, 'errors' => $validationResult->toArray()); } } } } if (count($errors) == 0) { $operationResult = $persistenceHandler($entities, $params, $this->getPersistenceHandler(), $this->container); return array_merge($operationResult->toArray($this->getModelManager()), array('success' => true)); } else { return array('success' => false, 'errors' => $errors); } } else { $e = new BadRequestException("Invalid request structure. Valid request would either contain 'queries' and 'record' or 'records' keys."); $e->setPath($params); $e->setPath('/'); throw $e; } } catch (\Exception $e) { return $this->createExceptionResponse($e, ExceptionHandlerInterface::OPERATION_UPDATE); } }
public static function doSetUpBeforeClass() { $driver = new AnnotationDriver(self::$kernel->getContainer()->get('annotation_reader'), array(__DIR__)); Toolkit::addMetadataDriverForEntityManager(self::$em, $driver, __NAMESPACE__); }
public static function doTearDownAfterClass() { Toolkit::dropTableForEntity(self::$em, DummyArticle::clazz()); }
/** * Be aware, that "id" property will never be mapped to you entities even if it is provided * in $params, we presume that it always be generated automatically. * * @param Object $entity * @param array $params Data usually received from client-side * @param array $allowedFields Fields names you want to allow have mapped * @throws \RuntimeException */ public function mapEntity($entity, array $params, array $allowedFields) { $entityMethods = get_class_methods($entity); $metadata = $this->em->getClassMetadata(get_class($entity)); foreach ($metadata->getFieldNames() as $fieldName) { if (!in_array($fieldName, $allowedFields) || 'id' == $fieldName) { // ID is always generated dynamically continue; } if (isset($params[$fieldName])) { $value = $params[$fieldName]; $mapping = $metadata->getFieldMapping($fieldName); // if a field is number and at the same time its value was not provided, // then we are not touching it at all, if the model has specified // a default value for it - fine, everything's gonna be fine, otherwise // Doctrine will look if this field isNullable etc ... and throw // an exception if needed if (!(in_array($mapping['type'], array('integer', 'smallint', 'bigint', 'decimal', 'float')) && '' === $value)) { try { $methodParams = $this->paramsProvider->getParameters(get_class($entity), $this->fm->formatSetterName($fieldName)); $convertedValue = null; if (is_object($value) || is_array($value)) { foreach ($this->complexFiledValueConvertersProvider->getItems() as $converter) { /* @var ComplexFieldValueConverterInterface $converter */ if ($converter->isResponsible($value, $fieldName, $metadata)) { $convertedValue = $converter->convert($value, $fieldName, $metadata); } } } else { $convertedValue = $this->convertValue($value, $mapping['type']); } $methodParams = array_merge(array($convertedValue), $methodParams); $this->fm->set($entity, $fieldName, $methodParams); } catch (\Exception $e) { throw new \RuntimeException("Something went wrong during mapping of a scalar field '{$fieldName}' - " . $e->getMessage(), null, $e); } } } } foreach ($metadata->getAssociationMappings() as $mapping) { $fieldName = $mapping['fieldName']; if (!in_array($fieldName, $allowedFields)) { continue; } if (isset($params[$fieldName]) && null !== $params[$fieldName]) { if (in_array($mapping['type'], array(CMI::ONE_TO_ONE, CMI::MANY_TO_ONE))) { $rawValue = $params[$fieldName]; $methodParams = $this->paramsProvider->getParameters(get_class($entity), $this->fm->formatSetterName($fieldName)); if ('-' == $rawValue) { $this->fm->set($entity, $fieldName, array_merge(array(null), $methodParams)); } else { $value = $this->em->getRepository($mapping['targetEntity'])->find($rawValue); if ($value) { $this->fm->set($entity, $fieldName, array_merge(array($value), $methodParams)); } } } else { // one_to_many, many_to_many $rawValue = $params[$fieldName]; $col = $metadata->getFieldValue($entity, $fieldName); // if it is a new entity ( you should remember, the entity's constructor is not invoked ) // it will have no collection initialized, because this usually happens in the constructor if (!$col) { $col = new ArrayCollection(); $this->fm->set($entity, $fieldName, array($col)); } $oldIds = Toolkit::extractIds($col); $newIds = is_array($rawValue) ? $rawValue : explode(', ', $rawValue); $idsToDelete = array_diff($oldIds, $newIds); $idsToAdd = array_diff($newIds, $oldIds); $entitiesToDelete = $this->getEntitiesByIds($idsToDelete, $mapping['targetEntity']); $entitiesToAdd = $this->getEntitiesByIds($idsToAdd, $mapping['targetEntity']); /* * At first it will be checked if removeXXX/addXXX methods exist, if they * do, then they will be used, otherwise we will try to manage * relation manually */ $removeMethod = 'remove' . ucfirst(Toolkit::singlifyWord($fieldName)); if (in_array($removeMethod, $entityMethods) && count($idsToDelete) > 0) { foreach ($entitiesToDelete as $refEntity) { $methodParams = array_merge(array($refEntity), $this->paramsProvider->getParameters(get_class($entity), $removeMethod)); call_user_func_array(array($entity, $removeMethod), $methodParams); } } else { foreach ($entitiesToDelete as $refEntity) { if ($col->contains($refEntity)) { $col->removeElement($refEntity); if (CMI::MANY_TO_MANY == $mapping['type']) { $refMetadata = $this->em->getClassMetadata(get_class($refEntity)); // bidirectional if ($refMetadata->hasAssociation($mapping['mappedBy'])) { $inversedCol = $refMetadata->getFieldValue($refEntity, $mapping['mappedBy']); if ($inversedCol instanceof Collection) { $inversedCol->removeElement($entity); } } } else { // nulling the other side of relation $this->fm->set($refEntity, $mapping['mappedBy'], array(null)); } } } } $addMethod = 'add' . ucfirst(Toolkit::singlifyWord($fieldName)); if (in_array($addMethod, $entityMethods) && count($idsToAdd) > 0) { foreach ($entitiesToAdd as $refEntity) { $methodParams = array_merge(array($refEntity), $this->paramsProvider->getParameters(get_class($entity), $addMethod)); call_user_func_array(array($entity, $addMethod), $methodParams); } } else { foreach ($entitiesToAdd as $refEntity) { if (!$col->contains($refEntity)) { $col->add($refEntity); if (CMI::MANY_TO_MANY == $mapping['type']) { $refMetadata = $this->em->getClassMetadata(get_class($refEntity)); // bidirectional if ($refMetadata->hasAssociation($mapping['mappedBy'])) { $inversedCol = $refMetadata->getFieldValue($refEntity, $mapping['mappedBy']); if ($inversedCol instanceof Collection) { $inversedCol->add($entity); } } } else { $this->fm->set($refEntity, $mapping['mappedBy'], array($entity)); } } } } } } } }