-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Move current implementation into seperate class
- Loading branch information
1 parent
7eae818
commit f83d3e4
Showing
5 changed files
with
228 additions
and
67 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace AdvancedJsonRpc\Reflection\Dto; | ||
|
||
class Method | ||
{ | ||
/** @var string */ | ||
private $declaringClass; | ||
/** @var string|null */ | ||
private $docComment; | ||
/** @var Parameter[] */ | ||
private $parameters; | ||
/** @var Parameter[] */ | ||
private $paramTags; | ||
|
||
/** | ||
* @param string|null $docComment | ||
*/ | ||
public function __construct(string $declaringClass, $docComment, array $parameters, array $paramTags) | ||
{ | ||
$this->declaringClass = $declaringClass; | ||
$this->docComment = $docComment; | ||
$this->parameters = $parameters; | ||
$this->paramTags = $paramTags; | ||
} | ||
|
||
public function getDeclaringClass(): string | ||
{ | ||
return $this->declaringClass; | ||
} | ||
|
||
public function getDocComment(): string | ||
{ | ||
return $this->docComment; | ||
} | ||
|
||
public function getParameters(): array | ||
{ | ||
return $this->parameters; | ||
} | ||
|
||
public function getParamTags(): array | ||
{ | ||
return $this->paramTags; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace AdvancedJsonRpc\Reflection\Dto; | ||
|
||
|
||
class Parameter | ||
{ | ||
/** @var string */ | ||
private $name; | ||
/** @var Type|null */ | ||
private $type; | ||
|
||
public function __construct(string $name, Type $type = null) | ||
{ | ||
$this->name = $name; | ||
$this->type = $type; | ||
} | ||
|
||
public function getName(): string | ||
{ | ||
return $this->name; | ||
} | ||
|
||
public function getType(): Type | ||
{ | ||
return $this->type; | ||
} | ||
|
||
public function hasType(): bool | ||
{ | ||
return isset($this->type); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace AdvancedJsonRpc\Reflection\Dto; | ||
|
||
class Type | ||
{ | ||
/** @var string */ | ||
private $name; | ||
|
||
public function __construct(string $name) | ||
{ | ||
$this->name = $name; | ||
} | ||
|
||
public function getName(): string | ||
{ | ||
return $this->name; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace AdvancedJsonRpc\Reflection; | ||
|
||
|
||
use AdvancedJsonRpc\Error; | ||
use AdvancedJsonRpc\ErrorCode; | ||
use AdvancedJsonRpc\Reflection\Dto\Method; | ||
use AdvancedJsonRpc\Reflection\Dto\Parameter; | ||
use AdvancedJsonRpc\Reflection\Dto\Type; | ||
use phpDocumentor\Reflection\DocBlock\Tag; | ||
use phpDocumentor\Reflection\DocBlockFactory; | ||
use phpDocumentor\Reflection\Types; | ||
use ReflectionException; | ||
use ReflectionMethod; | ||
use ReflectionNamedType; | ||
|
||
class NativeReflection | ||
{ | ||
/** @var DocBlockFactory */ | ||
private $docBlockFactory; | ||
/** @var \phpDocumentor\Reflection\Types\ContextFactory */ | ||
private $contextFactory; | ||
/** @var Method[] */ | ||
private $methods = []; | ||
|
||
public function __construct() | ||
{ | ||
$this->docBlockFactory = DocBlockFactory::createInstance(); | ||
$this->contextFactory = new Types\ContextFactory(); | ||
} | ||
|
||
public function getMethodDetails($rpcMethod, $target, $nativeMethod): Method | ||
{ | ||
if (array_key_exists($rpcMethod, $this->methods)) { | ||
return $this->methods[$rpcMethod]; | ||
} | ||
|
||
try { | ||
$nativeMethod = new ReflectionMethod($target, $nativeMethod); | ||
} catch (ReflectionException $e) { | ||
throw new Error($e->getMessage(), ErrorCode::METHOD_NOT_FOUND, null, $e); | ||
} | ||
|
||
$paramTags = []; | ||
if ($nativeMethod->getDocComment()) { | ||
$docBlock = $this->docBlockFactory->create( | ||
$nativeMethod->getDocComment(), | ||
$this->contextFactory->createFromReflector($nativeMethod->getDeclaringClass()) | ||
); | ||
$paramTags = $docBlock->getTagsByName('param'); | ||
} | ||
|
||
$method = new Method( | ||
$nativeMethod->getDeclaringClass()->getName(), | ||
$nativeMethod->getDocComment() ?: null, | ||
array_map(function($p) { return $this->mapNativeReflectionParameterToParameter($p); }, $nativeMethod->getParameters()), | ||
array_map(function($p) { return $this->mapDocBlockTagToParameter($p); }, $paramTags) | ||
); | ||
|
||
$this->methods[$rpcMethod] = $method; | ||
|
||
return $method; | ||
} | ||
|
||
private function mapNativeReflectionParameterToParameter(\ReflectionParameter $native): Parameter | ||
{ | ||
$types = $this->mapNativeReflectionTypeToType($native->getType()); | ||
return new Parameter($native->getName(), $types); | ||
} | ||
|
||
private function mapDocBlockTagToParameter(Tag $tag): Parameter | ||
{ | ||
$type = $tag->getType(); | ||
// For union types, use the first one that is a class array (often it is SomeClass[]|null) | ||
if ($type instanceof Types\Compound) { | ||
for ($i = 0; $t = $type->get($i); $i++) { | ||
if ( | ||
$t instanceof Types\Array_ | ||
&& $t->getValueType() instanceof Types\Object_ | ||
&& (string)$t->getValueType() !== 'object' | ||
) { | ||
return new Parameter($tag->getName(), new Type((string)$t->getValueType()->getFqsen())); | ||
} | ||
} | ||
} else if ($type instanceof Types\Array_) { | ||
return new Parameter($tag->getName(), new Type((string)$type->getValueType()->getFqsen())); | ||
} | ||
} | ||
|
||
private function mapNativeReflectionTypeToType(\ReflectionType $native = null): Type | ||
{ | ||
if ($native instanceof ReflectionNamedType) { | ||
// We have object data to map and want the class name. | ||
// This should not include the `?` if the type was nullable. | ||
return new Type($native->getName()); | ||
} else { | ||
// Fallback for php 7.0, which is still supported (and doesn't have nullable). | ||
return new Type((string) $native); | ||
} | ||
} | ||
} |