Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:76422 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 12328 invoked from network); 11 Aug 2014 10:51:44 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 11 Aug 2014 10:51:44 -0000 Authentication-Results: pb1.pair.com smtp.mail=are.you.winning@gmail.com; spf=pass; sender-id=pass Authentication-Results: pb1.pair.com header.from=are.you.winning@gmail.com; sender-id=pass Received-SPF: pass (pb1.pair.com: domain gmail.com designates 209.85.216.180 as permitted sender) X-PHP-List-Original-Sender: are.you.winning@gmail.com X-Host-Fingerprint: 209.85.216.180 mail-qc0-f180.google.com Received: from [209.85.216.180] ([209.85.216.180:50315] helo=mail-qc0-f180.google.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id D6/10-11469-F30A8E35 for ; Mon, 11 Aug 2014 06:51:43 -0400 Received: by mail-qc0-f180.google.com with SMTP id l6so1428235qcy.11 for ; Mon, 11 Aug 2014 03:52:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:sender:in-reply-to:references:date:message-id:subject :from:cc:content-type; bh=rdX1wAZuCPvXRuFuLMy8ko6am60+CfYI4AO8Nqv8TBM=; b=Y4XLv+WvFXPTfrKhG2j+dkiPISvXhOWypqqNzhVvSuX/Nc6/knQsYbE2utZBF20rV4 iICptW7d0dJKe2KauLm7V9HVViqXSDiZHnevynoEuxwg+k6GDPuUyNxmGxqGB6ax9uln SxqaE1InbKyjnAr7t7xM3/FHBOO3F22EpmEzSSzkZGY/0jIT198wKmUUJxY8VKniS4o1 /89ujFXBZ9dnWjqLU8hXHlb6nHHQ7zvF8MjCKKNhU5vGdGjlN10J3YPUxiLk+wwAf4FV UNOR51bbFSiB+oWfP8vjGx84RKP5HdOp1DNW1sbaP6cM2NcIdrykLytgDe7UeHhCnGng qgYQ== MIME-Version: 1.0 X-Received: by 10.229.68.131 with SMTP id v3mt48702773qci.10.1407754341576; Mon, 11 Aug 2014 03:52:21 -0700 (PDT) Sender: are.you.winning@gmail.com Received: by 10.229.64.196 with HTTP; Mon, 11 Aug 2014 03:52:21 -0700 (PDT) In-Reply-To: References: Date: Mon, 11 Aug 2014 11:52:21 +0100 X-Google-Sender-Auth: LvQW0kk69fZq7TR8IqM8-JozvnY Message-ID: Cc: Tom Oram , PHP Internals Content-Type: text/plain; charset=UTF-8 Subject: Re: [PHP-DEV] Reflection to remove final From: daverandom@php.net (Chris Wright) On 11 August 2014 11:30, Chris Wright wrote: > Hi Tom > > On 9 August 2014 11:35, Tom Oram 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