Skip to content

Commit

Permalink
rework into mixins
Browse files Browse the repository at this point in the history
  • Loading branch information
taylorotwell committed Jun 27, 2017
1 parent 3b91f32 commit 353adbd
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 18 deletions.
13 changes: 0 additions & 13 deletions src/Illuminate/Contracts/Support/Macro.php

This file was deleted.

27 changes: 22 additions & 5 deletions src/Illuminate/Support/Traits/Macroable.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
namespace Illuminate\Support\Traits;

use Closure;
use ReflectionClass;
use ReflectionMethod;
use BadMethodCallException;
use Illuminate\Contracts\Support\Macro;

Expand All @@ -19,7 +21,7 @@ trait Macroable
* Register a custom macro.
*
* @param string $name
* @param \Illuminate\Contracts\Support\Macro|callable $macro
* @param object|callable $macro
*
* @return void
*/
Expand All @@ -28,6 +30,25 @@ public static function macro($name, $macro)
static::$macros[$name] = $macro;
}

/**
* Mix another object into the class.
*
* @param object $mixin
* @return void
*/
public static function mixin($mixin)
{
$methods = (new ReflectionClass($mixin))->getMethods(
ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_PROTECTED
);

foreach ($methods as $method) {
$method->setAccessible(true);

static::macro($method->name, $method->invoke($mixin));
}
}

/**
* Checks if macro is registered.
*
Expand Down Expand Up @@ -78,10 +99,6 @@ public function __call($method, $parameters)

$macro = static::$macros[$method];

if (is_string($macro) && is_a($macro, Macro::class, true)) {
$macro = (new $macro)->handle();
}

if ($macro instanceof Closure) {
return call_user_func_array($macro->bindTo($this, static::class), $parameters);
}
Expand Down
24 changes: 24 additions & 0 deletions tests/Support/SupportMacroableTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,13 @@ public function testWhenCallingMacroClosureIsBoundToObject()
$result = TestMacroable::tryStatic();
$this->assertEquals('static', $result);
}

public function testClassBasedMacros()
{
TestMacroable::mixin(new TestMixin);
$instance = new TestMacroable;
$this->assertEquals('instance-Adam', $instance->methodOne('Adam'));
}
}

class TestMacroable
Expand All @@ -66,3 +73,20 @@ protected static function getProtectedStatic()
return 'static';
}
}

class TestMixin
{
public function methodOne()
{
return function ($value) {
return $this->methodTwo($value);
};
}

protected function methodTwo()
{
return function ($value) {
return $this->protectedVariable.'-'.$value;
};
}
}

2 comments on commit 353adbd

@edmandiesamonte
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is kind of interesting. Playing around witht his one. Just a thought. Why return a function inside a method? Why not register the method itself? Kind of confusing given that the docs says Mix another object into the class. but the structure seems like Make another object register functions/methods into the class.

@edmandiesamonte
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like your work is the best we can do. I tried to look for a way to rebind method to another object of a different class and seems like it is still impossible. Even Closure::fromCallable([$mixin, $method->name]) throws Cannot bind method error.

Please sign in to comment.