|
1
|
|
|
<?php |
|
2
|
|
|
/** |
|
3
|
|
|
* YIKES Inc. Easy Forms. |
|
4
|
|
|
* |
|
5
|
|
|
* @package YIKES\EasyForms |
|
6
|
|
|
* @author Freddie Mixell |
|
7
|
|
|
* @license GPL2 |
|
8
|
|
|
*/ |
|
9
|
|
|
|
|
10
|
|
|
namespace YIKES\EasyForms\View; |
|
11
|
|
|
|
|
12
|
|
|
use YIKES\EasyForms\Exception\FailedToLoadView; |
|
13
|
|
|
use YIKES\EasyForms\Exception\InvalidURI; |
|
14
|
|
|
use YIKES\EasyForms\PluginHelper; |
|
15
|
|
|
|
|
16
|
|
|
/** |
|
17
|
|
|
* Class BaseView. |
|
18
|
|
|
* |
|
19
|
|
|
* Very basic View class to abstract away PHP view rendering. |
|
20
|
|
|
* |
|
21
|
|
|
* Note: This should normally be done through a dedicated package. |
|
22
|
|
|
* |
|
23
|
|
|
* @since %VERSION% |
|
24
|
|
|
* |
|
25
|
|
|
* @package YIKES\EasyForms |
|
26
|
|
|
* @author Jeremy Pry |
|
27
|
|
|
*/ |
|
28
|
|
|
class BaseView implements View { |
|
29
|
|
|
|
|
30
|
|
|
use PluginHelper; |
|
31
|
|
|
|
|
32
|
|
|
/** |
|
33
|
|
|
* Extension to use for view files. |
|
34
|
|
|
* |
|
35
|
|
|
* @since %VERSION% |
|
36
|
|
|
*/ |
|
37
|
|
|
const VIEW_EXTENSION = 'php'; |
|
38
|
|
|
|
|
39
|
|
|
/** |
|
40
|
|
|
* Contexts to use for escaping. |
|
41
|
|
|
* |
|
42
|
|
|
* @since %VERSION% |
|
43
|
|
|
*/ |
|
44
|
|
|
const CONTEXT_HTML = 'html'; |
|
45
|
|
|
const CONTEXT_JAVASCRIPT = 'js'; |
|
46
|
|
|
|
|
47
|
|
|
/** |
|
48
|
|
|
* URI to the view file to render. |
|
49
|
|
|
* |
|
50
|
|
|
* @since %VERSION% |
|
51
|
|
|
* |
|
52
|
|
|
* @var string |
|
53
|
|
|
*/ |
|
54
|
|
|
protected $uri; |
|
55
|
|
|
|
|
56
|
|
|
/** |
|
57
|
|
|
* Internal storage for passed-in context. |
|
58
|
|
|
* |
|
59
|
|
|
* @since %VERSION% |
|
60
|
|
|
* |
|
61
|
|
|
* @var array |
|
62
|
|
|
*/ |
|
63
|
|
|
protected $_context_ = []; |
|
64
|
|
|
|
|
65
|
|
|
/** |
|
66
|
|
|
* Instantiate a View object. |
|
67
|
|
|
* |
|
68
|
|
|
* @since %VERSION% |
|
69
|
|
|
* |
|
70
|
|
|
* @param string $uri URI to the view file to render. |
|
71
|
|
|
* |
|
72
|
|
|
* @throws InvalidURI If an invalid URI was passed into the View. |
|
73
|
|
|
*/ |
|
74
|
|
|
public function __construct( $uri ) { |
|
75
|
|
|
$this->uri = $this->validate( $uri ); |
|
76
|
|
|
} |
|
77
|
|
|
|
|
78
|
|
|
/** |
|
79
|
|
|
* Render a given URI. |
|
80
|
|
|
* |
|
81
|
|
|
* @since %VERSION% |
|
82
|
|
|
* |
|
83
|
|
|
* @param array $context Context in which to render. |
|
84
|
|
|
* |
|
85
|
|
|
* @return string Rendered HTML. |
|
86
|
|
|
* @throws FailedToLoadView If the View URI could not be loaded. |
|
87
|
|
|
*/ |
|
88
|
|
|
public function render( array $context = [] ) { |
|
89
|
|
|
|
|
90
|
|
|
// Add context to the current instance to make it available within the |
|
91
|
|
|
// rendered view. |
|
92
|
|
|
foreach ( $context as $key => $value ) { |
|
93
|
|
|
$this->$key = $value; |
|
94
|
|
|
} |
|
95
|
|
|
|
|
96
|
|
|
// Add entire context as array to the current instance to pass onto |
|
97
|
|
|
// partial views. |
|
98
|
|
|
$this->_context_ = $context; |
|
99
|
|
|
|
|
100
|
|
|
// Save current buffering level so we can backtrack in case of an error. |
|
101
|
|
|
// This is needed because the view itself might also add an unknown |
|
102
|
|
|
// number of output buffering levels. |
|
103
|
|
|
$buffer_level = ob_get_level(); |
|
104
|
|
|
ob_start(); |
|
105
|
|
|
|
|
106
|
|
|
try { |
|
107
|
|
|
include $this->uri; |
|
108
|
|
|
} catch ( \Exception $exception ) { |
|
109
|
|
|
// Remove whatever levels were added up until now. |
|
110
|
|
|
while ( ob_get_level() > $buffer_level ) { |
|
111
|
|
|
ob_end_clean(); |
|
112
|
|
|
} |
|
113
|
|
|
throw FailedToLoadView::view_exception( |
|
114
|
|
|
$this->uri, |
|
115
|
|
|
$exception |
|
116
|
|
|
); |
|
117
|
|
|
} |
|
118
|
|
|
|
|
119
|
|
|
return ob_get_clean(); |
|
120
|
|
|
} |
|
121
|
|
|
|
|
122
|
|
|
/** |
|
123
|
|
|
* Render a partial view. |
|
124
|
|
|
* |
|
125
|
|
|
* This can be used from within a currently rendered view, to include |
|
126
|
|
|
* nested partials. |
|
127
|
|
|
* |
|
128
|
|
|
* The passed-in context is optional, and will fall back to the parent's |
|
129
|
|
|
* context if omitted. |
|
130
|
|
|
* |
|
131
|
|
|
* @since %VERSION% |
|
132
|
|
|
* |
|
133
|
|
|
* @param string $uri URI of the partial to render. |
|
134
|
|
|
* @param array|null $context Context in which to render the partial. |
|
135
|
|
|
* |
|
136
|
|
|
* @return string Rendered HTML. |
|
137
|
|
|
* @throws InvalidURI If the provided URI was not valid. |
|
138
|
|
|
* @throws FailedToLoadView If the view could not be loaded. |
|
139
|
|
|
*/ |
|
140
|
|
|
public function render_partial( $uri, array $context = null ) { |
|
141
|
|
|
$view = new static( $uri ); |
|
142
|
|
|
|
|
143
|
|
|
return $view->render( $context ?: $this->_context_ ); |
|
144
|
|
|
} |
|
145
|
|
|
|
|
146
|
|
|
/** |
|
147
|
|
|
* Validate an URI. |
|
148
|
|
|
* |
|
149
|
|
|
* @since %VERSION% |
|
150
|
|
|
* |
|
151
|
|
|
* @param string $uri URI to validate. |
|
152
|
|
|
* |
|
153
|
|
|
* @return string Validated URI. |
|
154
|
|
|
* @throws InvalidURI If an invalid URI was passed into the View. |
|
155
|
|
|
*/ |
|
156
|
|
View Code Duplication |
protected function validate( $uri ) { |
|
|
|
|
|
|
157
|
|
|
$uri = $this->check_extension( $uri, static::VIEW_EXTENSION ); |
|
158
|
|
|
$uri = trailingslashit( $this->get_root_dir() ) . $uri; |
|
159
|
|
|
|
|
160
|
|
|
if ( ! is_readable( $uri ) ) { |
|
161
|
|
|
throw InvalidURI::from_uri( $uri ); |
|
162
|
|
|
} |
|
163
|
|
|
|
|
164
|
|
|
return $uri; |
|
165
|
|
|
} |
|
166
|
|
|
|
|
167
|
|
|
/** |
|
168
|
|
|
* Check that the URI has the correct extension. |
|
169
|
|
|
* |
|
170
|
|
|
* Optionally adds the extension if none was detected. |
|
171
|
|
|
* |
|
172
|
|
|
* @since %VERSION% |
|
173
|
|
|
* |
|
174
|
|
|
* @param string $uri URI to check the extension of. |
|
175
|
|
|
* @param string $extension Extension to use. |
|
176
|
|
|
* |
|
177
|
|
|
* @return string URI with correct extension. |
|
178
|
|
|
*/ |
|
179
|
|
View Code Duplication |
protected function check_extension( $uri, $extension ) { |
|
|
|
|
|
|
180
|
|
|
$detected_extension = pathinfo( $uri, PATHINFO_EXTENSION ); |
|
181
|
|
|
|
|
182
|
|
|
if ( $extension !== $detected_extension ) { |
|
183
|
|
|
$uri .= '.' . $extension; |
|
184
|
|
|
} |
|
185
|
|
|
|
|
186
|
|
|
return $uri; |
|
187
|
|
|
} |
|
188
|
|
|
} |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.