/** * @param ParameterReflection $reflectionParameter * @return ParameterGenerator */ public static function fromReflection(ParameterReflection $reflectionParameter) { $param = new ParameterGenerator(); $param->setName($reflectionParameter->getName()); if ($type = self::extractFQCNTypeFromReflectionType($reflectionParameter)) { $param->setType($type); } $param->setPosition($reflectionParameter->getPosition()); $variadic = method_exists($reflectionParameter, 'isVariadic') && $reflectionParameter->isVariadic(); $param->setVariadic($variadic); if (!$variadic && $reflectionParameter->isOptional()) { try { $param->setDefaultValue($reflectionParameter->getDefaultValue()); } catch (\ReflectionException $e) { $param->setDefaultValue(null); } } $param->setPassedByReference($reflectionParameter->isPassedByReference()); return $param; }
private function buildClass($replacement) { $type = $this->splitNsandClass($replacement['originalFullyQualifiedType']); $class = new ClassGenerator(); $class->setName($type['class']); $class->setNamespaceName($type['ns']); $class->setExtendedClass('\\Brads\\Ppm\\Proxy'); $properties = []; $methods = []; $implementedInterfaces = []; foreach ($versions as $version => $info) { foreach ($info['files'] as $file) { echo "Parsing: " . $this->vendorDir . '/' . $package . '/' . $version . '/' . $file . "\n"; $parsedFile = new ReflectionFile($this->vendorDir . '/' . $package . '/' . $version . '/' . $file); $parsedClass = $parsedFile->getFileNamespace($info['toNs'])->getClass($info['toNs'] . '\\' . $type['class']); if ($parsedClass->getInterfaceNames() != null) { $implementedInterfaces = array_merge($implementedInterfaces, $parsedClass->getInterfaceNames()); } foreach ($parsedClass->getMethods() as $method) { if ($method->isPublic()) { $generatedMethod = new MethodGenerator(); $generatedMethod->setName($method->name); $generatedMethod->setBody('echo "Hello world!";'); $generatedMethod->setAbstract($method->isAbstract()); $generatedMethod->setFinal($method->isFinal()); $generatedMethod->setStatic($method->isStatic()); $generatedMethod->setVisibility(MethodGenerator::VISIBILITY_PUBLIC); foreach ($method->getParameters() as $param) { $generatedParam = new ParameterGenerator(); $generatedParam->setName($param->name); if ($param->hasType()) { $generatedParam->setType($param->getType()); } //$generatedParam->setDefaultValue($param->getDefaultValue()); $generatedParam->setPosition($param->getPosition()); $generatedParam->setVariadic($param->isVariadic()); $generatedParam->setPassedByReference($param->isPassedByReference()); $generatedMethod->setParameter($generatedParam); } $existingMethod = Linq::from($methods)->firstOrDefault(null, function (MethodGenerator $v) use($method) { return $v->getName() == $method->name; }); if ($existingMethod != null) { $existingParams = $existingMethod->getParameters(); foreach ($generatedMethod->getParameters() as $newParam) { $existingParam = Linq::from($existingParams)->firstOrDefault(function (ParameterGenerator $v) { return $v->getName() == $newParam->getName(); }); if ($existingParam == null) { $existingMethod->setParameter($newParam); } } } else { $methods[] = $generatedMethod; } } } foreach ($parsedClass->getProperties() as $prop) { //$properties[] = PropertyGenerator::fromReflection($prop); } } } $class->setImplementedInterfaces($implementedInterfaces); $class->addMethods($methods); $class->addProperties($properties); return (new FileGenerator(['classes' => [$class]]))->generate(); }
private function buildProxyClass(string $entityInterfaceName, string $proxyNamespace, string $proxyClassName) : string { $reflectionClass = new ReflectionClass($entityInterfaceName); if (!$reflectionClass->isInterface()) { throw InvalidInterfaceException::fromInvalidInterface($entityInterfaceName); } $classGenerator = new ClassGenerator(); $classGenerator->setNamespaceName($proxyNamespace); $classGenerator->setName($proxyClassName); $classGenerator->setImplementedInterfaces([$entityInterfaceName, ProxyInterface::class]); $classGenerator->addProperty('initializer', null, PropertyGenerator::FLAG_PRIVATE); $classGenerator->addProperty('relationId', null, PropertyGenerator::FLAG_PRIVATE); $classGenerator->addProperty('realEntity', null, PropertyGenerator::FLAG_PRIVATE); $constructorGenerator = new MethodGenerator('__construct', [['name' => 'initializer', 'type' => 'callable'], ['name' => 'relationId']]); $constructorGenerator->setBody(' $this->initializer = $initializer; $this->relationId = $relationId; '); $classGenerator->addMethodFromGenerator($constructorGenerator); $getRelationIdGenerator = new MethodGenerator('__getRelationId'); $getRelationIdGenerator->setBody(' return $this->relationId; '); $classGenerator->addMethodFromGenerator($getRelationIdGenerator); $getRealEntityGenerator = new MethodGenerator('__getRealEntity'); $getRealEntityGenerator->setBody(' if (null === $this->realEntity) { $this->realEntity = ($this->initializer)(); \\Assert\\Assertion::isInstanceOf($this->realEntity, \\' . $entityInterfaceName . '::class); }; return $this->realEntity; '); $classGenerator->addMethodFromGenerator($getRealEntityGenerator); foreach ($reflectionClass->getMethods(ReflectionMethod::IS_PUBLIC) as $reflectionMethod) { $parameters = []; $parameterGenerators = []; $returnType = $reflectionMethod->getReturnType(); foreach ($reflectionMethod->getParameters() as $reflectionParameter) { $parameterGenerator = new ParameterGenerator($reflectionParameter->getName(), $reflectionParameter->getType(), $reflectionParameter->isDefaultValueAvailable() ? $reflectionParameter->getDefaultValue() : null); $parameterGenerator->setVariadic($reflectionParameter->isVariadic()); $parameterGenerators[] = $parameterGenerator; if ($reflectionParameter->isVariadic()) { $parameters[] = '...$' . $reflectionParameter->getName(); } else { $parameters[] = '$' . $reflectionParameter->getName(); } } $methodGenerator = new MethodGenerator(); $methodGenerator->setName($reflectionMethod->getName()); $methodGenerator->setVisibility(MethodGenerator::VISIBILITY_PUBLIC); $methodGenerator->setParameters($parameterGenerators); $methodGenerator->setReturnType($returnType); $body = ' if (null === $this->realEntity) { $this->realEntity = ($this->initializer)(); \\Assert\\Assertion::isInstanceOf($this->realEntity, \\' . $entityInterfaceName . '::class); }; '; if ('void' !== $returnType) { $body .= 'return '; } $body .= '$this->realEntity->' . $reflectionMethod->getName() . '(' . implode(', ', $parameters) . ');'; $methodGenerator->setBody($body); $classGenerator->addMethodFromGenerator($methodGenerator); } $fileGenerator = new FileGenerator(); $fileGenerator->setClass($classGenerator); $filename = null === $this->proxyFolder ? tempnam(sys_get_temp_dir(), $proxyClassName) : sprintf('%s/%s.php', $this->proxyFolder, $proxyClassName); $fileGenerator->setFilename($filename); $fileGenerator->write(); return $filename; }