Bug #29449

Add safeguard preventing to reflect Doctrine Proxies

Added by Sebastian Kurfuerst about 10 years ago. Updated about 10 years ago.

Status:
Resolved
Priority:
Must have
Category:
Reflection
Start date:
2011-09-01
Due date:
% Done:

100%

Estimated time:
PHP Version:
Has patch:
Complexity:

Description

In some custom application of mine, I have accidentally reflected a doctrine proxy class; which lead to the ReflectionService being called like this:

ReflectionService::reflectClass('TYPO3\FLOW3\Persistence\Doctrine\Proxies\SandstormMediaWorkflowDomainModelProcessInstanceProxy')

The ReflectionService reflected the class, returned the expected result and then saved the information about the above classname in the cache.

Unluckily, the above class implements multiple interfaces:

  • Doctrine\ORM\Proxy\Proxy
  • TYPO3\FLOW3\AOP\ProxyInterface (as also some aspects apply to the above class)

Now, on the next FLOW3 run, the following happens:

  • The Object\Configuration\ConfigurationBuilder iterates through all available class names, thus it will also iterate over Doctrine\ORM\Proxy\Proxy
  • The ConfigurationBuilder then asks ReflectionService::getDefaultImplementationClassNameForInterface('Doctrine\ORM\Proxy\Proxy')
  • The ReflectionService returns our above initial class (....Proxies\SandstormMedia.....Proxy); because that's the only known implementation of the Proxy interface
  • then, various weird things can happen... for example ReflectionService::getMethodTagsValues(...) might fail because the ...Proxy class could not be loaded by the autoloader.

This leads to errors like:

Uncaught Exception in FLOW3 Class TYPO3\FLOW3\Persistence\Doctrine\Proxies\SandstormMediaWorkflowDomainModelProcessInstanceProxy does not exist thrown in file Packages/Framework/TYPO3.FLOW3/Classes/Reflection/ReflectionService.php in line 595 #0 TYPO3\FLOW3\Error\DebugExceptionHandler::echoExceptionCli() Packages/Framework/TYPO3.FLOW3/Classes/Error/AbstractExceptionHandler.php:60 #1 TYPO3\FLOW3\Error\AbstractExceptionHandler::handleException()

So, the behavior is as follows:

  • on first hit, everything works.
  • on second hit, at compile time, the system seems to break randomly (took me quite some time to figure out what happens)

Root Cause

The issue was caused by some custom package of mine, calling the ReflectionService in a wrong/unspecified way. I did $reflectionService->getClassSchema(get_class($object));
where $object was a doctrine proxy. And this lead to the above behavior.

Possible Solutions

We somehow need to prevent the above root cause. For that, I see three possibilities, all of them adding a check to ReflectionService::reflectClass()

  1. fail silently when detecting that the incoming class name is a doctrine proxy
  2. throw an exception when detecting that the incoming class name is a doctrine proxy
  3. when detecting a doctrine proxy, find out the class name the user really wanted to reflect instead, and return this reflection data instead.

3) might have some side-effects; as we would need to touch most of the methods in the ReflectionService, everywhere $this->reflectClass() is called. That's why my preferred solution is 2).

How to continue

I'll fix this issue; I'd just like your opinion which solution you like most.

Greets, Sebastian

#1

Updated by Robert Lemke about 10 years ago

We somehow need to prevent the above root cause. For that, I see three possibilities, all of them adding a check to ReflectionService::reflectClass()

  1. fail silently when detecting that the incoming class name is a doctrine proxy
  2. throw an exception when detecting that the incoming class name is a doctrine proxy
  3. when detecting a doctrine proxy, find out the class name the user really wanted to reflect instead, and return this reflection data instead.

I also opt for 2). The question is if the Doctrine Proxy should be or can be identified by an interface which is part of the FLOW3 package. But that's probably of minor importance.

#2

Updated by Karsten Dambekalns about 10 years ago

  • Status changed from New to Accepted

Definitely solution 2)

#3

Updated by Karsten Dambekalns about 10 years ago

Robert Lemke wrote:

The question is if the Doctrine Proxy should be or can be identified by an interface which is part of the FLOW3 package.

Why? There are a number of places where code is tied to Doctrine, and if it is, this should be visible IMHO. Effectively hiding that fact in some other interface name doesn't help, does it?

#4

Updated by Mr. Hudson about 10 years ago

  • Status changed from Accepted to Under Review

Patch set 1 of change Ia709b70e4e31facfd88563c5836009d7cee6d7b2 has been pushed to the review server.
It is available at http://review.typo3.org/4738

#5

Updated by Sebastian Kurfuerst about 10 years ago

  • Status changed from Under Review to Resolved
  • % Done changed from 0 to 100

Also available in: Atom PDF