| 1 |
<?php |
| 2 |
|
| 3 |
/* |
| 4 |
* This file is part of the WindPress package. |
| 5 |
* |
| 6 |
* (c) Joshua Gugun Siagian <suabahasa@gmail.com> |
| 7 |
* |
| 8 |
* For the full copyright and license information, please view the LICENSE |
| 9 |
* file that was distributed with this source code. |
| 10 |
*/ |
| 11 |
declare (strict_types=1); |
| 12 |
namespace WindPress\WindPress\Api; |
| 13 |
|
| 14 |
use ReflectionClass; |
| 15 |
use WindPressDeps\Symfony\Component\Finder\Finder; |
| 16 |
use WIND_PRESS; |
| 17 |
class Router |
| 18 |
{ |
| 19 |
/** |
| 20 |
* List of APIs services. |
| 21 |
* |
| 22 |
* @var ApiInterface[] |
| 23 |
*/ |
| 24 |
private array $apis = []; |
| 25 |
public function __construct() |
| 26 |
{ |
| 27 |
$this->scan_apis(); |
| 28 |
add_action('rest_api_init', function () { |
| 29 |
$this->register_apis(); |
| 30 |
}); |
| 31 |
} |
| 32 |
public function scan_apis() |
| 33 |
{ |
| 34 |
// Get cached APIs |
| 35 |
$transient_name = 'windpress_scanned_apis_' . WIND_PRESS::VERSION; |
| 36 |
/** @var ApiInterface[]|false $cached */ |
| 37 |
$cached = get_transient($transient_name); |
| 38 |
if (!\WP_DEBUG && $cached !== \false) { |
| 39 |
$this->apis = $cached; |
| 40 |
return; |
| 41 |
} |
| 42 |
$finder = new Finder(); |
| 43 |
$finder->files()->in(__DIR__)->name('*.php'); |
| 44 |
/** |
| 45 |
* Add additional places to scan for APIs. |
| 46 |
* |
| 47 |
* @param Finder $finder The Finder instance. |
| 48 |
*/ |
| 49 |
do_action('a!windpress/api/router:before_scan', $finder); |
| 50 |
foreach ($finder as $file) { |
| 51 |
$api_file = $file->getPathname(); |
| 52 |
if (!is_readable($api_file)) { |
| 53 |
continue; |
| 54 |
} |
| 55 |
require_once $api_file; |
| 56 |
} |
| 57 |
// Find any APIs that extends ApiInterface class |
| 58 |
$declared_classes = get_declared_classes(); |
| 59 |
foreach ($declared_classes as $declared_class) { |
| 60 |
if (!class_exists($declared_class)) { |
| 61 |
continue; |
| 62 |
} |
| 63 |
$reflector = new ReflectionClass($declared_class); |
| 64 |
if (!$reflector->isSubclassOf(\WindPress\WindPress\Api\ApiInterface::class)) { |
| 65 |
continue; |
| 66 |
} |
| 67 |
// Get API detail and push to Router::$apis to be register later |
| 68 |
/** @var ApiInterface $api */ |
| 69 |
$api = $reflector->newInstanceWithoutConstructor(); |
| 70 |
$this->apis[$api->get_prefix()] = ['name' => $api->get_prefix(), 'file_path' => $reflector->getFileName(), 'class_name' => $reflector->getName()]; |
| 71 |
} |
| 72 |
// Cache the scanned APIs |
| 73 |
set_transient($transient_name, $this->apis, \HOUR_IN_SECONDS); |
| 74 |
} |
| 75 |
/** |
| 76 |
* Register APIs. |
| 77 |
*/ |
| 78 |
public function register_apis(): void |
| 79 |
{ |
| 80 |
/** |
| 81 |
* Filter the APIs before register to WP Rest. |
| 82 |
* |
| 83 |
* @param ApiInterface[] $apis |
| 84 |
* @return ApiInterface[] |
| 85 |
*/ |
| 86 |
/** @var ApiInterface[] $apis */ |
| 87 |
$apis = apply_filters('f!windpress/api/router:register_apis', $this->apis); |
| 88 |
foreach ($apis as $api) { |
| 89 |
// Create new instance of API class and register custom endpoints |
| 90 |
/** @var ApiInterface $apiInstance */ |
| 91 |
$apiInstance = new $api['class_name'](); |
| 92 |
$apiInstance->register_custom_endpoints(); |
| 93 |
} |
| 94 |
} |
| 95 |
} |
| 96 |
|