Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:76420 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 8322 invoked from network); 11 Aug 2014 10:30:11 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 11 Aug 2014 10:30:11 -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.173 as permitted sender) X-PHP-List-Original-Sender: are.you.winning@gmail.com X-Host-Fingerprint: 209.85.216.173 mail-qc0-f173.google.com Received: from [209.85.216.173] ([209.85.216.173:45636] helo=mail-qc0-f173.google.com) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 63/80-02984-23B98E35 for ; Mon, 11 Aug 2014 06:30:10 -0400 Received: by mail-qc0-f173.google.com with SMTP id w7so1371055qcr.4 for ; Mon, 11 Aug 2014 03:30:49 -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:to:cc:content-type; bh=4+NeZ7VKubhBKAuqPPNNTu17Xuuf1/xzk/80IX5BK10=; b=fQ9s5njJ5l2lPP6Lrze+vtJYCtBSo7ZDt5yklCUqRwozNNAlp2VdoBoy3BcddXzHu+ kIy5I7jjWbhxGQzSWN28enfVJfQzw8DPNkuIvEclLdvFnvf4R0eNtm2/zkANi/mGP8o5 HAoLm3iW6xFBBMpbDU5usZjpOIXQjbxlLGLc00Ze0yFFyLF/1tS0ldaZl+alnOV++hmg TH60gQHDCLp+stG8FixbhXatom6k2HXRQ0n+s64ssPKPZCmLja7KPcKVkkChu4FHUl9r Fa+Pk6cRfIk1OSg8B4MpXp7ODTAd6QsH0H79hSrzBcWdUlgU4FHaQgDf5APr4PrELquQ hlzQ== MIME-Version: 1.0 X-Received: by 10.140.37.178 with SMTP id r47mr45660195qgr.59.1407753048037; Mon, 11 Aug 2014 03:30:48 -0700 (PDT) Sender: are.you.winning@gmail.com Received: by 10.229.64.196 with HTTP; Mon, 11 Aug 2014 03:30:47 -0700 (PDT) In-Reply-To: References: Date: Mon, 11 Aug 2014 11:30:47 +0100 X-Google-Sender-Auth: rZBHK30zYOoUCyQ8Mzkk25_GSXo Message-ID: To: Tom Oram Cc: PHP Internals Content-Type: text/plain; charset=UTF-8 Subject: Re: [PHP-DEV] Reflection to remove final From: daverandom@php.net (Chris Wright) 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', ); 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