/** * @param string $nodeId * @param ModelRelationsAndAttributesToWorkflowAdapter $modelToWorkflowAdapter * @param RedBeanModel $precedingModel * @param string $precedingRelation */ protected function resolvePrecedingModelRelationAndAdapterByNodeId($nodeId, &$modelToWorkflowAdapter, &$precedingModel, &$precedingRelation) { assert('$modelToWorkflowAdapter instanceof ModelRelationsAndAttributesToWorkflowAdapter'); if ($nodeId == 'source') { return; } $relations = explode(FormModelUtil::RELATION_DELIMITER, $nodeId); $lastRelation = end($relations); foreach ($relations as $relation) { $relationModelClassName = $modelToWorkflowAdapter->getRelationModelClassName($relation); $precedingRelation = $relation; if ($relation != $lastRelation) { $precedingModel = new $relationModelClassName(false); } elseif (count($relations) == 1) { $precedingModel = $modelToWorkflowAdapter->getModel(); } $modelToWorkflowAdapter = $this->makeModelRelationsAndAttributesToWorkflowAdapter($relationModelClassName::getModuleClassName(), $relationModelClassName); } }
/** * @param string $relation * @param $model * @return array of models */ public static function getInferredModelsByAtrributeAndModel($relation, $model) { assert('is_string($relation)'); $realAttributeName = ModelRelationsAndAttributesToWorkflowAdapter::resolveRealAttributeName($relation); $relationModelClassName = ModelRelationsAndAttributesToWorkflowAdapter::getInferredRelationModelClassName($relation); $relatedModels = array(); foreach ($model->{$realAttributeName} as $item) { try { $modelDerivationPathToItem = RuntimeUtil::getModelDerivationPathToItem($relationModelClassName); $relatedModels[] = $item->castDown(array($modelDerivationPathToItem)); } catch (NotFoundException $e) { } } return $relatedModels; }
protected static function resolveRelatedModelsForInferredRelations($attribute, $model, $relation, $resolvedAttributeModelClassName) { if (ModelRelationsAndAttributesToWorkflowAdapter::isAttributeInferred($attribute)) { $relatedModels = array(); foreach ($model->{$relation} as $item) { if (get_class($item) == $resolvedAttributeModelClassName) { $relatedModels[] = $item; } else { try { $modelDerivationPathToItem = RuntimeUtil::getModelDerivationPathToItem($resolvedAttributeModelClassName); $relatedModels[] = $item->castDown(array($modelDerivationPathToItem)); } catch (NotFoundException $e) { } } } return $relatedModels; } else { return $model->{$relation}; } }
/** * Notice the use of $modelToForgetCache. This was needed to avoid a caching issue with the following example. * If an opportunity fires, and a related account's opportunity is created. This new opportunity had a cached * model for account that was null. So this is fixed by forgetting the new model after it is added to the account. * @throws FailedToSaveModelException * @throws NotSupportedException */ protected function processCreateRelatedAction() { if ($this->action->relationFilter != ActionForWorkflowForm::RELATION_FILTER_ALL) { throw new NotSupportedException(); } $modelClassName = get_class($this->triggeredModel); if ($this->triggeredModel->isADerivedRelationViaCastedUpModel($this->action->relation) && $this->triggeredModel->getDerivedRelationType($this->action->relation) == RedBeanModel::MANY_MANY) { foreach (WorkflowUtil::resolveDerivedModels($this->triggeredModel, $this->action->relation) as $relatedModel) { if ($this->resolveCreateModel($relatedModel, $this->action->relatedModelRelation)) { $saved = $relatedModel->save(); if (!$saved) { throw new FailedToSaveModelException(); } } } } elseif ($this->triggeredModel->getInferredRelationModelClassNamesForRelation(ModelRelationsAndAttributesToWorkflowAdapter::resolveRealAttributeName($this->action->relation)) != null) { foreach (WorkflowUtil::getInferredModelsByAtrributeAndModel($this->action->relation, $this->triggeredModel) as $relatedModel) { if ($this->resolveCreateModel($relatedModel, $this->action->relatedModelRelation)) { $saved = $relatedModel->save(); if (!$saved) { throw new FailedToSaveModelException(); } } } } elseif ($this->triggeredModel->{$this->action->relation} instanceof RedBeanMutableRelatedModels) { foreach ($this->triggeredModel->{$this->action->relation} as $relatedModel) { if ($this->resolveCreateModel($relatedModel, $this->action->relatedModelRelation)) { $saved = $relatedModel->save(); if (!$saved) { throw new FailedToSaveModelException(); } } } } elseif ($modelClassName::isRelationTypeAHasOneVariant($this->action->relation) && !$modelClassName::isOwnedRelation($this->action->relation)) { $relatedModel = $this->triggeredModel->{$this->action->relation}; $modelToForgetCache = null; if ($this->resolveCreateModel($relatedModel, $this->action->relatedModelRelation, $modelToForgetCache)) { $saved = $relatedModel->save(); if (!$saved) { throw new FailedToSaveModelException(); } if ($modelToForgetCache instanceof RedBeanModel) { $modelToForgetCache->forget(); } } } else { throw new NotSupportedException(); } }
/** * @param RedBeanModel $model * @param User $triggeredByUser * @return array * @throws NotSupportedException */ public function makeRecipients(RedBeanModel $model, User $triggeredByUser) { $modelClassName = $this->modelClassName; $recipients = array(); if ($model->isADerivedRelationViaCastedUpModel($this->relation) && $model->getDerivedRelationType($this->relation) == RedBeanModel::MANY_MANY) { foreach (WorkflowUtil::resolveDerivedModels($model, $this->relation) as $resolvedModel) { $recipients = self::resolveRecipientsAsUniquePeople($recipients, $this->resolveRecipients($resolvedModel)); } } elseif ($modelClassName::getInferredRelationModelClassNamesForRelation(ModelRelationsAndAttributesToWorkflowAdapter::resolveRealAttributeName($this->relation)) != null) { foreach (WorkflowUtil::getInferredModelsByAtrributeAndModel($this->relation, $model) as $resolvedModel) { $recipients = self::resolveRecipientsAsUniquePeople($recipients, $this->resolveRecipients($resolvedModel)); } } elseif ($model->{$this->relation} instanceof RedBeanMutableRelatedModels) { if (!$this->relationFilter == self::RELATION_FILTER_ALL) { throw new NotSupportedException(); } foreach ($model->{$this->relation} as $resolvedModel) { $recipients = self::resolveRecipientsAsUniquePeople($recipients, $this->resolveRecipients($resolvedModel)); } } elseif ($modelClassName::isRelationTypeAHasOneVariant($this->relation)) { if ($model->{$this->relation}->id > 0) { $recipients = $this->resolveRecipients($model->{$this->relation}); } } else { throw new NotSupportedException(); } return $recipients; }
/** * @param string $methodToCall * @return array */ protected function resolveActionAttributeFormsAndLabelsAndSortByMethod($methodToCall) { assert('$methodToCall == "getNonRequiredAttributesForActions" || $methodToCall == "getRequiredAttributesForActions" || $methodToCall == "getAllAttributesForActions"'); $modelClassName = $this->getModelClassNameAndResolveForRelations(); $attributeFormsIndexedByAttribute = array(); $adapter = ModelRelationsAndAttributesToWorkflowAdapter::make($modelClassName::getModuleClassName(), $modelClassName, $this->_workflowType); foreach ($adapter->{$methodToCall}() as $attribute => $data) { if ($this->hasActionAttributeFormByName($attribute)) { $attributeFormsIndexedByAttribute[$attribute] = $this->getActionAttributeFormByName($attribute); } else { $attributeFormsIndexedByAttribute[$attribute] = $this->makeActionAttributeFormByAttribute($attribute); } if ($methodToCall == 'getRequiredAttributesForActions') { $attributeFormsIndexedByAttribute[$attribute]->shouldSetValue = true; } $additionalLabelContent = $this->resolveTooltipHelpContentByElementType($adapter->getModel(), $attribute); $attributeFormsIndexedByAttribute[$attribute]->setDisplayLabel($data['label'] . $additionalLabelContent); } $this->resolvePermissionsAttributeForm($modelClassName, $methodToCall, $attributeFormsIndexedByAttribute); return $attributeFormsIndexedByAttribute; }
/** * @param array $attributeAndRelationData * @return string */ protected function resolveRealAttributeNameForPenultimateRelation(array $attributeAndRelationData) { assert('count($this->attributeAndRelationData) > 0'); array_pop($attributeAndRelationData); return ModelRelationsAndAttributesToWorkflowAdapter::resolveRealAttributeName(end($attributeAndRelationData)); }
/** * @depends testGetSelectableRelationsDataForEmailMessageRecipientModelRelation */ public function testGetSelectableContactRelationsDataForEmailMessageRecipientModelRelation() { $model = new Account(); $rules = new AccountsWorkflowRules(); $workflow = new Workflow(); $workflow->setType(Workflow::TYPE_ON_SAVE); $workflow->setModuleClassName('AccountsModule'); $adapter = new ModelRelationsAndAttributesToWorkflowAdapter($model, $rules, $workflow->getType()); $relations = $adapter->getSelectableContactRelationsDataForEmailMessageRecipientModelRelation(); $this->assertEquals(1, count($relations)); $this->assertTrue(isset($relations['contacts'])); $model = new Contact(); $rules = new ContactsWorkflowRules(); $workflow = new Workflow(); $workflow->setType(Workflow::TYPE_ON_SAVE); $workflow->setModuleClassName('ContactsModule'); $adapter = new ModelRelationsAndAttributesToWorkflowAdapter($model, $rules, $workflow->getType()); $relations = $adapter->getSelectableContactRelationsDataForEmailMessageRecipientModelRelation(); $this->assertEquals(0, count($relations)); $model = new Task(); $rules = new TasksWorkflowRules(); $workflow = new Workflow(); $workflow->setType(Workflow::TYPE_ON_SAVE); $workflow->setModuleClassName('TasksModule'); $adapter = new ModelRelationsAndAttributesToWorkflowAdapter($model, $rules, $workflow->getType()); $relations = $adapter->getSelectableContactRelationsDataForEmailMessageRecipientModelRelation(); $this->assertEquals(1, count($relations)); $this->assertTrue(isset($relations['Contact__activityItems__Inferred'])); }
/** * @return string * @throws NotSupportedException */ protected function resolveModelClassName() { $modelClassName = $this->modelClassName; if ($this->relation == null) { return $modelClassName; } if ($modelClassName::isADerivedRelationViaCastedUpModel($this->relation) && $modelClassName::getDerivedRelationType($this->relation) == RedBeanModel::MANY_MANY) { return $modelClassName::getDerivedRelationModelClassName($this->relation); } elseif ($modelClassName::getInferredRelationModelClassNamesForRelation(ModelRelationsAndAttributesToWorkflowAdapter::resolveRealAttributeName($this->relation)) != null) { return ModelRelationsAndAttributesToWorkflowAdapter::getInferredRelationModelClassName($this->relation); } elseif ($modelClassName::isRelationTypeAHasManyVariant($this->relation) || $modelClassName::isRelationTypeAHasOneVariant($this->relation)) { return $modelClassName::getRelationModelClassName($this->relation); } else { throw new NotSupportedException(); } }