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

Reply via email to