Skip to content
This repository

DCOM-93 - Add ReflectionService and RuntimeReflectionService, change Cla... #89

Merged
merged 4 commits into from over 2 years ago

5 participants

Benjamin Eberlei Fedor Christophe Coevoet Johannes Guilherme Blanco
Benjamin Eberlei
Owner

...ssMetadata to use it and ClassMetadataFactory to delegate reflection init/wakup to metadata. This way we can remove the ClassMetadata + ClassMetadataInfo double madness in all the managers.

added some commits
Benjamin Eberlei DCOM-93 - Add ReflectionService and RuntimeReflectionService, change …
…ClassMetadata to use it and ClassMetadataFactory to delegate reflection init/wakup to metadata. This way we can remove the ClassMetadata + ClassMetadataInfo double madness in all the managers.
80cd74e
Benjamin Eberlei DCOM-93 - Fix typo 6150024
Guilherme Blanco

Util is not a good namespace to place such an important Mapping feature.
I'd rather create a subnamespace inside of Mapping for that (Reflection is my suggestion).

Owner

This feature has nothing to do with mapping Its just a simple abstraction/factory for the reflection stuff.

Guilherme Blanco

I didn't like the *Service here. The purpose of this class contract is not to expose a Service, but rather a Implementor.
My naming suggestion for this interface is "Implementor".

Owner

by that reason every reason would be named "implementor". I don't like that name, it conveys no further meaning.

Guilherme Blanco

Following the same idea of the other class, this class would be called:

Doctrine\Common\Mapping\Reflection\RuntimeReflectionImplementor

Collaborator

Do you plan to provide a cache based reflection service? Otherwise a class with some static methods should be enough, no?

Benjamin Eberlei beberlei merged commit 44ca64d into from
Benjamin Eberlei beberlei closed this
Fedor

Why is "getClass" in "StaticReflectionService", while stating it should return ReflectionClass|null, returns always null, which leads to generate:entities in Symfony2 not working? Shouldn't it be something like that instead (which is working)?

return $class ? new \ReflectionClass($class) : null;
Christophe Coevoet
Collaborator

because this implementation is meant to be used in the EntityGenerator, when the class does not exist yet. So it cannot return a Reflection in such place (you would have an exception)

Fedor

So this seems to be a temporary Symfony2 issue.

Christophe Coevoet
Collaborator

@suxxes btw, which version of Symfony are you using ? 2.0.x or master ?

Fedor

@stof in this case it's an s-s edition, which is the master for Symfony2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 4 unique commits by 1 author.

Dec 29, 2011
Benjamin Eberlei DCOM-93 - Add ReflectionService and RuntimeReflectionService, change …
…ClassMetadata to use it and ClassMetadataFactory to delegate reflection init/wakup to metadata. This way we can remove the ClassMetadata + ClassMetadataInfo double madness in all the managers.
80cd74e
Benjamin Eberlei DCOM-93 - Fix typo 6150024
Benjamin Eberlei DCOM-93 - Fix typo in method name d8feaae
Benjamin Eberlei DCOM-93 - Move ReflectionService to Mapping subnamespace to make clea…
…rer where it belongs.
4e9be5b
This page is out of date. Refresh to see the latest.
39  lib/Doctrine/Common/Persistence/Mapping/AbstractClassMetadataFactory.php
@@ -19,6 +19,8 @@
19 19
 
20 20
 namespace Doctrine\Common\Persistence\Mapping;
21 21
 
  22
+use Doctrine\Common\Cache\Cache;
  23
+
22 24
 /**
23 25
  * The ClassMetadataFactory is used to create ClassMetadata objects that contain all the
24 26
  * metadata mapping informations of a class which describes how a class should be mapped
@@ -57,11 +59,16 @@
57 59
     protected $initialized = false;
58 60
 
59 61
     /**
  62
+     * @var ReflectionService
  63
+     */
  64
+    private $reflectionService;
  65
+
  66
+    /**
60 67
      * Sets the cache driver used by the factory to cache ClassMetadata instances.
61 68
      *
62 69
      * @param Doctrine\Common\Cache\Cache $cacheDriver
63 70
      */
64  
-    public function setCacheDriver($cacheDriver)
  71
+    public function setCacheDriver(Cache $cacheDriver = null)
65 72
     {
66 73
         $this->cacheDriver = $cacheDriver;
67 74
     }
