First of all, what is “monkey patch”? As Wiki says “A monkey patch is a way to extend or modify the run-time code of dynamic languages without altering the original source code.” (see Monkey patch article for reference).
What about Features functionality for regular modules' and even core source code?
Imagine that we have 2 places to store some code that is intended to be patched: one is in a file (as usual) and another - is in database. That is how Features works.
Think of module's source code as a component for Features, which could be incorporated into your own feature (see Features documentation for “component” definition).
When it is time to execute that piece of code, we switch to database version of needed function (which is patched as we need), leaving source code untouched.
Besides that, we will have our feature overriden - so we could decide whether to revert or to save back to code (using Drush or other tools - so we don't need to let Patch Manager do dangerous things).
So, we would have all of Features advantages, applying to modules' and core source code management - it is going to be amazing, isn't it?
It appears that we don't need much of stuff Patch Manager currently has:
No need in having Patch node type declaration: Features together with Diff will provide to us all information about how source code is overridden.
No need in having an ability to patch source code: Because WE WILL NOT PATCH SOURCE CODE ANYMORE. What we need is an infrastructure to store and an interface to edit current state of overridden code (see details below).
Though we have to implement some additional stuff:
We have to depend on Libraries: As we need a way to override function (and object methods) defintion during evaluation, I am going to use patchwork library for it. The only thing it requires is PHP version >= 5.3.0, which is a Drupal 7 recommended requirement.
As Patch Manager continues to be intended to be used on dev environment, it is acceptable.
So we just need to depend on Libraries. Not a big deal, in my view.
(under consideration) We might depend on Module Object Oriented Programming API: Moopapi has some kind of similar effort: it turns each module into an object and its functions - into methods of this object.
We could place dependency on patchwork and Libraries to Moopapi, letting Patch Manager depend on Moopapi.
Moopapi currently only allows to wrap a function that DOES NOT EXIST - that is, it DOES NOT REPLACE functions' and methods' definitions. With patchwork - it will be able to.
The only thing I am in doubt of: is it appropriate to use a library (patchwork) and even depend on it inside a module that has very much different title (Moopapi)? I see a couple of options where to place dependency on patchwork library:
Create a separate module, called Patchwork
I think the most preferable is to place it to Moopapi, making Patch Manager depending on Moopapi.
The second place is taken by placing directly to Patch Manager.
And I think we don't need to create a separate module.
Feel free to shoot a comment if you have some thoughts about it.
We have to implement an infrastructure to store and an interface to edit current state of overridden code: I am going to use the power of Drupal Entity API together with powerful Field API, which works out-of-the-box, so no need in custom coding, custom testing and custom debugging - we just rely on mighty solution.
So what is the proposed infrastructure? It consists just of 2 entity types (and a couple of additional dependencies): Module and Method, which are defined as follows:
Module has fields:
Title (text up to 255 characters): Human-readable name of the module.
Machine name (machine name (so we should depend on it)): Machine name of the module.
Methods (entityreference (so we should depend on it too) with unlimited number of values): A place where overridden code is stored.
Method has fields:
Machine name (machine name): Machine name of the method.
Code: The OVERRIDDEN code of the method will be stored here.
As a result, we should depend on several modules: Moopapi (which is going to depend on Libraries and to use patchwork library), Entity, Entityreference, Machine Name, Features, Diff (optionally).
How it is supposed to work?
Just regular Features workflow: create a feature, add some module to it (NB: not only as a dependency but as source code) to track its source code changes, override its functions at your choice (it makes feature “overridden”) - and then update source code using Drush or revert your changes to default state.
Initial functionality: empower placing modules' and core source code into a feature (some kind of Hacked! functionality):
Refactor Moopapi using patchwork library: see corresponding #2004492: Use monkey patching to “hack without hacking”
Create necessary entity types
Implement logic of evaluating overridden code instead of default, placed in a file
Room for further development:
Create an opportunity to save back to code (NB: using Drush, not via web UI - so we could get rid of “Scary warning” at project main page)