Класс Route который позволит регистрировать маршруты REST API в WordPress

Задача

Реализуйте класс Route который позволит регистрировать маршруты REST API в WordPress с использованием функций-посредников (Middleware). Требуемый интерфейс:

Route::register(
    string $namespace,
    array $routes,
    array $middlewares = []
);

$namespace — пространство имён REST в WordPress.

$routes — ассоциативный массив, где ключ — это шаблон пути маршрута REST API, а значение — массив параметров для конечной точки. Пример:

$routes = [
    '/post/(?P<id>\d+)' => [
		'methods' => 'GET',
		'callback' => function (WP_REST_Request $request) {
			//...
		}
    ]
];

$middlewares — массив функций-посредников, которые выполняются последовательно перед каждым зарегистрированным обработчиком маршрута. Могут использоваться для авторизации, преобразования параметров запроса, запуска параллельных процессов и т. п. Пример:

$middlewares = [
    function($data, $next) {
		if (authorize_user($data)) {
			return $next($data);
		} else {
			return "You are not authorized";
		}
    },
    function($data, $next) {
		log_activity($data);
		return $next($data);
    }
];

Для простоты считайте, что массивы $routes и $middlewares всегда состоят только из валидных элементов.

 

Реализация

Выполнен как плагин, должен располагаться по адресу: /wp-content/plugins/dw_route.php

<?php

/*
 * Plugin Name: Disweb Route
 * Plugin URI: https://disweb.ru
 * Description:
 * Version: 1.0
 * Author: DisWEB
 * Author URI: https://disweb.ru
*/

namespace Disweb;

// begin: Script

class Route
{
	public static $ar = [];
	
	public function __construct()
    {
		\add_action('rest_api_init', [$this, 'init'], 10);
	}
	
	public function init()
    {
		foreach (self::$ar as $k => $v)
		{
			foreach ($v['routes'] as $route => $args)
			{
				$args['permission_callback'] = function ($request) use ($k) {
					Route::middlewares($request, $k);
					
					return true;
				};
				
				\register_rest_route($v['namespace'], $route, $args);
			}
		}
	}
	
	public static function middlewares($request, $k)
	{
		foreach (self::$ar[$k]['middlewares'] as $middlewares)
		{
			$uniqid = uniqid();
			
			$res = $middlewares($request, function ($request) use ($uniqid) {
				return $uniqid;
			});
			
			if ($uniqid != $res)
			{
				die($res);
			}
		}
	}
	
	public static function register(
		string $namespace,
		array $routes,
		array $middlewares = []
	)
	{
		self::$ar[] = [
			'namespace' => $namespace,
			'routes' => $routes,
			'middlewares' => $middlewares,
		];
	}
	
}

new Route();

// end: Script

// ***************************************************

/*

URL:
https://example.com/wp-json/yt/v1/post/543
https://example.com/wp-json/yt/v1/test_sr/543
RESULT:
{"status":"ok","request":{"id":"543","test":"md-1"}}

URL:
https://example.com/wp-json/yt/v1/post2/543
https://example.com/wp-json/yt/v1/test_sr2/543
RESULT:
Not found data!

*/

// begin: Example

Route::register('yt/v1', [
	'/post/(?P<id>\d+)' => [
		'methods' => 'GET',
		'callback' => function (\WP_REST_Request $request) {
			return [
				'status' => 'ok',
				'request' => $request->get_params(),
			];
		}
	],
	'/test_sr/(?P<id>\d+)' => [
		'methods' => 'GET',
		'callback' => function (\WP_REST_Request $request) {
			return [
				'status' => 'ok',
				'request' => $request->get_params(),
			];
		}
	],
], [
	function ($data, $next) {
		$data->set_param('test', 'md-1');
		return $next($data);
	},
	function ($data, $next) {
		return $next($data);
		return "Not found data!";
	},
]);

Route::register('yt/v1', [
	'/post2/(?P<id>\d+)' => [
		'methods' => 'GET',
		'callback' => function (\WP_REST_Request $request) {
			return [
				'status' => 'ok',
				'request' => $request->get_params(),
			];
		}
	],
	'/test_sr2/(?P<id>\d+)' => [
		'methods' => 'GET',
		'callback' => function (\WP_REST_Request $request) {
			return [
				'status' => 'ok',
				'request' => $request->get_params(),
			];
		}
	],
], [
	function ($data, $next) {
		$data->set_param('test', 'md-2');
		$data->set_param('test2', 'md-2');
		return $next($data);
	},
	function ($data, $next) {
		//return $next($data);
		return "Not found data!";
	},
]);

// end: Example

В реализации для middleware передаваться будет только объект. Строковые, массивы и т.д. передаваться не будут.