/**
* Renders additional code for the __construct() method of the Proxy Class which realizes constructor injection.
*
* @param Configuration $objectConfiguration
* @return string The built code
* @throws ObjectException\UnknownObjectException
*/
protected function buildConstructorInjectionCode(Configuration $objectConfiguration)
{
$assignments = [];
$argumentConfigurations = $objectConfiguration->getArguments();
$constructorParameterInfo = $this->reflectionService->getMethodParameters($objectConfiguration->getClassName(), '__construct');
$argumentNumberToOptionalInfo = [];
foreach ($constructorParameterInfo as $parameterInfo) {
$argumentNumberToOptionalInfo[$parameterInfo['position'] + 1] = $parameterInfo['optional'];
}
$highestArgumentPositionWithAutowiringEnabled = -1;
foreach ($argumentConfigurations as $argumentNumber => $argumentConfiguration) {
if ($argumentConfiguration === null) {
continue;
}
$argumentPosition = $argumentNumber - 1;
if ($argumentConfiguration->getAutowiring() === Configuration::AUTOWIRING_MODE_ON) {
$highestArgumentPositionWithAutowiringEnabled = $argumentPosition;
}
$argumentValue = $argumentConfiguration->getValue();
$assignmentPrologue = 'if (!array_key_exists(' . ($argumentNumber - 1) . ', $arguments)) $arguments[' . ($argumentNumber - 1) . '] = ';
if ($argumentValue === null && isset($argumentNumberToOptionalInfo[$argumentNumber]) && $argumentNumberToOptionalInfo[$argumentNumber] === true) {
$assignments[$argumentPosition] = $assignmentPrologue . 'NULL';
} else {
switch ($argumentConfiguration->getType()) {
case ConfigurationArgument::ARGUMENT_TYPES_OBJECT:
if ($argumentValue instanceof Configuration) {
$argumentValueObjectName = $argumentValue->getObjectName();
$argumentValueClassName = $argumentValue->getClassName();
if ($argumentValueClassName === null) {
$preparedArgument = $this->buildCustomFactoryCall($argumentValue->getFactoryObjectName(), $argumentValue->getFactoryMethodName(), $argumentValue->getArguments());
$assignments[$argumentPosition] = $assignmentPrologue . $preparedArgument;
} else {
if ($this->objectConfigurations[$argumentValueObjectName]->getScope() === Configuration::SCOPE_PROTOTYPE) {
$assignments[$argumentPosition] = $assignmentPrologue . 'new \\' . $argumentValueObjectName . '(' . $this->buildMethodParametersCode($argumentValue->getArguments()) . ')';
} else {
$assignments[$argumentPosition] = $assignmentPrologue . '\\Neos\\Flow\\Core\\Bootstrap::$staticObjectManager->get(\'' . $argumentValueObjectName . '\')';
}
}
} else {
if (strpos($argumentValue, '.') !== false) {
$settingPath = explode('.', $argumentValue);
$settings = Arrays::getValueByPath($this->configurationManager->getConfiguration(ConfigurationManager::CONFIGURATION_TYPE_SETTINGS), array_shift($settingPath));
$argumentValue = Arrays::getValueByPath($settings, $settingPath);
}
if (!isset($this->objectConfigurations[$argumentValue])) {
throw new ObjectException\UnknownObjectException('The object "' . $argumentValue . '" which was specified as an argument in the object configuration of object "' . $objectConfiguration->getObjectName() . '" does not exist.', 1264669967);
}
$assignments[$argumentPosition] = $assignmentPrologue . '\\Neos\\Flow\\Core\\Bootstrap::$staticObjectManager->get(\'' . $argumentValue . '\')';
}
break;
case ConfigurationArgument::ARGUMENT_TYPES_STRAIGHTVALUE:
$assignments[$argumentPosition] = $assignmentPrologue . var_export($argumentValue, true);
break;
case ConfigurationArgument::ARGUMENT_TYPES_SETTING:
$assignments[$argumentPosition] = $assignmentPrologue . '\\Neos\\Flow\\Core\\Bootstrap::$staticObjectManager->getSettingsByPath(explode(\'.\', \'' . $argumentValue . '\'))';
break;
}
}
}
for ($argumentCounter = count($assignments) - 1; $argumentCounter > $highestArgumentPositionWithAutowiringEnabled; $argumentCounter--) {
unset($assignments[$argumentCounter]);
}
$code = $argumentCounter >= 0 ? "\n " . implode(";\n ", $assignments) . ";\n" : '';
$index = 0;
foreach ($constructorParameterInfo as $parameterName => $parameterInfo) {
if ($parameterInfo['optional'] === true) {
break;
}
if ($objectConfiguration->getScope() === Configuration::SCOPE_SINGLETON) {
$code .= ' if (!array_key_exists(' . $index . ', $arguments)) throw new \\Neos\\Flow\\ObjectManagement\\Exception\\UnresolvedDependenciesException(\'Missing required constructor argument $' . $parameterName . ' in class \' . __CLASS__ . \'. Please check your calling code and Dependency Injection configuration.\', 1296143787);' . "\n";
} else {
$code .= ' if (!array_key_exists(' . $index . ', $arguments)) throw new \\Neos\\Flow\\ObjectManagement\\Exception\\UnresolvedDependenciesException(\'Missing required constructor argument $' . $parameterName . ' in class \' . __CLASS__ . \'. Note that constructor injection is only support for objects of scope singleton (and this is not a singleton) – for other scopes you must pass each required argument to the constructor yourself.\', 1296143788);' . "\n";
}
$index++;
}
return $code;
}