public function compileParameters($userSupplied, $needles, $needleUserParameters, &$incompatibilities = array(), &$userRequiredParameters) { if (is_array($needles)) { $needlesCollection = new Collection($needles); } else { $needlesCollection = $needles; } $disallowedNeedles = $needlesCollection->diff($this->Needles); foreach ($disallowedNeedles as $needle) { $incompatibilities[] = "Needle {$needle->Name} is not marked for use in this combination"; } $allowedNeedles = $needlesCollection->intersect($this->Needles); $attributionsWithoutNeedle = ParameterAttribution::join("Parameter", "Parameter.Id", "=", "Parameter_Attribution.Parameter_Id")->addSelect("Parameter_Attribution.*", "Parameter.Name AS parameterName", "Parameter_Attribution.Value AS parameterValue"); $automaticFields = array_diff($this->attributingFields, ['Protocol']); foreach ($automaticFields as $field) { $property = train_case($field); $class = get_class($this->{$property}); $attributionsWithoutNeedle = $attributionsWithoutNeedle->where(function ($q) use($field, $property, $class) { $q->whereNull($class::$idField)->orWhere($class::$idField, "=", $this->{$property}->Id); }); } $resultList = new Collection(); if (in_array('Protocol', $this->attributingFields)) { $resultList = $resultList->merge($this->Protocol->Algorithms->lists('Result')); } foreach ($this->Protocol->Algorithms as $algorithm) { $algorithms = $this->Protocol->Algorithms; $attributionsWithoutNeedle = $attributionsWithoutNeedle->where(function ($q) use($algorithms) { $q->whereNull("Algorithm_Id"); foreach ($algorithms as $algorithm) { $q->orWhere("Algorithm_Id", "=", $algorithm->Id); } }); } $needleParametersByNeedle = []; if (count($allowedNeedles)) { foreach ($needlesCollection as $needleIx => $needle) { if (!in_array($needle, $allowedNeedles->all())) { continue; } $attributions = with(clone $attributionsWithoutNeedle)->where(function ($q) use($needle) { $q = $q->whereNull("Needle_Id"); $q = $q->orWhere("Needle_Id", "=", $needle->Id); }); $requirements = with(clone $attributions)->whereNull("Parameter_Attribution.Value"); $supplies = with(clone $attributions)->whereNotNull("Parameter_Attribution.Value"); $needleParameters = []; foreach ($supplies->get() as $a) { $name = $a->Parameter->Name; if (!isset($needleParameters[$name])) { $needleParameters[$name] = []; } $needleParameters[$name][] = $a; } array_walk($needleParameters, function (&$v, $name) { /* Remove any redundant parameters - only needle parameters and parameters * overriding a needle-specific parameter count */ if (!count(array_filter($v, function ($n) { return $n->Needle_Id !== null; }))) { $v = false; } else { $v = $this->chooseAttribution($v); } }); $needleParameters = array_filter($needleParameters); $needleUser = isset($needleUserParameters[$needleIx]) ? $needleUserParameters[$needleIx] : []; foreach ($needleUser as $needleUserParameter) { $needleParameters[$needleUserParameter->Name] = $needleUserParameter; } $needleParametersByNeedle[$needleIx] = $needleParameters; $requirementsList = $requirements->lists("parameterName"); $supplyList = $supplies->lists("parameterName"); $needleUserSupplied = []; if (isset($needleUserParameters[$needleIx])) { $needleUserSupplied = $needleUserParameters[$needleIx]->lists('Name'); } $undefinedList = array_diff($requirementsList, $supplyList, $needleUserSupplied, $userSupplied->lists('Name')); $undefinedList = array_diff($undefinedList, $resultList->lists("Name")); if (!empty($undefinedList)) { $requirementsMap = array_combine($requirements->lists("parameterName"), $requirements->get()->all()); foreach ($undefinedList as $missingParameterName) { $editable = $requirementsMap[$missingParameterName]->Editable >= 2; if ($editable) { $userRequiredParameters[] = $requirementsMap[$missingParameterName]->Parameter; } else { $incompatibilities[] = "Parameter {$missingParameterName} is missing"; } } } } } else { $requirements = with(clone $attributionsWithoutNeedle)->whereNull("Parameter_Attribution.Value"); $supplies = with(clone $attributionsWithoutNeedle)->whereNotNull("Parameter_Attribution.Value"); $requirementsList = $requirements->lists("parameterName"); $supplyList = $supplies->lists("parameterName"); $undefinedList = array_diff($requirementsList, $supplyList, $userSupplied->lists('Name')); $undefinedList = array_diff($undefinedList, $resultList->lists("Name")); if (!empty($undefinedList)) { $requirementsMap = array_combine($requirements->lists("parameterName"), $requirements->get()->all()); foreach ($undefinedList as $missingParameterName) { $editable = $requirementsMap[$missingParameterName]->Editable >= 2; if ($editable) { $userRequiredParameters[] = $requirementsMap[$missingParameterName]->Parameter; } else { $incompatibilities[] = "Parameter {$missingParameterName} is missing"; } } } } $supplies = $attributionsWithoutNeedle->whereNull("Needle_Id")->whereNotNull("Parameter_Attribution.Value"); $attributions = []; foreach ($supplies->get() as $attribution) { $name = $attribution->Parameter->Name; if (!isset($attributions[$name])) { $attributions[$name] = []; } $attributions[$name][] = $attribution; } $parameters = []; foreach ($attributions as $name => $available) { $parameters[$name] = $this->chooseAttribution($available); } foreach ($userSupplied as $userParameter) { if ($userParameter->Value === null) { $userParameter->Value = $userParameter->pivot->ValueSet; } $parameters[$userParameter->Name] = $userParameter; } foreach ($parameters as $parameter) { if ($parameter->Editable == 3) { /* Always editable */ $userRequiredParameters[] = $parameter; } } foreach ($needleParametersByNeedle as $needle => $needleParameters) { foreach ($needleParameters as $parameter) { if ($parameter->Editable == 3) { /* Always editable */ $userRequiredParameters[] = $parameter; } } } return [$parameters, $needleParametersByNeedle]; }