Skip to content

Commit c65e6e6

Browse files
committed
Fix the file discovery functionalities
1 parent 3ea662b commit c65e6e6

12 files changed

Lines changed: 213 additions & 38 deletions

File tree

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php
2+
/**
3+
* Trait that walks a PSR-4 directory tree and returns each PHP file's class path relative to it.
4+
* Discovery must see classes grouped into subfolders, which a flat glob() of the top level misses.
5+
* Used by the listener and policy discovery to turn nested files into namespaced class names.
6+
*
7+
* @package Framework
8+
* @subpackage Concerns
9+
* @since 1.0.0
10+
*/
11+
namespace Framework\Concerns;
12+
13+
defined('ABSPATH') || exit;
14+
15+
use FilesystemIterator;
16+
use RecursiveDirectoryIterator;
17+
use RecursiveIteratorIterator;
18+
19+
trait DiscoversClassFiles
20+
{
21+
/**
22+
* Get the class path of every PHP file beneath the directory, relative to it.
23+
*
24+
* A file at `Order/SendInvoice.php` yields `Order\SendInvoice`, ready to be appended to the
25+
* directory's base namespace. The result is sorted so the generated cache files stay stable
26+
* regardless of the order the filesystem returns entries in.
27+
*
28+
* @param string $directory The directory to walk.
29+
*
30+
* @return array
31+
*
32+
* @since 1.0.0
33+
*/
34+
protected function class_files(string $directory)
35+
{
36+
$class_files = [];
37+
38+
if (!is_dir($directory)) {
39+
return $class_files;
40+
}
41+
42+
$prefix_length = strlen(rtrim($directory, '\/')) + 1;
43+
$files = new RecursiveIteratorIterator(
44+
new RecursiveDirectoryIterator($directory, FilesystemIterator::SKIP_DOTS)
45+
);
46+
47+
foreach ($files as $file) {
48+
if (!$file->isFile() || $file->getExtension() !== 'php') {
49+
continue;
50+
}
51+
52+
$relative_path = substr($file->getPathname(), $prefix_length, -strlen('.php'));
53+
$class_files[] = str_replace('/', '\\', $relative_path);
54+
}
55+
56+
sort($class_files);
57+
58+
return $class_files;
59+
}
60+
}

‎src/Discovery/ListenerDiscovery.php‎

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
defined('ABSPATH') || exit;
1414

15+
use Framework\Concerns\DiscoversClassFiles;
1516
use Framework\Contracts\Cacheable;
1617
use Framework\Contracts\Discoverable;
1718
use Framework\Supports\Facades\File;
@@ -26,6 +27,8 @@
2627