@@ -158,6 +165,7 @@ public function getMetadataFor($className)
158 165
             if ($this->cacheDriver) {
159 166
                 if (($cached = $this->cacheDriver->fetch($realClassName . $this->cacheSalt)) !== false) {
160 167
                     $this->loadedMetadata[$realClassName] = $cached;
  168
+                    $cached->wakeupReflection($this->getReflectionService());
161 169
                 } else {
162 170
                     foreach ($this->loadMetadata($realClassName) as $loadedClassName) {
163 171
                         $this->cacheDriver->save(
@@ -212,7 +220,7 @@ protected function getParentClasses($name)
212 220
     {
213 221
         // Collect parent classes, ignoring transient (not-mapped) classes.
214 222
         $parentClasses = array();
215  
-        foreach (array_reverse(class_parents($name)) as $parentClass) {
  223
+        foreach (array_reverse($this->getReflectionService()->getParentClasses($name)) as $parentClass) {
216 224
             if ( ! $this->getDriver()->isTransient($parentClass)) {
217 225
                 $parentClasses[] = $parentClass;
218 226
             }
@@ -242,6 +250,7 @@ protected function loadMetadata($name)
242 250
         $parent = null;
243 251
         $rootEntityFound = false;
244 252
         $visited = array();
  253
+        $reflService = $this->getReflectionService();
245 254
         foreach ($parentClasses as $className) {
246 255
             if (isset($this->loadedMetadata[$className])) {
247 256
                 $parent = $this->loadedMetadata[$className];
@@ -265,6 +274,9 @@ protected function loadMetadata($name)
265 274
                 array_unshift($visited, $className);
266 275
             }
267 276
 
  277
+            $class->initializeReflection($reflService);
  278
+            $class->wakeupReflection($reflService);
  279
+
268 280
             $loaded[] = $className;
269 281
         }
270 282
 
@@ -303,4 +315,27 @@ public function isTransient($class)
303 315
 
304 316
         return $this->getDriver()->isTransient($class);
305 317
     }
  318
+
  319
+    /**
  320
+     * Set reflectionService.
  321
+     *
  322
+     * @param ReflectionService $reflectionService
  323
+     */
  324
+    public function setReflectionService(ReflectionService $reflectionService)
  325
+    {
  326
+        $this->reflectionService = $reflectionService;
  327
+    }
  328
+
  329
+    /**
  330
+     * Get the reflection service associated with this metadata factory.
  331
+     *
  332
+     * @return ReflectionService
  333
+     */
  334
+    public function getReflectionService()
  335
+    {
  336
+        if ($this->reflectionService === null) {
  337
+            $this->reflectionService = new RuntimeReflectionService();
  338
+        }
  339
+        return $this->reflectionService;
  340
+    }
306 341
 }
23  lib/Doctrine/Common/Persistence/Mapping/ClassMetadata.php
@@ -162,4 +162,27 @@ function getAssociationMappedByTargetField($assocName);
162 162
      * @return array
163 163
      */
164 164
     function getIdentifierValues($object);
  165
+
  166
+    /**
  167
+     * Initialize Reflection services
  168
+     *
  169
+     * This method is called from a metadata factory after an uncached
  170
+     * initialization. Data set in this method should be serialized and
  171
+     * reconstituted on wakeup.
  172
+     *
  173
+     * @param ReflectionService $reflService
  174
+     * @return void
  175
+     */
  176
+    function initializeReflection(ReflectionService $reflService);
  177
+
  178
+    /**
  179
+     * Wakeup Reflection
  180
+     *
  181
+     * Method is called when the metadata instance is reconstituted from the
  182
+     * cache and also after initialization.
  183
+     *
  184
+     * @param ReflectionService $reflService
  185
+     * @return void
  186
+     */
  187
+    function wakeupReflection(ReflectionService $reflService);
165 188
 }
80  lib/Doctrine/Common/Persistence/Mapping/ReflectionService.php
... ...
@@ -0,0 +1,80 @@
  1
+<?php
  2
+/*
  3
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  4
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  5
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  6
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  7
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  8
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  9
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  10
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  11
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  12
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  13
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  14
+ *
  15
+ * This software consists of voluntary contributions made by many individuals
  16
+ * and is licensed under the LGPL. For more information, see
  17
+ * <http://www.doctrine-project.org>.
  18
+ */
  19
+
  20
+namespace Doctrine\Common\Persistence\Mapping;
  21
+
  22
+/**
  23
+ * Very simple reflection service abstraction.
  24
+ *
  25
+ * This is required inside metadata layers that may require either
  26
+ * static or runtime reflection.
  27
+ *
  28
+ * @author Benjamin Eberlei <kontakt@beberlei.de>
  29
+ */
  30
+interface ReflectionService
  31
+{
  32
+    /**
  33
+     * Return an array of the parent classes (not interfaces) for the given class.
  34
+     *
  35
+     * @param string $class
  36
+     * @return array
  37
+     */
  38
+    function getParentClasses($class);
  39
+
  40
+    /**
  41
+     * Return the shortname of a class.
  42
+     *
  43
+     * @param string $class
  44
+     * @return string
  45
+     */
  46
+    function getClassShortName($class);
  47
+
  48
+    /**
  49
+     * @param string $class
  50
+     * @return string
  51
+     */
  52
+    function getClassNamespace($class);
  53
+
  54
+    /**
  55
+     * Return a reflection class instance or null
  56
+     *
  57
+     * @param string $class
  58
+     * @return ReflectionClass|null
  59
+     */
  60
+    function getClass($class);
  61
+
  62
+    /**
  63
+     * Return an accessible property (setAccessible(true)) or null.
  64
+     *
  65
+     * @param string $class
  66
+     * @param string $property
  67
+     * @return ReflectionProperty|null
  68
+     */
  69
+    function getAccessibleProperty($class, $property);
  70
+
  71
+    /**
  72
+     * Check if the class have a public method with the given name.
  73
+     *
  74
+     * @param mixed $class
  75
+     * @param mixed $method
  76
+     * @return bool
  77
+     */
  78
+    function hasPublicMethod($class, $method);
  79
+}
  80
+
102  lib/Doctrine/Common/Persistence/Mapping/RuntimeReflectionService.php
... ...
@@ -0,0 +1,102 @@
  1
+<?php
  2
+/*
  3
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  4
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  5
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  6
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  7
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  8
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  9
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  10
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  11
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  12
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  13
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  14
+ *
  15
+ * This software consists of voluntary contributions made by many individuals
  16
+ * and is licensed under the LGPL. For more information, see
  17
+ * <http://www.doctrine-project.org>.
  18
+ */
  19
+
  20
+namespace Doctrine\Common\Persistence\Mapping;
  21
+
  22
+use ReflectionClass;
  23
+use ReflectionProperty;
  24
+
  25
+/**
  26
+ * PHP Runtime Reflection Service
  27
+ *
  28
+ * @author Benjamin Eberlei <kontakt@beberlei.de>
  29
+ */
  30
+class RuntimeReflectionService implements ReflectionService
  31
+{
  32
+    /**
  33
+     * Return an array of the parent classes (not interfaces) for the given class.
  34
+     *
  35
+     * @param string $class
  36
+     * @return array
  37
+     */
  38
+    public function getParentClasses($class)
  39
+    {
  40
+        return class_parents($class);
  41
+    }
  42
+
  43
+    /**
  44
+     * Return the shortname of a class.
  45
+     *
  46
+     * @param string $class
  47
+     * @return string
  48
+     */
  49
+    public function getClassShortName($class)
  50
+    {
  51
+        $r = new ReflectionClass($class);
  52
+        return $r->getShortName();
  53
+    }
  54
+
  55
+    /**
  56
+     * @param string $class
  57
+     * @return string
  58
+     */
  59
+    public function getClassNamespace($class)
  60
+    {
  61
+        $r = new ReflectionClass($class);
  62
+        return $r->getNamespaceName();
  63
+    }
  64
+
  65
+    /**
  66
+     * Return a reflection class instance or null
  67
+     *
  68
+     * @param string $class
  69
+     * @return ReflectionClass|null
  70
+     */
  71
+    public function getClass($class)
  72
+    {
  73
+        return new ReflectionClass($class);
  74
+    }
  75
+
  76
+    /**
  77
+     * Return an accessible property (setAccessible(true)) or null.
  78
+     *
  79
+     * @param string $class
  80
+     * @param string $property
  81
+     * @return ReflectionProperty|null
  82
+     */
  83
+    public function getAccessibleProperty($class, $property)
  84
+    {
  85
+        $property = new ReflectionProperty($class, $property);
  86
+        $property->setAccessible(true);
  87
+        return $property;
  88
+    }
  89
+
  90
+    /**
  91
+     * Check if the class have a public method with the given name.
  92
+     *
  93
+     * @param mixed $class
  94
+     * @param mixed $method
  95
+     * @return bool
  96
+     */
  97
+    public function hasPublicMethod($class, $method)
  98
+    {
  99
+        return method_exists($class, $method) && is_callable(array($class, $method));
  100
+    }
  101
+}
  102
+
70  tests/Doctrine/Tests/Common/Persistence/Mapping/RuntimeReflectionServiceTest.php
... ...
@@ -0,0 +1,70 @@
  1
+<?php
  2
+/*
  3
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  4
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  5
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  6
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  7
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  8
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  9
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  10
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  11
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  12
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  13
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  14
+ *
  15
+ * This software consists of voluntary contributions made by many individuals
  16
+ * and is licensed under the LGPL. For more information, see
  17
+ * <http://www.doctrine-project.org>.
  18
+ */
  19
+
  20
+namespace Doctrine\Tests\Common\Persistence\Mapping;
  21
+
  22
+use Doctrine\Common\Persistence\Mapping\RuntimeReflectionService;
  23
+
  24
+/**
  25
+ * @group DCOM-93
  26
+ */
  27
+class RuntimeReflectionServiceTest extends \PHPUnit_Framework_TestCase
  28
+{
  29
+    private $reflectionService;
  30
+
  31
+    public function setUp()
  32
+    {
  33
+        $this->reflectionService = new RuntimeReflectionService();
  34
+    }
  35
+
  36
+    public function testShortname()
  37
+    {
  38
+        $this->assertEquals("RuntimeReflectionServiceTest", $this->reflectionService->getClassShortName(__CLASS__));
  39
+    }
  40
+
  41
+    public function testClassNamespaceName()
  42
+    {
  43
+        $this->assertEquals("Doctrine\Tests\Common\Persistence\Mapping", $this->reflectionService->getClassNamespace(__CLASS__));
  44
+    }
  45
+
  46
+    public function testGetParentClasses()
  47
+    {
  48
+        $classes = $this->reflectionService->getParentClasses(__CLASS__);
  49
+        $this->assertTrue(count($classes) >= 1, "The test class ".__CLASS__." should have at least one parent.");
  50
+    }
  51
+
  52
+    public function testGetReflectionClass()
  53
+    {
  54
+        $class = $this->reflectionService->getClass(__CLASS__);
  55
+        $this->assertInstanceOf("ReflectionClass", $class);
  56
+    }
  57
+
  58
+    public function testGetMethods()
  59
+    {
  60
+        $this->assertTrue($this->reflectionService->hasPublicMethod(__CLASS__, "testGetMethods"));
  61
+        $this->assertFalse($this->reflectionService->hasPublicMethod(__CLASS__, "testGetMethods2"));
  62
+    }
  63
+
  64
+    public function testGetAccessibleProperty()
  65
+    {
  66
+        $reflProp = $this->reflectionService->getAccessibleProperty(__CLASS__, "reflectionService");
  67
+        $this->assertInstanceOf("ReflectionProperty", $reflProp);
  68
+    }
  69
+}
  70
+
11  tests/Doctrine/Tests/Common/Persistence/PersistentObjectTest.php
@@ -4,6 +4,7 @@
4 4
 
5 5
 use Doctrine\Common\Persistence\PersistentObject;
6 6
 use Doctrine\Common\Persistence\Mapping\ClassMetadata;
  7
+use Doctrine\Common\Persistence\Mapping\ReflectionService;
7 8
 
8 9
 /**
9 10
  * @group DDC-1448
@@ -233,4 +234,14 @@ public function getIdentifierFieldNames()
233 234
     {
234 235
 
235 236
     }
  237
+
  238
+    public function initializeReflection(ReflectionService $reflService)
  239
+    {
  240
+
  241
+    }
  242
+
  243
+    public function wakeupReflection(ReflectionService $reflService)
  244
+    {
  245
+
  246
+    }
236 247
 }
Commit_comment_tip

Tip: You can add notes to lines in a file. Hover to the left of a line to make a note

Something went wrong with that request. Please try again.