diff --git a/src/Oro/Bundle/EntityConfigBundle/EventListener/OptionSetListener.php b/src/Oro/Bundle/EntityConfigBundle/EventListener/OptionSetListener.php index 5ed92edf22a..be64047fa3c 100644 --- a/src/Oro/Bundle/EntityConfigBundle/EventListener/OptionSetListener.php +++ b/src/Oro/Bundle/EntityConfigBundle/EventListener/OptionSetListener.php @@ -48,7 +48,7 @@ public function postPersist(LifecycleEventArgs $event) return; } - foreach ($schema['relation'] as $fieldName) { + foreach ($schema['relation'] as $fieldName => $fieldOptions) { if (!$configProvider->hasConfig($className, $fieldName)) { continue; } diff --git a/src/Oro/Bundle/EntityConfigBundle/Tests/Unit/EventListener/OptionSetListenerTest.php b/src/Oro/Bundle/EntityConfigBundle/Tests/Unit/EventListener/OptionSetListenerTest.php index 7fab975b732..96d52d26ec8 100644 --- a/src/Oro/Bundle/EntityConfigBundle/Tests/Unit/EventListener/OptionSetListenerTest.php +++ b/src/Oro/Bundle/EntityConfigBundle/Tests/Unit/EventListener/OptionSetListenerTest.php @@ -113,7 +113,11 @@ public function testPostPersist() $fieldName = 'testFieldName'; $secondFieldName = 'secondTestField'; - $schema = array('relation' => array($fieldName, $secondFieldName, $thirdFieldName)); + $schema = array('relation' => array( + $fieldName => array(), + $secondFieldName => array(), + $thirdFieldName => array() + )); $configProvider = $this->getMockBuilder('Oro\Bundle\EntityConfigBundle\Provider\ConfigProvider') ->disableOriginalConstructor() diff --git a/src/Oro/Bundle/EntityExtendBundle/Tests/Unit/Tools/DumperExtensions/EnumEntityConfigDumperExtensionTest.php b/src/Oro/Bundle/EntityExtendBundle/Tests/Unit/Tools/DumperExtensions/EnumEntityConfigDumperExtensionTest.php index 0663fc9fcab..c64632ccaca 100644 --- a/src/Oro/Bundle/EntityExtendBundle/Tests/Unit/Tools/DumperExtensions/EnumEntityConfigDumperExtensionTest.php +++ b/src/Oro/Bundle/EntityExtendBundle/Tests/Unit/Tools/DumperExtensions/EnumEntityConfigDumperExtensionTest.php @@ -560,8 +560,7 @@ public function testPostUpdateForMultiEnumFields() ] ], 'property' => [ - ExtendHelper::getMultiEnumSnapshotFieldName('field1') => - ExtendHelper::getMultiEnumSnapshotFieldName('field1') + ExtendHelper::getMultiEnumSnapshotFieldName('field1') => [] ] ], $entityConfig1->get('schema') @@ -636,11 +635,85 @@ public function testPostUpdateForMultiEnumFieldsInCustomEntity() ] ], 'property' => [ - ExtendHelper::getMultiEnumSnapshotFieldName('field1') => - ExtendHelper::getMultiEnumSnapshotFieldName('field1') + ExtendHelper::getMultiEnumSnapshotFieldName('field1') => [] ] ], $entityConfig1->get('schema') ); } + + public function testPostUpdateForDeletedMultiEnumField() + { + $entityConfig = new Config(new EntityConfigId('extend', 'Extend\EnumValue1')); + $entityConfig->set('owner', ExtendScope::OWNER_CUSTOM); + $entityConfig->set('is_extend', true); + $entityConfig->set( + 'schema', + [ + 'doctrine' => [ + 'Extend\EnumValue1' => [ + 'fields' => [ + ExtendHelper::getMultiEnumSnapshotFieldName('field2') => [ + 'column' => 'field2' + ] + ] + ] + ] + ] + ); + + $fieldConfig = new Config(new FieldConfigId('extend', 'Extend\EnumValue1', 'field1', 'multiEnum')); + $fieldConfig->set('is_deleted', true); + + $entityConfigs = [$entityConfig]; + $fieldConfigs = [$fieldConfig]; + + $extendConfigProvider = $this->getMockBuilder('Oro\Bundle\EntityConfigBundle\Provider\ConfigProvider') + ->disableOriginalConstructor() + ->getMock(); + $this->configManager->expects($this->once()) + ->method('getProvider') + ->with('extend') + ->will($this->returnValue($extendConfigProvider)); + $extendConfigProvider->expects($this->at(0)) + ->method('getConfigs') + ->with(null, true) + ->will($this->returnValue($entityConfigs)); + $extendConfigProvider->expects($this->at(1)) + ->method('getConfigs') + ->with($entityConfig->getId()->getClassName()) + ->will($this->returnValue($fieldConfigs)); + + $this->configManager->expects($this->once()) + ->method('persist') + ->with($this->identicalTo($entityConfig)); + + $this->extension->postUpdate(); + + $this->assertEquals( + [ + 'doctrine' => [ + 'Extend\EnumValue1' => [ + 'fields' => [ + ExtendHelper::getMultiEnumSnapshotFieldName('field1') => [ + 'column' => $this->nameGenerator->generateMultiEnumSnapshotColumnName('field1'), + 'type' => 'string', + 'nullable' => true, + 'length' => ExtendHelper::MAX_ENUM_SNAPSHOT_LENGTH, + ], + ExtendHelper::getMultiEnumSnapshotFieldName('field2') => [ + 'column' => 'field2' + ] + ] + ] + ], + 'property' => [ + ExtendHelper::getMultiEnumSnapshotFieldName('field1') => [ + 'private' => true + ] + ] + ], + $entityConfig->get('schema') + ); + } } diff --git a/src/Oro/Bundle/EntityExtendBundle/Tools/DumperExtensions/EnumEntityConfigDumperExtension.php b/src/Oro/Bundle/EntityExtendBundle/Tools/DumperExtensions/EnumEntityConfigDumperExtension.php index d1040780d6b..37d0a38d484 100644 --- a/src/Oro/Bundle/EntityExtendBundle/Tools/DumperExtensions/EnumEntityConfigDumperExtension.php +++ b/src/Oro/Bundle/EntityExtendBundle/Tools/DumperExtensions/EnumEntityConfigDumperExtension.php @@ -190,7 +190,10 @@ public function postUpdate() continue; } - $schema['property'][$snapshotFieldName] = $snapshotFieldName; + $schema['property'][$snapshotFieldName] = []; + if ($fieldConfig->is('is_deleted')) { + $schema['property'][$snapshotFieldName]['private'] = true; + } $schema['doctrine'][$mappingClassName]['fields'][$snapshotFieldName] = [ 'column' => $this->nameGenerator->generateMultiEnumSnapshotColumnName($fieldName), diff --git a/src/Oro/Bundle/EntityExtendBundle/Tools/ExtendConfigDumper.php b/src/Oro/Bundle/EntityExtendBundle/Tools/ExtendConfigDumper.php index 3074b77a9fb..a879882fb3a 100644 --- a/src/Oro/Bundle/EntityExtendBundle/Tools/ExtendConfigDumper.php +++ b/src/Oro/Bundle/EntityExtendBundle/Tools/ExtendConfigDumper.php @@ -204,22 +204,37 @@ protected function checkFields( array &$properties, array &$doctrine ) { + if ($fieldConfig->is('state', ExtendScope::STATE_DELETE)) { + $fieldConfig->set('is_deleted', true); + } else { + $fieldConfig->set('state', ExtendScope::STATE_ACTIVE); + } if ($fieldConfig->is('is_extend')) { /** @var FieldConfigId $fieldConfigId */ $fieldConfigId = $fieldConfig->getId(); $fieldName = $fieldConfigId->getFieldName(); $fieldType = $fieldConfigId->getFieldType(); + $isDeleted = $fieldConfig->is('is_deleted'); $underlyingFieldType = $this->fieldTypeHelper->getUnderlyingType($fieldType); if (in_array($underlyingFieldType, array_merge(RelationType::$anyToAnyRelations, ['optionSet']))) { - $relationProperties[$fieldName] = $fieldName; + $relationProperties[$fieldName] = []; + if ($isDeleted) { + $relationProperties[$fieldName]['private'] = true; + } if ($underlyingFieldType !== RelationType::MANY_TO_ONE && !$fieldConfig->is('without_default')) { $defaultName = self::DEFAULT_PREFIX . $fieldName; - $defaultProperties[$defaultName] = $defaultName; + $defaultProperties[$defaultName] = []; + if ($isDeleted) { + $defaultProperties[$defaultName]['private'] = true; + } } } else { - $properties[$fieldName] = $fieldName; + $properties[$fieldName] = []; + if ($isDeleted) { + $properties[$fieldName]['private'] = true; + } $doctrine[$entityName]['fields'][$fieldName] = [ 'column' => $fieldName, @@ -231,12 +246,6 @@ protected function checkFields( ]; } } - - if ($fieldConfig->is('state', ExtendScope::STATE_DELETE)) { - $fieldConfig->set('is_deleted', true); - } else { - $fieldConfig->set('state', ExtendScope::STATE_ACTIVE); - } } /** @@ -244,8 +253,8 @@ protected function checkFields( * @SuppressWarnings(PHPMD.ExcessiveMethodLength) * * @param ConfigInterface $extendConfig - * @param array|null $aliases - * @param array|null $skippedOrigins + * @param array|null $aliases + * @param array|null $skippedOrigins */ protected function checkSchema(ConfigInterface $extendConfig, $aliases, array $skippedOrigins = null) { @@ -279,11 +288,12 @@ protected function checkSchema(ConfigInterface $extendConfig, $aliases, array $s ]; } - $schema = $extendConfig->get('schema'); - $properties = []; - $relationProperties = $schema ? $schema['relation'] : []; - $defaultProperties = []; - $addRemoveMethods = []; + $schema = $extendConfig->get('schema', false, []); + $properties = isset($schema['property']) && !empty($skippedOrigins) ? $schema['property'] : []; + // Need to check if relations already exists cause we can update them in updateRelationValues. + $relationProperties = isset($schema['relation']) ? $schema['relation'] : []; + $defaultProperties = isset($schema['default']) && !empty($skippedOrigins) ? $schema['default'] : []; + $addRemoveMethods = isset($schema['addremove']) && !empty($skippedOrigins) ? $schema['addremove'] : []; $fieldConfigs = $extendProvider->filter($this->createOriginFilterCallback($skippedOrigins), $className, true); foreach ($fieldConfigs as $fieldConfig) { @@ -301,24 +311,33 @@ protected function checkSchema(ConfigInterface $extendConfig, $aliases, array $s $relations = $extendConfig->get('relation', false, []); foreach ($relations as &$relation) { - if (!$relation['field_id']) { + /** @var FieldConfigId $fieldId */ + $fieldId = $relation['field_id']; + if (!$fieldId) { continue; } $relation['assign'] = true; - if ($relation['field_id']->getFieldType() !== RelationType::MANY_TO_ONE) { - $fieldName = $relation['field_id']->getFieldName(); - - $addRemoveMethods[$fieldName]['self'] = $fieldName; - if ($relation['target_field_id']) { - $addRemoveMethods[$fieldName]['target'] = - $relation['target_field_id']->getFieldName(); - $addRemoveMethods[$fieldName]['is_target_addremove'] = - $relation['field_id']->getFieldType() === RelationType::MANY_TO_MANY; + if ($fieldId->getFieldType() !== RelationType::MANY_TO_ONE) { + $fieldName = $fieldId->getFieldName(); + $isDeleted = $extendProvider->hasConfig($fieldId->getClassName(), $fieldName) + ? $extendProvider->getConfig($fieldId->getClassName(), $fieldName)->is('is_deleted') + : false; + + if (!$isDeleted) { + $addRemoveMethods[$fieldName]['self'] = $fieldName; + /** @var FieldConfigId $targetFieldId */ + $targetFieldId = $relation['target_field_id']; + if ($targetFieldId) { + $addRemoveMethods[$fieldName]['target'] = + $targetFieldId->getFieldName(); + $addRemoveMethods[$fieldName]['is_target_addremove'] = + $targetFieldId->getFieldType() === RelationType::MANY_TO_MANY; + } } } - $this->updateRelationValues($relation['target_entity'], $relation['field_id']); + $this->updateRelationValues($relation['target_entity'], $fieldId); } $extendConfig->set('relation', $relations); @@ -423,7 +442,7 @@ protected function updateRelationValues($targetClass, FieldConfigId $fieldId) /** @var FieldConfigId $relationFieldId */ $relationFieldId = $relation['field_id']; if ($relationFieldId) { - $schema['relation'][$relationFieldId->getFieldName()] = $relationFieldId->getFieldName(); + $schema['relation'][$relationFieldId->getFieldName()] = []; } } } diff --git a/src/Oro/Bundle/EntityExtendBundle/Tools/GeneratorExtensions/ExtendEntityGeneratorExtension.php b/src/Oro/Bundle/EntityExtendBundle/Tools/GeneratorExtensions/ExtendEntityGeneratorExtension.php index 3c664263e91..ba22df543f6 100644 --- a/src/Oro/Bundle/EntityExtendBundle/Tools/GeneratorExtensions/ExtendEntityGeneratorExtension.php +++ b/src/Oro/Bundle/EntityExtendBundle/Tools/GeneratorExtensions/ExtendEntityGeneratorExtension.php @@ -89,15 +89,15 @@ protected function generateToStringMethod(array $schema, PhpClass $class) { $toString = []; foreach ($schema['property'] as $fieldName => $config) { - if ($schema['doctrine'][$schema['entity']]['fields'][$fieldName]['type'] == 'string') { + $isPrivate = is_array($config) && isset($config['private']) && $config['private']; + if (!$isPrivate && $schema['doctrine'][$schema['entity']]['fields'][$fieldName]['type'] === 'string') { $toString[] = '$this->' . $this->generateGetMethodName($fieldName) . '()'; } } - $toStringBody = 'return (string) $this->getId();'; - if (count($toString) > 0) { - $toStringBody = 'return (string)' . implode(' . ', $toString) . ';'; - } + $toStringBody = empty($toString) + ? 'return (string) $this->getId();' + : 'return (string)' . implode(' . ', $toString) . ';'; $class->setMethod($this->generateClassMethod('__toString', $toStringBody)); } @@ -109,21 +109,25 @@ protected function generateToStringMethod(array $schema, PhpClass $class) protected function generateProperties($propertyType, array $schema, PhpClass $class) { foreach ($schema[$propertyType] as $fieldName => $config) { - $class - ->setProperty(PhpProperty::create($fieldName)->setVisibility('protected')) - ->setMethod( - $this->generateClassMethod( - $this->generateGetMethodName($fieldName), - 'return $this->' . $fieldName . ';' + $class->setProperty(PhpProperty::create($fieldName)->setVisibility('protected')); + + $isPrivate = is_array($config) && isset($config['private']) && $config['private']; + if (!$isPrivate) { + $class + ->setMethod( + $this->generateClassMethod( + $this->generateGetMethodName($fieldName), + 'return $this->' . $fieldName . ';' + ) ) - ) - ->setMethod( - $this->generateClassMethod( - $this->generateSetMethodName($fieldName), - $this->getSetterBody($fieldName, $schema), - ['value'] - ) - ); + ->setMethod( + $this->generateClassMethod( + $this->generateSetMethodName($fieldName), + $this->getSetterBody($fieldName, $schema), + ['value'] + ) + ); + } } } diff --git a/src/Oro/Bundle/TrackingBundle/Command/ImportLogsCommand.php b/src/Oro/Bundle/TrackingBundle/Command/ImportLogsCommand.php index 815b212240f..f810a5fca9e 100644 --- a/src/Oro/Bundle/TrackingBundle/Command/ImportLogsCommand.php +++ b/src/Oro/Bundle/TrackingBundle/Command/ImportLogsCommand.php @@ -3,7 +3,9 @@ namespace Oro\Bundle\TrackingBundle\Command; use Akeneo\Bundle\BatchBundle\Job\BatchStatus; +use Akeneo\Bundle\BatchBundle\Job\DoctrineJobRepository; +use Doctrine\DBAL\Types\Type; use Doctrine\ORM\QueryBuilder; use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; @@ -85,19 +87,23 @@ public function execute(InputInterface $input, OutputInterface $output) $fileName = $file->getFilename(); $options = [ - 'entityName' => $this->getContainer()->getParameter('oro_tracking.tracking_data.class'), - 'processorAlias' => 'oro_tracking.processor.data', - 'file' => $pathName + ProcessorRegistry::TYPE_IMPORT => [ + 'entityName' => $this->getContainer()->getParameter('oro_tracking.tracking_data.class'), + 'processorAlias' => 'oro_tracking.processor.data', + 'file' => $pathName, + ], ]; if ($this->isFileProcessed($options)) { + $output->writeln(sprintf('"%s" already processed', $fileName)); + continue; } $jobResult = $this->getJobExecutor()->executeJob( ProcessorRegistry::TYPE_IMPORT, 'import_log_to_database', - ['import' => $options] + $options ); if ($jobResult->isSuccessful()) { @@ -132,26 +138,26 @@ protected function getJobExecutor() */ protected function isFileProcessed(array $options) { - $className = 'Akeneo\Bundle\BatchBundle\Entity\JobExecution'; + /** @var DoctrineJobRepository $repo */ + $repo = $this->getContainer()->get('akeneo_batch.job_repository'); + + $manager = $repo->getJobManager(); - $qb = $this - ->getContainer() - ->get('doctrine') - ->getManagerForClass($className) - ->getRepository($className) + $qb = $manager + ->getRepository('Akeneo\Bundle\BatchBundle\Entity\JobExecution') ->createQueryBuilder('je'); /** @var QueryBuilder $qb */ $result = $qb ->select('COUNT(je) as jobs') ->leftJoin('je.jobInstance', 'ji') - ->where('je.status NOT IN (:statuses)') + ->where($qb->expr()->lt('je.status', ':status')) + ->setParameter('status', BatchStatus::FAILED) + ->andWhere('ji.rawConfiguration = :rawConfiguration') ->setParameter( - 'statuses', - [BatchStatus::STARTING, BatchStatus::STARTED] + 'rawConfiguration', + $manager->getConnection()->convertToDatabaseValue($options, Type::TARRAY) ) - ->andWhere('ji.rawConfiguration = :rawConfiguration') - ->setParameter('rawConfiguration', serialize($options)) ->getQuery() ->getOneOrNullResult(); diff --git a/src/Oro/Bundle/TrackingBundle/Controller/TrackingDataController.php b/src/Oro/Bundle/TrackingBundle/Controller/TrackingDataController.php index 624adfe113e..2d7a0c9277f 100644 --- a/src/Oro/Bundle/TrackingBundle/Controller/TrackingDataController.php +++ b/src/Oro/Bundle/TrackingBundle/Controller/TrackingDataController.php @@ -29,7 +29,7 @@ public function createAction(Request $request) ProcessorRegistry::TYPE_IMPORT, 'import_request_to_database', [ - 'import' => [ + ProcessorRegistry::TYPE_IMPORT => [ 'entityName' => $this->container->getParameter('oro_tracking.tracking_data.class'), 'processorAlias' => 'oro_tracking.processor.data', 'data' => $request->query->all(), @@ -44,7 +44,8 @@ public function createAction(Request $request) $response['errors'] = $jobResult->getFailureExceptions(); } - if ($validationErrors = $jobResult->getContext()->getErrors()) { + $validationErrors = $jobResult->getContext()->getErrors(); + if ($validationErrors) { $isSuccessful = false; $response['validation'] = $validationErrors; diff --git a/src/Oro/Bundle/TrackingBundle/Tests/Functional/Command/ImportLogsCommandTest.php b/src/Oro/Bundle/TrackingBundle/Tests/Functional/Command/ImportLogsCommandTest.php index 84465a94f5f..ef247fc5930 100644 --- a/src/Oro/Bundle/TrackingBundle/Tests/Functional/Command/ImportLogsCommandTest.php +++ b/src/Oro/Bundle/TrackingBundle/Tests/Functional/Command/ImportLogsCommandTest.php @@ -4,6 +4,7 @@ use Symfony\Component\Filesystem\Filesystem; +use Oro\Bundle\ImportExportBundle\Processor\ProcessorRegistry; use Oro\Bundle\TestFrameworkBundle\Test\WebTestCase; /** @@ -33,10 +34,17 @@ protected function setUp() $this->fs = new Filesystem(); $this->directory = sys_get_temp_dir() . DIRECTORY_SEPARATOR . time(); + + $this->getContainer()->get('akeneo_batch.job_repository')->getJobManager()->beginTransaction(); } protected function tearDown() { + // clear DB from separate connection + $manager = $this->getContainer()->get('akeneo_batch.job_repository')->getJobManager(); + $manager->rollback(); + $manager->getConnection()->close(); + $this->fs->remove($this->directory); } @@ -87,4 +95,33 @@ public function testCurrentFileNotProcessed() $this->assertFileExists($this->directory . DIRECTORY_SEPARATOR . $file); $this->assertNotContains(sprintf('Successful: "%s"', $file), $result); } + + public function testIsFileProcessed() + { + $date = new \DateTime('now', new \DateTimeZone('UTC')); + $fileName = $date->modify('-1 day')->format('Ymd-H') . '-60-1.log'; + $file = $this->directory . DIRECTORY_SEPARATOR . $fileName; + + $this->fs->dumpFile($file, json_encode(['prop' => 'value'])); + + $jobResult = $this->getContainer()->get('oro_importexport.job_executor')->executeJob( + ProcessorRegistry::TYPE_IMPORT, + 'import_log_to_database', + [ + ProcessorRegistry::TYPE_IMPORT => [ + 'entityName' => $this->getContainer()->getParameter('oro_tracking.tracking_data.class'), + 'processorAlias' => 'oro_tracking.processor.data', + 'file' => $file, + ], + ] + ); + $this->assertTrue($jobResult->isSuccessful()); + + $result = $this->runCommand( + 'oro:cron:import-tracking', + ['--directory' => $this->directory] + ); + $this->assertFileNotExists($this->directory . DIRECTORY_SEPARATOR . $file); + $this->assertContains(sprintf('"%s" already processed', $fileName), $result); + } } diff --git a/src/Oro/Bundle/WorkflowBundle/Tests/Functional/Entity/Repository/ProcessJobRepositoryTest.php b/src/Oro/Bundle/WorkflowBundle/Tests/Functional/Entity/Repository/ProcessJobRepositoryTest.php index bbaaeac3e44..931b3819b91 100644 --- a/src/Oro/Bundle/WorkflowBundle/Tests/Functional/Entity/Repository/ProcessJobRepositoryTest.php +++ b/src/Oro/Bundle/WorkflowBundle/Tests/Functional/Entity/Repository/ProcessJobRepositoryTest.php @@ -37,30 +37,32 @@ class ProcessJobRepositoryTest extends WebTestCase protected function setUp() { $this->initClient(); + + $this->getContainer()->get('akeneo_batch.job_repository')->getJobManager()->beginTransaction(); + $this->dropJobsRecords(); $this->registry = $this->getContainer()->get('doctrine'); $this->entityManager = $this->registry->getManagerForClass('OroWorkflowBundle:ProcessJob'); $this->repository = $this->registry->getRepository('OroWorkflowBundle:ProcessJob'); - $this->loadFixtures(array('Oro\Bundle\WorkflowBundle\Tests\Functional\DataFixtures\LoadProcessEntities')); + $this->loadFixtures(['Oro\Bundle\WorkflowBundle\Tests\Functional\DataFixtures\LoadProcessEntities']); } protected function tearDown() { - parent::tearDown(); + // clear DB from separate connection + $manager = $this->getContainer()->get('akeneo_batch.job_repository')->getJobManager(); + $manager->rollback(); + $manager->getConnection()->close(); $this->dropJobsRecords(); + + parent::tearDown(); } protected function dropJobsRecords() { - // clear DB from separate connection - $batchJobManager = $this->getContainer()->get('akeneo_batch.job_repository')->getJobManager(); - $batchJobManager->createQuery('DELETE AkeneoBatchBundle:JobInstance')->execute(); - $batchJobManager->createQuery('DELETE AkeneoBatchBundle:JobExecution')->execute(); - $batchJobManager->createQuery('DELETE AkeneoBatchBundle:StepExecution')->execute(); - $this->getContainer() ->get('doctrine') ->getManager() @@ -89,7 +91,7 @@ public function testFindByIds() $this->assertCount($count, $expectedJobs); - $ids = array(); + $ids = []; /** @var ProcessJob $job */ foreach ($expectedJobs as $job) { $ids[] = $job->getId(); @@ -146,10 +148,10 @@ protected function createProcessJobs($count) ); $trigger = $this->entityManager->getRepository('OroWorkflowBundle:ProcessTrigger') - ->findOneBy(array('definition' => $definition)); + ->findOneBy(['definition' => $definition]); $entity = $this->getUser(); - $entityHashes = array(); + $entityHashes = []; for ($i = 0; $i < $count; $i++) { $processData = new ProcessData();