Skip to content

Commit 16d70b1

Browse files
committed
Merge branch 'develop'
2 parents f5136cd + 3369286 commit 16d70b1

14 files changed

+1168
-434
lines changed

FileIterator.php

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace MaplePHP\Unitary;
6+
7+
use Closure;
8+
use RuntimeException;
9+
use MaplePHP\Blunder\Handlers\CliHandler;
10+
use MaplePHP\Blunder\Run;
11+
use RecursiveDirectoryIterator;
12+
use RecursiveIteratorIterator;
13+
use SplFileInfo;
14+
15+
class FileIterator
16+
{
17+
public const PATTERN = 'unitary-*.php';
18+
19+
private array $args;
20+
21+
public function __construct(array $args = [])
22+
{
23+
$this->args = $args;
24+
}
25+
26+
/**
27+
* Will Execute all unitary test files.
28+
* @param string $directory
29+
* @return void
30+
* @throws RuntimeException
31+
*/
32+
public function executeAll(string $directory): void
33+
{
34+
$files = $this->findFiles($directory);
35+
if (empty($files)) {
36+
throw new RuntimeException("No files found matching the pattern \"" . (string)(static::PATTERN ?? "") . "\" in directory \"$directory\" ");
37+
} else {
38+
foreach ($files as $file) {
39+
extract($this->args, EXTR_PREFIX_SAME, "wddx");
40+
Unit::resetUnit();
41+
Unit::setHeaders([
42+
"args" => $this->args,
43+
"file" => $file,
44+
"checksum" => md5((string)$file)
45+
]);
46+
47+
$call = $this->requireUnitFile((string)$file);
48+
if (!is_null($call)) {
49+
$call();
50+
}
51+
if(!Unit::hasUnit()) {
52+
throw new RuntimeException("The Unitary Unit class has not been initiated inside \"$file\".");
53+
}
54+
}
55+
56+
Unit::completed();
57+
}
58+
}
59+
60+
/**
61+
* Will Scan and find all unitary test files
62+
* @param string $dir
63+
* @return array
64+
*/
65+
private function findFiles(string $dir): array
66+
{
67+
$files = [];
68+
$realDir = realpath($dir);
69+
if($realDir === false) {
70+
throw new RuntimeException("Directory \"$dir\" does not exist. Try using a absolut path!");
71+
}
72+
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir));
73+
74+
/** @var string $pattern */
75+
$pattern = static::PATTERN;
76+
foreach ($iterator as $file) {
77+
if (($file instanceof SplFileInfo) && fnmatch($pattern, $file->getFilename()) &&
78+
(isset($this->args['path']) || !str_contains($file->getPathname(), DIRECTORY_SEPARATOR . "vendor" . DIRECTORY_SEPARATOR))) {
79+
if(!$this->findExcluded($this->exclude(), $dir, $file->getPathname())) {
80+
$files[] = $file->getPathname();
81+
}
82+
}
83+
}
84+
return $files;
85+
}
86+
87+
/**
88+
* Get exclude parameter
89+
* @return array
90+
*/
91+
public function exclude(): array
92+
{
93+
$excl = [];
94+
if(isset($this->args['exclude']) && is_string($this->args['exclude'])) {
95+
$exclude = explode(',', $this->args['exclude']);
96+
foreach ($exclude as $file) {
97+
$file = str_replace(['"', "'"], "", $file);
98+
$new = trim($file);
99+
$lastChar = substr($new, -1);
100+
if($lastChar === DIRECTORY_SEPARATOR) {
101+
$new .= "*";
102+
}
103+
$excl[] = trim($new);
104+
}
105+
}
106+
return $excl;
107+
}
108+
109+
/**
110+
* Validate a exclude path
111+
* @param array $exclArr
112+
* @param string $relativeDir
113+
* @param string $file
114+
* @return bool
115+
*/
116+
public function findExcluded(array $exclArr, string $relativeDir, string $file): bool
117+
{
118+
$file = $this->getNaturalPath($file);
119+
foreach ($exclArr as $excl) {
120+
$relativeExclPath = $this->getNaturalPath($relativeDir . DIRECTORY_SEPARATOR . (string)$excl);
121+
if(fnmatch($relativeExclPath, $file)) {
122+
return true;
123+
}
124+
}
125+
return false;
126+
}
127+
128+
/**
129+
* Get path as natural path
130+
* @param string $path
131+
* @return string
132+
*/
133+
public function getNaturalPath(string $path): string
134+
{
135+
return str_replace("\\", "/", $path);
136+
}
137+
138+
/**
139+
* Require file without inheriting any class information
140+
* @param string $file
141+
* @return Closure|null
142+
*/
143+
private function requireUnitFile(string $file): ?Closure
144+
{
145+
$clone = clone $this;
146+
$call = function () use ($file, $clone): void {
147+
$cli = new CliHandler();
148+
if(isset(self::$headers['args']['trace'])) {
149+
$cli->enableTraceLines(true);
150+
}
151+
$run = new Run($cli);
152+
$run->load();
153+
154+
ob_start();
155+
if (!is_file($file)) {
156+
throw new RuntimeException("File \"$file\" do not exists.");
157+
}
158+
require_once($file);
159+
160+
$clone->getUnit()->execute();
161+
162+
$outputBuffer = ob_get_clean();
163+
if (strlen($outputBuffer) && Unit::hasUnit()) {
164+
$clone->getUnit()->buildNotice("Note:", $outputBuffer, 80);
165+
}
166+
};
167+
return $call->bindTo(null);
168+
}
169+
170+
/**
171+
* @return Unit
172+
* @throws RuntimeException|\Exception
173+
*/
174+
protected function getUnit(): Unit
175+
{
176+
$unit = Unit::getUnit();
177+
if (is_null($unit)) {
178+
throw new RuntimeException("The Unit instance has not been initiated.");
179+
}
180+
return $unit;
181+
182+
}
183+
}

