On 11 August 2014 11:30, Chris Wright <daveran...@php.net> wrote: > Hi Tom > > On 9 August 2014 11:35, Tom Oram <t...@scl.co.uk> wrote: >> I've just been looking back at the history of this previous conversation... >> >> http://marc.info/?l=php-internals&m=132673741606531&w=2 >> >> as a mockist tester I'd really REALLY like to see this be possible but I >> can see the problem with the original patch modifying the actual existing >> class. >> >> One solution I propose is rather than modify it would it be possible for >> the reflection class to be able to duplicate the class with the finals >> removed so something like this could be possible: >> >> final class A >> { >> } >> >> $r = new ReflectionClass('A'); >> >> $r->defineExtendableClass('ExtendableA'); >> >> class MockA extends ExtendabledA >> { >> } >> >> I'm unfamiliar with the PHP codebase so I thought I'd just ask here to find >> out if it sounds possible before diving into the code > > Yes it's definitely possible, all you need to do is duplicate the > class definition and perform &= ~ZEND_ACC_FINAL on the class entry > structure flags, however... > > Joe Watkins' uopz [1][2] extension already provides a mechanism to do > what you want to do. I've not tested this, but I quickly bounced a > couple of questions off Joe and I believe this should work: > > final class A {} > class MockA {} > uopz_extend('MockA', 'A'); > > A word of warning though: if a *method* is explicitly declared final > (rather than implicitly because the class is final), and the mock > overrides this method, this will be checked at runtime and cause a > fatal error. In order to work around this, you need to use > uopz_flags() as well: > > class B { > final public function c() {} > } > class MockB { > public function c() {} > } > uopz_flags('B', 'c', ZEND_ACC_PUBLIC); // remove ZEND_ACC_FINAL > uopz_flags('B', 'c', );
That last line should read: uopz_extend('MockB', 'B'); > Note also that if you are using this approach - modifying symbol flags > at runtime - it is important that you do not declare the inheritance > relationship explicitly (i.e. class MockA extends A {}) as this will > error out before the runtime modifications are made. > > If you want to look at adding similar functionality to reflection, > then looking at how uopz works would be a good place to start - but > personally I'm not sure if there's any value in this since anyone who > wants the functionality can just use uopz. > > [1] https://github.com/krakjoe/uopz > [2] http://php.net/uopz > >> Thoughts? >> >> Regards, >> Tom > > Thanks, Chris -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php