Emancipate and adopt do not appear to change class hierarchy #13

Closed
danwilliams opened this Issue Jun 23, 2011 · 4 comments

Comments

Projects
None yet
3 participants

Minimal code to reproduce the problem:

class myParent {}
class myUncle {}
class myChild extends myParent {}
runkit_class_emancipate("myChild");
runkit_class_adopt("myChild", "myUncle");```

The above results in an error:

PHP Warning: runkit_class_adopt(): Class mychild already has a parent

Explanation of what is expected from the code

class myParent {}
class myUncle {}
class myChild extends myParent {}
echo get_parent_class("myChild") . "\n";
runkit_class_emancipate("myChild");
//  Now expect myChild to have no parent...
echo get_parent_class("myChild") . "\n";
//  Actual output is still myParent.
//  Emancipated myChild, so should be able to adopt myUncle...
runkit_class_adopt("myChild", "myUncle");
//  Actual result is:
//      PHP Warning:  runkit_class_adopt(): Class mychild already has a parent
echo get_parent_class("myChild") . "\n";
//  Parent of myChild is still myParent - expected to be myUncle by now.```

Comparison of output

The above example produces:

myParent
myParent
PHP Warning:  runkit_class_adopt(): Class mychild already has a parent
myParent

It should produce:

myParent
(blank)
myUncle

Summary

Although the methods are being changed (i.e. inherited methods are removed from myChild when emancipated), the class hierarchy does not appear to be altered. Therefore, there is no way to actually change the ancestry of a class.

Versions

I have tried this with the Runkit 1.0.0 from SVN and also the Runkit 1.0.3-dev from Git, with the same result.

In both cases, I am using PHP 5.3.3.7 on Debian Squeeze (PHP installed from APT as a package, and Runkit applied using PECL).

Also perhaps with noting that this is an x86_64 system, and the tests have been run through CLI (not through a webserver).

Output from phpinfo()

runkit

runkit support => enabled
version => 1.0.3-dev
Custom Superglobal support => enabled
Sandbox Support => disable or unavailable
Runtime Manipulation => enabled

gmalysa commented Aug 10, 2011

Quickly checking the source code, it seems that all that the emancipate/adopt calls do is add/remove methods to the class in question (and its subclasses). They don't modify member data or change the zend_class_entries associated with the classes in question.

I'm using runkit to provide support for creating dummy classes that can be used simultaneously to implement a fake form of multiple inheritance and primitive template support to do things like implement an instance counter template with static methods and then copy the functionality into multiple classes without repeating the code for it, but I wouldn't mind taking a look at this as well before trying to get my changes pushed upstream, since it doesn't seem like it'd be too complicated to fix (famous last words).

Heheh - that's very similar to what I am trying to do with runkit also :o) At least, in terms of multiple inheritance.

I would be happy to give some form of donation if you were able to resolve my issue?

@gmalysa gmalysa added a commit to gmalysa/runkit that referenced this issue Aug 16, 2011

@gmalysa gmalysa Fixed bug #13 from github; added test for bug #13 71ae168

gmalysa commented Aug 16, 2011

Hi Dan, I've committed something to my branch that should address the problem you were having. It's not the commit referenced above, I had some more experimental code lying around that I had to clean up so you should check the HEAD revision on my fork. I'm looking to expand emancipate()/adopt() to deal with member data, but I'm unsure of a safe way to decide which variables to remove (but I imagine it would be pretty important to at least import all member variables when copying over methods).

@zenovich zenovich added a commit that referenced this issue Sep 17, 2012

@zenovich zenovich All ways of adding and removing magic methods and old-style construct…
…ors were reworked and corrected (issue #35).

Magic methods __isset, __unset, __callStatic, and __toString are now supported.
Functions runkit_class_adopt & runkit_class_emancipate now change class-hierarchy (issue #13).
tony2001's patch d63c984 was applied and reworked.
New tests were added.
7f5b7b1
Owner

zenovich commented Sep 17, 2012

Thanks for the report. I'm so much sorry for the huge delay. The issue should be fixed by now in the master branch.

@tony2001 tony2001 added a commit to tony2001/runkit that referenced this issue Sep 18, 2012

@tony2001 tony2001 Merge git://github.com/zenovich/runkit
* git://github.com/zenovich/runkit:
  Adding and redefining functions and methods, which return references, were fully implemented (#12). New optional argument 'return_ref' of functions runkit_function_add and runkit_function_redefine was introduced. New constant RUNKIT_ACC_RETURN_REFERENCE was introduced for use with functions runkit_method_add and runkit_method_redefine. New tests were added.
  The possible crash on manipulating constants having length less than two characters was eliminated. Functions manipulating constants were corrected to work in PHP5.4, new tests were added.
  All ways of adding and removing magic methods and old-style constructors were reworked and corrected (issue #35). Magic methods __isset, __unset, __callStatic, and __toString are now supported. Functions runkit_class_adopt & runkit_class_emancipate now change class-hierarchy (issue #13). tony2001's patch d63c984 was applied and reworked. New tests were added.
  functions and methods redefining in PHP 5.4 was corrected in all places, new tests were added (#36, #32)
  a fix was added to package.xml
  mad casing of classnames in different versions of PHP
  compilation bug (gcc 4.3+) with definition of internal function was fixed
3c35dda

zenovich closed this Oct 27, 2012

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment