Skip to content

Commit b701ba5

Browse files
committed
Support for loading methods on classes
1 parent e78462d commit b701ba5

File tree

3 files changed

+85
-34
lines changed

3 files changed

+85
-34
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ composer require knivey/cmdr
1717
## Documentation & Examples
1818

1919
Setup the command router object and find commands
20+
2021
```php
2122
use knivey\cmdr;
2223
$router = new cmdr\Cmdr();
@@ -31,14 +32,15 @@ function exampleFunc($additonal, $arguments, cmdr\Request $request) {
3132
}
3233

3334
//Do this AFTER all functions you want to load are defined
34-
$router->loadFuncsByAttributes();
35+
$router->loadFuncs();
3536

3637
// This will return what the command function returns
3738
// Exceptions can be throw if the args given don't pass the syntax
3839
$router->call('example', 'arguments given to cmd', $additional, $arguments);
3940
```
4041
Note that command names cannot contain a # in them.
4142

43+
To load public methods from a class object use `loadMethods($obj)`
4244
### Argument Syntax Rules
4345
* `<arg>` is a required arg
4446
* `<arg>...` required multiword arg, must be last in list

src/Cmdr.php

Lines changed: 36 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -31,41 +31,47 @@ function get(string $command, string $text) : Request|false {
3131
return new Request($args, $cmd);
3232
}
3333

34-
function loadMethodsByAttributes(object $obj) {
35-
//TODO
34+
function loadMethods(object $obj) {
35+
$objRef = new \ReflectionObject($obj);
36+
foreach($objRef->getMethods(\ReflectionMethod::IS_PUBLIC) as $rf) {
37+
$this->attrAddCmd($rf, [$obj, $rf->name]);
38+
}
39+
}
40+
41+
protected function attrAddCmd($rf, $f) {
42+
$cmdAttr = $rf->getAttributes(attributes\Cmd::class);
43+
if (count($cmdAttr) == 0)
44+
return;
45+
$cmdAttr = $cmdAttr[0]->newInstance();
46+
$syntaxAttr = $rf->getAttributes(attributes\Syntax::class);
47+
$syntax = '';
48+
$callWrapper = null;
49+
$callWrapperPre = [];
50+
$callWrapperPost = [];
51+
if (isset($syntaxAttr[0])) {
52+
$sa = $syntaxAttr[0]->newInstance();
53+
$syntax = $sa->syntax;
54+
}
55+
$callWrapAttr = $rf->getAttributes(attributes\CallWrap::class);
56+
if (isset($callWrapAttr[0])) {
57+
$cw = $callWrapAttr[0]->newInstance();
58+
$callWrapper = $cw->caller;
59+
$callWrapperPre = $cw->preArgs;
60+
$callWrapperPost = $cw->postArgs;
61+
}
62+
foreach ($cmdAttr->args as $command) {
63+
if ($callWrapper != null)
64+
$this->cmds[$command] = new Cmd($command, $callWrapper, [...$callWrapperPre, $f], $callWrapperPost, $syntax);
65+
else
66+
$this->cmds[$command] = new Cmd($command, $f, $callWrapperPre, $callWrapperPost, $syntax);
67+
}
3668
}
3769

38-
function loadFuncsByAttributes() {
70+
function loadFuncs() {
3971
$funcs = get_defined_functions(true)["user"];
4072
foreach ($funcs as $f) {
4173
$rf = new \ReflectionFunction($f);
42-
//all commands should at least have Cmd attribute
43-
$cmdAttr = $rf->getAttributes(attributes\Cmd::class);
44-
if(count($cmdAttr) == 0)
45-
continue;
46-
$cmdAttr = $cmdAttr[0]->newInstance();
47-
$syntaxAttr = $rf->getAttributes(attributes\Syntax::class);
48-
$syntax = '';
49-
$callWrapper = null;
50-
$callWrapperPre = [];
51-
$callWrapperPost = [];
52-
if(isset($syntaxAttr[0])) {
53-
$sa = $syntaxAttr[0]->newInstance();
54-
$syntax = $sa->syntax;
55-
}
56-
$callWrapAttr = $rf->getAttributes(attributes\CallWrap::class);
57-
if(isset($callWrapAttr[0])) {
58-
$cw = $callWrapAttr[0]->newInstance();
59-
$callWrapper = $cw->caller;
60-
$callWrapperPre = $cw->preArgs;
61-
$callWrapperPost = $cw->postArgs;
62-
}
63-
foreach ($cmdAttr->args as $command) {
64-
if($callWrapper != null)
65-
$this->cmds[$command] = new Cmd($command, $callWrapper, [...$callWrapperPre, $f], $callWrapperPost, $syntax);
66-
else
67-
$this->cmds[$command] = new Cmd($command, $f, $callWrapperPre, $callWrapperPost, $syntax);
68-
}
74+
$this->attrAddCmd($rf, $f);
6975
}
7076
}
7177

tests/CmdrTest.php

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ public function testBadNameException()
8383
$cmdr->add('#test', $lol);
8484
}
8585

86-
public function testLoadFuncsByAttributes()
86+
public function testLoadFuncs()
8787
{
8888
global $testFunc;
8989
$cnt = 0;
@@ -93,12 +93,27 @@ function ($req) use(&$cnt) {
9393
$this->assertEquals('abc def', $req->args['foo']);
9494
$cnt++;
9595
};
96-
$cmdr->loadFuncsByAttributes();
96+
$cmdr->loadFuncs();
9797
$cmdr->call('testattrs', 'abc def');
9898
$cmdr->call('noexist', 'abc def');
9999
$this->assertEquals(1, $cnt);
100100
}
101101

102+
public function testLoadMethods()
103+
{
104+
global $testFunc;
105+
$cnt = 0;
106+
$cmdr = new Cmdr();
107+
$testFunc =
108+
function ($req) use(&$cnt) {
109+
$cnt++;
110+
};
111+
$obj = new weeclass();
112+
$cmdr->loadMethods($obj);
113+
$cmdr->call('wee', '');
114+
$this->assertEquals(1, $cnt);
115+
}
116+
102117
public function testPrePost()
103118
{
104119
$cmdr = new Cmdr();
@@ -129,9 +144,22 @@ public function testCallWrapAttribute()
129144
$cnt++;
130145
};
131146

132-
$cmdr->loadFuncsByAttributes();
147+
$cmdr->loadFuncs();
133148
$cmdr->call('testCallWrap', 'abc def');
134149
$this->assertEquals(1, $cnt);
150+
151+
152+
$obj = new weeclass();
153+
$testFunc = function ($func, $req) use(&$cnt, $obj) {
154+
//php namespace&functions are lowered internally
155+
$this->assertEquals([$obj, 'eew'], $func);
156+
$cnt++;
157+
};
158+
$cmdr = new Cmdr();
159+
$cnt = 0;
160+
$cmdr->loadMethods($obj);
161+
$cmdr->call('eew', 'abc def');
162+
$this->assertEquals(1, $cnt);
135163
}
136164
}
137165

@@ -154,3 +182,18 @@ function wrapTestFunc(...$args) {
154182
$testFunc(...$args);
155183
};
156184

185+
186+
// not sure phpunit supports mocking with attributes yet
187+
class weeclass {
188+
#[Cmd('wee')]
189+
public function example($req) {
190+
global $testFunc;
191+
$testFunc($req);
192+
}
193+
194+
#[Cmd('eew')]
195+
#[CallWrap(__namespace__.'\wrapTestFunc')]
196+
public function eew($req) {
197+
}
198+
}
199+

0 commit comments

Comments
 (0)