Skip to content

Commit

Permalink
Improve generate ID
Browse files Browse the repository at this point in the history
Get the right source if extending the Todo class
  • Loading branch information
robertology committed Oct 1, 2022
1 parent 18c2940 commit b0042ce
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 6 deletions.
56 changes: 56 additions & 0 deletions src/TodoOrDie/System/Trace.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php
declare(strict_types=1);

namespace Robertology\TodoOrDie\System;

class Trace {

/**
* Get a trace starting from the first call to the given class
*
* Considers parent & child class to be same as class
* Note: this is a backtrace, so "start" means "going backward"
*/
static public function fromOutside(string $class) : array {
$trace = static::startAt($class);

foreach ($trace as $key => $entry) {
$check = $entry['class'] ?? '';
if (empty($check) || ! static::_isA($check, $class)) {
$key--;
break;
}
}

return isset($key) ? array_splice($trace, $key) : [];
}

/**
* Get a trace starting at calls involving the given class
*
* Considers parent & child class to be same as class
* Note: this is a backtrace, so "start" means "going backward"
*/
static public function startAt(string $class) : array {
$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);

$check = $trace[0];
while (! static::_isA($class, $check['class'] ?? '')) {
array_shift($trace);
$check = reset($trace);
}


// renumber the keys with array_values()
return array_values($trace);
}

/**
* Companre the class names for match or subclass in either direction
*/
static protected function _isA(string $a, string $b) : bool {
return is_a($a, $b, true) ||
is_a($b, $a, true);
}

}
8 changes: 2 additions & 6 deletions src/TodoOrDie/Todo.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
Check,
Check\Defined as BooleanCheck,
OverdueError as Exception,
TodoIdGenerator,
TodoState,
};

Expand Down Expand Up @@ -63,12 +64,7 @@ protected function _dieIf(Check $check) {
}

protected function _generateId() : string {
// The first entry will be the call to this method; use the second one
$trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2)[1] ?? [];
$file = $trace['file'] ?? '';
$line = $trace['line'] ?? 0;

return "{$file}:{$line}";
return (new TodoIdGenerator($this))();
}

protected function _getState() : TodoState {
Expand Down
28 changes: 28 additions & 0 deletions src/TodoOrDie/TodoIdGenerator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php
declare(strict_types=1);

namespace Robertology\TodoOrDie;

use Robertology\TodoOrDie\ {
System\Trace,
Todo,
};

class TodoIdGenerator {

private Todo $_todo;

public function __construct(Todo $todo) {
$this->_todo = $todo;
}

public function __invoke() : string {
$entry = Trace::fromOutside(get_class($this->_todo))[0] ?? [];

$file = $entry['file'] ?? '';
$line = $entry['line'] ?? 0;

return "{$file}:{$line}";
}

}
19 changes: 19 additions & 0 deletions test/TodoOrDie/TodoTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,21 @@ public function testConstructingWithTriggeringCheckObject() {
new Todo('Some message', new BooleanCheck(true));
}

public function testGenerateId() {
$file = __FILE__;
$line = __LINE__ + 1;
$todo = new Todo('test', false);

$this->assertSame("{$file}:{$line}", $todo->getId());
}

public function testGenerateIdOfExtendedTodo() {
$file = __FILE__;
$line = __LINE__ + 1;
$todo = new ExtendedTodo('test', false);

$this->assertSame("{$file}:{$line}", $todo->getId());
}

}

Expand All @@ -180,6 +195,10 @@ protected function _die() {
self::$_mock->die();
}

protected function _generateId() : string {
return parent::_generateId();
}

}

/**
Expand Down

0 comments on commit b0042ce

Please sign in to comment.