Issues (5)

src/Route/Route.php (2 issues)

Severity
1
<?php
2
3
declare(strict_types=1);
4
5
/**
6
 * A route definition.
7
 *
8
 * @package PinkCrab\Route\Route
9
 * @author Glynn Quelch [email protected]
10
 * @since 0.0.1
11
 */
12
13
namespace PinkCrab\Route\Route;
14
15
class Route extends Abstract_Route {
16
17
	public const GET    = 'GET';
18
	public const POST   = 'POST';
19
	public const PATCH  = 'PATCH';
20
	public const PUT    = 'PUT';
21
	public const DELETE = 'DELETE';
22
23
	/**
24
	 * @var string
25
	 */
26
	protected string $route;
27
28
	/**
29
	 * @var string
30
	 */
31
	protected string $method;
32
33
	/**
34
	 * @var callable(\WP_REST_Request): (\WP_HTTP_Response|\WP_Error)|null
35
	 */
36
	protected $callback = null;
37
38
39
	public function __construct( string $method, string $route ) {
40
		$this->method = $method;
41
		$this->route  = $this->format_route( $route );
42
	}
43
44
	/**
45
	 * Formats a route with a leading slash.
46
	 *
47
	 * @param string $route
48
	 * @return string
49
	 */
50
	protected function format_route( string $route ): string {
51
		$route = $this->translate_arguments( $route );
52
		return '/' . ltrim( $route, '/\\' );
53
	}
54
55
	/**
56
	 * Translates shortcut route arguments.
57
	 *
58
	 * @see https://stackoverflow.com/questions/30130913/how-to-do-url-matching-regex-for-routing-framework
59
	 * @param string $route
60
	 * @return string
61
	 */
62
	protected function translate_arguments( string $route ): string {
63
		if ( preg_match( '/[^-:\/_{}()a-zA-Z\d]/', $route ) ) {
64
			return $route;
65
		}
66
67
		// Create capture group for ":parameter"
68
		$allowed_chars = '[\@a-zA-Z0-9&.?:-_=#]*';
69
		$route         = preg_replace(
70
			'/:(' . $allowed_chars . ')/',
71
			'(?<$1>' . $allowed_chars . ')',
72
			$route
73
		);
74
75
		// Create capture group for '{parameter}'
76
		$route = preg_replace(
77
			'/{(' . $allowed_chars . ')}/',
78
			'(?<$1>' . $allowed_chars . ')',
79
			is_string( $route ) ? $route : ''
0 ignored issues
show
The condition is_string($route) is always true.
Loading history...
80
		);
81
82
		return is_string( $route ) ? $route : '';
0 ignored issues
show
The condition is_string($route) is always true.
Loading history...
83
	}
84
85
	/**
86
	 * Get the value of callback
87
	 *
88
	 * @return null|callable
89
	 */
90
	public function get_callback(): ?callable {
91
		return $this->callback;
92
	}
93
94
	/**
95
	 * Set the value of callback
96
	 *
97
	 * @param callable $callback
98
	 *
99
	 * @return self
100
	 */
101
	public function callback( callable $callback ): self {
102
		$this->callback = $callback;
103
		return $this;
104
	}
105
106
	/**
107
	 * Get the value of route
108
	 *
109
	 * @return string
110
	 */
111
	public function get_route(): string {
112
		return $this->route;
113
	}
114
115
	/**
116
	 * Get the value of method
117
	 *
118
	 * @return string
119
	 */
120
	public function get_method(): string {
121
		return $this->method;
122
	}
123
124
	/**
125
	 * Set the value of namespace
126
	 *
127
	 * @param string $namespace
128
	 * @return static
129
	 */
130
	public function namespace( string $namespace ) {
131
		$this->namespace = $namespace;
132
		return $this;
133
	}
134
135
	/**
136
	 * Returns the route with a different method.
137
	 *
138
	 * @param string $method
139
	 * @return self
140
	 */
141
	public function with_method( string $method ): self {
142
		$clone = new self( $method, $this->get_route() );
143
		// Arguments
144
		if ( ! empty( $this->arguments ) ) {
145
			foreach ( $this->arguments as $argument ) {
146
				$clone->argument( $argument );
147
			}
148
		}
149
		// Authentication
150
		if ( ! empty( $this->authentication ) ) {
151
			foreach ( $this->authentication as $authentication ) {
152
				$clone->authentication( $authentication );
153
			}
154
		}
155
		// Callback
156
		if ( ! empty( $this->callback ) ) {
157
			$clone->callback( $this->callback );
158
		}
159
		// Namespace
160
		if ( ! empty( $this->namespace ) ) {
161
			$clone->namespace( $this->namespace );
162
		}
163
164
		return $clone;
165
	}
166
}
167
168