forked from Ocramius/GeneratedHydrator
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
13 changed files
with
580 additions
and
0 deletions.
There are no files selected for viewing
29 changes: 29 additions & 0 deletions
29
benchmarks/GeneratedHydratorBenchmark/FileClosureAllPrivateClassHydrationBench.php
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,29 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace GeneratedHydratorBenchmark; | ||
|
||
/** | ||
* Benchmark class that contains only private properties hydration | ||
* | ||
* @BeforeMethods({"setUp"}) | ||
*/ | ||
class FileClosureAllPrivateClassHydrationBench extends RuntimeClosureHydrationBench | ||
{ | ||
public function setUp() : void | ||
{ | ||
$this->createHydrator(AllPrivateClass::class); | ||
$this->createData(); | ||
$this->object = new AllPrivateClass(); | ||
} | ||
|
||
/** | ||
* @Revs(100) | ||
* @Iterations(200) | ||
*/ | ||
public function benchConsume() : void | ||
{ | ||
($this->hydrator)($this->object, $this->data); | ||
} | ||
} |
29 changes: 29 additions & 0 deletions
29
benchmarks/GeneratedHydratorBenchmark/FileClosureAllPublicClassHydrationBench.php
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,29 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace GeneratedHydratorBenchmark; | ||
|
||
/** | ||
* Benchmark class that contains only public properties hydration | ||
* | ||
* @BeforeMethods({"setUp"}) | ||
*/ | ||
class FileClosureAllPublicClassHydrationBench extends RuntimeClosureHydrationBench | ||
{ | ||
public function setUp() : void | ||
{ | ||
$this->createHydrator(AllPublicClass::class); | ||
$this->createData(); | ||
$this->object = new AllPublicClass(); | ||
} | ||
|
||
/** | ||
* @Revs(100) | ||
* @Iterations(200) | ||
*/ | ||
public function benchConsume() : void | ||
{ | ||
($this->hydrator)($this->object, $this->data); | ||
} | ||
} |
41 changes: 41 additions & 0 deletions
41
benchmarks/GeneratedHydratorBenchmark/FileClosureHydrationBench.php
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,41 @@ | ||
<?php | ||
|
||
namespace GeneratedHydratorBenchmark; | ||
|
||
use GeneratedHydrator\ClosureGenerator\GenerateFileHydrator; | ||
use GeneratedHydrator\ClosureGenerator\GenerateRuntimeHydrator; | ||
|
||
class FileClosureHydrationBench extends HydrationBench | ||
{ | ||
/** @var callable */ | ||
protected $hydrator; | ||
|
||
/** @var mixed[] */ | ||
protected $data; | ||
|
||
/** @var mixed */ | ||
protected $object; | ||
|
||
/** | ||
* Create and set the hydrator | ||
*/ | ||
protected function createHydrator(string $class) : void | ||
{ | ||
$this->hydrator = (new GenerateFileHydrator())($class); | ||
} | ||
|
||
/** | ||
* Populate test data array | ||
*/ | ||
protected function createData() : void | ||
{ | ||
$this->data = [ | ||
'foo' => 'some foo string', | ||
'bar' => 42, | ||
'baz' => new \DateTime(), | ||
'someFooProperty' => [12, 13, 14], | ||
'someBarProperty' => 12354.4578, | ||
'someBazProperty' => new \stdClass(), | ||
]; | ||
} | ||
} |
29 changes: 29 additions & 0 deletions
29
benchmarks/GeneratedHydratorBenchmark/RuntimeClosureAllPrivateClassHydrationBench.php
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,29 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace GeneratedHydratorBenchmark; | ||
|
||
/** | ||
* Benchmark class that contains only private properties hydration | ||
* | ||
* @BeforeMethods({"setUp"}) | ||
*/ | ||
class RuntimeClosureAllPrivateClassHydrationBench extends RuntimeClosureHydrationBench | ||
{ | ||
public function setUp() : void | ||
{ | ||
$this->createHydrator(AllPrivateClass::class); | ||
$this->createData(); | ||
$this->object = new AllPrivateClass(); | ||
} | ||
|
||
/** | ||
* @Revs(100) | ||
* @Iterations(200) | ||
*/ | ||
public function benchConsume() : void | ||
{ | ||
($this->hydrator)($this->object, $this->data); | ||
} | ||
} |
29 changes: 29 additions & 0 deletions
29
benchmarks/GeneratedHydratorBenchmark/RuntimeClosureAllPublicClassHydrationBench.php
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,29 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace GeneratedHydratorBenchmark; | ||
|
||
/** | ||
* Benchmark class that contains only public properties hydration | ||
* | ||
* @BeforeMethods({"setUp"}) | ||
*/ | ||
class RuntimeClosureAllPublicClassHydrationBench extends RuntimeClosureHydrationBench | ||
{ | ||
public function setUp() : void | ||
{ | ||
$this->createHydrator(AllPublicClass::class); | ||
$this->createData(); | ||
$this->object = new AllPublicClass(); | ||
} | ||
|
||
/** | ||
* @Revs(100) | ||
* @Iterations(200) | ||
*/ | ||
public function benchConsume() : void | ||
{ | ||
($this->hydrator)($this->object, $this->data); | ||
} | ||
} |
40 changes: 40 additions & 0 deletions
40
benchmarks/GeneratedHydratorBenchmark/RuntimeClosureHydrationBench.php
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,40 @@ | ||
<?php | ||
|
||
namespace GeneratedHydratorBenchmark; | ||
|
||
use GeneratedHydrator\ClosureGenerator\GenerateRuntimeHydrator; | ||
|
||
class RuntimeClosureHydrationBench extends HydrationBench | ||
{ | ||
/** @var callable */ | ||
protected $hydrator; | ||
|
||
/** @var mixed[] */ | ||
protected $data; | ||
|
||
/** @var mixed */ | ||
protected $object; | ||
|
||
/** | ||
* Create and set the hydrator | ||
*/ | ||
protected function createHydrator(string $class) : void | ||
{ | ||
$this->hydrator = (new GenerateRuntimeHydrator())($class); | ||
} | ||
|
||
/** | ||
* Populate test data array | ||
*/ | ||
protected function createData() : void | ||
{ | ||
$this->data = [ | ||
'foo' => 'some foo string', | ||
'bar' => 42, | ||
'baz' => new \DateTime(), | ||
'someFooProperty' => [12, 13, 14], | ||
'someBarProperty' => 12354.4578, | ||
'someBazProperty' => new \stdClass(), | ||
]; | ||
} | ||
} |
10 changes: 10 additions & 0 deletions
10
src/GeneratedHydrator/ClosureGenerator/GenerateExtractor.php
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,10 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace GeneratedHydrator\ClosureGenerator; | ||
|
||
interface GenerateExtractor | ||
{ | ||
public function __invoke(string $className): callable; | ||
} |
111 changes: 111 additions & 0 deletions
111
src/GeneratedHydrator/ClosureGenerator/GenerateFileHydrator.php
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,111 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace GeneratedHydrator\ClosureGenerator; | ||
|
||
use ReflectionClass; | ||
use ReflectionException; | ||
use RuntimeException; | ||
use function class_exists; | ||
use function file_exists; | ||
use function file_put_contents; | ||
use function sha1; | ||
use function sys_get_temp_dir; | ||
|
||
final class GenerateFileHydrator implements GenerateHydrator | ||
{ | ||
/** @var string */ | ||
private $targetDir; | ||
|
||
/** @var callable[] */ | ||
private static $hydratorsCache; | ||
|
||
/** @var ReflectionClass[] */ | ||
private static $classesCache; | ||
|
||
public function __construct(?string $targetDir = null) | ||
{ | ||
$this->targetDir = $targetDir ?? sys_get_temp_dir() . DIRECTORY_SEPARATOR; | ||
} | ||
|
||
public function __invoke(string $className): callable | ||
{ | ||
if (isset(self::$hydratorsCache[$className])) { | ||
return self::$hydratorsCache[$className]; | ||
} | ||
|
||
$classId = str_replace('\\', '_', $className); | ||
$filename = $this->targetDir . $classId . '.php'; | ||
$hydratorName = "hydrator_" . $classId; | ||
if (! file_exists($filename)) { | ||
$content = <<<PHP | ||
<?php | ||
declare(strict_types=1); | ||
namespace GeneratedHydrator\Hydrators; | ||
\$hydrator_{$classId} = \Closure::bind(function (\\{$className} \$object, array \$data) : void { | ||
PHP; | ||
|
||
foreach ($this->getPropertyNames($className) as $propertyName) { | ||
$content .= " \$object->{$propertyName} = \$data['{$propertyName}'];" . PHP_EOL; | ||
} | ||
$content .= <<<PHP | ||
}, null, \\{$className}::class); | ||
PHP; | ||
file_put_contents($filename, $content); | ||
} | ||
require_once $filename; | ||
|
||
return self::$hydratorsCache[$className] = $$hydratorName; | ||
} | ||
|
||
private function generateParentHydrator($className): ?callable | ||
{ | ||
$parent = $this->getClass($className)->getParentClass(); | ||
if ($parent === false) { | ||
return null; | ||
} | ||
|
||
return $this($parent->getName()); | ||
} | ||
|
||
/** | ||
* @return string[] | ||
*/ | ||
private function getPropertyNames(string $className): array | ||
{ | ||
$class = $this->getClass($className); | ||
$propertyNames = []; | ||
foreach ($class->getProperties() as $property) { | ||
if ($property->isStatic()) { | ||
continue; | ||
} | ||
$propertyNames[] = $property->getName(); | ||
} | ||
return $propertyNames; | ||
} | ||
|
||
private function getClass(string $className): ReflectionClass | ||
{ | ||
if (isset(self::$classesCache[$className])) { | ||
return self::$classesCache[$className]; | ||
} | ||
|
||
if (!class_exists($className, true)) { | ||
throw new RuntimeException("Class $className not found"); | ||
} | ||
|
||
try { | ||
$class = new ReflectionClass($className); | ||
} catch (ReflectionException $e) { | ||
throw new RuntimeException("Can't reflect class $className", 0, $e); | ||
} | ||
|
||
return self::$classesCache[$className] = $class; | ||
} | ||
} |
10 changes: 10 additions & 0 deletions
10
src/GeneratedHydrator/ClosureGenerator/GenerateHydrator.php
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,10 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace GeneratedHydrator\ClosureGenerator; | ||
|
||
interface GenerateHydrator | ||
{ | ||
public function __invoke(string $className): callable; | ||
} |
Oops, something went wrong.