public function attribute($data, $context = null, $overwrite = true, $overwrite_parameter = false) { $name = $data['Name']; if (!$this->Id) { throw new InvalidArgumentException("Cowardly refusing to create an empty (universal) attribute"); } /* Convention over configuration */ $id_name = train_case(get_class($this)) . '_Id'; if ($id_name == 'Context_Id') { $id_name = Context::$idField; } $parameterClause = ParameterAttribution::where($id_name, '=', $this->Id); $activeFields = [snake_case(get_class($this))]; if ($context !== null) { $activeFields[] = 'context'; $parameterClause = $parameterClause->where(Context::$idContext, '=', $context->Id); } $parameterAttributions = $parameterClause->whereHas('parameter', function ($q) use($name) { $q->where('Name', '=', $name); })->get()->filter(function ($pa) use($activeFields) { return empty(array_diff(array_values($pa->activeFields()), array_values($activeFields))); }); $parameterAttribution = $parameterAttributions->first(); $parameterAttributions->each(function ($pa) { $pa->delete(); }); if (array_key_exists('Value', $data)) { $value = $data['Value']; unset($data['Value']); } else { $value = null; } if (array_key_exists('Widget', $data)) { $widget = $data['Widget']; unset($data['Widget']); } else { $widget = null; } if (array_key_exists('Units', $data)) { $units = $data['Units']; unset($data['Units']); } else { $units = null; } if (array_key_exists('Editable', $data)) { $editable = $data['Editable']; unset($data['Editable']); } else { $editable = 2; } if ($parameterAttribution) { $parameter = $parameterAttribution->parameter; if ($overwrite) { $parameterAttribution->Value = $value; $parameterAttribution->Editable = $editable; $parameterAttribution->Widget = $widget; $parameterAttribution->Units = $units; $parameterAttribution->save(); } else { $value = $parameterAttribution->Value; $editable = $parameterAttribution->Editable; $widget = $parameterAttribution->Widget; $units = $parameterAttribution->Units; } } else { $parameter = Parameter::whereName($data['Name'])->first(); if (empty($parameter)) { $parameter = Parameter::create($data); } else { $parameter->update(array_filter($data)); } /* Convention over configuration */ $id_name = train_case(get_class($this)) . '_Id'; if ($id_name == 'Context_Id') { $id_name = Context::$idField; } $type = array_key_exists('Type', $data) ? $data['Type'] : $parameter->Type; $widget = isset($widget) ? $widget : $parameter->Widget; $units = isset($units) ? $units : $parameter->Units; $attribution = [$id_name => $this->Id, 'Parameter_Id' => $parameter->Id, 'Value' => $value, 'Format' => $type, 'Editable' => $editable, 'Widget' => $widget, 'Units' => $units]; if ($context !== null) { $attribution[Context::$idContext] = $context->Id; } $parameterAttribution = ParameterAttribution::create($attribution); } if ($parameter->Widget === null && $parameter->Units === null || $overwrite_parameter) { $parameter->Widget = $widget; $parameter->Units = $units; } $parameter->Value = $value; $parameter->Editable = $editable; $parameter->Widget = $widget; $parameter->Units = $units; $parameterAttribution->save(); return $parameter; }
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]; }