/** * @param LoggerInterface $logger * @param bool $dryRun */ protected function addActivityContactColumns(LoggerInterface $logger, $dryRun = false) { $hasSchemaChanges = false; $toSchema = clone $this->schema; $contactingActivityClasses = $this->activityContactProvider->getSupportedActivityClasses(); $entities = $this->getConfigurableEntitiesData($logger); foreach ($entities as $entityClassName => $config) { // Skipp excluded entity if (TargetExcludeList::isExcluded($entityClassName)) { continue; } if ($this->canAddField($config, $contactingActivityClasses)) { $tableName = $this->getTableName($config, $entityClassName); // Process only existing tables if (!$toSchema->hasTable($tableName)) { continue; } $table = $toSchema->getTable($tableName); $tableColumns = $table->getColumns(); /** * Check if entity already has all needed columns. * If at least one is not present we should check and add it. */ if ($this->hasEntityNeededColumns($tableColumns)) { continue; } foreach (ActivityScope::$fieldsConfiguration as $fieldName => $fieldConfig) { if (!$table->hasColumn($fieldName)) { $hasSchemaChanges = $this->addColumn($table, $fieldName, $fieldConfig); } } } } $this->runSchemaRelated($logger, $dryRun, $hasSchemaChanges, $toSchema); }
/** {@inheritdoc} */ public function isApplicable($entity = null, $pageType = null) { $entityClass = $this->doctrineHelper->getEntityClass($entity); if (TargetExcludeList::isExcluded($entityClass)) { return false; } return parent::isApplicable($entity, $pageType); }
/** * {@inheritdoc} */ public function preUpdate() { /** @var ConfigProvider $extendConfigProvider */ $extendConfigProvider = $this->configManager->getProvider('extend'); /** @var ConfigProvider $activityConfigProvider */ $activityConfigProvider = $this->configManager->getProvider('activity'); $contactingActivityClasses = $this->activityContactProvider->getSupportedActivityClasses(); $entityConfigs = $extendConfigProvider->getConfigs(); foreach ($entityConfigs as $entityConfig) { if ($entityConfig->is('is_extend')) { $entityClassName = $entityConfig->getId()->getClassName(); // Skipp excluded entity if (TargetExcludeList::isExcluded($entityClassName)) { continue; } /** * Check if entity has any activity from contact activities group */ $entityActivities = $activityConfigProvider->getConfig($entityClassName)->get('activities'); if (!$entityActivities || !array_intersect($contactingActivityClasses, $entityActivities)) { continue; } /** @var ConfigInterface[] $entityFields */ $entityFields = $extendConfigProvider->getConfigs($entityClassName); $entityFieldNames = array_map(function (ConfigInterface $item) { return $item->getId()->getFieldName(); }, $entityFields); /** * Check if entity already has all needed fields. * If at least one is not present we should check and add it too. */ if (false === (bool) array_diff(array_keys(ActivityScope::$fieldsConfiguration), array_intersect($entityFieldNames, array_keys(ActivityScope::$fieldsConfiguration)))) { continue; } foreach (ActivityScope::$fieldsConfiguration as $fieldName => $fieldConfig) { if (!in_array($fieldName, $entityFieldNames)) { $this->configManager->createConfigFieldModel($entityClassName, $fieldName, $fieldConfig['type'], $fieldConfig['mode']); $this->updateConfigs($entityClassName, $fieldName, $fieldConfig['options']); } } } } }
/** * Collect activities changes * * @param OnFlushEventArgs $args */ public function onFlush(OnFlushEventArgs $args) { $entitiesToDelete = $args->getEntityManager()->getUnitOfWork()->getScheduledEntityDeletions(); $entitiesToUpdate = $args->getEntityManager()->getUnitOfWork()->getScheduledEntityUpdates(); if (!empty($entitiesToDelete) || !empty($entitiesToUpdate)) { foreach ($entitiesToDelete as $entity) { $class = $this->doctrineHelper->getEntityClass($entity); $id = $this->doctrineHelper->getSingleEntityIdentifier($entity); $key = $class . '_' . $id; if (!isset($this->deletedEntities[$key]) && $this->activityContactProvider->isSupportedEntity($class)) { $targets = $entity->getActivityTargetEntities(); $targetsInfo = []; foreach ($targets as $target) { if (!TargetExcludeList::isExcluded(ClassUtils::getClass($target))) { $targetsInfo[] = ['class' => $this->doctrineHelper->getEntityClass($target), 'id' => $this->doctrineHelper->getSingleEntityIdentifier($target), 'direction' => $this->activityContactProvider->getActivityDirection($entity, $target)]; } } $this->deletedEntities[$key] = ['class' => $class, 'id' => $id, 'contactDate' => $this->activityContactProvider->getActivityDate($entity), 'targets' => $targetsInfo]; } } foreach ($entitiesToUpdate as $entity) { $class = $this->doctrineHelper->getEntityClass($entity); $id = $this->doctrineHelper->getSingleEntityIdentifier($entity); $key = $class . '_' . $id; if (!isset($this->updatedEntities[$key]) && $this->activityContactProvider->isSupportedEntity($class)) { $changes = $args->getEntityManager()->getUnitOfWork()->getEntityChangeSet($entity); $isDirectionChanged = $this->activityContactProvider->getActivityDirectionProvider($entity)->isDirectionChanged($changes); $targets = $entity->getActivityTargetEntities(); $targetsInfo = []; foreach ($targets as $target) { if (!TargetExcludeList::isExcluded(ClassUtils::getClass($target))) { $targetsInfo[] = ['class' => $this->doctrineHelper->getEntityClass($target), 'id' => $this->doctrineHelper->getSingleEntityIdentifier($target), 'direction' => $this->activityContactProvider->getActivityDirection($entity, $target), 'is_direction_changed' => $isDirectionChanged]; } } $this->updatedEntities[$key] = ['class' => $class, 'id' => $id, 'contactDate' => $this->activityContactProvider->getActivityDate($entity), 'targets' => $targetsInfo]; } } } }
/** * @param AbstractLogger $logger * * @return int */ public function recalculate(AbstractLogger $logger) { $logger->notice('Recalculating contacting activities...'); $logger->info(sprintf('<info>Processing started at %s</info>', date('Y-m-d H:i:s'))); /** @var ConfigProvider $activityConfigProvider */ $activityConfigProvider = $this->getContainer()->get('oro_entity_config.provider.activity'); /** @var ActivityContactProvider $activityContactProvider */ $activityContactProvider = $this->getContainer()->get('orocrm_activity_contact.provider'); $contactingActivityClasses = $activityContactProvider->getSupportedActivityClasses(); $entityConfigsWithApplicableActivities = $activityConfigProvider->filter(function (ConfigInterface $entity) use($contactingActivityClasses) { return $entity->get('activities') && array_intersect($contactingActivityClasses, $entity->get('activities')); }); if ($entityConfigsWithApplicableActivities) { $logger->info(sprintf('<comment>Total found %d entities with enabled contacting activities</comment>', count($entityConfigsWithApplicableActivities))); $this->em = $this->getContainer()->get('doctrine')->getManager(); $this->activityListRepository = $this->em->getRepository(ActivityList::ENTITY_NAME); /** @var ActivityListener $activityListener */ $activityListener = $this->getContainer()->get('orocrm_activity_contact.listener.activity_listener'); /** @var ActivityListFilterHelper $activityListHelper */ $activityListHelper = $this->getContainer()->get('oro_activity_list.filter.helper'); foreach ($entityConfigsWithApplicableActivities as $activityScopeConfig) { $entityClassName = $activityScopeConfig->getId()->getClassName(); if (TargetExcludeList::isExcluded($entityClassName)) { continue; } $offset = 0; $startTimestamp = time(); $allRecordIds = $this->getTargetIds($entityClassName); $this->resetRecordsWithoutActivities($entityClassName, $allRecordIds); while ($allRecords = $this->getRecordsToRecalculate($entityClassName, $allRecordIds, $offset)) { $needsFlush = false; foreach ($allRecords as $record) { $this->resetRecordStatistic($record); /** @var QueryBuilder $qb */ $qb = $this->activityListRepository->getBaseActivityListQueryBuilder($entityClassName, $record->getId()); $activityListHelper->addFiltersToQuery($qb, ['activityType' => ['value' => $contactingActivityClasses]]); /** @var ActivityList[] $activities */ $activities = $qb->getQuery()->getResult(); if ($activities) { foreach ($activities as $activityListItem) { /** @var object $activity */ $activity = $this->em->getRepository($activityListItem->getRelatedActivityClass())->find($activityListItem->getRelatedActivityId()); $activityListener->onAddActivity(new ActivityEvent($activity, $record)); } $this->em->persist($record); $needsFlush = true; } } if ($needsFlush) { $this->em->flush(); } $this->em->clear(); $offset += self::BATCH_SIZE; } $endTimestamp = time(); $logger->info(sprintf('Entity "%s", %d records processed (<comment>%d sec.</comment>).', $entityClassName, count($allRecordIds), $endTimestamp - $startTimestamp)); } } $logger->info(sprintf('<info>Processing finished at %s</info>', date('Y-m-d H:i:s'))); return self::STATUS_SUCCESS; }