Handlers/FileHandler.php

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace MaplePHP\Unitary\Handlers;
6+
7+
use MaplePHP\Http\Stream;
8+
use MaplePHP\Http\UploadedFile;
9+
use MaplePHP\Prompts\Command;
10+
11+
class FileHandler implements HandlerInterface
12+
{
13+
private string $file;
14+
private Stream $stream;
15+
private Command $command;
16+
17+
/**
18+
* Construct the file handler
19+
* The handler will pass stream to a file
20+
* @param string $file
21+
*/
22+
public function __construct(string $file)
23+
{
24+
$this->stream = new Stream(Stream::TEMP);
25+
$this->command = new Command($this->stream);
26+
$this->command->getAnsi()->disableAnsi(true);
27+
$this->file = $file;
28+
}
29+
30+
/**
31+
* Access the command stream
32+
* @return Command
33+
*/
34+
public function getCommand(): Command
35+
{
36+
return $this->command;
37+
}
38+
39+
/**
40+
* Execute the handler
41+
* This will automatically be called inside the Unit execution
42+
* @return void
43+
*/
44+
public function execute(): void
45+
{
46+
$upload = new UploadedFile($this->stream);
47+
$upload->moveTo($this->file);
48+
}
49+
}

Handlers/HandlerInterface.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace MaplePHP\Unitary\Handlers;
6+
7+
use MaplePHP\Prompts\Command;
8+
9+
interface HandlerInterface
10+
{
11+
/**
12+
* Access the command stream
13+
* @return Command
14+
*/
15+
public function getCommand(): Command;
16+
17+
/**
18+
* Execute the handler
19+
* This will automatically be called inside the Unit execution
20+
* @return void
21+
*/
22+
public function execute(): void;
23+
}

Handlers/HtmlHandler.php

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace MaplePHP\Unitary\Handlers;
6+
7+
use MaplePHP\Http\Stream;
8+
use MaplePHP\Prompts\Command;
9+
10+
class HtmlHandler implements HandlerInterface
11+
{
12+
private Stream $stream;
13+
private Command $command;
14+
15+
/**
16+
* Construct the file handler
17+
* The handler will pass stream to a file
18+
*/
19+
public function __construct()
20+
{
21+
$this->stream = new Stream(Stream::TEMP);
22+
$this->command = new Command($this->stream);
23+
$this->command->getAnsi()->disableAnsi(true);
24+
}
25+
26+
/**
27+
* Access the command stream
28+
* @return Command
29+
*/
30+
public function getCommand(): Command
31+
{
32+
return $this->command;
33+
}
34+
35+
/**
36+
* Execute the handler
37+
* This will automatically be called inside the Unit execution
38+
* @return void
39+
*/
40+
public function execute(): void
41+
{
42+
$this->stream->rewind();
43+
$out = $this->stream->getContents();
44+
$style = 'background-color: #F1F1F1; color: #000; font-size: 2rem; font-weight: normal; font-family: "Lucida Console", Monaco, monospace;';
45+
$out = str_replace(["[", "]"], ['<span style="background-color: #666; color: #FFF; padding: 4px 2px">', '</span>'], $out);
46+
echo '<pre style="' . $style . '">' . $out . '</pre>';
47+
}
48+
}

0 commit comments

Comments
 (0)