/** * @param ConfigInterface $config * @param ClassMetadataBuilder $cmBuilder */ protected function prepareRelations(ConfigInterface $config, ClassMetadataBuilder $cmBuilder) { if ($config->is('relation')) { foreach ($config->get('relation') as $relation) { /** @var FieldConfigId $fieldId */ if ($relation['assign'] && ($fieldId = $relation['field_id'])) { /** @var FieldConfigId $targetFieldId */ $targetFieldId = $relation['target_field_id']; $targetFieldName = $targetFieldId ? ExtendConfigDumper::FIELD_PREFIX . $targetFieldId->getFieldName() : null; $fieldName = ExtendConfigDumper::FIELD_PREFIX . $fieldId->getFieldName(); $defaultName = ExtendConfigDumper::DEFAULT_PREFIX . $fieldId->getFieldName(); switch ($fieldId->getFieldType()) { case 'manyToOne': $builder = $cmBuilder->createManyToOne($fieldName, $relation['target_entity']); if ($targetFieldName) { $builder->inversedBy($targetFieldName); } $builder->addJoinColumn($fieldName . '_id', 'id', true, false, 'SET NULL'); $builder->cascadeDetach(); $builder->build(); break; case 'oneToMany': /** create 1:* */ $builder = $cmBuilder->createOneToMany($fieldName, $relation['target_entity']); $builder->mappedBy($targetFieldName); $builder->cascadeDetach(); $builder->build(); /** create 1:1 default */ $builder = $cmBuilder->createOneToOne($defaultName, $relation['target_entity']); $builder->addJoinColumn($defaultName . '_id', 'id', true, false, 'SET NULL'); $builder->build(); break; case 'manyToMany': if ($relation['owner']) { $builder = $cmBuilder->createManyToMany($fieldName, $relation['target_entity']); if ($targetFieldName) { $builder->inversedBy($targetFieldName); } $builder->setJoinTable(ExtendHelper::generateManyToManyJoinTableName($fieldId, $relation['target_entity'])); $builder->build(); $builder = $cmBuilder->createOneToOne($defaultName, $relation['target_entity']); $builder->addJoinColumn($defaultName . '_id', 'id', true, false, 'SET NULL'); $builder->build(); } else { $cmBuilder->addInverseManyToMany($fieldName, $relation['target_entity'], $targetFieldName); } break; } } } } }
/** * @param ConfigInterface $fieldConfig */ protected function createRelation(ConfigInterface $fieldConfig) { if (!$fieldConfig->is('relation_key')) { $this->createSelfRelation($fieldConfig); } else { $relationKey = $fieldConfig->get('relation_key'); $selfConfig = $this->extendConfigProvider->getConfig($fieldConfig->getId()->getClassName()); $selfRelations = $selfConfig->get('relation', false, []); if (!isset($selfRelations[$relationKey])) { $this->createSelfRelation($fieldConfig); } $this->ensureReverseRelationCompleted($fieldConfig); } }
/** * @param ConfigInterface $fieldConfig */ protected function createRelation(ConfigInterface $fieldConfig) { if (!$fieldConfig->is('relation_key')) { $this->setRelationKeyToFieldConfig($fieldConfig); $this->createSelfRelation($fieldConfig); } else { $entityConfig = $this->getEntityConfig($fieldConfig->getId()->getClassName()); $relations = $entityConfig->get('relation', false, []); $relationKey = $fieldConfig->get('relation_key'); if (!isset($relations[$relationKey])) { $this->createSelfRelation($fieldConfig); $this->ensureReverseRelationCompleted($fieldConfig); } else { $relation = $relations[$relationKey]; if (array_key_exists('owner', $relation)) { $this->ensureReverseRelationCompleted($fieldConfig); } elseif (isset($relation['target_field_id']) && $relation['target_field_id']) { $this->completeSelfRelation($fieldConfig); } } } }
/** * @param ConfigInterface $fieldConfig */ protected function createRelation(ConfigInterface $fieldConfig) { $createSelfRelation = true; if ($fieldConfig->is('relation_key')) { $relationKey = $fieldConfig->get('relation_key'); $selfConfig = $this->extendConfigProvider->getConfig($fieldConfig->getId()->getClassName()); $selfRelations = $selfConfig->get('relation'); if (isset($selfRelations[$relationKey]['field_id'])) { $createSelfRelation = false; } else { $targetConfig = $this->extendConfigProvider->getConfig($fieldConfig->get('target_entity')); $targetRelations = $targetConfig->get('relation'); if (isset($targetRelations[$relationKey])) { $this->createTargetRelation($fieldConfig, $relationKey); if ($targetRelations[$relationKey]['assign']) { $createSelfRelation = false; } } } } if ($createSelfRelation) { $this->createSelfRelation($fieldConfig); } }
/** * {@inheritdoc} */ protected function apply(ConfigInterface $config) { $configId = $config->getId(); $className = $configId->getClassName(); if ($configId instanceof FieldConfigId) { $fieldName = $configId->getFieldName(); if (!isset($this->initialStates['fields'][$className][$fieldName])) { return true; } $initialState = $this->initialStates['fields'][$className][$fieldName]; } else { if (!isset($this->initialStates['entities'][$className])) { return true; } $initialState = $this->initialStates['entities'][$className]; } if ($initialState === ExtendScope::STATE_ACTIVE) { return true; } if ($initialState === ExtendScope::STATE_DELETE && !$config->is('state', ExtendScope::STATE_DELETE)) { return true; } return false; }
/** * @param ConfigInterface $extendConfig * @param ConfigProviderInterface $extendConfigProvider * * @return bool */ protected function isApplicableField(ConfigInterface $extendConfig, ConfigProviderInterface $extendConfigProvider) { return !$extendConfig->is('is_deleted') && $extendConfig->is('owner', ExtendScope::OWNER_CUSTOM) && !$extendConfig->is('state', ExtendScope::STATE_NEW) && !in_array($extendConfig->getId()->getFieldType(), ['ref-one', 'ref-many']) && (!$extendConfig->has('target_entity') || !$extendConfigProvider->getConfig($extendConfig->get('target_entity'))->is('is_deleted')); }
/** * Get dynamic field or empty array if field is not visible * * @param $alias * @param ConfigInterface $extendConfig * @return array */ public function getDynamicFieldItem($alias, ConfigInterface $extendConfig) { /** @var FieldConfigId $fieldConfig */ $fieldConfig = $extendConfig->getId(); $fieldName = $fieldConfig->getFieldName(); $field = []; $select = ''; // no need to add to select enything here if (in_array($fieldName, $this->relationConfig->get('target_grid'))) { /** @var ConfigProvider $entityConfigProvider */ $entityConfigProvider = $this->configManager->getProvider('entity'); $entityConfig = $entityConfigProvider->getConfig($this->entityClass, $fieldName); $label = $entityConfig->get('label') ?: $fieldName; $code = $extendConfig->is('owner', ExtendManager::OWNER_CUSTOM) ? ExtendConfigDumper::FIELD_PREFIX . $fieldName : $fieldName; $this->queryFields[] = $code; $field = $field = $this->createFieldArrayDefinition($code, $label, $fieldConfig); $select = $alias . '.' . $code; } return [$field, $select]; }
/** * @param ConfigInterface $extendConfig * * @return bool */ protected function checkState(ConfigInterface $extendConfig) { $hasChanges = false; $extendProvider = $this->em->getExtendConfigProvider(); $className = $extendConfig->getId()->getClassName(); if ($extendConfig->is('state', ExtendScope::STATE_DELETE)) { // mark entity as deleted if (!$extendConfig->is('is_deleted')) { $extendConfig->set('is_deleted', true); $extendProvider->persist($extendConfig); $hasChanges = true; } // mark all fields as deleted $fieldConfigs = $extendProvider->getConfigs($className, true); foreach ($fieldConfigs as $fieldConfig) { if (!$fieldConfig->is('is_deleted')) { $fieldConfig->set('is_deleted', true); $extendProvider->persist($fieldConfig); $hasChanges = true; } } } elseif (!$extendConfig->is('state', ExtendScope::STATE_ACTIVE)) { $extendConfig->set('state', ExtendScope::STATE_ACTIVE); $extendProvider->persist($extendConfig); $hasChanges = true; } return $hasChanges; }
/** * {@inheritdoc} */ public function supports(ConfigInterface $extendConfig) { return $extendConfig->is('relation'); }
/** * @param ConfigInterface $extendConfig * * @return bool */ protected function isApplicableField(ConfigInterface $extendConfig) { return !$extendConfig->is('is_deleted') && $extendConfig->is('owner', ExtendScope::OWNER_CUSTOM) && !$extendConfig->is('state', ExtendScope::STATE_NEW) && !in_array($extendConfig->getId()->getFieldType(), RelationType::$toAnyRelations) && (!$extendConfig->has('target_entity') || !$this->extendConfigProvider->getConfig($extendConfig->get('target_entity'))->is('is_deleted')); }
/** * @param ConfigInterface $config * @return bool */ public function filterFields(ConfigInterface $config) { $extendConfig = $this->extendProvider->getConfigById($config->getId()); /** @var FieldConfigId $fieldConfigId */ $fieldConfigId = $extendConfig->getId(); // skip system and not accessible fields if (!$config->is('owner', ExtendScope::OWNER_CUSTOM) || !ExtendHelper::isFieldAccessible($config)) { return false; } // skip invisible fields if (!$this->viewProvider->getConfigById($config->getId())->is('is_displayable')) { return false; } // skip relations if they are referenced to not accessible entity $underlyingFieldType = $this->fieldTypeHelper->getUnderlyingType($fieldConfigId->getFieldType()); if (in_array($underlyingFieldType, RelationType::$anyToAnyRelations, true) && !ExtendHelper::isEntityAccessible($this->extendProvider->getConfig($extendConfig->get('target_entity')))) { return false; } return true; }
/** * Check if field marked as title_field, add this field to titles * * @param array $mapConfig * @param ConfigInterface $searchConfig * @param string $className * @param string $fieldName */ protected function processTitles(&$mapConfig, ConfigInterface $searchConfig, $className, $fieldName) { if ($searchConfig->is('title_field')) { $mapConfig[$className][self::TITLE_FIELDS_PATH] = array_merge($mapConfig[$className][self::TITLE_FIELDS_PATH], [$fieldName]); } }
/** * {@inheritdoc} */ protected function isTargetEntityApplicable(ConfigInterface $targetEntityConfig) { return $targetEntityConfig->is($this->getAssociationAttributeName()); }
/** * @param ConfigInterface $entityConfig * @param ConfigProvider $configProvider */ protected function updateStateValues(ConfigInterface $entityConfig, ConfigProvider $configProvider) { if ($entityConfig->is('state', ExtendScope::STATE_DELETE)) { // mark entity as deleted if (!$entityConfig->is('is_deleted')) { $entityConfig->set('is_deleted', true); $this->configManager->persist($entityConfig); } // mark all fields as deleted $fieldConfigs = $configProvider->getConfigs($entityConfig->getId()->getClassName(), true); foreach ($fieldConfigs as $fieldConfig) { if (!$fieldConfig->is('is_deleted')) { $fieldConfig->set('is_deleted', true); $this->configManager->persist($fieldConfig); } } } elseif (!$entityConfig->is('state', ExtendScope::STATE_ACTIVE)) { $hasNotActiveFields = false; $fieldConfigs = $configProvider->getConfigs($entityConfig->getId()->getClassName(), true); foreach ($fieldConfigs as $fieldConfig) { if (!$fieldConfig->in('state', [ExtendScope::STATE_ACTIVE, ExtendScope::STATE_DELETE])) { $hasNotActiveFields = true; break; } } // Set entity state to active if all fields are active or deleted if (!$hasNotActiveFields) { $entityConfig->set('state', ExtendScope::STATE_ACTIVE); $this->configManager->persist($entityConfig); } } }
/** * Get dynamic field or empty array if field is not visible * * @param $alias * @param ConfigInterface $extendConfig * @return array */ public function getDynamicFieldItem($alias, ConfigInterface $extendConfig) { /** @var FieldConfigId $fieldConfig */ $fieldConfig = $extendConfig->getId(); /** @var ConfigProvider $datagridProvider */ $datagridConfigProvider = $this->configManager->getProvider('datagrid'); $datagridConfig = $datagridConfigProvider->getConfig($this->entityClass, $fieldConfig->getFieldName()); $select = ''; $field = []; if ($datagridConfig->is('is_visible')) { /** @var ConfigProvider $entityConfigProvider */ $entityConfigProvider = $this->configManager->getProvider('entity'); $entityConfig = $entityConfigProvider->getConfig($this->entityClass, $fieldConfig->getFieldName()); $label = $entityConfig->get('label') ?: $fieldConfig->getFieldName(); $code = $extendConfig->is('owner', ExtendManager::OWNER_CUSTOM) ? ExtendConfigDumper::FIELD_PREFIX . $fieldConfig->getFieldName() : $fieldConfig->getFieldName(); $this->queryFields[] = $code; $field = $this->createFieldArrayDefinition($code, $label, $fieldConfig); $select = $alias . '.' . $code; } return [$field, $select]; }
/** * @param ConfigInterface $extendConfig * * @return bool */ protected function updateStateValues(ConfigInterface $extendConfig) { $hasChanges = false; $extendProvider = $this->em->getExtendConfigProvider(); $className = $extendConfig->getId()->getClassName(); $fieldConfigs = $extendProvider->getConfigs($className, true); if ($extendConfig->is('state', ExtendScope::STATE_DELETE)) { // mark entity as deleted if (!$extendConfig->is('is_deleted')) { $extendConfig->set('is_deleted', true); $extendProvider->persist($extendConfig); $hasChanges = true; } // mark all fields as deleted foreach ($fieldConfigs as $fieldConfig) { if (!$fieldConfig->is('is_deleted')) { $fieldConfig->set('is_deleted', true); $extendProvider->persist($fieldConfig); $hasChanges = true; } } } elseif (!$extendConfig->is('state', ExtendScope::STATE_ACTIVE)) { $hasNotActiveFields = false; foreach ($fieldConfigs as $fieldConfig) { if (!$fieldConfig->is('state', ExtendScope::STATE_DELETE) && !$fieldConfig->is('state', ExtendScope::STATE_ACTIVE)) { $hasNotActiveFields = true; break; } } // Set entity state to active if all fields are active or deleted if (!$hasNotActiveFields) { $extendConfig->set('state', ExtendScope::STATE_ACTIVE); $extendProvider->persist($extendConfig); } $hasChanges = true; } if ($hasChanges) { $extendProvider->flush(); } }
/** * @param ConfigInterface $extendConfig * @param ConfigProvider $extendConfigProvider * * @return bool */ protected function isApplicableField(ConfigInterface $extendConfig, ConfigProvider $extendConfigProvider) { return $extendConfig->is('owner', ExtendScope::OWNER_CUSTOM) && ExtendHelper::isFieldAccessible($extendConfig) && !in_array($extendConfig->getId()->getFieldType(), RelationType::$toAnyRelations, true) && (!$extendConfig->has('target_entity') || ExtendHelper::isEntityAccessible($extendConfigProvider->getConfig($extendConfig->get('target_entity')))); }
/** * @param ConfigInterface $config * @return bool */ public function filterFields(ConfigInterface $config) { $extendConfig = $this->extendProvider->getConfigById($config->getId()); /** @var FieldConfigId $fieldConfigId */ $fieldConfigId = $extendConfig->getId(); // skip system, new and deleted fields if (!$config->is('owner', ExtendScope::OWNER_CUSTOM) || $config->is('state', ExtendScope::STATE_NEW) || $config->is('is_deleted')) { return false; } // skip invisible fields if (!$this->viewProvider->getConfigById($config->getId())->is('is_displayable')) { return false; } // skip relations if they are referenced to deleted entity $underlyingFieldType = $this->fieldTypeHelper->getUnderlyingType($fieldConfigId->getFieldType()); if (in_array($underlyingFieldType, RelationType::$anyToAnyRelations) && $this->extendProvider->getConfig($extendConfig->get('target_entity'))->is('is_deleted', true)) { return false; } return true; }
/** * Check if the given configurable field is ready to be used in a business logic. * It means that a field should exist in a class and should not be marked as deleted. * * @param ConfigInterface $extendFieldConfig The field's configuration in the 'extend' scope * * @return bool */ public static function isFieldAccessible(ConfigInterface $extendFieldConfig) { if ($extendFieldConfig->is('is_extend')) { if ($extendFieldConfig->is('is_deleted')) { return false; } if ($extendFieldConfig->is('state', ExtendScope::STATE_NEW)) { return false; } // check if a new field has been requested to be deleted before schema is updated if ($extendFieldConfig->is('state', ExtendScope::STATE_DELETE)) { /** @var FieldConfigId $fieldId */ $fieldId = $extendFieldConfig->getId(); if (!property_exists($fieldId->getClassName(), $fieldId->getFieldName())) { return false; } } } return true; }
/** * @param ConfigInterface $extendConfig * * @return bool */ protected function isEnum(ConfigInterface $extendConfig) { if (!$extendConfig->is('inherit', ExtendHelper::BASE_ENUM_VALUE_CLASS)) { return false; } if ($extendConfig->is('state', ExtendScope::STATE_NEW) || $extendConfig->is('is_deleted')) { return false; } return true; }