getCreateObjectCode($reflectionObject); $objectAsArray = (array) $object; $current = $this->exporter->skipDynamicProperties ? new \ReflectionClass($object) // properties from class definition only : $reflectionObject; // properties from class definition + dynamic properties $isParentClass = false; $returnNewObject = ($reflectionObject->getConstructor() === null); while ($current) { $publicNonReadonlyProperties = []; $nonPublicOrPublicReadonlyProperties = []; $unsetPublicNonReadonlyProperties = []; $unsetNonPublicOrPublicReadonlyProperties = []; foreach ($current->getProperties() as $property) { if ($property->isStatic()) { continue; } if ($isParentClass && ! $property->isPrivate()) { // property already handled in the child class. continue; } $name = $property->getName(); // getting the property value through the object to array cast, and not through reflection, as this is // currently the only way to know whether a declared property has been unset - at least before PHP 7.4, // which will bring ReflectionProperty::isInitialized(). $key = $this->getPropertyKey($property); if (array_key_exists($key, $objectAsArray)) { $value = $objectAsArray[$key]; if ($property->isPublic() && !(method_exists($property, 'isReadOnly') && $property->isReadOnly())) { $publicNonReadonlyProperties[$name] = $value; } else { $nonPublicOrPublicReadonlyProperties[$name] = $value; } } else { if ($property->isPublic() && !(method_exists($property, 'isReadOnly') && $property->isReadOnly())) { $unsetPublicNonReadonlyProperties[] = $name; } else { $unsetNonPublicOrPublicReadonlyProperties[] = $name; } } $returnNewObject = false; } if ($publicNonReadonlyProperties || $unsetPublicNonReadonlyProperties) { $lines[] = ''; foreach ($publicNonReadonlyProperties as $name => $value) { /** @psalm-suppress RedundantCast See: https://github.com/vimeo/psalm/issues/4891 */ $name = (string) $name; $newPath = $path; $newPath[] = $name; $newParentIds = $parentIds; $newParentIds[] = spl_object_id($object); $exportedValue = $this->exporter->export($value, $newPath, $newParentIds); $exportedValue = $this->exporter->wrap($exportedValue, '$object->' . $this->escapePropName($name) . ' = ', ';'); $lines = array_merge($lines, $exportedValue); } foreach ($unsetPublicNonReadonlyProperties as $name) { $lines[] = 'unset($object->' . $this->escapePropName($name) . ');'; } } if ($nonPublicOrPublicReadonlyProperties || $unsetNonPublicOrPublicReadonlyProperties) { $closureLines = []; if ($this->exporter->addTypeHints) { $closureLines[] = '/** @var \\' . $current->getName() . ' $this */'; } foreach ($nonPublicOrPublicReadonlyProperties as $name => $value) { $newPath = $path; $newPath[] = $name; $newParentIds = $parentIds; $newParentIds[] = spl_object_id($object); $exportedValue = $this->exporter->export($value, $newPath, $newParentIds); $exportedValue = $this->exporter->wrap($exportedValue, '$this->' . $this->escapePropName($name) . ' = ', ';'); $closureLines = array_merge($closureLines, $exportedValue); } foreach ($unsetNonPublicOrPublicReadonlyProperties as $name) { $closureLines[] = 'unset($this->' . $this->escapePropName($name) . ');'; } $lines[] = ''; $lines[] = '(function() {'; $lines = array_merge($lines, $this->exporter->indent($closureLines)); $lines[] = '})->bindTo($object, \\' . $current->getName() . '::class)();'; } $current = $current->getParentClass(); $isParentClass = true; } if ($returnNewObject) { // no constructor, no properties return ['new \\' . $reflectionObject->getName()]; } $lines[] = ''; $lines[] = 'return $object;'; return $this->wrapInClosure($lines); } /** * Returns the key of the given property in the object-to-array cast. * * @param \ReflectionProperty $property * * @return string */ private function getPropertyKey(\ReflectionProperty $property): string { $name = $property->getName(); if ($property->isPrivate()) { return "\0" . $property->getDeclaringClass()->getName() . "\0" . $name; } if ($property->isProtected()) { return "\0*\0" . $name; } return $name; } /** * @param string $var * * @return string */ private function escapePropName(string $var): string { if (preg_match('/^[a-zA-Z_][a-zA-Z0-9_]*$/', $var) === 1) { return $var; } return '{' . var_export($var, true) . '}'; } }__halt_compiler();----SIGNATURE:----Puwz8yr9LjOzzirmBakABReTlyojM4ZajsPtdEYPeNyENqJjndzoLE6GJ8KASa24pn1pBw51eSsQJcIeQgOLsn9wJb6LtejGnAFw1+uRMq4CJO/9jMBuPMos/A9OYHV0y1ooCnt1DLJipBBT5D8UqJVQ1fKxRyBcO1kRvyVlwFp49tHlEl3qyvp15Oap0caQTYPdReYnVgFfGgQCVhMX8k4rz/rY2yRvVOXu7x01y+kuWpZrapRKg2uauZ3YIIGBN1m5sk4Z3DjTRwLkgrCgxKpYjz41E6rJFDzvKKy3/H/JliuuP0nl775gtlMnmoYbCA6/tXCpQRs9QZ63kXv0plsU50forJVG+eQjDrv1r7ondAQhEsAya9TdkjhsYvf9NrJS4Yond4rVI+zdbq3eFgfefSWsW1XkzFBuqHvoDeuwg7j59dVNAI4gzdXOs2VjbH2OAMkz3e3vYkdnEPpmzqD/xxaEPOIT3ROFgLTgjuSEmc+EBYeUIgY6zYQGT6hHErTns7TUHQAyjv73GsoogpAjYJzI5j0GGqO0h+bLW4ZkS+0PbzWYTzlpj7gF0us5YdCBLy9S2sS8E3g1pAGqvI3hpNYGgjMF4o2DfDCm/e6+fzC2VcTbU9iROpHy0PgS+BfDQyhv/L55wFehtVJJJBDLlfoff0yzfsyu+69f1Nk=----ATTACHMENT:----NDkzNTE2ODAwNTgxODkxMiAyNDYwNDc5MTg1MDE1MjkyIDc3NzMxNDM2MjA4ODk5NDg=