/** * {@inheritDoc} */ public function load(ObjectManager $manager) { $entityManager = $this->container->get('doctrine')->getManager(); // first definition $firstDefinition = new ProcessDefinition(); $firstDefinition->setName(self::FIRST_DEFINITION)->setLabel(self::FIRST_DEFINITION)->setRelatedEntity('Test\\Entity')->setExecutionOrder(10); $updateTrigger = new ProcessTrigger(); $updateTrigger->setDefinition($firstDefinition)->setEvent(ProcessTrigger::EVENT_UPDATE)->setField(self::UPDATE_TRIGGER_FIELD); $entityManager->persist($firstDefinition); $entityManager->persist($updateTrigger); // second definition $secondDefinition = new ProcessDefinition(); $secondDefinition->setName(self::SECOND_DEFINITION)->setLabel(self::SECOND_DEFINITION)->setRelatedEntity('Test\\Entity')->setExecutionOrder(20); $createTrigger = new ProcessTrigger(); $createTrigger->setDefinition($secondDefinition)->setEvent(ProcessTrigger::EVENT_CREATE); $deleteTrigger = new ProcessTrigger(); $deleteTrigger->setDefinition($secondDefinition)->setEvent(ProcessTrigger::EVENT_DELETE); $entityManager->persist($secondDefinition); $entityManager->persist($createTrigger); $entityManager->persist($deleteTrigger); // disabled definition $disabledDefinition = new ProcessDefinition(); $disabledDefinition->setName(self::DISABLED_DEFINITION)->setLabel(self::DISABLED_DEFINITION)->setRelatedEntity('Test\\Entity')->setExecutionOrder(30)->setEnabled(false); $createTrigger = new ProcessTrigger(); $createTrigger->setDefinition($disabledDefinition)->setEvent(ProcessTrigger::EVENT_CREATE); $entityManager->persist($disabledDefinition); $entityManager->persist($createTrigger); $entityManager->flush(); }
/** * @param array $configuration * @param ProcessDefinition $definition * @return ProcessTrigger * @throws InvalidParameterException */ public function buildProcessTrigger(array $configuration, ProcessDefinition $definition) { $this->assertConfigurationOptions($configuration, array('event')); $event = $configuration['event']; if (!in_array($event, ProcessTrigger::getAllowedEvents())) { throw new InvalidParameterException(sprintf('Event "%s" is not allowed', $event)); } $field = $this->getConfigurationOption($configuration, 'field', null); $priority = $this->getConfigurationOption($configuration, 'priority', Job::PRIORITY_DEFAULT); $queued = $this->getConfigurationOption($configuration, 'queued', false); $timeShift = $this->getConfigurationOption($configuration, 'time_shift', null); if ($timeShift && !is_int($timeShift) && !$timeShift instanceof \DateInterval) { throw new InvalidParameterException('Time shift parameter must be either integer or DateInterval'); } if ($field && $event != ProcessTrigger::EVENT_UPDATE) { throw new InvalidParameterException('Field is only allowed for update event'); } $trigger = new ProcessTrigger(); $trigger->setEvent($event)->setField($field)->setPriority($priority)->setQueued($queued)->setDefinition($definition); if ($timeShift instanceof \DateInterval) { $trigger->setTimeShiftInterval($timeShift); } else { $trigger->setTimeShift($timeShift); } return $trigger; }
/** * @param string $message * @param ProcessTrigger $trigger * @param ProcessData $data */ public function debug($message, ProcessTrigger $trigger, ProcessData $data) { if ($this->logger) { $context = array('definition' => $trigger->getDefinition()->getName(), 'event' => $trigger->getEvent(), 'entityId' => $this->doctrineHelper->getSingleEntityIdentifier($data['data'], false)); $this->logger->debug($message, $context); } }
public function testPostFlush() { $serializedData = 'serializedData'; $processDefinition = new ProcessDefinition(); $processDefinition->setRelatedEntity(self::TEST_CLASS); $processTrigger = new ProcessTrigger(); $processTrigger->setDefinition($processDefinition); $processData = new ProcessData(); $processData->set('test', 'value'); $processJob = new ProcessJob(); $processJob->setProcessTrigger($processTrigger)->setData($processData); $unitOfWork = $this->getMockBuilder('Doctrine\\ORM\\UnitOfWork')->disableOriginalConstructor()->getMock(); $unitOfWork->expects($this->at(0))->method('getScheduledEntityInsertions')->will($this->returnValue(array($processJob))); $unitOfWork->expects($this->at(1))->method('getScheduledEntityUpdates')->will($this->returnValue(array($processJob))); $entityId = 1; $entityHash = ProcessJob::generateEntityHash(self::TEST_CLASS, $entityId); $this->serializer->expects($this->exactly(2))->method('serialize')->with($processJob->getData(), 'json', array('processJob' => $processJob))->will($this->returnCallback(function () use($processJob, $entityId, $serializedData) { $processJob->setEntityId($entityId); return $serializedData; })); $entityManager = $this->getMockBuilder('Doctrine\\ORM\\EntityManager')->disableOriginalConstructor()->getMock(); $entityManager->expects($this->any())->method('getUnitOfWork')->will($this->returnValue($unitOfWork)); $entityManager->expects($this->once())->method('flush'); $this->listener->onFlush(new OnFlushEventArgs($entityManager)); $this->listener->postFlush(new PostFlushEventArgs($entityManager)); $this->assertEquals($serializedData, $processJob->getSerializedData()); $this->assertEquals($entityId, $processJob->getEntityId()); $this->assertEquals($entityHash, $processJob->getEntityHash()); $this->assertFalse($processJob->getData()->isModified()); }
/** * @param bool $hasLogger * @dataProvider debugDataProvider */ public function testDebug($hasLogger) { $doctrineHelper = $this->getMockBuilder('Oro\\Bundle\\EntityBundle\\ORM\\DoctrineHelper')->disableOriginalConstructor()->getMock(); $definitionName = 'test_definition'; $definition = new ProcessDefinition(); $definition->setName($definitionName); $triggerEvent = ProcessTrigger::EVENT_UPDATE; $trigger = new ProcessTrigger(); $trigger->setEvent($triggerEvent)->setDefinition($definition); $entity = new \stdClass(); $entityId = 1; $data = new ProcessData(array('data' => $entity)); $message = 'Test debug message'; $context = array('definition' => $definitionName, 'event' => $triggerEvent, 'entityId' => $entityId); if ($hasLogger) { $doctrineHelper->expects($this->once())->method('getSingleEntityIdentifier')->with($entity, false)->will($this->returnValue($entityId)); $logger = $this->getMock('Psr\\Log\\LoggerInterface'); $logger->expects($this->once())->method('debug')->with($message, $context); } else { $doctrineHelper->expects($this->never())->method('getSingleEntityIdentifier'); $logger = null; } $processLogger = new ProcessLogger($doctrineHelper, $logger); $processLogger->debug($message, $trigger, $data); }
public function testEqualTriggers() { $definition = $this->entityManager->find('OroWorkflowBundle:ProcessDefinition', LoadProcessEntities::FIRST_DEFINITION); $trigger = $this->repository->findOneBy(array('definition' => $definition)); // test equal (existing) trigger $equalTrigger = new ProcessTrigger(); $equalTrigger->setDefinition($definition)->setEvent(ProcessTrigger::EVENT_UPDATE)->setField(LoadProcessEntities::UPDATE_TRIGGER_FIELD); $this->assertEquals($trigger, $this->repository->findEqualTrigger($equalTrigger)); $this->assertTrue($this->repository->isEqualTriggerExists($equalTrigger)); // test not equal (not existing) trigger $notEqualTrigger = new ProcessTrigger(); $notEqualTrigger->setDefinition($definition)->setEvent(ProcessTrigger::EVENT_CREATE); $this->assertNull($this->repository->findEqualTrigger($notEqualTrigger)); $this->assertFalse($this->repository->isEqualTriggerExists($notEqualTrigger)); }
/** * @param ArrayNodeDefinition $nodeDefinition * @return ArrayNodeDefinition * * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) */ public function addTriggerNodes(ArrayNodeDefinition $nodeDefinition) { $nodeDefinition->children()->enumNode('event')->defaultNull()->values(ProcessTrigger::getAllowedEvents())->end()->scalarNode('field')->defaultNull()->end()->integerNode('priority')->defaultValue(Job::PRIORITY_DEFAULT)->end()->booleanNode('queued')->defaultFalse()->end()->scalarNode('time_shift')->defaultNull()->validate()->always(function ($value) { // if value is an integer value $integerValue = filter_var($value, FILTER_VALIDATE_INT); if (false !== $integerValue) { return $integerValue; } // if value is DateInterval spec try { return ProcessTrigger::convertDateIntervalToSeconds(new \DateInterval($value)); } catch (\Exception $e) { throw new \LogicException(sprintf('Time shift "%s" is not compatible with DateInterval', $value)); } })->end()->end()->scalarNode('cron')->defaultNull()->validate()->always(function ($value) { if ($value !== null) { // validate expression string CronExpression::factory($value); } return $value; })->end()->end()->end()->validate()->always(function ($data) { if ($data['event'] && $data['cron']) { throw new \LogicException('Only one child node "event" or "cron" must be configured.'); } if ($data['cron'] && ($data['field'] || $data['queued'] || $data['time_shift'])) { throw new \LogicException('Nodes "field", "queued" and "time_shift" are only allowed with event node.'); } if ($data['field'] && $data['event'] !== ProcessTrigger::EVENT_UPDATE) { throw new \LogicException('Field is only allowed for update event'); } return $data; })->end(); return $nodeDefinition; }
/** * {@inheritDoc} */ public function load(ObjectManager $manager) { foreach ($this->definitions as $name => $config) { $definition = new ProcessDefinition(); $definition->setName($name)->setLabel($name)->setRelatedEntity($config['related_entity'])->setExecutionOrder($config['execution_order'])->setEnabled($config['enabled']); $this->definitions[$name] = $definition; $manager->persist($definition); } foreach ($this->triggers as $key => $config) { $trigger = new ProcessTrigger(); $trigger->setDefinition($this->definitions[$config['definition']])->setEvent($config['event'])->setField($config['field'])->setCron($config['cron']); $manager->persist($trigger); $this->addReference($key, $trigger); } $manager->flush(); }
/** * @param array $expected * @param ProcessDefinition $definition * @param ProcessTrigger $trigger */ protected function assertProcessTrigger(array $expected, ProcessDefinition $definition, ProcessTrigger $trigger) { $this->assertEquals($expected['event'], $trigger->getEvent()); $this->assertEquals($expected['field'], $trigger->getField()); $this->assertEquals($expected['queued'], $trigger->isQueued()); $this->assertEquals($expected['priority'], $trigger->getPriority()); $this->assertSame($expected['time_shift'], $trigger->getTimeShift()); $this->assertSame($expected['cron'], $trigger->getCron()); $this->assertSame($definition, $trigger->getDefinition()); }
/** * Schedules EmailBody for processing. * * @param EmailBody $emailBody */ protected function scheduleProcess(EmailBody $emailBody) { /* * Retrieve all process definitions to trigger */ $definitions = $this->processStorage->getService()->getProcessDefinitionNames(); $definitions = $this->getDefinitionRepository()->findBy(['name' => $definitions]); /* * Trigger process definitions with provided data */ foreach ($definitions as $definition) { $trigger = new ProcessTrigger(); $trigger->setDefinition($definition); $data = new ProcessData(); $data->set('data', $emailBody); $this->handler->handleTrigger($trigger, $data); } }
/** * Schedules EmailBody for processing. * * @param EmailBody $emailBody */ protected function scheduleProcess(EmailBody $emailBody) { /* * Retrieve all process definitions to trigger */ $definitions = $this->processStorage->getService()->getProcessDefinitionNames(); $definitions = $this->getDefinitionRepository()->findBy(['name' => $definitions]); /* * Trigger process definitions with provided data */ foreach ($definitions as $definition) { $trigger = new ProcessTrigger(); //id must be unique otherwise in cache will be saved and runned first definition with id = null $trigger->setId($definition->getName()); $trigger->setDefinition($definition); $data = new ProcessData(); $data->set('data', $emailBody); $this->handler->handleTrigger($trigger, $data); } }
public function testSetGetEntityIdAndHash() { $entityClass = 'Test\\Entity'; $entityId = 12; $definition = new ProcessDefinition(); $definition->setRelatedEntity($entityClass); $trigger = new ProcessTrigger(); $trigger->setDefinition($definition); $this->entity->setProcessTrigger($trigger); $this->assertNull($this->entity->getEntityId()); $this->assertNull($this->entity->getEntityHash()); $this->entity->setEntityId($entityId); $this->assertEquals($entityId, $this->entity->getEntityId()); $this->assertEquals(ProcessJob::generateEntityHash($entityClass, $entityId), $this->entity->getEntityHash()); $this->entity->setEntityId(null); $this->assertNull($this->entity->getEntityId()); $this->assertNull($this->entity->getEntityHash()); }
/** * @param string $event * @return ProcessJob */ protected function createProcessJob($event) { $definition = new ProcessDefinition(); $definition->setRelatedEntity('Test\\Entity'); $trigger = new ProcessTrigger(); $trigger->setDefinition($definition)->setEvent($event); $job = new ProcessJob(); $job->setProcessTrigger($trigger); return $job; }
/** * @param \PHPUnit_Framework_MockObject_MockObject $entityManager * @param array $expected * @param int $callOrder */ protected function assertJMSJobPersist($entityManager, array $expected, $callOrder) { $entityManager->expects($this->at($callOrder))->method('persist')->with($this->isInstanceOf('JMS\\JobQueueBundle\\Entity\\Job'))->will($this->returnCallback(function (Job $jmsJob) use($expected) { $this->assertEquals(ExecuteProcessJobCommand::NAME, $jmsJob->getCommand()); $this->assertEquals($expected['commandArgs'], $jmsJob->getArgs()); $this->assertEquals($expected['priority'], $jmsJob->getPriority()); $timeShiftInterval = ProcessTrigger::convertSecondsToDateInterval($expected['timeShift']); $executeAfter = new \DateTime('now', new \DateTimeZone('UTC')); $executeAfter->add($timeShiftInterval); $this->assertLessThanOrEqual($executeAfter, $jmsJob->getExecuteAfter()); })); }
/** * @param ProcessTrigger $trigger * @return ProcessTrigger */ public function import(ProcessTrigger $trigger) { $this->setEvent($trigger->getEvent())->setField($trigger->getField())->setPriority($trigger->getPriority())->setQueued($trigger->isQueued())->setTimeShift($trigger->getTimeShift())->setDefinition($trigger->getDefinition()); return $this; }
/** * @param array $data */ protected function prepareRegistryForBuild(array $data) { // generate triggers $triggers = array(); foreach ($data as $entityClass => $events) { $definition = new ProcessDefinition(); $definition->setRelatedEntity($entityClass); foreach ($events as $event) { $trigger = new ProcessTrigger(); $trigger->setDefinition($definition)->setEvent($event); $triggers[] = $trigger; } } // set mocks $triggerClass = 'OroWorkflowBundle:ProcessTrigger'; $repository = $this->getMockBuilder('Oro\\Bundle\\WorkflowBundle\\Entity\\Repository\\ProcessTriggerRepository')->disableOriginalConstructor()->getMock(); $repository->expects($this->any())->method('findAllWithDefinitions')->will($this->returnValue($triggers)); $entityManager = $this->getMockBuilder('Doctrine\\ORM\\EntityManager')->disableOriginalConstructor()->getMock(); $entityManager->expects($this->any())->method('getRepository')->with($triggerClass)->will($this->returnValue($repository)); $this->registry->expects($this->any())->method('getManagerForClass')->with($triggerClass)->will($this->returnValue($entityManager)); }
/** * @param string $event * @param string $cron * @throws InvalidParameterException */ protected function validateEventAndCronParameters($event, $cron) { if ($cron && $event) { throw new InvalidParameterException('Only one parameter "event" or "cron" must be configured.'); } if (!$cron && !in_array($event, ProcessTrigger::getAllowedEvents(), true)) { throw new InvalidParameterException(sprintf('Event "%s" is not allowed', $event)); } }
/** * @param ProcessTrigger $processTrigger * @return Process */ protected function getProcess(ProcessTrigger $processTrigger) { if (!array_key_exists($processTrigger->getId(), $this->processes)) { $this->processes[$processTrigger->getId()] = $this->factory->create($processTrigger->getDefinition()); } return $this->processes[$processTrigger->getId()]; }
/** * @param array $ids * @return ProcessJob[] */ protected function populateProcessJobs(array $ids) { $result = []; foreach ($ids as $id) { $process = $this->getMockBuilder('Oro\\Bundle\\WorkflowBundle\\Entity\\ProcessJob')->disableOriginalConstructor()->getMock(); $process->expects($this->any())->method('getId')->will($this->returnValue($id)); $definition = new ProcessDefinition(); $definition->setName('name'); $definition->setLabel('label'); $processTrigger = new ProcessTrigger(); $processTrigger->setDefinition($definition); $process->expects($this->any())->method('getProcessTrigger')->will($this->returnValue($processTrigger)); $result[] = $process; } return $result; }
/** * @param int $id * @return ProcessTrigger */ protected function createProcessTrigger($id) { $definition = new ProcessDefinition(); $definition->setName('name')->setLabel('label')->setRelatedEntity('\\StdClass'); $processTrigger = new ProcessTrigger(); $processTrigger->setDefinition($definition); $class = new \ReflectionClass($processTrigger); $prop = $class->getProperty('id'); $prop->setAccessible(true); $prop->setValue($processTrigger, $id); return $processTrigger; }
/** * Create JMS jobs for queued process jobs * * @param \Doctrine\ORM\EntityManager $entityManager */ protected function createJobs($entityManager) { if (empty($this->queuedJobs)) { return; } foreach ($this->queuedJobs as $timeShift => $processJobBatch) { foreach ($processJobBatch as $priority => $processJobs) { $args = array(); /** @var ProcessJob $processJob */ foreach ($processJobs as $processJob) { $args[] = '--id=' . $processJob->getId(); $this->logger->debug('Process queued', $processJob->getProcessTrigger(), $processJob->getData()); } $jmsJob = new Job(ExecuteProcessJobCommand::NAME, $args, true, Job::DEFAULT_QUEUE, $priority); if ($timeShift) { $timeShiftInterval = ProcessTrigger::convertSecondsToDateInterval($timeShift); $executeAfter = new \DateTime('now', new \DateTimeZone('UTC')); $executeAfter->add($timeShiftInterval); $jmsJob->setExecuteAfter($executeAfter); } $entityManager->persist($jmsJob); } } $this->queuedJobs = array(); $entityManager->flush(); }
/** * @param ProcessTrigger $expectedEntity * @param ProcessTrigger $actualEntity * @param bool $isEquals */ protected function assertProcessTriggerEntitiesEquals($expectedEntity, $actualEntity, $isEquals = true) { $method = $isEquals ? 'assertEquals' : 'assertNotEquals'; $this->{$method}($expectedEntity->getEvent(), $actualEntity->getEvent()); $this->{$method}($expectedEntity->getField(), $actualEntity->getField()); $this->{$method}($expectedEntity->getPriority(), $actualEntity->getPriority()); $this->{$method}($expectedEntity->isQueued(), $actualEntity->isQueued()); $this->{$method}($expectedEntity->getTimeShift(), $actualEntity->getTimeShift()); $this->{$method}($expectedEntity->getDefinition(), $actualEntity->getDefinition()); }
/** * @param ProcessTrigger $trigger * @return null|ProcessTrigger */ public function findEqualTrigger(ProcessTrigger $trigger) { return $this->findOneBy(array('event' => $trigger->getEvent(), 'field' => $trigger->getField(), 'definition' => $trigger->getDefinition())); }
/** * Not allow scheduling definition if it's excluded by some process. * * @param ProcessTrigger $processTrigger * @param ProcessData $processData * @return bool */ public function isScheduleAllowed(ProcessTrigger $processTrigger, ProcessData $processData) { $name = $processTrigger->getDefinition()->getName(); return !isset($this->excludeDefinitions[$name]) || $this->excludeDefinitions[$name] == 0; }