2728
class ListenerDiscovery implements Discoverable, Cacheable
2829
{
30+
use DiscoversClassFiles;
31+
2932
/**
3033
* The discovered listeners array .
3134
*
@@ -66,16 +69,14 @@ protected function create_cache_file()
6669
return $this;
6770
}
6871

69-
$listeners_files = glob($listeners_directory . '/*.php');
72+
$listeners_files = $this->class_files($listeners_directory);
7073

7174
if (empty($listeners_files)) {
7275
return $this;
7376
}
7477

75-
foreach ($listeners_files as $file) {
76-
$listener = $this->listener_class(
77-
$this->filename($file)
78-
);
78+
foreach ($listeners_files as $filename) {
79+
$listener = $this->listener_class($filename);
7980

8081
if (!$this->is_valid_listener($listener)) {
8182
continue;
@@ -158,24 +159,10 @@ protected function event_class(string $listener)
158159
return $type_name;
159160
}
160161

161-
/**
162-
* Get the filename of the listener.
163-
*
164-
* @param string $file The file.
165-
*
166-
* @return string
167-
*
168-
* @since 1.0.0
169-
*/
170-
protected function filename(string $file)
171-
{
172-
return basename($file, '.php');
173-
}
174-
175162
/**
176163
* Get the listener class of the filename.
177164
*
178-
* @param string $filename The filename.
165+
* @param string $filename The class path relative to the listeners directory.
179166
*
180167
* @return string
181168
*

‎src/Discovery/PolicyDiscovery.php‎

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
defined('ABSPATH') || exit;
1414

15+
use Framework\Concerns\DiscoversClassFiles;
1516
use Framework\Contracts\Cacheable;
1617
use Framework\Contracts\Discoverable;
1718
use Framework\Supports\Facades\File;
@@ -23,6 +24,8 @@
2324

2425
class PolicyDiscovery implements Discoverable, Cacheable
2526
{
27+
use DiscoversClassFiles;
28+
2629
/**
2730
* The discovered policies array.
2831
*
@@ -65,15 +68,13 @@ protected function create_cache_file()
6568
return $this;
6669
}
6770

68-
$policy_files = glob($policies_directory . '/*.php');
71+
$policy_files = $this->class_files($policies_directory);
6972

7073
if (empty($policy_files)) {
7174
return $this;
7275
}
7376

74-
foreach ($policy_files as $policy_file) {
75-
$policy_name = $this->filename($policy_file);
76-
77+
foreach ($policy_files as $policy_name) {
7778
if (!$this->is_valid_policy_name($policy_name)) {
7879
continue;
7980
}
@@ -87,20 +88,6 @@ protected function create_cache_file()
8788
return $this;
8889
}
8990

90-
/**
91-
* Get the filename of the policy.
92-
*
93-
* @param string $path The path.
94-
*
95-
* @return string
96-
*
97-
* @since 1.0.0
98-
*/
99-
protected function filename(string $path)
100-
{
101-
return basename($path, '.php');
102-
}
103-
10491
/**
10592
* Add a policy to the policies array.
10693
*
@@ -148,6 +135,9 @@ protected function policy_class(string $policy_name)
148135
/**
149136
* Get the model class from the policy name.
150137
*
138+
* A policy in a subfolder maps to a model in the matching subfolder, so
139+
* `Policies\Shop\ProductPolicy` is paired with `Models\Shop\Product`.
140+
*
151141
* @param string $policy_name The policy name.
152142
*
153143
* @return string
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
3+
namespace Framework\Tests\Support\Discovery\App\Events;
4+
5+
class OrderPlaced
6+
{
7+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
namespace Framework\Tests\Support\Discovery\App\Listeners;
4+
5+
use Framework\Tests\Support\Discovery\App\Events\OrderPlaced;
6+
use Framework\Listener;
7+
8+
class LogOrder extends Listener
9+
{
10+
public function handle(OrderPlaced $event)
11+
{
12+
}
13+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
namespace Framework\Tests\Support\Discovery\App\Listeners\Order\Paid;
4+
5+
use Framework\Tests\Support\Discovery\App\Events\OrderPlaced;
6+
use Framework\Listener;
7+
8+
class NotifyWarehouse extends Listener
9+
{
10+
public function handle(OrderPlaced $event)
11+
{
12+
}
13+
14+
public function priority()
15+
{
16+
return 10;
17+
}
18+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
namespace Framework\Tests\Support\Discovery\App\Listeners\Order;
4+
5+
use Framework\Tests\Support\Discovery\App\Events\OrderPlaced;
6+
use Framework\Listener;
7+
8+
class SendInvoice extends Listener
9+
{
10+
public function handle(OrderPlaced $event)
11+
{
12+
}
13+
14+
public function priority()
15+
{
16+
return 5;
17+
}
18+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
3+
namespace Framework\Tests\Support\Discovery\App\Models;
4+
5+
class Post
6+
{
7+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
3+
namespace Framework\Tests\Support\Discovery\App\Models\Shop;
4+
5+
class Product
6+
{
7+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
3+
namespace Framework\Tests\Support\Discovery\App\Policies;
4+
5+
class PostPolicy
6+
{
7+
}

0 commit comments

Comments
 (0)