@@ -71,7 +71,7 @@ discard block |
||
71 | 71 | */ |
72 | 72 | public function __construct() |
73 | 73 | { |
74 | - if (! $this->_model_name_extended) { |
|
74 | + if ( ! $this->_model_name_extended) { |
|
75 | 75 | throw new EE_Error( |
76 | 76 | esc_html__( |
77 | 77 | "When declaring a model extension, you must define its _model_name_extended property. It should be a model name like 'Attendee' or 'Event'", |
@@ -79,7 +79,7 @@ discard block |
||
79 | 79 | ) |
80 | 80 | ); |
81 | 81 | } |
82 | - $construct_end_action = 'AHEE__EEM_' . $this->_model_name_extended . '__construct__end'; |
|
82 | + $construct_end_action = 'AHEE__EEM_'.$this->_model_name_extended.'__construct__end'; |
|
83 | 83 | if (did_action($construct_end_action)) { |
84 | 84 | throw new EE_Error( |
85 | 85 | sprintf( |
@@ -94,15 +94,15 @@ discard block |
||
94 | 94 | ); |
95 | 95 | } |
96 | 96 | add_filter( |
97 | - 'FHEE__EEM_' . $this->_model_name_extended . '__construct__tables', |
|
97 | + 'FHEE__EEM_'.$this->_model_name_extended.'__construct__tables', |
|
98 | 98 | array($this, 'add_extra_tables_on_filter') |
99 | 99 | ); |
100 | 100 | add_filter( |
101 | - 'FHEE__EEM_' . $this->_model_name_extended . '__construct__fields', |
|
101 | + 'FHEE__EEM_'.$this->_model_name_extended.'__construct__fields', |
|
102 | 102 | array($this, 'add_extra_fields_on_filter') |
103 | 103 | ); |
104 | 104 | add_filter( |
105 | - 'FHEE__EEM_' . $this->_model_name_extended . '__construct__model_relations', |
|
105 | + 'FHEE__EEM_'.$this->_model_name_extended.'__construct__model_relations', |
|
106 | 106 | array($this, 'add_extra_relations_on_filter') |
107 | 107 | ); |
108 | 108 | $this->_register_extending_methods(); |
@@ -127,12 +127,12 @@ discard block |
||
127 | 127 | { |
128 | 128 | if ($this->_extra_fields) { |
129 | 129 | foreach ($this->_extra_fields as $table_alias => $fields) { |
130 | - if (! isset($existing_fields[ $table_alias ])) { |
|
131 | - $existing_fields[ $table_alias ] = array(); |
|
130 | + if ( ! isset($existing_fields[$table_alias])) { |
|
131 | + $existing_fields[$table_alias] = array(); |
|
132 | 132 | } |
133 | - $existing_fields[ $table_alias ] = array_merge( |
|
134 | - (array) $existing_fields[ $table_alias ], |
|
135 | - $this->_extra_fields[ $table_alias ] |
|
133 | + $existing_fields[$table_alias] = array_merge( |
|
134 | + (array) $existing_fields[$table_alias], |
|
135 | + $this->_extra_fields[$table_alias] |
|
136 | 136 | ); |
137 | 137 | } |
138 | 138 | } |
@@ -163,7 +163,7 @@ discard block |
||
163 | 163 | $callback_name = "FHEE__EEM_{$this->_model_name_extended}__$method_name_on_model"; |
164 | 164 | add_filter( |
165 | 165 | $callback_name, |
166 | - array($this, self::dynamic_callback_method_prefix . $method_name_on_model), |
|
166 | + array($this, self::dynamic_callback_method_prefix.$method_name_on_model), |
|
167 | 167 | 10, |
168 | 168 | 10 |
169 | 169 | ); |
@@ -178,15 +178,15 @@ discard block |
||
178 | 178 | public function deregister() |
179 | 179 | { |
180 | 180 | remove_filter( |
181 | - 'FHEE__EEM_' . $this->_model_name_extended . '__construct__tables', |
|
181 | + 'FHEE__EEM_'.$this->_model_name_extended.'__construct__tables', |
|
182 | 182 | array($this, 'add_extra_tables_on_filter') |
183 | 183 | ); |
184 | 184 | remove_filter( |
185 | - 'FHEE__EEM_' . $this->_model_name_extended . '__construct__fields', |
|
185 | + 'FHEE__EEM_'.$this->_model_name_extended.'__construct__fields', |
|
186 | 186 | array($this, 'add_extra_fields_on_filter') |
187 | 187 | ); |
188 | 188 | remove_filter( |
189 | - 'FHEE__EEM_' . $this->_model_name_extended . '__construct__model_relations', |
|
189 | + 'FHEE__EEM_'.$this->_model_name_extended.'__construct__model_relations', |
|
190 | 190 | array($this, 'add_extra_relations_on_filter') |
191 | 191 | ); |
192 | 192 | $all_methods = get_class_methods(get_class($this)); |
@@ -196,13 +196,13 @@ discard block |
||
196 | 196 | $callback_name = "FHEE__EEM_{$this->_model_name_extended}__$method_name_on_model"; |
197 | 197 | remove_filter( |
198 | 198 | $callback_name, |
199 | - array($this, self::dynamic_callback_method_prefix . $method_name_on_model), |
|
199 | + array($this, self::dynamic_callback_method_prefix.$method_name_on_model), |
|
200 | 200 | 10 |
201 | 201 | ); |
202 | 202 | } |
203 | 203 | } |
204 | 204 | /** @var EEM_Base $model_to_reset */ |
205 | - $model_to_reset = 'EEM_' . $this->_model_name_extended; |
|
205 | + $model_to_reset = 'EEM_'.$this->_model_name_extended; |
|
206 | 206 | if (class_exists($model_to_reset)) { |
207 | 207 | $model_to_reset::reset(); |
208 | 208 | } |
@@ -224,7 +224,7 @@ discard block |
||
224 | 224 | // phpcs:disable WordPress.WP.I18n.SingleUnderscoreGetTextFunction |
225 | 225 | $this->_ = $model_called; |
226 | 226 | // phpcs:enable |
227 | - $extending_method = self::extending_method_prefix . $method_called_on_model; |
|
227 | + $extending_method = self::extending_method_prefix.$method_called_on_model; |
|
228 | 228 | if (method_exists($this, $extending_method)) { |
229 | 229 | return call_user_func_array(array($this, $extending_method), $args_provided_to_method_on_model); |
230 | 230 | } else { |
@@ -43,211 +43,211 @@ |
||
43 | 43 | */ |
44 | 44 | abstract class EEME_Base |
45 | 45 | { |
46 | - const extending_method_prefix = 'ext_'; |
|
47 | - const dynamic_callback_method_prefix = 'dynamic_callback_method_'; |
|
48 | - |
|
49 | - protected $_extra_tables = array(); |
|
50 | - protected $_extra_fields = array(); |
|
51 | - protected $_extra_relations = array(); |
|
52 | - |
|
53 | - /** |
|
54 | - * The model name that is extended (not classname) |
|
55 | - * |
|
56 | - * @var string |
|
57 | - */ |
|
58 | - protected $_model_name_extended = null; |
|
59 | - |
|
60 | - /** |
|
61 | - * The model this extends |
|
62 | - * |
|
63 | - * @var EEM_Base |
|
64 | - */ |
|
65 | - protected $_ = null; |
|
66 | - |
|
67 | - |
|
68 | - /** |
|
69 | - * @throws \EE_Error |
|
70 | - */ |
|
71 | - public function __construct() |
|
72 | - { |
|
73 | - if (! $this->_model_name_extended) { |
|
74 | - throw new EE_Error( |
|
75 | - esc_html__( |
|
76 | - "When declaring a model extension, you must define its _model_name_extended property. It should be a model name like 'Attendee' or 'Event'", |
|
77 | - "event_espresso" |
|
78 | - ) |
|
79 | - ); |
|
80 | - } |
|
81 | - $construct_end_action = 'AHEE__EEM_' . $this->_model_name_extended . '__construct__end'; |
|
82 | - if (did_action($construct_end_action)) { |
|
83 | - throw new EE_Error( |
|
84 | - sprintf( |
|
85 | - esc_html__( |
|
86 | - "Hooked in model extension '%s' too late! The model %s has already been used! We know because the action %s has been fired", |
|
87 | - "event_espresso" |
|
88 | - ), |
|
89 | - get_class($this), |
|
90 | - $this->_model_name_extended, |
|
91 | - $construct_end_action |
|
92 | - ) |
|
93 | - ); |
|
94 | - } |
|
95 | - add_filter( |
|
96 | - 'FHEE__EEM_' . $this->_model_name_extended . '__construct__tables', |
|
97 | - array($this, 'add_extra_tables_on_filter') |
|
98 | - ); |
|
99 | - add_filter( |
|
100 | - 'FHEE__EEM_' . $this->_model_name_extended . '__construct__fields', |
|
101 | - array($this, 'add_extra_fields_on_filter') |
|
102 | - ); |
|
103 | - add_filter( |
|
104 | - 'FHEE__EEM_' . $this->_model_name_extended . '__construct__model_relations', |
|
105 | - array($this, 'add_extra_relations_on_filter') |
|
106 | - ); |
|
107 | - $this->_register_extending_methods(); |
|
108 | - } |
|
109 | - |
|
110 | - |
|
111 | - /** |
|
112 | - * @param array $existing_tables |
|
113 | - * @return array |
|
114 | - */ |
|
115 | - public function add_extra_tables_on_filter($existing_tables) |
|
116 | - { |
|
117 | - return array_merge((array) $existing_tables, $this->_extra_tables); |
|
118 | - } |
|
119 | - |
|
120 | - |
|
121 | - /** |
|
122 | - * @param array $existing_fields |
|
123 | - * @return array |
|
124 | - */ |
|
125 | - public function add_extra_fields_on_filter($existing_fields) |
|
126 | - { |
|
127 | - if ($this->_extra_fields) { |
|
128 | - foreach ($this->_extra_fields as $table_alias => $fields) { |
|
129 | - if (! isset($existing_fields[ $table_alias ])) { |
|
130 | - $existing_fields[ $table_alias ] = array(); |
|
131 | - } |
|
132 | - $existing_fields[ $table_alias ] = array_merge( |
|
133 | - (array) $existing_fields[ $table_alias ], |
|
134 | - $this->_extra_fields[ $table_alias ] |
|
135 | - ); |
|
136 | - } |
|
137 | - } |
|
138 | - return $existing_fields; |
|
139 | - } |
|
140 | - |
|
141 | - |
|
142 | - /** |
|
143 | - * @param array $existing_relations |
|
144 | - * @return array |
|
145 | - */ |
|
146 | - public function add_extra_relations_on_filter($existing_relations) |
|
147 | - { |
|
148 | - return array_merge((array) $existing_relations, $this->_extra_relations); |
|
149 | - } |
|
150 | - |
|
151 | - |
|
152 | - /** |
|
153 | - * scans the child of EEME_Base for functions starting with ext_, and magically makes them functions on the |
|
154 | - * model extended. (Internally uses filters, and the __call magic method) |
|
155 | - */ |
|
156 | - protected function _register_extending_methods() |
|
157 | - { |
|
158 | - $all_methods = get_class_methods(get_class($this)); |
|
159 | - foreach ($all_methods as $method_name) { |
|
160 | - if (strpos($method_name, self::extending_method_prefix) === 0) { |
|
161 | - $method_name_on_model = str_replace(self::extending_method_prefix, '', $method_name); |
|
162 | - $callback_name = "FHEE__EEM_{$this->_model_name_extended}__$method_name_on_model"; |
|
163 | - add_filter( |
|
164 | - $callback_name, |
|
165 | - array($this, self::dynamic_callback_method_prefix . $method_name_on_model), |
|
166 | - 10, |
|
167 | - 10 |
|
168 | - ); |
|
169 | - } |
|
170 | - } |
|
171 | - } |
|
172 | - |
|
173 | - /** |
|
174 | - * scans the child of EEME_Base for functions starting with ext_, and magically REMOVES them as functions on the |
|
175 | - * model extended. (Internally uses filters, and the __call magic method) |
|
176 | - */ |
|
177 | - public function deregister() |
|
178 | - { |
|
179 | - remove_filter( |
|
180 | - 'FHEE__EEM_' . $this->_model_name_extended . '__construct__tables', |
|
181 | - array($this, 'add_extra_tables_on_filter') |
|
182 | - ); |
|
183 | - remove_filter( |
|
184 | - 'FHEE__EEM_' . $this->_model_name_extended . '__construct__fields', |
|
185 | - array($this, 'add_extra_fields_on_filter') |
|
186 | - ); |
|
187 | - remove_filter( |
|
188 | - 'FHEE__EEM_' . $this->_model_name_extended . '__construct__model_relations', |
|
189 | - array($this, 'add_extra_relations_on_filter') |
|
190 | - ); |
|
191 | - $all_methods = get_class_methods(get_class($this)); |
|
192 | - foreach ($all_methods as $method_name) { |
|
193 | - if (strpos($method_name, self::extending_method_prefix) === 0) { |
|
194 | - $method_name_on_model = str_replace(self::extending_method_prefix, '', $method_name); |
|
195 | - $callback_name = "FHEE__EEM_{$this->_model_name_extended}__$method_name_on_model"; |
|
196 | - remove_filter( |
|
197 | - $callback_name, |
|
198 | - array($this, self::dynamic_callback_method_prefix . $method_name_on_model), |
|
199 | - 10 |
|
200 | - ); |
|
201 | - } |
|
202 | - } |
|
203 | - /** @var EEM_Base $model_to_reset */ |
|
204 | - $model_to_reset = 'EEM_' . $this->_model_name_extended; |
|
205 | - if (class_exists($model_to_reset)) { |
|
206 | - $model_to_reset::reset(); |
|
207 | - } |
|
208 | - } |
|
209 | - |
|
210 | - |
|
211 | - /** |
|
212 | - * @param string $callback_method_name |
|
213 | - * @param array $args |
|
214 | - * @return mixed |
|
215 | - * @throws EE_Error |
|
216 | - */ |
|
217 | - public function __call($callback_method_name, $args) |
|
218 | - { |
|
219 | - if (strpos($callback_method_name, self::dynamic_callback_method_prefix) === 0) { |
|
220 | - // it's a dynamic callback for a method name |
|
221 | - $method_called_on_model = str_replace(self::dynamic_callback_method_prefix, '', $callback_method_name); |
|
222 | - list($original_return_val, $model_called, $args_provided_to_method_on_model) = (array) $args; |
|
223 | - // phpcs:disable WordPress.WP.I18n.SingleUnderscoreGetTextFunction |
|
224 | - $this->_ = $model_called; |
|
225 | - // phpcs:enable |
|
226 | - $extending_method = self::extending_method_prefix . $method_called_on_model; |
|
227 | - if (method_exists($this, $extending_method)) { |
|
228 | - return call_user_func_array(array($this, $extending_method), $args_provided_to_method_on_model); |
|
229 | - } else { |
|
230 | - throw new EE_Error( |
|
231 | - sprintf( |
|
232 | - esc_html__( |
|
233 | - "An odd error occurred. Model '%s' had a method called on it that it didn't recognize. So it passed it onto the model extension '%s' (because it had a function named '%s' which should be able to handle it), but the function '%s' doesnt exist!)", |
|
234 | - "event_espresso" |
|
235 | - ), |
|
236 | - $this->_model_name_extended, |
|
237 | - get_class($this), |
|
238 | - $extending_method, |
|
239 | - $extending_method |
|
240 | - ) |
|
241 | - ); |
|
242 | - } |
|
243 | - } else { |
|
244 | - throw new EE_Error( |
|
245 | - sprintf( |
|
246 | - esc_html__("There is no method named '%s' on '%s'", "event_espresso"), |
|
247 | - $callback_method_name, |
|
248 | - get_class($this) |
|
249 | - ) |
|
250 | - ); |
|
251 | - } |
|
252 | - } |
|
46 | + const extending_method_prefix = 'ext_'; |
|
47 | + const dynamic_callback_method_prefix = 'dynamic_callback_method_'; |
|
48 | + |
|
49 | + protected $_extra_tables = array(); |
|
50 | + protected $_extra_fields = array(); |
|
51 | + protected $_extra_relations = array(); |
|
52 | + |
|
53 | + /** |
|
54 | + * The model name that is extended (not classname) |
|
55 | + * |
|
56 | + * @var string |
|
57 | + */ |
|
58 | + protected $_model_name_extended = null; |
|
59 | + |
|
60 | + /** |
|
61 | + * The model this extends |
|
62 | + * |
|
63 | + * @var EEM_Base |
|
64 | + */ |
|
65 | + protected $_ = null; |
|
66 | + |
|
67 | + |
|
68 | + /** |
|
69 | + * @throws \EE_Error |
|
70 | + */ |
|
71 | + public function __construct() |
|
72 | + { |
|
73 | + if (! $this->_model_name_extended) { |
|
74 | + throw new EE_Error( |
|
75 | + esc_html__( |
|
76 | + "When declaring a model extension, you must define its _model_name_extended property. It should be a model name like 'Attendee' or 'Event'", |
|
77 | + "event_espresso" |
|
78 | + ) |
|
79 | + ); |
|
80 | + } |
|
81 | + $construct_end_action = 'AHEE__EEM_' . $this->_model_name_extended . '__construct__end'; |
|
82 | + if (did_action($construct_end_action)) { |
|
83 | + throw new EE_Error( |
|
84 | + sprintf( |
|
85 | + esc_html__( |
|
86 | + "Hooked in model extension '%s' too late! The model %s has already been used! We know because the action %s has been fired", |
|
87 | + "event_espresso" |
|
88 | + ), |
|
89 | + get_class($this), |
|
90 | + $this->_model_name_extended, |
|
91 | + $construct_end_action |
|
92 | + ) |
|
93 | + ); |
|
94 | + } |
|
95 | + add_filter( |
|
96 | + 'FHEE__EEM_' . $this->_model_name_extended . '__construct__tables', |
|
97 | + array($this, 'add_extra_tables_on_filter') |
|
98 | + ); |
|
99 | + add_filter( |
|
100 | + 'FHEE__EEM_' . $this->_model_name_extended . '__construct__fields', |
|
101 | + array($this, 'add_extra_fields_on_filter') |
|
102 | + ); |
|
103 | + add_filter( |
|
104 | + 'FHEE__EEM_' . $this->_model_name_extended . '__construct__model_relations', |
|
105 | + array($this, 'add_extra_relations_on_filter') |
|
106 | + ); |
|
107 | + $this->_register_extending_methods(); |
|
108 | + } |
|
109 | + |
|
110 | + |
|
111 | + /** |
|
112 | + * @param array $existing_tables |
|
113 | + * @return array |
|
114 | + */ |
|
115 | + public function add_extra_tables_on_filter($existing_tables) |
|
116 | + { |
|
117 | + return array_merge((array) $existing_tables, $this->_extra_tables); |
|
118 | + } |
|
119 | + |
|
120 | + |
|
121 | + /** |
|
122 | + * @param array $existing_fields |
|
123 | + * @return array |
|
124 | + */ |
|
125 | + public function add_extra_fields_on_filter($existing_fields) |
|
126 | + { |
|
127 | + if ($this->_extra_fields) { |
|
128 | + foreach ($this->_extra_fields as $table_alias => $fields) { |
|
129 | + if (! isset($existing_fields[ $table_alias ])) { |
|
130 | + $existing_fields[ $table_alias ] = array(); |
|
131 | + } |
|
132 | + $existing_fields[ $table_alias ] = array_merge( |
|
133 | + (array) $existing_fields[ $table_alias ], |
|
134 | + $this->_extra_fields[ $table_alias ] |
|
135 | + ); |
|
136 | + } |
|
137 | + } |
|
138 | + return $existing_fields; |
|
139 | + } |
|
140 | + |
|
141 | + |
|
142 | + /** |
|
143 | + * @param array $existing_relations |
|
144 | + * @return array |
|
145 | + */ |
|
146 | + public function add_extra_relations_on_filter($existing_relations) |
|
147 | + { |
|
148 | + return array_merge((array) $existing_relations, $this->_extra_relations); |
|
149 | + } |
|
150 | + |
|
151 | + |
|
152 | + /** |
|
153 | + * scans the child of EEME_Base for functions starting with ext_, and magically makes them functions on the |
|
154 | + * model extended. (Internally uses filters, and the __call magic method) |
|
155 | + */ |
|
156 | + protected function _register_extending_methods() |
|
157 | + { |
|
158 | + $all_methods = get_class_methods(get_class($this)); |
|
159 | + foreach ($all_methods as $method_name) { |
|
160 | + if (strpos($method_name, self::extending_method_prefix) === 0) { |
|
161 | + $method_name_on_model = str_replace(self::extending_method_prefix, '', $method_name); |
|
162 | + $callback_name = "FHEE__EEM_{$this->_model_name_extended}__$method_name_on_model"; |
|
163 | + add_filter( |
|
164 | + $callback_name, |
|
165 | + array($this, self::dynamic_callback_method_prefix . $method_name_on_model), |
|
166 | + 10, |
|
167 | + 10 |
|
168 | + ); |
|
169 | + } |
|
170 | + } |
|
171 | + } |
|
172 | + |
|
173 | + /** |
|
174 | + * scans the child of EEME_Base for functions starting with ext_, and magically REMOVES them as functions on the |
|
175 | + * model extended. (Internally uses filters, and the __call magic method) |
|
176 | + */ |
|
177 | + public function deregister() |
|
178 | + { |
|
179 | + remove_filter( |
|
180 | + 'FHEE__EEM_' . $this->_model_name_extended . '__construct__tables', |
|
181 | + array($this, 'add_extra_tables_on_filter') |
|
182 | + ); |
|
183 | + remove_filter( |
|
184 | + 'FHEE__EEM_' . $this->_model_name_extended . '__construct__fields', |
|
185 | + array($this, 'add_extra_fields_on_filter') |
|
186 | + ); |
|
187 | + remove_filter( |
|
188 | + 'FHEE__EEM_' . $this->_model_name_extended . '__construct__model_relations', |
|
189 | + array($this, 'add_extra_relations_on_filter') |
|
190 | + ); |
|
191 | + $all_methods = get_class_methods(get_class($this)); |
|
192 | + foreach ($all_methods as $method_name) { |
|
193 | + if (strpos($method_name, self::extending_method_prefix) === 0) { |
|
194 | + $method_name_on_model = str_replace(self::extending_method_prefix, '', $method_name); |
|
195 | + $callback_name = "FHEE__EEM_{$this->_model_name_extended}__$method_name_on_model"; |
|
196 | + remove_filter( |
|
197 | + $callback_name, |
|
198 | + array($this, self::dynamic_callback_method_prefix . $method_name_on_model), |
|
199 | + 10 |
|
200 | + ); |
|
201 | + } |
|
202 | + } |
|
203 | + /** @var EEM_Base $model_to_reset */ |
|
204 | + $model_to_reset = 'EEM_' . $this->_model_name_extended; |
|
205 | + if (class_exists($model_to_reset)) { |
|
206 | + $model_to_reset::reset(); |
|
207 | + } |
|
208 | + } |
|
209 | + |
|
210 | + |
|
211 | + /** |
|
212 | + * @param string $callback_method_name |
|
213 | + * @param array $args |
|
214 | + * @return mixed |
|
215 | + * @throws EE_Error |
|
216 | + */ |
|
217 | + public function __call($callback_method_name, $args) |
|
218 | + { |
|
219 | + if (strpos($callback_method_name, self::dynamic_callback_method_prefix) === 0) { |
|
220 | + // it's a dynamic callback for a method name |
|
221 | + $method_called_on_model = str_replace(self::dynamic_callback_method_prefix, '', $callback_method_name); |
|
222 | + list($original_return_val, $model_called, $args_provided_to_method_on_model) = (array) $args; |
|
223 | + // phpcs:disable WordPress.WP.I18n.SingleUnderscoreGetTextFunction |
|
224 | + $this->_ = $model_called; |
|
225 | + // phpcs:enable |
|
226 | + $extending_method = self::extending_method_prefix . $method_called_on_model; |
|
227 | + if (method_exists($this, $extending_method)) { |
|
228 | + return call_user_func_array(array($this, $extending_method), $args_provided_to_method_on_model); |
|
229 | + } else { |
|
230 | + throw new EE_Error( |
|
231 | + sprintf( |
|
232 | + esc_html__( |
|
233 | + "An odd error occurred. Model '%s' had a method called on it that it didn't recognize. So it passed it onto the model extension '%s' (because it had a function named '%s' which should be able to handle it), but the function '%s' doesnt exist!)", |
|
234 | + "event_espresso" |
|
235 | + ), |
|
236 | + $this->_model_name_extended, |
|
237 | + get_class($this), |
|
238 | + $extending_method, |
|
239 | + $extending_method |
|
240 | + ) |
|
241 | + ); |
|
242 | + } |
|
243 | + } else { |
|
244 | + throw new EE_Error( |
|
245 | + sprintf( |
|
246 | + esc_html__("There is no method named '%s' on '%s'", "event_espresso"), |
|
247 | + $callback_method_name, |
|
248 | + get_class($this) |
|
249 | + ) |
|
250 | + ); |
|
251 | + } |
|
252 | + } |
|
253 | 253 | } |
@@ -49,7 +49,7 @@ discard block |
||
49 | 49 | |
50 | 50 | public function __construct() |
51 | 51 | { |
52 | - if (! $this->_model_name_extended) { |
|
52 | + if ( ! $this->_model_name_extended) { |
|
53 | 53 | throw new EE_Error( |
54 | 54 | sprintf( |
55 | 55 | esc_html__( |
@@ -59,7 +59,7 @@ discard block |
||
59 | 59 | ) |
60 | 60 | ); |
61 | 61 | } |
62 | - if (did_action('AHEE__EE_' . $this->_model_name_extended . '__construct__end')) { |
|
62 | + if (did_action('AHEE__EE_'.$this->_model_name_extended.'__construct__end')) { |
|
63 | 63 | throw new EE_Error( |
64 | 64 | sprintf( |
65 | 65 | esc_html__( |
@@ -87,7 +87,7 @@ discard block |
||
87 | 87 | $callback_name = "FHEE__EE_{$this->_model_name_extended}__$method_name_on_model"; |
88 | 88 | add_filter( |
89 | 89 | $callback_name, |
90 | - array($this, self::dynamic_callback_method_prefix . $method_name_on_model), |
|
90 | + array($this, self::dynamic_callback_method_prefix.$method_name_on_model), |
|
91 | 91 | 10, |
92 | 92 | 10 |
93 | 93 | ); |
@@ -108,7 +108,7 @@ discard block |
||
108 | 108 | $callback_name = "FHEE__EE_{$this->_model_name_extended}__$method_name_on_model"; |
109 | 109 | remove_filter( |
110 | 110 | $callback_name, |
111 | - array($this, self::dynamic_callback_method_prefix . $method_name_on_model), |
|
111 | + array($this, self::dynamic_callback_method_prefix.$method_name_on_model), |
|
112 | 112 | 10 |
113 | 113 | ); |
114 | 114 | } |
@@ -127,7 +127,7 @@ discard block |
||
127 | 127 | $this->_ = $model_called; |
128 | 128 | // phpcs:enable |
129 | 129 | $args_provided_to_method_on_model = $args[2]; |
130 | - $extending_method = self::extending_method_prefix . $method_called_on_model; |
|
130 | + $extending_method = self::extending_method_prefix.$method_called_on_model; |
|
131 | 131 | if (method_exists($this, $extending_method)) { |
132 | 132 | return call_user_func_array(array($this, $extending_method), $args_provided_to_method_on_model); |
133 | 133 | } else { |
@@ -31,126 +31,126 @@ |
||
31 | 31 | */ |
32 | 32 | class EEE_Base_Class |
33 | 33 | { |
34 | - const extending_method_prefix = 'ext_'; |
|
35 | - const dynamic_callback_method_prefix = 'dynamic_callback_method_'; |
|
36 | - /** |
|
37 | - * The model name that is extended (not classname) |
|
38 | - * |
|
39 | - * @var string |
|
40 | - */ |
|
41 | - protected $_model_name_extended = null; |
|
42 | - /** |
|
43 | - * The model this extends |
|
44 | - * |
|
45 | - * @var EE_Base_Class |
|
46 | - */ |
|
47 | - protected $_ = null; |
|
34 | + const extending_method_prefix = 'ext_'; |
|
35 | + const dynamic_callback_method_prefix = 'dynamic_callback_method_'; |
|
36 | + /** |
|
37 | + * The model name that is extended (not classname) |
|
38 | + * |
|
39 | + * @var string |
|
40 | + */ |
|
41 | + protected $_model_name_extended = null; |
|
42 | + /** |
|
43 | + * The model this extends |
|
44 | + * |
|
45 | + * @var EE_Base_Class |
|
46 | + */ |
|
47 | + protected $_ = null; |
|
48 | 48 | |
49 | - public function __construct() |
|
50 | - { |
|
51 | - if (! $this->_model_name_extended) { |
|
52 | - throw new EE_Error( |
|
53 | - sprintf( |
|
54 | - esc_html__( |
|
55 | - "When declaring a class extension, you must define its _model_name_extended property. It should be a model name like 'Attendee' or 'Event'", |
|
56 | - "event_espresso" |
|
57 | - ) |
|
58 | - ) |
|
59 | - ); |
|
60 | - } |
|
61 | - if (did_action('AHEE__EE_' . $this->_model_name_extended . '__construct__end')) { |
|
62 | - throw new EE_Error( |
|
63 | - sprintf( |
|
64 | - esc_html__( |
|
65 | - "Hooked in model object extension '%s' too late! The model object %s has already been used!", |
|
66 | - "event_espresso" |
|
67 | - ), |
|
68 | - get_class($this), |
|
69 | - $this->_model_name_extended |
|
70 | - ) |
|
71 | - ); |
|
72 | - } |
|
73 | - $this->_register_extending_methods(); |
|
74 | - } |
|
49 | + public function __construct() |
|
50 | + { |
|
51 | + if (! $this->_model_name_extended) { |
|
52 | + throw new EE_Error( |
|
53 | + sprintf( |
|
54 | + esc_html__( |
|
55 | + "When declaring a class extension, you must define its _model_name_extended property. It should be a model name like 'Attendee' or 'Event'", |
|
56 | + "event_espresso" |
|
57 | + ) |
|
58 | + ) |
|
59 | + ); |
|
60 | + } |
|
61 | + if (did_action('AHEE__EE_' . $this->_model_name_extended . '__construct__end')) { |
|
62 | + throw new EE_Error( |
|
63 | + sprintf( |
|
64 | + esc_html__( |
|
65 | + "Hooked in model object extension '%s' too late! The model object %s has already been used!", |
|
66 | + "event_espresso" |
|
67 | + ), |
|
68 | + get_class($this), |
|
69 | + $this->_model_name_extended |
|
70 | + ) |
|
71 | + ); |
|
72 | + } |
|
73 | + $this->_register_extending_methods(); |
|
74 | + } |
|
75 | 75 | |
76 | - /** |
|
77 | - * scans the child of EEME_Base for functions starting with ext_, and magically makes them functions on the |
|
78 | - * model extended. (Internally uses filters, and the __call magic method) |
|
79 | - */ |
|
80 | - protected function _register_extending_methods() |
|
81 | - { |
|
82 | - $all_methods = get_class_methods(get_class($this)); |
|
83 | - foreach ($all_methods as $method_name) { |
|
84 | - if (strpos($method_name, self::extending_method_prefix) === 0) { |
|
85 | - $method_name_on_model = str_replace(self::extending_method_prefix, '', $method_name); |
|
86 | - $callback_name = "FHEE__EE_{$this->_model_name_extended}__$method_name_on_model"; |
|
87 | - add_filter( |
|
88 | - $callback_name, |
|
89 | - array($this, self::dynamic_callback_method_prefix . $method_name_on_model), |
|
90 | - 10, |
|
91 | - 10 |
|
92 | - ); |
|
93 | - } |
|
94 | - } |
|
95 | - } |
|
76 | + /** |
|
77 | + * scans the child of EEME_Base for functions starting with ext_, and magically makes them functions on the |
|
78 | + * model extended. (Internally uses filters, and the __call magic method) |
|
79 | + */ |
|
80 | + protected function _register_extending_methods() |
|
81 | + { |
|
82 | + $all_methods = get_class_methods(get_class($this)); |
|
83 | + foreach ($all_methods as $method_name) { |
|
84 | + if (strpos($method_name, self::extending_method_prefix) === 0) { |
|
85 | + $method_name_on_model = str_replace(self::extending_method_prefix, '', $method_name); |
|
86 | + $callback_name = "FHEE__EE_{$this->_model_name_extended}__$method_name_on_model"; |
|
87 | + add_filter( |
|
88 | + $callback_name, |
|
89 | + array($this, self::dynamic_callback_method_prefix . $method_name_on_model), |
|
90 | + 10, |
|
91 | + 10 |
|
92 | + ); |
|
93 | + } |
|
94 | + } |
|
95 | + } |
|
96 | 96 | |
97 | - /** |
|
98 | - * scans the child of EEME_Base for functions starting with ext_, and magically REMOVES them as functions on the |
|
99 | - * model extended. (Internally uses filters, and the __call magic method) |
|
100 | - */ |
|
101 | - public function deregister() |
|
102 | - { |
|
103 | - $all_methods = get_class_methods(get_class($this)); |
|
104 | - foreach ($all_methods as $method_name) { |
|
105 | - if (strpos($method_name, self::extending_method_prefix) === 0) { |
|
106 | - $method_name_on_model = str_replace(self::extending_method_prefix, '', $method_name); |
|
107 | - $callback_name = "FHEE__EE_{$this->_model_name_extended}__$method_name_on_model"; |
|
108 | - remove_filter( |
|
109 | - $callback_name, |
|
110 | - array($this, self::dynamic_callback_method_prefix . $method_name_on_model), |
|
111 | - 10 |
|
112 | - ); |
|
113 | - } |
|
114 | - } |
|
115 | - } |
|
97 | + /** |
|
98 | + * scans the child of EEME_Base for functions starting with ext_, and magically REMOVES them as functions on the |
|
99 | + * model extended. (Internally uses filters, and the __call magic method) |
|
100 | + */ |
|
101 | + public function deregister() |
|
102 | + { |
|
103 | + $all_methods = get_class_methods(get_class($this)); |
|
104 | + foreach ($all_methods as $method_name) { |
|
105 | + if (strpos($method_name, self::extending_method_prefix) === 0) { |
|
106 | + $method_name_on_model = str_replace(self::extending_method_prefix, '', $method_name); |
|
107 | + $callback_name = "FHEE__EE_{$this->_model_name_extended}__$method_name_on_model"; |
|
108 | + remove_filter( |
|
109 | + $callback_name, |
|
110 | + array($this, self::dynamic_callback_method_prefix . $method_name_on_model), |
|
111 | + 10 |
|
112 | + ); |
|
113 | + } |
|
114 | + } |
|
115 | + } |
|
116 | 116 | |
117 | 117 | |
118 | - public function __call($callback_method_name, $args) |
|
119 | - { |
|
120 | - if (strpos($callback_method_name, self::dynamic_callback_method_prefix) === 0) { |
|
121 | - // it's a dynamic callback for a method name |
|
122 | - $method_called_on_model = str_replace(self::dynamic_callback_method_prefix, '', $callback_method_name); |
|
123 | - $original_return_val = $args[0]; |
|
124 | - $model_called = $args[1]; |
|
125 | - // phpcs:disable WordPress.WP.I18n.SingleUnderscoreGetTextFunction |
|
126 | - $this->_ = $model_called; |
|
127 | - // phpcs:enable |
|
128 | - $args_provided_to_method_on_model = $args[2]; |
|
129 | - $extending_method = self::extending_method_prefix . $method_called_on_model; |
|
130 | - if (method_exists($this, $extending_method)) { |
|
131 | - return call_user_func_array(array($this, $extending_method), $args_provided_to_method_on_model); |
|
132 | - } else { |
|
133 | - throw new EE_Error( |
|
134 | - sprintf( |
|
135 | - esc_html__( |
|
136 | - "An odd error occurred. Model '%s' had a method called on it that it didn't recognize. So it passed it onto the model extension '%s' (because it had a function named '%s' which should be able to handle it), but the function '%s' doesnt exist!)", |
|
137 | - "event_espresso" |
|
138 | - ), |
|
139 | - $this->_model_name_extended, |
|
140 | - get_class($this), |
|
141 | - $extending_method, |
|
142 | - $extending_method |
|
143 | - ) |
|
144 | - ); |
|
145 | - } |
|
146 | - } else { |
|
147 | - throw new EE_Error( |
|
148 | - sprintf( |
|
149 | - esc_html__("There is no method named '%s' on '%s'", "event_espresso"), |
|
150 | - $callback_method_name, |
|
151 | - get_class($this) |
|
152 | - ) |
|
153 | - ); |
|
154 | - } |
|
155 | - } |
|
118 | + public function __call($callback_method_name, $args) |
|
119 | + { |
|
120 | + if (strpos($callback_method_name, self::dynamic_callback_method_prefix) === 0) { |
|
121 | + // it's a dynamic callback for a method name |
|
122 | + $method_called_on_model = str_replace(self::dynamic_callback_method_prefix, '', $callback_method_name); |
|
123 | + $original_return_val = $args[0]; |
|
124 | + $model_called = $args[1]; |
|
125 | + // phpcs:disable WordPress.WP.I18n.SingleUnderscoreGetTextFunction |
|
126 | + $this->_ = $model_called; |
|
127 | + // phpcs:enable |
|
128 | + $args_provided_to_method_on_model = $args[2]; |
|
129 | + $extending_method = self::extending_method_prefix . $method_called_on_model; |
|
130 | + if (method_exists($this, $extending_method)) { |
|
131 | + return call_user_func_array(array($this, $extending_method), $args_provided_to_method_on_model); |
|
132 | + } else { |
|
133 | + throw new EE_Error( |
|
134 | + sprintf( |
|
135 | + esc_html__( |
|
136 | + "An odd error occurred. Model '%s' had a method called on it that it didn't recognize. So it passed it onto the model extension '%s' (because it had a function named '%s' which should be able to handle it), but the function '%s' doesnt exist!)", |
|
137 | + "event_espresso" |
|
138 | + ), |
|
139 | + $this->_model_name_extended, |
|
140 | + get_class($this), |
|
141 | + $extending_method, |
|
142 | + $extending_method |
|
143 | + ) |
|
144 | + ); |
|
145 | + } |
|
146 | + } else { |
|
147 | + throw new EE_Error( |
|
148 | + sprintf( |
|
149 | + esc_html__("There is no method named '%s' on '%s'", "event_espresso"), |
|
150 | + $callback_method_name, |
|
151 | + get_class($this) |
|
152 | + ) |
|
153 | + ); |
|
154 | + } |
|
155 | + } |
|
156 | 156 | } |
@@ -73,7 +73,7 @@ discard block |
||
73 | 73 | ); |
74 | 74 | } |
75 | 75 | |
76 | - if (! is_array($setup_args) || (empty($setup_args['cpts']) && empty($setup_args['cts']))) { |
|
76 | + if ( ! is_array($setup_args) || (empty($setup_args['cpts']) && empty($setup_args['cts']))) { |
|
77 | 77 | throw new EE_Error( |
78 | 78 | esc_html__( |
79 | 79 | 'In order to register custom post types or custom taxonomies, you must include an array containing either an array of custom post types to register (key "cpts"), an array of custom taxonomies ("cts") or both.', |
@@ -83,13 +83,13 @@ discard block |
||
83 | 83 | } |
84 | 84 | |
85 | 85 | // make sure we don't register twice |
86 | - if (isset(self::$_registry[ $identifier ])) { |
|
86 | + if (isset(self::$_registry[$identifier])) { |
|
87 | 87 | return; |
88 | 88 | } |
89 | 89 | |
90 | 90 | // make sure cpt ref is unique. |
91 | - if (isset(self::$_registry[ $identifier ])) { |
|
92 | - $identifier = uniqid() . '_' . $identifier; |
|
91 | + if (isset(self::$_registry[$identifier])) { |
|
92 | + $identifier = uniqid().'_'.$identifier; |
|
93 | 93 | } |
94 | 94 | |
95 | 95 | // make sure this was called in the right place! |
@@ -119,7 +119,7 @@ discard block |
||
119 | 119 | : [], |
120 | 120 | ]; |
121 | 121 | |
122 | - self::$_registry[ $identifier ] = $validated; |
|
122 | + self::$_registry[$identifier] = $validated; |
|
123 | 123 | |
124 | 124 | // hook into to cpt system |
125 | 125 | add_filter( |
@@ -152,7 +152,7 @@ discard block |
||
152 | 152 | { |
153 | 153 | foreach (self::$_registry as $registries) { |
154 | 154 | foreach ($registries['cpts'] as $cpt_name => $cpt_settings) { |
155 | - $custom_post_type_definitions[ $cpt_name ] = $cpt_settings; |
|
155 | + $custom_post_type_definitions[$cpt_name] = $cpt_settings; |
|
156 | 156 | } |
157 | 157 | } |
158 | 158 | return $custom_post_type_definitions; |
@@ -171,7 +171,7 @@ discard block |
||
171 | 171 | { |
172 | 172 | foreach (self::$_registry as $registries) { |
173 | 173 | foreach ($registries['cts'] as $ct_name => $ct_settings) { |
174 | - $custom_taxonomy_definitions[ $ct_name ] = $ct_settings; |
|
174 | + $custom_taxonomy_definitions[$ct_name] = $ct_settings; |
|
175 | 175 | } |
176 | 176 | } |
177 | 177 | return $custom_taxonomy_definitions; |
@@ -211,7 +211,7 @@ discard block |
||
211 | 211 | { |
212 | 212 | foreach (self::$_registry as $registries) { |
213 | 213 | foreach ($registries['cpts'] as $cpt_name => $cpt_settings) { |
214 | - $cpts[ $cpt_name ] = $cpt_settings; |
|
214 | + $cpts[$cpt_name] = $cpt_settings; |
|
215 | 215 | } |
216 | 216 | } |
217 | 217 | return $cpts; |
@@ -227,7 +227,7 @@ discard block |
||
227 | 227 | { |
228 | 228 | foreach (self::$_registry as $registries) { |
229 | 229 | foreach ($registries['cts'] as $ct_name => $ct_settings) { |
230 | - $cts[ $ct_name ] = $ct_settings; |
|
230 | + $cts[$ct_name] = $ct_settings; |
|
231 | 231 | } |
232 | 232 | } |
233 | 233 | return $cts; |
@@ -262,6 +262,6 @@ discard block |
||
262 | 262 | */ |
263 | 263 | public static function deregister($identifier = '') |
264 | 264 | { |
265 | - unset(self::$_registry[ $identifier ]); |
|
265 | + unset(self::$_registry[$identifier]); |
|
266 | 266 | } |
267 | 267 | } |
@@ -12,255 +12,255 @@ |
||
12 | 12 | */ |
13 | 13 | class EE_Register_CPT implements EEI_Plugin_API |
14 | 14 | { |
15 | - /** |
|
16 | - * Holds values for registered variations |
|
17 | - * |
|
18 | - * @since 4.5.0 |
|
19 | - * |
|
20 | - * @var array[][][] |
|
21 | - */ |
|
22 | - protected static $_registry = []; |
|
15 | + /** |
|
16 | + * Holds values for registered variations |
|
17 | + * |
|
18 | + * @since 4.5.0 |
|
19 | + * |
|
20 | + * @var array[][][] |
|
21 | + */ |
|
22 | + protected static $_registry = []; |
|
23 | 23 | |
24 | 24 | |
25 | - /** |
|
26 | - * Used to register new CPTs and Taxonomies. |
|
27 | - * |
|
28 | - * @param string $identifier reference used for the addon registering cpts and cts |
|
29 | - * @param array $setup_args { |
|
30 | - * An array of required values for registering the cpts and taxonomies |
|
31 | - * @type array $cpts { |
|
32 | - * An array of cpts and their arguments.(short example below) |
|
33 | - * @return void |
|
34 | - * @throws EE_Error |
|
35 | - * @see CustomPostTypeDefinitions::setDefinitions for a more complete example. |
|
36 | - * 'people' => array( |
|
37 | - * 'singular_name' => esc_html__('People', 'event_espresso'), |
|
38 | - * 'plural_name' => esc_html__('People', 'event_espresso'), |
|
39 | - * 'singular_slug' => esc_html__('people', 'event_espresso'), |
|
40 | - * 'plural_slug' => esc_html__('peoples', 'event_espresso'), |
|
41 | - * 'class_name' => 'EE_People' |
|
42 | - * ) |
|
43 | - * }, |
|
44 | - * @type array $cts { |
|
45 | - * An array of custom taxonomies and their arguments (short example below). |
|
46 | - * @see CustomTaxonomyDefinitions::setTaxonomies() for a more complete example. |
|
47 | - * 'espresso_people_type' => array( |
|
48 | - * 'singular_name' => esc_html__('People Type', 'event_espresso'), |
|
49 | - * 'plural_name' => esc_html__('People Types', 'event_espresso'), |
|
50 | - * 'args' => array() |
|
51 | - * ) |
|
52 | - * }, |
|
53 | - * @type array $default_terms { |
|
54 | - * An array of terms to set as the default for a given taxonomy and the |
|
55 | - * custom post types applied to. |
|
56 | - * 'taxonomy_name' => array( |
|
57 | - * 'term' => array( 'cpt_a_name', 'cpt_b_name' ) |
|
58 | - * ) |
|
59 | - * } |
|
60 | - * } |
|
61 | - */ |
|
62 | - public static function register($identifier = '', array $setup_args = []) |
|
63 | - { |
|
25 | + /** |
|
26 | + * Used to register new CPTs and Taxonomies. |
|
27 | + * |
|
28 | + * @param string $identifier reference used for the addon registering cpts and cts |
|
29 | + * @param array $setup_args { |
|
30 | + * An array of required values for registering the cpts and taxonomies |
|
31 | + * @type array $cpts { |
|
32 | + * An array of cpts and their arguments.(short example below) |
|
33 | + * @return void |
|
34 | + * @throws EE_Error |
|
35 | + * @see CustomPostTypeDefinitions::setDefinitions for a more complete example. |
|
36 | + * 'people' => array( |
|
37 | + * 'singular_name' => esc_html__('People', 'event_espresso'), |
|
38 | + * 'plural_name' => esc_html__('People', 'event_espresso'), |
|
39 | + * 'singular_slug' => esc_html__('people', 'event_espresso'), |
|
40 | + * 'plural_slug' => esc_html__('peoples', 'event_espresso'), |
|
41 | + * 'class_name' => 'EE_People' |
|
42 | + * ) |
|
43 | + * }, |
|
44 | + * @type array $cts { |
|
45 | + * An array of custom taxonomies and their arguments (short example below). |
|
46 | + * @see CustomTaxonomyDefinitions::setTaxonomies() for a more complete example. |
|
47 | + * 'espresso_people_type' => array( |
|
48 | + * 'singular_name' => esc_html__('People Type', 'event_espresso'), |
|
49 | + * 'plural_name' => esc_html__('People Types', 'event_espresso'), |
|
50 | + * 'args' => array() |
|
51 | + * ) |
|
52 | + * }, |
|
53 | + * @type array $default_terms { |
|
54 | + * An array of terms to set as the default for a given taxonomy and the |
|
55 | + * custom post types applied to. |
|
56 | + * 'taxonomy_name' => array( |
|
57 | + * 'term' => array( 'cpt_a_name', 'cpt_b_name' ) |
|
58 | + * ) |
|
59 | + * } |
|
60 | + * } |
|
61 | + */ |
|
62 | + public static function register($identifier = '', array $setup_args = []) |
|
63 | + { |
|
64 | 64 | |
65 | - // check for required params |
|
66 | - if (empty($identifier)) { |
|
67 | - throw new EE_Error( |
|
68 | - esc_html__( |
|
69 | - 'In order to register custom post types and custom taxonomies, you must include a value to reference what had been registered', |
|
70 | - 'event_espresso' |
|
71 | - ) |
|
72 | - ); |
|
73 | - } |
|
65 | + // check for required params |
|
66 | + if (empty($identifier)) { |
|
67 | + throw new EE_Error( |
|
68 | + esc_html__( |
|
69 | + 'In order to register custom post types and custom taxonomies, you must include a value to reference what had been registered', |
|
70 | + 'event_espresso' |
|
71 | + ) |
|
72 | + ); |
|
73 | + } |
|
74 | 74 | |
75 | - if (! is_array($setup_args) || (empty($setup_args['cpts']) && empty($setup_args['cts']))) { |
|
76 | - throw new EE_Error( |
|
77 | - esc_html__( |
|
78 | - 'In order to register custom post types or custom taxonomies, you must include an array containing either an array of custom post types to register (key "cpts"), an array of custom taxonomies ("cts") or both.', |
|
79 | - 'event_espresso' |
|
80 | - ) |
|
81 | - ); |
|
82 | - } |
|
75 | + if (! is_array($setup_args) || (empty($setup_args['cpts']) && empty($setup_args['cts']))) { |
|
76 | + throw new EE_Error( |
|
77 | + esc_html__( |
|
78 | + 'In order to register custom post types or custom taxonomies, you must include an array containing either an array of custom post types to register (key "cpts"), an array of custom taxonomies ("cts") or both.', |
|
79 | + 'event_espresso' |
|
80 | + ) |
|
81 | + ); |
|
82 | + } |
|
83 | 83 | |
84 | - // make sure we don't register twice |
|
85 | - if (isset(self::$_registry[ $identifier ])) { |
|
86 | - return; |
|
87 | - } |
|
84 | + // make sure we don't register twice |
|
85 | + if (isset(self::$_registry[ $identifier ])) { |
|
86 | + return; |
|
87 | + } |
|
88 | 88 | |
89 | - // make sure cpt ref is unique. |
|
90 | - if (isset(self::$_registry[ $identifier ])) { |
|
91 | - $identifier = uniqid() . '_' . $identifier; |
|
92 | - } |
|
89 | + // make sure cpt ref is unique. |
|
90 | + if (isset(self::$_registry[ $identifier ])) { |
|
91 | + $identifier = uniqid() . '_' . $identifier; |
|
92 | + } |
|
93 | 93 | |
94 | - // make sure this was called in the right place! |
|
95 | - if (did_action('AHEE__EE_System__load_CPTs_and_session__complete')) { |
|
96 | - EE_Error::doing_it_wrong( |
|
97 | - __METHOD__, |
|
98 | - sprintf( |
|
99 | - esc_html__( |
|
100 | - 'EE_Register_CPT has been called and given a reference of "%s". It may or may not work because it should be called on or before "AHEE__EE_System__load_CPTs_and_session__complete" action hook.', |
|
101 | - 'event_espresso' |
|
102 | - ), |
|
103 | - $identifier |
|
104 | - ), |
|
105 | - '4.5.0' |
|
106 | - ); |
|
107 | - } |
|
108 | - // validate incoming args |
|
109 | - $validated = [ |
|
110 | - 'cpts' => isset($setup_args['cpts']) |
|
111 | - ? (array) $setup_args['cpts'] |
|
112 | - : [], |
|
113 | - 'cts' => isset($setup_args['cts']) |
|
114 | - ? (array) $setup_args['cts'] |
|
115 | - : [], |
|
116 | - 'default_terms' => isset($setup_args['default_terms']) |
|
117 | - ? (array) $setup_args['default_terms'] |
|
118 | - : [], |
|
119 | - ]; |
|
94 | + // make sure this was called in the right place! |
|
95 | + if (did_action('AHEE__EE_System__load_CPTs_and_session__complete')) { |
|
96 | + EE_Error::doing_it_wrong( |
|
97 | + __METHOD__, |
|
98 | + sprintf( |
|
99 | + esc_html__( |
|
100 | + 'EE_Register_CPT has been called and given a reference of "%s". It may or may not work because it should be called on or before "AHEE__EE_System__load_CPTs_and_session__complete" action hook.', |
|
101 | + 'event_espresso' |
|
102 | + ), |
|
103 | + $identifier |
|
104 | + ), |
|
105 | + '4.5.0' |
|
106 | + ); |
|
107 | + } |
|
108 | + // validate incoming args |
|
109 | + $validated = [ |
|
110 | + 'cpts' => isset($setup_args['cpts']) |
|
111 | + ? (array) $setup_args['cpts'] |
|
112 | + : [], |
|
113 | + 'cts' => isset($setup_args['cts']) |
|
114 | + ? (array) $setup_args['cts'] |
|
115 | + : [], |
|
116 | + 'default_terms' => isset($setup_args['default_terms']) |
|
117 | + ? (array) $setup_args['default_terms'] |
|
118 | + : [], |
|
119 | + ]; |
|
120 | 120 | |
121 | - self::$_registry[ $identifier ] = $validated; |
|
121 | + self::$_registry[ $identifier ] = $validated; |
|
122 | 122 | |
123 | - // hook into to cpt system |
|
124 | - add_filter( |
|
125 | - 'FHEE__EventEspresso_core_domain_entities_custom_post_types_CustomPostTypeDefinitions__getCustomPostTypes', |
|
126 | - [__CLASS__, 'filterCustomPostTypeDefinitions'], |
|
127 | - 5 |
|
128 | - ); |
|
129 | - add_filter( |
|
130 | - 'FHEE__EventEspresso_core_domain_entities_custom_post_types_TaxonomyDefinitions__getTaxonomies', |
|
131 | - [__CLASS__, 'filterCustomTaxonomyDefinitions'], |
|
132 | - 5 |
|
133 | - ); |
|
134 | - add_action( |
|
135 | - 'AHEE__EventEspresso_core_domain_services_custom_post_types_RegisterCustomTaxonomyTerms__construct_end', |
|
136 | - [__CLASS__, 'registerCustomTaxonomyTerm'], |
|
137 | - 5 |
|
138 | - ); |
|
139 | - } |
|
123 | + // hook into to cpt system |
|
124 | + add_filter( |
|
125 | + 'FHEE__EventEspresso_core_domain_entities_custom_post_types_CustomPostTypeDefinitions__getCustomPostTypes', |
|
126 | + [__CLASS__, 'filterCustomPostTypeDefinitions'], |
|
127 | + 5 |
|
128 | + ); |
|
129 | + add_filter( |
|
130 | + 'FHEE__EventEspresso_core_domain_entities_custom_post_types_TaxonomyDefinitions__getTaxonomies', |
|
131 | + [__CLASS__, 'filterCustomTaxonomyDefinitions'], |
|
132 | + 5 |
|
133 | + ); |
|
134 | + add_action( |
|
135 | + 'AHEE__EventEspresso_core_domain_services_custom_post_types_RegisterCustomTaxonomyTerms__construct_end', |
|
136 | + [__CLASS__, 'registerCustomTaxonomyTerm'], |
|
137 | + 5 |
|
138 | + ); |
|
139 | + } |
|
140 | 140 | |
141 | 141 | |
142 | - /** |
|
143 | - * Callback for |
|
144 | - * FHEE__EventEspresso_core_domain_entities_custom_post_types_CustomPostTypeDefinitions__getCustomPostTypes |
|
145 | - * that adds additional custom post types to be registered. |
|
146 | - * |
|
147 | - * @param array $custom_post_type_definitions array of cpts that are already set |
|
148 | - * @return array new array of cpts and their registration information |
|
149 | - */ |
|
150 | - public static function filterCustomPostTypeDefinitions(array $custom_post_type_definitions) |
|
151 | - { |
|
152 | - foreach (self::$_registry as $registries) { |
|
153 | - foreach ($registries['cpts'] as $cpt_name => $cpt_settings) { |
|
154 | - $custom_post_type_definitions[ $cpt_name ] = $cpt_settings; |
|
155 | - } |
|
156 | - } |
|
157 | - return $custom_post_type_definitions; |
|
158 | - } |
|
142 | + /** |
|
143 | + * Callback for |
|
144 | + * FHEE__EventEspresso_core_domain_entities_custom_post_types_CustomPostTypeDefinitions__getCustomPostTypes |
|
145 | + * that adds additional custom post types to be registered. |
|
146 | + * |
|
147 | + * @param array $custom_post_type_definitions array of cpts that are already set |
|
148 | + * @return array new array of cpts and their registration information |
|
149 | + */ |
|
150 | + public static function filterCustomPostTypeDefinitions(array $custom_post_type_definitions) |
|
151 | + { |
|
152 | + foreach (self::$_registry as $registries) { |
|
153 | + foreach ($registries['cpts'] as $cpt_name => $cpt_settings) { |
|
154 | + $custom_post_type_definitions[ $cpt_name ] = $cpt_settings; |
|
155 | + } |
|
156 | + } |
|
157 | + return $custom_post_type_definitions; |
|
158 | + } |
|
159 | 159 | |
160 | 160 | |
161 | - /** |
|
162 | - * Callback for |
|
163 | - * FHEE__EventEspresso_core_domain_entities_custom_post_types_TaxonomyDefinitions__getTaxonomies |
|
164 | - * that adds additional custom taxonomies to be registered. |
|
165 | - * |
|
166 | - * @param array $custom_taxonomy_definitions array of cts that are already set. |
|
167 | - * @return array new array of cts and their registration information. |
|
168 | - */ |
|
169 | - public static function filterCustomTaxonomyDefinitions(array $custom_taxonomy_definitions) |
|
170 | - { |
|
171 | - foreach (self::$_registry as $registries) { |
|
172 | - foreach ($registries['cts'] as $ct_name => $ct_settings) { |
|
173 | - $custom_taxonomy_definitions[ $ct_name ] = $ct_settings; |
|
174 | - } |
|
175 | - } |
|
176 | - return $custom_taxonomy_definitions; |
|
177 | - } |
|
161 | + /** |
|
162 | + * Callback for |
|
163 | + * FHEE__EventEspresso_core_domain_entities_custom_post_types_TaxonomyDefinitions__getTaxonomies |
|
164 | + * that adds additional custom taxonomies to be registered. |
|
165 | + * |
|
166 | + * @param array $custom_taxonomy_definitions array of cts that are already set. |
|
167 | + * @return array new array of cts and their registration information. |
|
168 | + */ |
|
169 | + public static function filterCustomTaxonomyDefinitions(array $custom_taxonomy_definitions) |
|
170 | + { |
|
171 | + foreach (self::$_registry as $registries) { |
|
172 | + foreach ($registries['cts'] as $ct_name => $ct_settings) { |
|
173 | + $custom_taxonomy_definitions[ $ct_name ] = $ct_settings; |
|
174 | + } |
|
175 | + } |
|
176 | + return $custom_taxonomy_definitions; |
|
177 | + } |
|
178 | 178 | |
179 | 179 | |
180 | - /** |
|
181 | - * Callback for |
|
182 | - * AHEE__EventEspresso_core_domain_services_custom_post_types_RegisterCustomTaxonomyTerms__construct_end |
|
183 | - * which is used to set the default terms |
|
184 | - * |
|
185 | - * @param RegisterCustomTaxonomyTerms $register_custom_taxonomy_terms |
|
186 | - * @return void |
|
187 | - */ |
|
188 | - public static function registerCustomTaxonomyTerm(RegisterCustomTaxonomyTerms $register_custom_taxonomy_terms) |
|
189 | - { |
|
190 | - foreach (self::$_registry as $registries) { |
|
191 | - foreach ($registries['default_terms'] as $taxonomy => $terms) { |
|
192 | - foreach ($terms as $term => $cpts) { |
|
193 | - $register_custom_taxonomy_terms->registerCustomTaxonomyTerm( |
|
194 | - $taxonomy, |
|
195 | - $term, |
|
196 | - $cpts |
|
197 | - ); |
|
198 | - } |
|
199 | - } |
|
200 | - } |
|
201 | - } |
|
180 | + /** |
|
181 | + * Callback for |
|
182 | + * AHEE__EventEspresso_core_domain_services_custom_post_types_RegisterCustomTaxonomyTerms__construct_end |
|
183 | + * which is used to set the default terms |
|
184 | + * |
|
185 | + * @param RegisterCustomTaxonomyTerms $register_custom_taxonomy_terms |
|
186 | + * @return void |
|
187 | + */ |
|
188 | + public static function registerCustomTaxonomyTerm(RegisterCustomTaxonomyTerms $register_custom_taxonomy_terms) |
|
189 | + { |
|
190 | + foreach (self::$_registry as $registries) { |
|
191 | + foreach ($registries['default_terms'] as $taxonomy => $terms) { |
|
192 | + foreach ($terms as $term => $cpts) { |
|
193 | + $register_custom_taxonomy_terms->registerCustomTaxonomyTerm( |
|
194 | + $taxonomy, |
|
195 | + $term, |
|
196 | + $cpts |
|
197 | + ); |
|
198 | + } |
|
199 | + } |
|
200 | + } |
|
201 | + } |
|
202 | 202 | |
203 | 203 | |
204 | - /** |
|
205 | - * @param array $cpts array of cpts that are already set |
|
206 | - * @return array new array of cpts and their registration information |
|
207 | - * @deprecated 4.9.62.p |
|
208 | - */ |
|
209 | - public static function filter_cpts(array $cpts) |
|
210 | - { |
|
211 | - foreach (self::$_registry as $registries) { |
|
212 | - foreach ($registries['cpts'] as $cpt_name => $cpt_settings) { |
|
213 | - $cpts[ $cpt_name ] = $cpt_settings; |
|
214 | - } |
|
215 | - } |
|
216 | - return $cpts; |
|
217 | - } |
|
204 | + /** |
|
205 | + * @param array $cpts array of cpts that are already set |
|
206 | + * @return array new array of cpts and their registration information |
|
207 | + * @deprecated 4.9.62.p |
|
208 | + */ |
|
209 | + public static function filter_cpts(array $cpts) |
|
210 | + { |
|
211 | + foreach (self::$_registry as $registries) { |
|
212 | + foreach ($registries['cpts'] as $cpt_name => $cpt_settings) { |
|
213 | + $cpts[ $cpt_name ] = $cpt_settings; |
|
214 | + } |
|
215 | + } |
|
216 | + return $cpts; |
|
217 | + } |
|
218 | 218 | |
219 | 219 | |
220 | - /** |
|
221 | - * @param array $cts array of cts that are already set. |
|
222 | - * @return array new array of cts and their registration information. |
|
223 | - * @deprecated 4.9.62.p |
|
224 | - */ |
|
225 | - public static function filter_cts(array $cts) |
|
226 | - { |
|
227 | - foreach (self::$_registry as $registries) { |
|
228 | - foreach ($registries['cts'] as $ct_name => $ct_settings) { |
|
229 | - $cts[ $ct_name ] = $ct_settings; |
|
230 | - } |
|
231 | - } |
|
232 | - return $cts; |
|
233 | - } |
|
220 | + /** |
|
221 | + * @param array $cts array of cts that are already set. |
|
222 | + * @return array new array of cts and their registration information. |
|
223 | + * @deprecated 4.9.62.p |
|
224 | + */ |
|
225 | + public static function filter_cts(array $cts) |
|
226 | + { |
|
227 | + foreach (self::$_registry as $registries) { |
|
228 | + foreach ($registries['cts'] as $ct_name => $ct_settings) { |
|
229 | + $cts[ $ct_name ] = $ct_settings; |
|
230 | + } |
|
231 | + } |
|
232 | + return $cts; |
|
233 | + } |
|
234 | 234 | |
235 | 235 | |
236 | - /** |
|
237 | - * @param EE_Register_CPTs $cpt_class |
|
238 | - * @return void |
|
239 | - * @deprecated 4.9.62.p |
|
240 | - */ |
|
241 | - public static function default_terms(EE_Register_CPTs $cpt_class) |
|
242 | - { |
|
243 | - foreach (self::$_registry as $registries) { |
|
244 | - foreach ($registries['default_terms'] as $taxonomy => $terms) { |
|
245 | - foreach ($terms as $term => $cpts) { |
|
246 | - $cpt_class->set_default_term($taxonomy, $term, $cpts); |
|
247 | - } |
|
248 | - } |
|
249 | - } |
|
250 | - } |
|
236 | + /** |
|
237 | + * @param EE_Register_CPTs $cpt_class |
|
238 | + * @return void |
|
239 | + * @deprecated 4.9.62.p |
|
240 | + */ |
|
241 | + public static function default_terms(EE_Register_CPTs $cpt_class) |
|
242 | + { |
|
243 | + foreach (self::$_registry as $registries) { |
|
244 | + foreach ($registries['default_terms'] as $taxonomy => $terms) { |
|
245 | + foreach ($terms as $term => $cpts) { |
|
246 | + $cpt_class->set_default_term($taxonomy, $term, $cpts); |
|
247 | + } |
|
248 | + } |
|
249 | + } |
|
250 | + } |
|
251 | 251 | |
252 | 252 | |
253 | - /** |
|
254 | - * This deregisters whats been registered on this class (for the given slug). |
|
255 | - * |
|
256 | - * @param string $identifier The reference for the item registered to be removed. |
|
257 | - * |
|
258 | - * @return void |
|
259 | - * @since 4.5.0 |
|
260 | - * |
|
261 | - */ |
|
262 | - public static function deregister($identifier = '') |
|
263 | - { |
|
264 | - unset(self::$_registry[ $identifier ]); |
|
265 | - } |
|
253 | + /** |
|
254 | + * This deregisters whats been registered on this class (for the given slug). |
|
255 | + * |
|
256 | + * @param string $identifier The reference for the item registered to be removed. |
|
257 | + * |
|
258 | + * @return void |
|
259 | + * @since 4.5.0 |
|
260 | + * |
|
261 | + */ |
|
262 | + public static function deregister($identifier = '') |
|
263 | + { |
|
264 | + unset(self::$_registry[ $identifier ]); |
|
265 | + } |
|
266 | 266 | } |
@@ -44,7 +44,7 @@ discard block |
||
44 | 44 | { |
45 | 45 | |
46 | 46 | // check that an admin_page has not already been registered with that name |
47 | - if (isset(self::$_ee_admin_page_registry[ $identifier ])) { |
|
47 | + if (isset(self::$_ee_admin_page_registry[$identifier])) { |
|
48 | 48 | throw new EE_Error( |
49 | 49 | sprintf( |
50 | 50 | esc_html__( |
@@ -67,11 +67,11 @@ discard block |
||
67 | 67 | } |
68 | 68 | |
69 | 69 | // make sure we don't register twice |
70 | - if (isset(self::$_ee_admin_page_registry[ $identifier ])) { |
|
70 | + if (isset(self::$_ee_admin_page_registry[$identifier])) { |
|
71 | 71 | return; |
72 | 72 | } |
73 | 73 | |
74 | - if (! did_action('AHEE__EE_System__load_espresso_addons') || did_action('AHEE__EE_Admin__loaded')) { |
|
74 | + if ( ! did_action('AHEE__EE_System__load_espresso_addons') || did_action('AHEE__EE_Admin__loaded')) { |
|
75 | 75 | EE_Error::doing_it_wrong( |
76 | 76 | __METHOD__, |
77 | 77 | sprintf( |
@@ -86,7 +86,7 @@ discard block |
||
86 | 86 | } |
87 | 87 | |
88 | 88 | // add incoming stuff to our registry property |
89 | - self::$_ee_admin_page_registry[ $identifier ] = [ |
|
89 | + self::$_ee_admin_page_registry[$identifier] = [ |
|
90 | 90 | 'page_path' => $setup_args['page_path'], |
91 | 91 | 'config' => $setup_args, |
92 | 92 | ]; |
@@ -113,7 +113,7 @@ discard block |
||
113 | 113 | */ |
114 | 114 | public static function deregister($identifier = '') |
115 | 115 | { |
116 | - unset(self::$_ee_admin_page_registry[ $identifier ]); |
|
116 | + unset(self::$_ee_admin_page_registry[$identifier]); |
|
117 | 117 | } |
118 | 118 | |
119 | 119 | |
@@ -125,9 +125,9 @@ discard block |
||
125 | 125 | */ |
126 | 126 | public static function set_page_basename($installed_refs) |
127 | 127 | { |
128 | - if (! empty(self::$_ee_admin_page_registry)) { |
|
128 | + if ( ! empty(self::$_ee_admin_page_registry)) { |
|
129 | 129 | foreach (self::$_ee_admin_page_registry as $basename => $args) { |
130 | - $installed_refs[ $basename ] = $args['page_path']; |
|
130 | + $installed_refs[$basename] = $args['page_path']; |
|
131 | 131 | } |
132 | 132 | } |
133 | 133 | return $installed_refs; |
@@ -143,7 +143,7 @@ discard block |
||
143 | 143 | public static function set_page_path($paths) |
144 | 144 | { |
145 | 145 | foreach (self::$_ee_admin_page_registry as $basename => $args) { |
146 | - $paths[ $basename ] = $args['page_path']; |
|
146 | + $paths[$basename] = $args['page_path']; |
|
147 | 147 | } |
148 | 148 | return $paths; |
149 | 149 | } |
@@ -10,139 +10,139 @@ |
||
10 | 10 | */ |
11 | 11 | class EE_Register_Admin_Page implements EEI_Plugin_API |
12 | 12 | { |
13 | - /** |
|
14 | - * Holds registered EE_Admin_Pages |
|
15 | - * |
|
16 | - * @var array |
|
17 | - */ |
|
18 | - protected static $_ee_admin_page_registry = []; |
|
19 | - |
|
20 | - |
|
21 | - /** |
|
22 | - * The purpose of this method is to provide an easy way for addons to register their admin pages (using the EE |
|
23 | - * Admin Page loader system). |
|
24 | - * |
|
25 | - * @param string $identifier This string represents the basename of the Admin |
|
26 | - * Page init. The init file must use this basename |
|
27 | - * in its name and class (i.e. |
|
28 | - * {page_basename}_Admin_Page_Init.core.php). |
|
29 | - * @param array $setup_args { An array of configuration options |
|
30 | - * that will be used in different circumstances |
|
31 | - * |
|
32 | - * @type string $page_path This is the path where the registered admin pages |
|
33 | - * reside ( used to setup autoloaders). |
|
34 | - * |
|
35 | - * } |
|
36 | - * @return void |
|
37 | - * @throws EE_Error |
|
38 | - * @since 4.3.0 |
|
39 | - * |
|
40 | - */ |
|
41 | - public static function register($identifier = '', array $setup_args = []) |
|
42 | - { |
|
43 | - |
|
44 | - // check that an admin_page has not already been registered with that name |
|
45 | - if (isset(self::$_ee_admin_page_registry[ $identifier ])) { |
|
46 | - throw new EE_Error( |
|
47 | - sprintf( |
|
48 | - esc_html__( |
|
49 | - 'An Admin Page with the name "%s" has already been registered and each Admin Page requires a unique name.', |
|
50 | - 'event_espresso' |
|
51 | - ), |
|
52 | - $identifier |
|
53 | - ) |
|
54 | - ); |
|
55 | - } |
|
56 | - |
|
57 | - // required fields MUST be present, so let's make sure they are. |
|
58 | - if (empty($identifier) || ! is_array($setup_args) || empty($setup_args['page_path'])) { |
|
59 | - throw new EE_Error( |
|
60 | - esc_html__( |
|
61 | - 'In order to register an Admin Page with EE_Register_Admin_Page::register(), you must include the "page_basename" (the class name of the page), and an array containing the following keys: "page_path" (the path where the registered admin pages reside)', |
|
62 | - 'event_espresso' |
|
63 | - ) |
|
64 | - ); |
|
65 | - } |
|
66 | - |
|
67 | - // make sure we don't register twice |
|
68 | - if (isset(self::$_ee_admin_page_registry[ $identifier ])) { |
|
69 | - return; |
|
70 | - } |
|
71 | - |
|
72 | - if (! did_action('AHEE__EE_System__load_espresso_addons') || did_action('AHEE__EE_Admin__loaded')) { |
|
73 | - EE_Error::doing_it_wrong( |
|
74 | - __METHOD__, |
|
75 | - sprintf( |
|
76 | - esc_html__( |
|
77 | - 'An attempt was made to register "%s" as an EE Admin page has failed because it was not registered at the correct time. Please use the "AHEE__EE_Admin__loaded" hook to register Admin pages.', |
|
78 | - 'event_espresso' |
|
79 | - ), |
|
80 | - $identifier |
|
81 | - ), |
|
82 | - '4.3' |
|
83 | - ); |
|
84 | - } |
|
85 | - |
|
86 | - // add incoming stuff to our registry property |
|
87 | - self::$_ee_admin_page_registry[ $identifier ] = [ |
|
88 | - 'page_path' => $setup_args['page_path'], |
|
89 | - 'config' => $setup_args, |
|
90 | - ]; |
|
91 | - |
|
92 | - // add filters |
|
93 | - |
|
94 | - add_filter( |
|
95 | - 'FHEE__EE_Admin_Page_Loader___get_installed_pages__installed_refs', |
|
96 | - ['EE_Register_Admin_Page', 'set_page_basename'], |
|
97 | - 10 |
|
98 | - ); |
|
99 | - add_filter('FHEE__EEH_Autoloader__load_admin_core', ['EE_Register_Admin_Page', 'set_page_path'], 10); |
|
100 | - } |
|
101 | - |
|
102 | - |
|
103 | - /** |
|
104 | - * This deregisters a EE_Admin page that is already registered. Note, this MUST be loaded after the |
|
105 | - * page being deregistered is loaded. |
|
106 | - * |
|
107 | - * @param string $identifier Use whatever string was used to register the admin page. |
|
108 | - * @return void |
|
109 | - * @since 4.3.0 |
|
110 | - * |
|
111 | - */ |
|
112 | - public static function deregister($identifier = '') |
|
113 | - { |
|
114 | - unset(self::$_ee_admin_page_registry[ $identifier ]); |
|
115 | - } |
|
116 | - |
|
117 | - |
|
118 | - /** |
|
119 | - * set_page_basename |
|
120 | - * |
|
121 | - * @param $installed_refs |
|
122 | - * @return mixed |
|
123 | - */ |
|
124 | - public static function set_page_basename($installed_refs) |
|
125 | - { |
|
126 | - if (! empty(self::$_ee_admin_page_registry)) { |
|
127 | - foreach (self::$_ee_admin_page_registry as $basename => $args) { |
|
128 | - $installed_refs[ $basename ] = $args['page_path']; |
|
129 | - } |
|
130 | - } |
|
131 | - return $installed_refs; |
|
132 | - } |
|
133 | - |
|
134 | - |
|
135 | - /** |
|
136 | - * set_page_path |
|
137 | - * |
|
138 | - * @param $paths |
|
139 | - * @return mixed |
|
140 | - */ |
|
141 | - public static function set_page_path($paths) |
|
142 | - { |
|
143 | - foreach (self::$_ee_admin_page_registry as $basename => $args) { |
|
144 | - $paths[ $basename ] = $args['page_path']; |
|
145 | - } |
|
146 | - return $paths; |
|
147 | - } |
|
13 | + /** |
|
14 | + * Holds registered EE_Admin_Pages |
|
15 | + * |
|
16 | + * @var array |
|
17 | + */ |
|
18 | + protected static $_ee_admin_page_registry = []; |
|
19 | + |
|
20 | + |
|
21 | + /** |
|
22 | + * The purpose of this method is to provide an easy way for addons to register their admin pages (using the EE |
|
23 | + * Admin Page loader system). |
|
24 | + * |
|
25 | + * @param string $identifier This string represents the basename of the Admin |
|
26 | + * Page init. The init file must use this basename |
|
27 | + * in its name and class (i.e. |
|
28 | + * {page_basename}_Admin_Page_Init.core.php). |
|
29 | + * @param array $setup_args { An array of configuration options |
|
30 | + * that will be used in different circumstances |
|
31 | + * |
|
32 | + * @type string $page_path This is the path where the registered admin pages |
|
33 | + * reside ( used to setup autoloaders). |
|
34 | + * |
|
35 | + * } |
|
36 | + * @return void |
|
37 | + * @throws EE_Error |
|
38 | + * @since 4.3.0 |
|
39 | + * |
|
40 | + */ |
|
41 | + public static function register($identifier = '', array $setup_args = []) |
|
42 | + { |
|
43 | + |
|
44 | + // check that an admin_page has not already been registered with that name |
|
45 | + if (isset(self::$_ee_admin_page_registry[ $identifier ])) { |
|
46 | + throw new EE_Error( |
|
47 | + sprintf( |
|
48 | + esc_html__( |
|
49 | + 'An Admin Page with the name "%s" has already been registered and each Admin Page requires a unique name.', |
|
50 | + 'event_espresso' |
|
51 | + ), |
|
52 | + $identifier |
|
53 | + ) |
|
54 | + ); |
|
55 | + } |
|
56 | + |
|
57 | + // required fields MUST be present, so let's make sure they are. |
|
58 | + if (empty($identifier) || ! is_array($setup_args) || empty($setup_args['page_path'])) { |
|
59 | + throw new EE_Error( |
|
60 | + esc_html__( |
|
61 | + 'In order to register an Admin Page with EE_Register_Admin_Page::register(), you must include the "page_basename" (the class name of the page), and an array containing the following keys: "page_path" (the path where the registered admin pages reside)', |
|
62 | + 'event_espresso' |
|
63 | + ) |
|
64 | + ); |
|
65 | + } |
|
66 | + |
|
67 | + // make sure we don't register twice |
|
68 | + if (isset(self::$_ee_admin_page_registry[ $identifier ])) { |
|
69 | + return; |
|
70 | + } |
|
71 | + |
|
72 | + if (! did_action('AHEE__EE_System__load_espresso_addons') || did_action('AHEE__EE_Admin__loaded')) { |
|
73 | + EE_Error::doing_it_wrong( |
|
74 | + __METHOD__, |
|
75 | + sprintf( |
|
76 | + esc_html__( |
|
77 | + 'An attempt was made to register "%s" as an EE Admin page has failed because it was not registered at the correct time. Please use the "AHEE__EE_Admin__loaded" hook to register Admin pages.', |
|
78 | + 'event_espresso' |
|
79 | + ), |
|
80 | + $identifier |
|
81 | + ), |
|
82 | + '4.3' |
|
83 | + ); |
|
84 | + } |
|
85 | + |
|
86 | + // add incoming stuff to our registry property |
|
87 | + self::$_ee_admin_page_registry[ $identifier ] = [ |
|
88 | + 'page_path' => $setup_args['page_path'], |
|
89 | + 'config' => $setup_args, |
|
90 | + ]; |
|
91 | + |
|
92 | + // add filters |
|
93 | + |
|
94 | + add_filter( |
|
95 | + 'FHEE__EE_Admin_Page_Loader___get_installed_pages__installed_refs', |
|
96 | + ['EE_Register_Admin_Page', 'set_page_basename'], |
|
97 | + 10 |
|
98 | + ); |
|
99 | + add_filter('FHEE__EEH_Autoloader__load_admin_core', ['EE_Register_Admin_Page', 'set_page_path'], 10); |
|
100 | + } |
|
101 | + |
|
102 | + |
|
103 | + /** |
|
104 | + * This deregisters a EE_Admin page that is already registered. Note, this MUST be loaded after the |
|
105 | + * page being deregistered is loaded. |
|
106 | + * |
|
107 | + * @param string $identifier Use whatever string was used to register the admin page. |
|
108 | + * @return void |
|
109 | + * @since 4.3.0 |
|
110 | + * |
|
111 | + */ |
|
112 | + public static function deregister($identifier = '') |
|
113 | + { |
|
114 | + unset(self::$_ee_admin_page_registry[ $identifier ]); |
|
115 | + } |
|
116 | + |
|
117 | + |
|
118 | + /** |
|
119 | + * set_page_basename |
|
120 | + * |
|
121 | + * @param $installed_refs |
|
122 | + * @return mixed |
|
123 | + */ |
|
124 | + public static function set_page_basename($installed_refs) |
|
125 | + { |
|
126 | + if (! empty(self::$_ee_admin_page_registry)) { |
|
127 | + foreach (self::$_ee_admin_page_registry as $basename => $args) { |
|
128 | + $installed_refs[ $basename ] = $args['page_path']; |
|
129 | + } |
|
130 | + } |
|
131 | + return $installed_refs; |
|
132 | + } |
|
133 | + |
|
134 | + |
|
135 | + /** |
|
136 | + * set_page_path |
|
137 | + * |
|
138 | + * @param $paths |
|
139 | + * @return mixed |
|
140 | + */ |
|
141 | + public static function set_page_path($paths) |
|
142 | + { |
|
143 | + foreach (self::$_ee_admin_page_registry as $basename => $args) { |
|
144 | + $paths[ $basename ] = $args['page_path']; |
|
145 | + } |
|
146 | + return $paths; |
|
147 | + } |
|
148 | 148 | } |
@@ -47,20 +47,20 @@ discard block |
||
47 | 47 | '[TKT_USES_*]' => esc_html__( |
48 | 48 | 'This attribute based shortcode parses to show the number of uses the ticket has. The optional "schema" attribute can be used to indicate what schema is used when the uses is infinite. Options are:', |
49 | 49 | 'event_espresso' |
50 | - ) . |
|
51 | - '<p><ul>' . |
|
52 | - '<li><strong>symbol</strong>:' . esc_html__( |
|
50 | + ). |
|
51 | + '<p><ul>'. |
|
52 | + '<li><strong>symbol</strong>:'.esc_html__( |
|
53 | 53 | 'This returns the ∞ symbol.', |
54 | 54 | 'event_espresso' |
55 | - ) . '</li>' . |
|
56 | - '<li><strong>text</strong>:' . esc_html__( |
|
55 | + ).'</li>'. |
|
56 | + '<li><strong>text</strong>:'.esc_html__( |
|
57 | 57 | 'This returns the word, "Unlimited". This is also the default if the "schema" attribute is not used.', |
58 | 58 | 'event_espresso' |
59 | - ) . '</li>' . |
|
60 | - '<li><strong>{custom}</strong>:' . esc_html__( |
|
59 | + ).'</li>'. |
|
60 | + '<li><strong>{custom}</strong>:'.esc_html__( |
|
61 | 61 | 'You can put anything you want as a string instead and that will be used. So you could have the world "any" and whenever uses for a ticket is infinity, this shortcode will parse to "any".', |
62 | 62 | 'event_espresso' |
63 | - ) . '</li>' . |
|
63 | + ).'</li>'. |
|
64 | 64 | '</ul></p>', |
65 | 65 | ); |
66 | 66 | } |
@@ -82,9 +82,9 @@ discard block |
||
82 | 82 | $this->_ticket = empty($this->_ticket) |
83 | 83 | && $this->_data instanceof EE_Line_Item |
84 | 84 | && $aee instanceof EE_Messages_Addressee |
85 | - && ! empty($aee->line_items_with_children[ $this->_data->ID() ]['EE_Ticket']) |
|
86 | - && $aee->line_items_with_children[ $this->_data->ID() ]['EE_Ticket'] instanceof EE_Ticket |
|
87 | - ? $aee->line_items_with_children[ $this->_data->ID() ]['EE_Ticket'] |
|
85 | + && ! empty($aee->line_items_with_children[$this->_data->ID()]['EE_Ticket']) |
|
86 | + && $aee->line_items_with_children[$this->_data->ID()]['EE_Ticket'] instanceof EE_Ticket |
|
87 | + ? $aee->line_items_with_children[$this->_data->ID()]['EE_Ticket'] |
|
88 | 88 | : $this->_ticket; |
89 | 89 | |
90 | 90 | // if still no ticket, then let's see if there is a reg_obj. If there IS, then we'll try and grab the ticket from the reg_obj instead. |
@@ -95,7 +95,7 @@ discard block |
||
95 | 95 | |
96 | 96 | |
97 | 97 | // If there is no event object by now then get out. |
98 | - if (! $this->_ticket instanceof EE_Ticket) { |
|
98 | + if ( ! $this->_ticket instanceof EE_Ticket) { |
|
99 | 99 | return ''; |
100 | 100 | } |
101 | 101 | |
@@ -121,7 +121,7 @@ discard block |
||
121 | 121 | break; |
122 | 122 | |
123 | 123 | case '[TKT_QTY_PURCHASED]': |
124 | - return $aee instanceof EE_Messages_Addressee ? $aee->tickets[ $this->_ticket->ID() ]['count'] : ''; |
|
124 | + return $aee instanceof EE_Messages_Addressee ? $aee->tickets[$this->_ticket->ID()]['count'] : ''; |
|
125 | 125 | break; |
126 | 126 | } |
127 | 127 |
@@ -17,123 +17,123 @@ |
||
17 | 17 | */ |
18 | 18 | class EE_Ticket_Shortcodes extends EE_Shortcodes |
19 | 19 | { |
20 | - /** |
|
21 | - * Will hold the EE_Ticket if available |
|
22 | - * |
|
23 | - * @var EE_Ticket |
|
24 | - */ |
|
25 | - protected $_ticket; |
|
26 | - |
|
27 | - |
|
28 | - protected function _init_props() |
|
29 | - { |
|
30 | - $this->label = esc_html__('Ticket Shortcodes', 'event_espresso'); |
|
31 | - $this->description = esc_html__('All shortcodes specific to ticket related data', 'event_espresso'); |
|
32 | - $this->_shortcodes = array( |
|
33 | - '[TICKET_ID]' => esc_html__('Will be replaced by the ticket ID of a ticket', 'event_espresso'), |
|
34 | - '[TICKET_NAME]' => esc_html__('The name of the ticket', 'event_espresso'), |
|
35 | - '[TICKET_DESCRIPTION]' => esc_html__('The description of the ticket', 'event_espresso'), |
|
36 | - '[TICKET_PRICE]' => esc_html__('The price of the ticket', 'event_espresso'), |
|
37 | - '[TICKET_PRICE_WITH_TAXES]' => esc_html__( |
|
38 | - 'The price of the ticket including any taxes that might be on the ticket', |
|
39 | - 'event_espresso' |
|
40 | - ), |
|
41 | - '[TKT_QTY_PURCHASED]' => esc_html__( |
|
42 | - 'The total quantity of the current ticket in the list that has been purchased in this transaction', |
|
43 | - 'event_espresso' |
|
44 | - ), |
|
45 | - '[TKT_USES_*]' => esc_html__( |
|
46 | - 'This attribute based shortcode parses to show the number of uses the ticket has. The optional "schema" attribute can be used to indicate what schema is used when the uses is infinite. Options are:', |
|
47 | - 'event_espresso' |
|
48 | - ) . |
|
49 | - '<p><ul>' . |
|
50 | - '<li><strong>symbol</strong>:' . esc_html__( |
|
51 | - 'This returns the ∞ symbol.', |
|
52 | - 'event_espresso' |
|
53 | - ) . '</li>' . |
|
54 | - '<li><strong>text</strong>:' . esc_html__( |
|
55 | - 'This returns the word, "Unlimited". This is also the default if the "schema" attribute is not used.', |
|
56 | - 'event_espresso' |
|
57 | - ) . '</li>' . |
|
58 | - '<li><strong>{custom}</strong>:' . esc_html__( |
|
59 | - 'You can put anything you want as a string instead and that will be used. So you could have the world "any" and whenever uses for a ticket is infinity, this shortcode will parse to "any".', |
|
60 | - 'event_espresso' |
|
61 | - ) . '</li>' . |
|
62 | - '</ul></p>', |
|
63 | - ); |
|
64 | - } |
|
65 | - |
|
66 | - |
|
67 | - protected function _parser($shortcode) |
|
68 | - { |
|
69 | - |
|
70 | - $this->_ticket = $this->_data instanceof EE_Ticket ? $this->_data : null; |
|
71 | - |
|
72 | - $aee = $this->_data instanceof EE_Messages_Addressee ? $this->_data : null; |
|
73 | - $aee = ! $aee instanceof EE_Messages_Addressee && is_array( |
|
74 | - $this->_extra_data |
|
75 | - ) && isset($this->_extra_data['data']) && $this->_extra_data['data'] instanceof EE_Messages_Addressee |
|
76 | - ? $this->_extra_data['data'] : $aee; |
|
77 | - |
|
78 | - |
|
79 | - // possible EE_Line_Item may be incoming data |
|
80 | - $this->_ticket = empty($this->_ticket) |
|
81 | - && $this->_data instanceof EE_Line_Item |
|
82 | - && $aee instanceof EE_Messages_Addressee |
|
83 | - && ! empty($aee->line_items_with_children[ $this->_data->ID() ]['EE_Ticket']) |
|
84 | - && $aee->line_items_with_children[ $this->_data->ID() ]['EE_Ticket'] instanceof EE_Ticket |
|
85 | - ? $aee->line_items_with_children[ $this->_data->ID() ]['EE_Ticket'] |
|
86 | - : $this->_ticket; |
|
87 | - |
|
88 | - // if still no ticket, then let's see if there is a reg_obj. If there IS, then we'll try and grab the ticket from the reg_obj instead. |
|
89 | - if (empty($this->_ticket)) { |
|
90 | - $this->_ticket = $aee instanceof EE_Messages_Addressee && $aee->reg_obj instanceof EE_Registration |
|
91 | - ? $aee->reg_obj->ticket() : null; |
|
92 | - } |
|
93 | - |
|
94 | - |
|
95 | - // If there is no event object by now then get out. |
|
96 | - if (! $this->_ticket instanceof EE_Ticket) { |
|
97 | - return ''; |
|
98 | - } |
|
99 | - |
|
100 | - switch ($shortcode) { |
|
101 | - case '[TICKET_ID]': |
|
102 | - return $this->_ticket->ID(); |
|
103 | - break; |
|
104 | - |
|
105 | - case '[TICKET_NAME]': |
|
106 | - return $this->_ticket->get('TKT_name'); |
|
107 | - break; |
|
108 | - |
|
109 | - case '[TICKET_DESCRIPTION]': |
|
110 | - return $this->_ticket->get('TKT_description'); |
|
111 | - break; |
|
112 | - |
|
113 | - case '[TICKET_PRICE]': |
|
114 | - return EEH_Template::format_currency($this->_ticket->get('TKT_price')); |
|
115 | - break; |
|
116 | - |
|
117 | - case '[TICKET_PRICE_WITH_TAXES]': |
|
118 | - return EEH_Template::format_currency($this->_ticket->get_ticket_total_with_taxes()); |
|
119 | - break; |
|
120 | - |
|
121 | - case '[TKT_QTY_PURCHASED]': |
|
122 | - return $aee instanceof EE_Messages_Addressee ? $aee->tickets[ $this->_ticket->ID() ]['count'] : ''; |
|
123 | - break; |
|
124 | - } |
|
125 | - |
|
126 | - if (strpos($shortcode, '[TKT_USES_*') !== false) { |
|
127 | - $attrs = $this->_get_shortcode_attrs($shortcode); |
|
128 | - $schema = empty($attrs['schema']) ? null : $attrs['schema']; |
|
129 | - return $this->_ticket->get_pretty('TKT_uses', $schema); |
|
130 | - } |
|
131 | - return ''; |
|
132 | - } |
|
133 | - |
|
134 | - |
|
135 | - public function get_ticket_set() |
|
136 | - { |
|
137 | - return $this->_ticket; |
|
138 | - } |
|
20 | + /** |
|
21 | + * Will hold the EE_Ticket if available |
|
22 | + * |
|
23 | + * @var EE_Ticket |
|
24 | + */ |
|
25 | + protected $_ticket; |
|
26 | + |
|
27 | + |
|
28 | + protected function _init_props() |
|
29 | + { |
|
30 | + $this->label = esc_html__('Ticket Shortcodes', 'event_espresso'); |
|
31 | + $this->description = esc_html__('All shortcodes specific to ticket related data', 'event_espresso'); |
|
32 | + $this->_shortcodes = array( |
|
33 | + '[TICKET_ID]' => esc_html__('Will be replaced by the ticket ID of a ticket', 'event_espresso'), |
|
34 | + '[TICKET_NAME]' => esc_html__('The name of the ticket', 'event_espresso'), |
|
35 | + '[TICKET_DESCRIPTION]' => esc_html__('The description of the ticket', 'event_espresso'), |
|
36 | + '[TICKET_PRICE]' => esc_html__('The price of the ticket', 'event_espresso'), |
|
37 | + '[TICKET_PRICE_WITH_TAXES]' => esc_html__( |
|
38 | + 'The price of the ticket including any taxes that might be on the ticket', |
|
39 | + 'event_espresso' |
|
40 | + ), |
|
41 | + '[TKT_QTY_PURCHASED]' => esc_html__( |
|
42 | + 'The total quantity of the current ticket in the list that has been purchased in this transaction', |
|
43 | + 'event_espresso' |
|
44 | + ), |
|
45 | + '[TKT_USES_*]' => esc_html__( |
|
46 | + 'This attribute based shortcode parses to show the number of uses the ticket has. The optional "schema" attribute can be used to indicate what schema is used when the uses is infinite. Options are:', |
|
47 | + 'event_espresso' |
|
48 | + ) . |
|
49 | + '<p><ul>' . |
|
50 | + '<li><strong>symbol</strong>:' . esc_html__( |
|
51 | + 'This returns the ∞ symbol.', |
|
52 | + 'event_espresso' |
|
53 | + ) . '</li>' . |
|
54 | + '<li><strong>text</strong>:' . esc_html__( |
|
55 | + 'This returns the word, "Unlimited". This is also the default if the "schema" attribute is not used.', |
|
56 | + 'event_espresso' |
|
57 | + ) . '</li>' . |
|
58 | + '<li><strong>{custom}</strong>:' . esc_html__( |
|
59 | + 'You can put anything you want as a string instead and that will be used. So you could have the world "any" and whenever uses for a ticket is infinity, this shortcode will parse to "any".', |
|
60 | + 'event_espresso' |
|
61 | + ) . '</li>' . |
|
62 | + '</ul></p>', |
|
63 | + ); |
|
64 | + } |
|
65 | + |
|
66 | + |
|
67 | + protected function _parser($shortcode) |
|
68 | + { |
|
69 | + |
|
70 | + $this->_ticket = $this->_data instanceof EE_Ticket ? $this->_data : null; |
|
71 | + |
|
72 | + $aee = $this->_data instanceof EE_Messages_Addressee ? $this->_data : null; |
|
73 | + $aee = ! $aee instanceof EE_Messages_Addressee && is_array( |
|
74 | + $this->_extra_data |
|
75 | + ) && isset($this->_extra_data['data']) && $this->_extra_data['data'] instanceof EE_Messages_Addressee |
|
76 | + ? $this->_extra_data['data'] : $aee; |
|
77 | + |
|
78 | + |
|
79 | + // possible EE_Line_Item may be incoming data |
|
80 | + $this->_ticket = empty($this->_ticket) |
|
81 | + && $this->_data instanceof EE_Line_Item |
|
82 | + && $aee instanceof EE_Messages_Addressee |
|
83 | + && ! empty($aee->line_items_with_children[ $this->_data->ID() ]['EE_Ticket']) |
|
84 | + && $aee->line_items_with_children[ $this->_data->ID() ]['EE_Ticket'] instanceof EE_Ticket |
|
85 | + ? $aee->line_items_with_children[ $this->_data->ID() ]['EE_Ticket'] |
|
86 | + : $this->_ticket; |
|
87 | + |
|
88 | + // if still no ticket, then let's see if there is a reg_obj. If there IS, then we'll try and grab the ticket from the reg_obj instead. |
|
89 | + if (empty($this->_ticket)) { |
|
90 | + $this->_ticket = $aee instanceof EE_Messages_Addressee && $aee->reg_obj instanceof EE_Registration |
|
91 | + ? $aee->reg_obj->ticket() : null; |
|
92 | + } |
|
93 | + |
|
94 | + |
|
95 | + // If there is no event object by now then get out. |
|
96 | + if (! $this->_ticket instanceof EE_Ticket) { |
|
97 | + return ''; |
|
98 | + } |
|
99 | + |
|
100 | + switch ($shortcode) { |
|
101 | + case '[TICKET_ID]': |
|
102 | + return $this->_ticket->ID(); |
|
103 | + break; |
|
104 | + |
|
105 | + case '[TICKET_NAME]': |
|
106 | + return $this->_ticket->get('TKT_name'); |
|
107 | + break; |
|
108 | + |
|
109 | + case '[TICKET_DESCRIPTION]': |
|
110 | + return $this->_ticket->get('TKT_description'); |
|
111 | + break; |
|
112 | + |
|
113 | + case '[TICKET_PRICE]': |
|
114 | + return EEH_Template::format_currency($this->_ticket->get('TKT_price')); |
|
115 | + break; |
|
116 | + |
|
117 | + case '[TICKET_PRICE_WITH_TAXES]': |
|
118 | + return EEH_Template::format_currency($this->_ticket->get_ticket_total_with_taxes()); |
|
119 | + break; |
|
120 | + |
|
121 | + case '[TKT_QTY_PURCHASED]': |
|
122 | + return $aee instanceof EE_Messages_Addressee ? $aee->tickets[ $this->_ticket->ID() ]['count'] : ''; |
|
123 | + break; |
|
124 | + } |
|
125 | + |
|
126 | + if (strpos($shortcode, '[TKT_USES_*') !== false) { |
|
127 | + $attrs = $this->_get_shortcode_attrs($shortcode); |
|
128 | + $schema = empty($attrs['schema']) ? null : $attrs['schema']; |
|
129 | + return $this->_ticket->get_pretty('TKT_uses', $schema); |
|
130 | + } |
|
131 | + return ''; |
|
132 | + } |
|
133 | + |
|
134 | + |
|
135 | + public function get_ticket_set() |
|
136 | + { |
|
137 | + return $this->_ticket; |
|
138 | + } |
|
139 | 139 | } |
@@ -29,15 +29,15 @@ discard block |
||
29 | 29 | 'Outputs a list of payment items. Note, this is a dynamic shortcode in that it accepts some attributes for setting certain defaults. Attributes that are available are:', |
30 | 30 | 'event_espresso' |
31 | 31 | ) |
32 | - . '<p><ul>' . |
|
33 | - '<li><strong>no_payments</strong>:' . sprintf( |
|
32 | + . '<p><ul>'. |
|
33 | + '<li><strong>no_payments</strong>:'.sprintf( |
|
34 | 34 | esc_html__( |
35 | 35 | 'Indicate with this attribute what will be used if there are no payments present. Default is: "%sNo approved payments have been received.%s"', |
36 | 36 | 'event_espresso' |
37 | 37 | ), |
38 | 38 | htmlspecialchars('<td class="aln-cntr" colspan="6">'), |
39 | 39 | htmlspecialchars('</td>') |
40 | - ) . '</li>' . |
|
40 | + ).'</li>'. |
|
41 | 41 | '</ul></p>', |
42 | 42 | ); |
43 | 43 | } |
@@ -67,7 +67,7 @@ discard block |
||
67 | 67 | $this->_validate_list_requirements(); |
68 | 68 | |
69 | 69 | |
70 | - if (! $this->_data['data'] instanceof EE_Messages_Addressee) { |
|
70 | + if ( ! $this->_data['data'] instanceof EE_Messages_Addressee) { |
|
71 | 71 | return ''; |
72 | 72 | } |
73 | 73 |
@@ -18,88 +18,88 @@ |
||
18 | 18 | */ |
19 | 19 | class EE_Payment_List_Shortcodes extends EE_Shortcodes |
20 | 20 | { |
21 | - protected function _init_props() |
|
22 | - { |
|
23 | - $this->label = esc_html__('Payment List Shortcodes', 'event_espresso'); |
|
24 | - $this->description = esc_html__('All shortcodes specific to payment lists', 'event_espresso'); |
|
25 | - $this->_shortcodes = array( |
|
26 | - '[PAYMENT_LIST_*]' => esc_html__( |
|
27 | - 'Outputs a list of payment items. Note, this is a dynamic shortcode in that it accepts some attributes for setting certain defaults. Attributes that are available are:', |
|
28 | - 'event_espresso' |
|
29 | - ) |
|
30 | - . '<p><ul>' . |
|
31 | - '<li><strong>no_payments</strong>:' . sprintf( |
|
32 | - esc_html__( |
|
33 | - 'Indicate with this attribute what will be used if there are no payments present. Default is: "%sNo approved payments have been received.%s"', |
|
34 | - 'event_espresso' |
|
35 | - ), |
|
36 | - htmlspecialchars('<td class="aln-cntr" colspan="6">'), |
|
37 | - htmlspecialchars('</td>') |
|
38 | - ) . '</li>' . |
|
39 | - '</ul></p>', |
|
40 | - ); |
|
41 | - } |
|
42 | - |
|
43 | - |
|
44 | - protected function _parser($shortcode) |
|
45 | - { |
|
46 | - |
|
47 | - if (strpos($shortcode, '[PAYMENT_LIST_*') !== false) { |
|
48 | - return $this->_get_payment_list($shortcode); |
|
49 | - } |
|
50 | - return ''; |
|
51 | - } |
|
52 | - |
|
53 | - |
|
54 | - /** |
|
55 | - * verify incoming data contains what is needed for retrieving and parsing each payment for transaction. |
|
56 | - * |
|
57 | - * @since 4.5.0 |
|
58 | - * |
|
59 | - * @param string $shortcode The incoming shortcode. |
|
60 | - * |
|
61 | - * @return string parsed ticket line item list. |
|
62 | - */ |
|
63 | - private function _get_payment_list($shortcode) |
|
64 | - { |
|
65 | - $this->_validate_list_requirements(); |
|
66 | - |
|
67 | - |
|
68 | - if (! $this->_data['data'] instanceof EE_Messages_Addressee) { |
|
69 | - return ''; |
|
70 | - } |
|
71 | - |
|
72 | - $valid_shortcodes = array('payment'); |
|
73 | - |
|
74 | - $addressee_obj = $this->_data['data']; |
|
75 | - $templates = $this->_extra_data['template']; |
|
76 | - $payments = apply_filters( |
|
77 | - 'FHEE__Payment_List_Shortcodes___get_payments_list__payments', |
|
78 | - $addressee_obj->payments |
|
79 | - ); |
|
80 | - |
|
81 | - // let's get any attributes that may be present and set the defaults. |
|
82 | - $atts = $this->_get_shortcode_attrs($shortcode); |
|
83 | - |
|
84 | - $no_payments_msg = empty($atts['no_payments']) ? esc_html__( |
|
85 | - 'No approved payments have been received.', |
|
86 | - 'event_espresso' |
|
87 | - ) : $atts['no_payments']; |
|
88 | - |
|
89 | - // made it here so we have an array of paymnets, so we should have what we need. |
|
90 | - $payment_content = empty($payments) ? $no_payments_msg : ''; |
|
91 | - |
|
92 | - $payments = (array) $payments; |
|
93 | - |
|
94 | - foreach ($payments as $payment) { |
|
95 | - $payment_content .= $this->_shortcode_helper->parse_payment_list_template( |
|
96 | - $templates['payment_list'], |
|
97 | - $payment, |
|
98 | - $valid_shortcodes, |
|
99 | - $this->_extra_data |
|
100 | - ); |
|
101 | - } |
|
102 | - |
|
103 | - return $payment_content; |
|
104 | - } |
|
21 | + protected function _init_props() |
|
22 | + { |
|
23 | + $this->label = esc_html__('Payment List Shortcodes', 'event_espresso'); |
|
24 | + $this->description = esc_html__('All shortcodes specific to payment lists', 'event_espresso'); |
|
25 | + $this->_shortcodes = array( |
|
26 | + '[PAYMENT_LIST_*]' => esc_html__( |
|
27 | + 'Outputs a list of payment items. Note, this is a dynamic shortcode in that it accepts some attributes for setting certain defaults. Attributes that are available are:', |
|
28 | + 'event_espresso' |
|
29 | + ) |
|
30 | + . '<p><ul>' . |
|
31 | + '<li><strong>no_payments</strong>:' . sprintf( |
|
32 | + esc_html__( |
|
33 | + 'Indicate with this attribute what will be used if there are no payments present. Default is: "%sNo approved payments have been received.%s"', |
|
34 | + 'event_espresso' |
|
35 | + ), |
|
36 | + htmlspecialchars('<td class="aln-cntr" colspan="6">'), |
|
37 | + htmlspecialchars('</td>') |
|
38 | + ) . '</li>' . |
|
39 | + '</ul></p>', |
|
40 | + ); |
|
41 | + } |
|
42 | + |
|
43 | + |
|
44 | + protected function _parser($shortcode) |
|
45 | + { |
|
46 | + |
|
47 | + if (strpos($shortcode, '[PAYMENT_LIST_*') !== false) { |
|
48 | + return $this->_get_payment_list($shortcode); |
|
49 | + } |
|
50 | + return ''; |
|
51 | + } |
|
52 | + |
|
53 | + |
|
54 | + /** |
|
55 | + * verify incoming data contains what is needed for retrieving and parsing each payment for transaction. |
|
56 | + * |
|
57 | + * @since 4.5.0 |
|
58 | + * |
|
59 | + * @param string $shortcode The incoming shortcode. |
|
60 | + * |
|
61 | + * @return string parsed ticket line item list. |
|
62 | + */ |
|
63 | + private function _get_payment_list($shortcode) |
|
64 | + { |
|
65 | + $this->_validate_list_requirements(); |
|
66 | + |
|
67 | + |
|
68 | + if (! $this->_data['data'] instanceof EE_Messages_Addressee) { |
|
69 | + return ''; |
|
70 | + } |
|
71 | + |
|
72 | + $valid_shortcodes = array('payment'); |
|
73 | + |
|
74 | + $addressee_obj = $this->_data['data']; |
|
75 | + $templates = $this->_extra_data['template']; |
|
76 | + $payments = apply_filters( |
|
77 | + 'FHEE__Payment_List_Shortcodes___get_payments_list__payments', |
|
78 | + $addressee_obj->payments |
|
79 | + ); |
|
80 | + |
|
81 | + // let's get any attributes that may be present and set the defaults. |
|
82 | + $atts = $this->_get_shortcode_attrs($shortcode); |
|
83 | + |
|
84 | + $no_payments_msg = empty($atts['no_payments']) ? esc_html__( |
|
85 | + 'No approved payments have been received.', |
|
86 | + 'event_espresso' |
|
87 | + ) : $atts['no_payments']; |
|
88 | + |
|
89 | + // made it here so we have an array of paymnets, so we should have what we need. |
|
90 | + $payment_content = empty($payments) ? $no_payments_msg : ''; |
|
91 | + |
|
92 | + $payments = (array) $payments; |
|
93 | + |
|
94 | + foreach ($payments as $payment) { |
|
95 | + $payment_content .= $this->_shortcode_helper->parse_payment_list_template( |
|
96 | + $templates['payment_list'], |
|
97 | + $payment, |
|
98 | + $valid_shortcodes, |
|
99 | + $this->_extra_data |
|
100 | + ); |
|
101 | + } |
|
102 | + |
|
103 | + return $payment_content; |
|
104 | + } |
|
105 | 105 | } |
@@ -118,7 +118,7 @@ discard block |
||
118 | 118 | $this->_gateway->set_unsupported_character_remover(new AsciiOnly()); |
119 | 119 | do_action('AHEE__EE_PMT_Base___construct__done_initializing_gateway_class', $this, $this->_gateway); |
120 | 120 | } |
121 | - if (! isset($this->_has_billing_form)) { |
|
121 | + if ( ! isset($this->_has_billing_form)) { |
|
122 | 122 | // by default, On Site gateways have a billing form |
123 | 123 | if ($this->payment_occurs() == EE_PMT_Base::onsite) { |
124 | 124 | $this->set_has_billing_form(true); |
@@ -127,7 +127,7 @@ discard block |
||
127 | 127 | } |
128 | 128 | } |
129 | 129 | |
130 | - if (! $this->_pretty_name) { |
|
130 | + if ( ! $this->_pretty_name) { |
|
131 | 131 | throw new EE_Error( |
132 | 132 | sprintf( |
133 | 133 | esc_html__( |
@@ -139,7 +139,7 @@ discard block |
||
139 | 139 | } |
140 | 140 | // if the child didn't specify a default button, use the credit card one |
141 | 141 | if ($this->_default_button_url === null) { |
142 | - $this->_default_button_url = EE_PLUGIN_DIR_URL . 'payment_methods/pay-by-credit-card.png'; |
|
142 | + $this->_default_button_url = EE_PLUGIN_DIR_URL.'payment_methods/pay-by-credit-card.png'; |
|
143 | 143 | } |
144 | 144 | } |
145 | 145 | |
@@ -160,7 +160,7 @@ discard block |
||
160 | 160 | { |
161 | 161 | $reflector = new ReflectionClass(get_class($this)); |
162 | 162 | $fn = $reflector->getFileName(); |
163 | - $this->_file_folder = dirname($fn) . '/'; |
|
163 | + $this->_file_folder = dirname($fn).'/'; |
|
164 | 164 | } |
165 | 165 | |
166 | 166 | |
@@ -193,7 +193,7 @@ discard block |
||
193 | 193 | */ |
194 | 194 | public function file_folder() |
195 | 195 | { |
196 | - if (! $this->_file_folder) { |
|
196 | + if ( ! $this->_file_folder) { |
|
197 | 197 | $this->_set_file_folder(); |
198 | 198 | } |
199 | 199 | return $this->_file_folder; |
@@ -205,7 +205,7 @@ discard block |
||
205 | 205 | */ |
206 | 206 | public function file_url() |
207 | 207 | { |
208 | - if (! $this->_file_url) { |
|
208 | + if ( ! $this->_file_url) { |
|
209 | 209 | $this->_set_file_url(); |
210 | 210 | } |
211 | 211 | return $this->_file_url; |
@@ -239,7 +239,7 @@ discard block |
||
239 | 239 | */ |
240 | 240 | public function settings_form() |
241 | 241 | { |
242 | - if (! $this->_settings_form) { |
|
242 | + if ( ! $this->_settings_form) { |
|
243 | 243 | $this->_settings_form = $this->generate_new_settings_form(); |
244 | 244 | $this->_settings_form->set_payment_method_type($this); |
245 | 245 | // if we have already assigned a model object to this pmt, make |
@@ -293,7 +293,7 @@ discard block |
||
293 | 293 | public function billing_form(EE_Transaction $transaction = null, $extra_args = array()) |
294 | 294 | { |
295 | 295 | // has billing form already been regenerated ? or overwrite cache? |
296 | - if (! $this->_billing_form instanceof EE_Billing_Info_Form || ! $this->_cache_billing_form) { |
|
296 | + if ( ! $this->_billing_form instanceof EE_Billing_Info_Form || ! $this->_cache_billing_form) { |
|
297 | 297 | $this->_billing_form = $this->generate_new_billing_form($transaction, $extra_args); |
298 | 298 | } |
299 | 299 | // if we know who the attendee is, and this is a billing form |
@@ -397,7 +397,7 @@ discard block |
||
397 | 397 | $payment = EEM_Payment::instance()->get_one(array($duplicate_properties)); |
398 | 398 | // if we didn't already have a payment in progress for the same thing, |
399 | 399 | // then we actually want to make a new payment |
400 | - if (! $payment instanceof EE_Payment) { |
|
400 | + if ( ! $payment instanceof EE_Payment) { |
|
401 | 401 | $payment = EE_Payment::new_instance( |
402 | 402 | array_merge( |
403 | 403 | $duplicate_properties, |
@@ -498,7 +498,7 @@ discard block |
||
498 | 498 | public function handle_ipn($req_data, $transaction) |
499 | 499 | { |
500 | 500 | $transaction = EEM_Transaction::instance()->ensure_is_obj($transaction); |
501 | - if (! $this->_gateway instanceof EE_Offsite_Gateway) { |
|
501 | + if ( ! $this->_gateway instanceof EE_Offsite_Gateway) { |
|
502 | 502 | throw new EE_Error( |
503 | 503 | sprintf( |
504 | 504 | esc_html__("Could not handle IPN because '%s' is not an offsite gateway", "event_espresso"), |
@@ -521,7 +521,7 @@ discard block |
||
521 | 521 | */ |
522 | 522 | protected function _save_billing_info_to_attendee($billing_form, $transaction) |
523 | 523 | { |
524 | - if (! $transaction || ! $transaction instanceof EE_Transaction) { |
|
524 | + if ( ! $transaction || ! $transaction instanceof EE_Transaction) { |
|
525 | 525 | EE_Error::add_error( |
526 | 526 | esc_html__("Cannot save billing info because no transaction was specified", "event_espresso"), |
527 | 527 | __FILE__, |
@@ -531,7 +531,7 @@ discard block |
||
531 | 531 | return false; |
532 | 532 | } |
533 | 533 | $primary_reg = $transaction->primary_registration(); |
534 | - if (! $primary_reg) { |
|
534 | + if ( ! $primary_reg) { |
|
535 | 535 | EE_Error::add_error( |
536 | 536 | esc_html__("Cannot save billing info because the transaction has no primary registration", "event_espresso"), |
537 | 537 | __FILE__, |
@@ -541,7 +541,7 @@ discard block |
||
541 | 541 | return false; |
542 | 542 | } |
543 | 543 | $attendee = $primary_reg->attendee(); |
544 | - if (! $attendee) { |
|
544 | + if ( ! $attendee) { |
|
545 | 545 | EE_Error::add_error( |
546 | 546 | esc_html__( |
547 | 547 | "Cannot save billing info because the transaction's primary registration has no attendee!", |
@@ -654,7 +654,7 @@ discard block |
||
654 | 654 | */ |
655 | 655 | public function payment_occurs() |
656 | 656 | { |
657 | - if (! $this->_gateway) { |
|
657 | + if ( ! $this->_gateway) { |
|
658 | 658 | return EE_PMT_Base::offline; |
659 | 659 | } elseif ($this->_gateway instanceof EE_Onsite_Gateway) { |
660 | 660 | return EE_PMT_Base::onsite; |
@@ -685,7 +685,7 @@ discard block |
||
685 | 685 | public function payment_overview_content(EE_Payment $payment) |
686 | 686 | { |
687 | 687 | return EEH_Template::display_template( |
688 | - EE_LIBRARIES . 'payment_methods/templates/payment_details_content.template.php', |
|
688 | + EE_LIBRARIES.'payment_methods/templates/payment_details_content.template.php', |
|
689 | 689 | array('payment_method' => $this->_pm_instance, 'payment' => $payment), |
690 | 690 | true |
691 | 691 | ); |
@@ -783,7 +783,7 @@ discard block |
||
783 | 783 | */ |
784 | 784 | public function get_help_tab_name() |
785 | 785 | { |
786 | - return 'ee_' . strtolower($this->system_name()) . '_help_tab'; |
|
786 | + return 'ee_'.strtolower($this->system_name()).'_help_tab'; |
|
787 | 787 | } |
788 | 788 | |
789 | 789 | /** |
@@ -794,7 +794,7 @@ discard block |
||
794 | 794 | */ |
795 | 795 | public function cap_name() |
796 | 796 | { |
797 | - return 'ee_payment_method_' . strtolower($this->system_name()); |
|
797 | + return 'ee_payment_method_'.strtolower($this->system_name()); |
|
798 | 798 | } |
799 | 799 | |
800 | 800 | /** |
@@ -828,7 +828,7 @@ discard block |
||
828 | 828 | public function introductory_html() |
829 | 829 | { |
830 | 830 | return EEH_Template::locate_template( |
831 | - $this->file_folder() . 'templates/' . strtolower($this->system_name()) . '_intro.template.php', |
|
831 | + $this->file_folder().'templates/'.strtolower($this->system_name()).'_intro.template.php', |
|
832 | 832 | array('pmt_obj' => $this, 'pm_instance' => $this->_pm_instance) |
833 | 833 | ); |
834 | 834 | } |
@@ -21,814 +21,814 @@ |
||
21 | 21 | */ |
22 | 22 | abstract class EE_PMT_Base |
23 | 23 | { |
24 | - const onsite = 'on-site'; |
|
25 | - const offsite = 'off-site'; |
|
26 | - const offline = 'off-line'; |
|
27 | - |
|
28 | - /** |
|
29 | - * @var EE_Payment_Method |
|
30 | - */ |
|
31 | - protected $_pm_instance = null; |
|
32 | - |
|
33 | - /** |
|
34 | - * @var boolean |
|
35 | - */ |
|
36 | - protected $_requires_https = false; |
|
37 | - |
|
38 | - /** |
|
39 | - * @var boolean |
|
40 | - */ |
|
41 | - protected $_has_billing_form; |
|
42 | - |
|
43 | - /** |
|
44 | - * @var EE_Gateway |
|
45 | - */ |
|
46 | - protected $_gateway = null; |
|
47 | - |
|
48 | - /** |
|
49 | - * @var EE_Payment_Method_Form |
|
50 | - */ |
|
51 | - protected $_settings_form = null; |
|
52 | - |
|
53 | - /** |
|
54 | - * @var EE_Form_Section_Proper |
|
55 | - */ |
|
56 | - protected $_billing_form = null; |
|
57 | - |
|
58 | - /** |
|
59 | - * @var boolean |
|
60 | - */ |
|
61 | - protected $_cache_billing_form = true; |
|
62 | - |
|
63 | - /** |
|
64 | - * String of the absolute path to the folder containing this file, with a trailing slash. |
|
65 | - * eg '/public_html/wp-site/wp-content/plugins/event-espresso/payment_methods/Invoice/' |
|
66 | - * |
|
67 | - * @var string |
|
68 | - */ |
|
69 | - protected $_file_folder = null; |
|
70 | - |
|
71 | - /** |
|
72 | - * String to the absolute URL to this file (useful for getting its web-accessible resources |
|
73 | - * like images, js, or css) |
|
74 | - * |
|
75 | - * @var string |
|
76 | - */ |
|
77 | - protected $_file_url = null; |
|
78 | - |
|
79 | - /** |
|
80 | - * Pretty name for the payment method |
|
81 | - * |
|
82 | - * @var string |
|
83 | - */ |
|
84 | - protected $_pretty_name = null; |
|
85 | - |
|
86 | - /** |
|
87 | - * |
|
88 | - * @var string |
|
89 | - */ |
|
90 | - protected $_default_button_url = null; |
|
91 | - |
|
92 | - /** |
|
93 | - * |
|
94 | - * @var string |
|
95 | - */ |
|
96 | - protected $_default_description = null; |
|
97 | - |
|
98 | - |
|
99 | - /** |
|
100 | - * |
|
101 | - * @param EE_Payment_Method $pm_instance |
|
102 | - * @throws EE_Error |
|
103 | - * @return EE_PMT_Base |
|
104 | - */ |
|
105 | - public function __construct($pm_instance = null) |
|
106 | - { |
|
107 | - if ($pm_instance instanceof EE_Payment_Method) { |
|
108 | - $this->set_instance($pm_instance); |
|
109 | - } |
|
110 | - if ($this->_gateway) { |
|
111 | - $this->_gateway->set_payment_model(EEM_Payment::instance()); |
|
112 | - $this->_gateway->set_payment_log(EEM_Change_Log::instance()); |
|
113 | - $this->_gateway->set_template_helper(new EEH_Template()); |
|
114 | - $this->_gateway->set_line_item_helper(new EEH_Line_Item()); |
|
115 | - $this->_gateway->set_money_helper(new EEH_Money()); |
|
116 | - $this->_gateway->set_gateway_data_formatter(new GatewayDataFormatter()); |
|
117 | - $this->_gateway->set_unsupported_character_remover(new AsciiOnly()); |
|
118 | - do_action('AHEE__EE_PMT_Base___construct__done_initializing_gateway_class', $this, $this->_gateway); |
|
119 | - } |
|
120 | - if (! isset($this->_has_billing_form)) { |
|
121 | - // by default, On Site gateways have a billing form |
|
122 | - if ($this->payment_occurs() == EE_PMT_Base::onsite) { |
|
123 | - $this->set_has_billing_form(true); |
|
124 | - } else { |
|
125 | - $this->set_has_billing_form(false); |
|
126 | - } |
|
127 | - } |
|
128 | - |
|
129 | - if (! $this->_pretty_name) { |
|
130 | - throw new EE_Error( |
|
131 | - sprintf( |
|
132 | - esc_html__( |
|
133 | - "You must set the pretty name for the Payment Method Type in the constructor (_pretty_name), and please make it internationalized", |
|
134 | - "event_espresso" |
|
135 | - ) |
|
136 | - ) |
|
137 | - ); |
|
138 | - } |
|
139 | - // if the child didn't specify a default button, use the credit card one |
|
140 | - if ($this->_default_button_url === null) { |
|
141 | - $this->_default_button_url = EE_PLUGIN_DIR_URL . 'payment_methods/pay-by-credit-card.png'; |
|
142 | - } |
|
143 | - } |
|
144 | - |
|
145 | - |
|
146 | - /** |
|
147 | - * @param boolean $has_billing_form |
|
148 | - */ |
|
149 | - public function set_has_billing_form($has_billing_form) |
|
150 | - { |
|
151 | - $this->_has_billing_form = filter_var($has_billing_form, FILTER_VALIDATE_BOOLEAN); |
|
152 | - } |
|
153 | - |
|
154 | - |
|
155 | - /** |
|
156 | - * sets the file_folder property |
|
157 | - */ |
|
158 | - protected function _set_file_folder() |
|
159 | - { |
|
160 | - $reflector = new ReflectionClass(get_class($this)); |
|
161 | - $fn = $reflector->getFileName(); |
|
162 | - $this->_file_folder = dirname($fn) . '/'; |
|
163 | - } |
|
164 | - |
|
165 | - |
|
166 | - /** |
|
167 | - * sets the file URL with a trailing slash for this PMT |
|
168 | - */ |
|
169 | - protected function _set_file_url() |
|
170 | - { |
|
171 | - $plugins_dir_fixed = str_replace('\\', '/', WP_PLUGIN_DIR); |
|
172 | - $file_folder_fixed = str_replace('\\', '/', $this->file_folder()); |
|
173 | - $file_path = str_replace($plugins_dir_fixed, WP_PLUGIN_URL, $file_folder_fixed); |
|
174 | - $this->_file_url = set_url_scheme($file_path); |
|
175 | - } |
|
176 | - |
|
177 | - /** |
|
178 | - * Gets the default description on all payment methods of this type |
|
179 | - * |
|
180 | - * @return string |
|
181 | - */ |
|
182 | - public function default_description() |
|
183 | - { |
|
184 | - return $this->_default_description; |
|
185 | - } |
|
186 | - |
|
187 | - |
|
188 | - /** |
|
189 | - * Returns the folder containing the PMT child class, with a trailing slash |
|
190 | - * |
|
191 | - * @return string |
|
192 | - */ |
|
193 | - public function file_folder() |
|
194 | - { |
|
195 | - if (! $this->_file_folder) { |
|
196 | - $this->_set_file_folder(); |
|
197 | - } |
|
198 | - return $this->_file_folder; |
|
199 | - } |
|
200 | - |
|
201 | - |
|
202 | - /** |
|
203 | - * @return string |
|
204 | - */ |
|
205 | - public function file_url() |
|
206 | - { |
|
207 | - if (! $this->_file_url) { |
|
208 | - $this->_set_file_url(); |
|
209 | - } |
|
210 | - return $this->_file_url; |
|
211 | - } |
|
212 | - |
|
213 | - |
|
214 | - /** |
|
215 | - * Sets the payment method instance this payment method type is for. |
|
216 | - * Its important teh payment method instance is set before |
|
217 | - * |
|
218 | - * @param EE_Payment_Method $payment_method_instance |
|
219 | - */ |
|
220 | - public function set_instance($payment_method_instance) |
|
221 | - { |
|
222 | - $this->_pm_instance = $payment_method_instance; |
|
223 | - // if they have already requested the settings form, make sure its |
|
224 | - // data matches this model object |
|
225 | - if ($this->_settings_form) { |
|
226 | - $this->settings_form()->populate_model_obj($payment_method_instance); |
|
227 | - } |
|
228 | - if ($this->_gateway && $this->_gateway instanceof EE_Gateway) { |
|
229 | - $this->_gateway->set_settings($payment_method_instance->settings_array()); |
|
230 | - } |
|
231 | - } |
|
232 | - |
|
233 | - |
|
234 | - /** |
|
235 | - * Gets teh form for displaying to admins where they setup the payment method |
|
236 | - * |
|
237 | - * @return EE_Payment_Method_Form |
|
238 | - */ |
|
239 | - public function settings_form() |
|
240 | - { |
|
241 | - if (! $this->_settings_form) { |
|
242 | - $this->_settings_form = $this->generate_new_settings_form(); |
|
243 | - $this->_settings_form->set_payment_method_type($this); |
|
244 | - // if we have already assigned a model object to this pmt, make |
|
245 | - // sure its reflected in teh form we just generated |
|
246 | - if ($this->_pm_instance) { |
|
247 | - $this->_settings_form->populate_model_obj($this->_pm_instance); |
|
248 | - } |
|
249 | - } |
|
250 | - return $this->_settings_form; |
|
251 | - } |
|
252 | - |
|
253 | - |
|
254 | - /** |
|
255 | - * Gets the form for all the settings related to this payment method type |
|
256 | - * |
|
257 | - * @return EE_Payment_Method_Form |
|
258 | - */ |
|
259 | - abstract public function generate_new_settings_form(); |
|
260 | - |
|
261 | - |
|
262 | - /** |
|
263 | - * Sets the form for settings. This may be useful if we have already received |
|
264 | - * a form submission and have form data it in, and want to use it anytime we're showing |
|
265 | - * this payment method type's settings form later in the request |
|
266 | - * |
|
267 | - * @param EE_Payment_Method_Form $form |
|
268 | - */ |
|
269 | - public function set_settings_form($form) |
|
270 | - { |
|
271 | - $this->_settings_form = $form; |
|
272 | - } |
|
273 | - |
|
274 | - |
|
275 | - /** |
|
276 | - * @return boolean |
|
277 | - */ |
|
278 | - public function has_billing_form() |
|
279 | - { |
|
280 | - return $this->_has_billing_form; |
|
281 | - } |
|
282 | - |
|
283 | - |
|
284 | - /** |
|
285 | - * Gets the form for displaying to attendees where they can enter their billing info |
|
286 | - * which will be sent to teh gateway (can be null) |
|
287 | - * |
|
288 | - * @param \EE_Transaction $transaction |
|
289 | - * @param array $extra_args |
|
290 | - * @return \EE_Billing_Attendee_Info_Form|\EE_Billing_Info_Form|null |
|
291 | - */ |
|
292 | - public function billing_form(EE_Transaction $transaction = null, $extra_args = array()) |
|
293 | - { |
|
294 | - // has billing form already been regenerated ? or overwrite cache? |
|
295 | - if (! $this->_billing_form instanceof EE_Billing_Info_Form || ! $this->_cache_billing_form) { |
|
296 | - $this->_billing_form = $this->generate_new_billing_form($transaction, $extra_args); |
|
297 | - } |
|
298 | - // if we know who the attendee is, and this is a billing form |
|
299 | - // that uses attendee info, populate it |
|
300 | - if ( |
|
301 | - apply_filters( |
|
302 | - 'FHEE__populate_billing_form_fields_from_attendee', |
|
303 | - ($this->_billing_form instanceof EE_Billing_Attendee_Info_Form |
|
304 | - && $transaction instanceof EE_Transaction |
|
305 | - && $transaction->primary_registration() instanceof EE_Registration |
|
306 | - && $transaction->primary_registration()->attendee() instanceof EE_Attendee |
|
307 | - ), |
|
308 | - $this->_billing_form, |
|
309 | - $transaction |
|
310 | - ) |
|
311 | - ) { |
|
312 | - $this->_billing_form->populate_from_attendee($transaction->primary_registration()->attendee()); |
|
313 | - } |
|
314 | - return $this->_billing_form; |
|
315 | - } |
|
316 | - |
|
317 | - |
|
318 | - /** |
|
319 | - * Creates the billing form for this payment method type |
|
320 | - * |
|
321 | - * @param \EE_Transaction $transaction |
|
322 | - * @return \EE_Billing_Info_Form |
|
323 | - */ |
|
324 | - abstract public function generate_new_billing_form(EE_Transaction $transaction = null); |
|
325 | - |
|
326 | - |
|
327 | - /** |
|
328 | - * apply_billing_form_debug_settings |
|
329 | - * applies debug data to the form |
|
330 | - * |
|
331 | - * @param \EE_Billing_Info_Form $billing_form |
|
332 | - * @return \EE_Billing_Info_Form |
|
333 | - */ |
|
334 | - public function apply_billing_form_debug_settings(EE_Billing_Info_Form $billing_form) |
|
335 | - { |
|
336 | - return $billing_form; |
|
337 | - } |
|
338 | - |
|
339 | - |
|
340 | - /** |
|
341 | - * Sets the billing form for this payment method type. You may want to use this |
|
342 | - * if you have form |
|
343 | - * |
|
344 | - * @param EE_Payment_Method $form |
|
345 | - */ |
|
346 | - public function set_billing_form($form) |
|
347 | - { |
|
348 | - $this->_billing_form = $form; |
|
349 | - } |
|
350 | - |
|
351 | - |
|
352 | - /** |
|
353 | - * Returns whether or not this payment method requires HTTPS to be used |
|
354 | - * |
|
355 | - * @return boolean |
|
356 | - */ |
|
357 | - public function requires_https() |
|
358 | - { |
|
359 | - return $this->_requires_https; |
|
360 | - } |
|
361 | - |
|
362 | - |
|
363 | - /** |
|
364 | - * |
|
365 | - * @param EE_Transaction $transaction |
|
366 | - * @param float $amount |
|
367 | - * @param EE_Billing_Info_Form $billing_info |
|
368 | - * @param string $return_url |
|
369 | - * @param string $fail_url |
|
370 | - * @param string $method |
|
371 | - * @param bool $by_admin |
|
372 | - * @return EE_Payment |
|
373 | - * @throws EE_Error |
|
374 | - */ |
|
375 | - public function process_payment( |
|
376 | - EE_Transaction $transaction, |
|
377 | - $amount = null, |
|
378 | - $billing_info = null, |
|
379 | - $return_url = null, |
|
380 | - $fail_url = '', |
|
381 | - $method = 'CART', |
|
382 | - $by_admin = false |
|
383 | - ) { |
|
384 | - // @todo: add surcharge for the payment method, if any |
|
385 | - if ($this->_gateway) { |
|
386 | - // there is a gateway, so we're going to make a payment object |
|
387 | - // but wait! do they already have a payment in progress that we thought was failed? |
|
388 | - $duplicate_properties = array( |
|
389 | - 'STS_ID' => EEM_Payment::status_id_failed, |
|
390 | - 'TXN_ID' => $transaction->ID(), |
|
391 | - 'PMD_ID' => $this->_pm_instance->ID(), |
|
392 | - 'PAY_source' => $method, |
|
393 | - 'PAY_amount' => $amount !== null ? $amount : $transaction->remaining(), |
|
394 | - 'PAY_gateway_response' => null, |
|
395 | - ); |
|
396 | - $payment = EEM_Payment::instance()->get_one(array($duplicate_properties)); |
|
397 | - // if we didn't already have a payment in progress for the same thing, |
|
398 | - // then we actually want to make a new payment |
|
399 | - if (! $payment instanceof EE_Payment) { |
|
400 | - $payment = EE_Payment::new_instance( |
|
401 | - array_merge( |
|
402 | - $duplicate_properties, |
|
403 | - array( |
|
404 | - 'PAY_timestamp' => time(), |
|
405 | - 'PAY_txn_id_chq_nmbr' => null, |
|
406 | - 'PAY_po_number' => null, |
|
407 | - 'PAY_extra_accntng' => null, |
|
408 | - 'PAY_details' => null, |
|
409 | - ) |
|
410 | - ) |
|
411 | - ); |
|
412 | - } |
|
413 | - // make sure the payment has been saved to show we started it, and so it has an ID should the gateway try to log it |
|
414 | - $payment->save(); |
|
415 | - $billing_values = $this->_get_billing_values_from_form($billing_info); |
|
416 | - |
|
417 | - // Offsite Gateway |
|
418 | - if ($this->_gateway instanceof EE_Offsite_Gateway) { |
|
419 | - $payment = $this->_gateway->set_redirection_info( |
|
420 | - $payment, |
|
421 | - $billing_values, |
|
422 | - $return_url, |
|
423 | - EE_Config::instance()->core->txn_page_url( |
|
424 | - array( |
|
425 | - 'e_reg_url_link' => $transaction->primary_registration()->reg_url_link(), |
|
426 | - 'ee_payment_method' => $this->_pm_instance->slug(), |
|
427 | - ) |
|
428 | - ), |
|
429 | - $fail_url |
|
430 | - ); |
|
431 | - $payment->save(); |
|
432 | - // Onsite Gateway |
|
433 | - } elseif ($this->_gateway instanceof EE_Onsite_Gateway) { |
|
434 | - $payment = $this->_gateway->do_direct_payment($payment, $billing_values); |
|
435 | - $payment->save(); |
|
436 | - } else { |
|
437 | - throw new EE_Error( |
|
438 | - sprintf( |
|
439 | - esc_html__( |
|
440 | - 'Gateway for payment method type "%s" is "%s", not a subclass of either EE_Offsite_Gateway or EE_Onsite_Gateway, or null (to indicate NO gateway)', |
|
441 | - 'event_espresso' |
|
442 | - ), |
|
443 | - get_class($this), |
|
444 | - gettype($this->_gateway) |
|
445 | - ) |
|
446 | - ); |
|
447 | - } |
|
448 | - } else { |
|
449 | - // no gateway provided |
|
450 | - // there is no payment. Must be an offline gateway |
|
451 | - // create a payment object anyways, but dont save it |
|
452 | - $payment = EE_Payment::new_instance( |
|
453 | - array( |
|
454 | - 'STS_ID' => EEM_Payment::status_id_pending, |
|
455 | - 'TXN_ID' => $transaction->ID(), |
|
456 | - 'PMD_ID' => $transaction->payment_method_ID(), |
|
457 | - 'PAY_amount' => 0.00, |
|
458 | - 'PAY_timestamp' => time(), |
|
459 | - ) |
|
460 | - ); |
|
461 | - } |
|
462 | - |
|
463 | - // if there is billing info, clean it and save it now |
|
464 | - if ($billing_info instanceof EE_Billing_Attendee_Info_Form) { |
|
465 | - $this->_save_billing_info_to_attendee($billing_info, $transaction); |
|
466 | - } |
|
467 | - |
|
468 | - return $payment; |
|
469 | - } |
|
470 | - |
|
471 | - /** |
|
472 | - * Gets the values we want to pass onto the gateway. Normally these |
|
473 | - * are just the 'pretty' values, but there may be times the data may need |
|
474 | - * a little massaging. Proper subsections will become arrays of inputs |
|
475 | - * |
|
476 | - * @param EE_Billing_Info_Form $billing_form |
|
477 | - * @return array |
|
478 | - */ |
|
479 | - protected function _get_billing_values_from_form($billing_form) |
|
480 | - { |
|
481 | - if ($billing_form instanceof EE_Form_Section_Proper) { |
|
482 | - return $billing_form->input_pretty_values(true); |
|
483 | - } else { |
|
484 | - return null; |
|
485 | - } |
|
486 | - } |
|
487 | - |
|
488 | - |
|
489 | - /** |
|
490 | - * Handles an instant payment notification when the transaction is known (by default). |
|
491 | - * |
|
492 | - * @param array $req_data |
|
493 | - * @param EE_Transaction $transaction |
|
494 | - * @return EE_Payment |
|
495 | - * @throws EE_Error |
|
496 | - */ |
|
497 | - public function handle_ipn($req_data, $transaction) |
|
498 | - { |
|
499 | - $transaction = EEM_Transaction::instance()->ensure_is_obj($transaction); |
|
500 | - if (! $this->_gateway instanceof EE_Offsite_Gateway) { |
|
501 | - throw new EE_Error( |
|
502 | - sprintf( |
|
503 | - esc_html__("Could not handle IPN because '%s' is not an offsite gateway", "event_espresso"), |
|
504 | - print_r($this->_gateway, true) |
|
505 | - ) |
|
506 | - ); |
|
507 | - } |
|
508 | - $payment = $this->_gateway->handle_payment_update($req_data, $transaction); |
|
509 | - return $payment; |
|
510 | - } |
|
511 | - |
|
512 | - |
|
513 | - /** |
|
514 | - * Saves the billing info onto the attendee of the primary registrant on this transaction, and |
|
515 | - * cleans it first. |
|
516 | - * |
|
517 | - * @param EE_Billing_Attendee_Info_Form $billing_form |
|
518 | - * @param EE_Transaction $transaction |
|
519 | - * @return boolean success |
|
520 | - */ |
|
521 | - protected function _save_billing_info_to_attendee($billing_form, $transaction) |
|
522 | - { |
|
523 | - if (! $transaction || ! $transaction instanceof EE_Transaction) { |
|
524 | - EE_Error::add_error( |
|
525 | - esc_html__("Cannot save billing info because no transaction was specified", "event_espresso"), |
|
526 | - __FILE__, |
|
527 | - __FUNCTION__, |
|
528 | - __LINE__ |
|
529 | - ); |
|
530 | - return false; |
|
531 | - } |
|
532 | - $primary_reg = $transaction->primary_registration(); |
|
533 | - if (! $primary_reg) { |
|
534 | - EE_Error::add_error( |
|
535 | - esc_html__("Cannot save billing info because the transaction has no primary registration", "event_espresso"), |
|
536 | - __FILE__, |
|
537 | - __FUNCTION__, |
|
538 | - __LINE__ |
|
539 | - ); |
|
540 | - return false; |
|
541 | - } |
|
542 | - $attendee = $primary_reg->attendee(); |
|
543 | - if (! $attendee) { |
|
544 | - EE_Error::add_error( |
|
545 | - esc_html__( |
|
546 | - "Cannot save billing info because the transaction's primary registration has no attendee!", |
|
547 | - "event_espresso" |
|
548 | - ), |
|
549 | - __FILE__, |
|
550 | - __FUNCTION__, |
|
551 | - __LINE__ |
|
552 | - ); |
|
553 | - return false; |
|
554 | - } |
|
555 | - return $attendee->save_and_clean_billing_info_for_payment_method($billing_form, $transaction->payment_method()); |
|
556 | - } |
|
557 | - |
|
558 | - |
|
559 | - /** |
|
560 | - * Gets the payment this IPN is for. Children may often want to |
|
561 | - * override this to inspect the request |
|
562 | - * |
|
563 | - * @param EE_Transaction $transaction |
|
564 | - * @param array $req_data |
|
565 | - * @return EE_Payment |
|
566 | - */ |
|
567 | - protected function find_payment_for_ipn(EE_Transaction $transaction, $req_data = array()) |
|
568 | - { |
|
569 | - return $transaction->last_payment(); |
|
570 | - } |
|
571 | - |
|
572 | - |
|
573 | - /** |
|
574 | - * In case generic code cannot provide the payment processor with a specific payment method |
|
575 | - * and transaction, it will try calling this method on each activate payment method. |
|
576 | - * If the payment method is able to identify the request as being for it, it should fetch |
|
577 | - * the payment its for and return it. If not, it should throw an EE_Error to indicate it cannot |
|
578 | - * handle the IPN |
|
579 | - * |
|
580 | - * @param array $req_data |
|
581 | - * @return EE_Payment only if this payment method can find the info its needs from $req_data |
|
582 | - * and identifies the IPN as being for this payment method (not just fo ra payment method of this type) |
|
583 | - * @throws EE_Error |
|
584 | - */ |
|
585 | - public function handle_unclaimed_ipn($req_data = array()) |
|
586 | - { |
|
587 | - throw new EE_Error( |
|
588 | - sprintf(esc_html__("Payment Method '%s' cannot handle unclaimed IPNs", "event_espresso"), get_class($this)) |
|
589 | - ); |
|
590 | - } |
|
591 | - |
|
592 | - |
|
593 | - /** |
|
594 | - * Logic to be accomplished when the payment attempt is complete. |
|
595 | - * Most payment methods don't need to do anything at this point; but some, like Mijireh, do. |
|
596 | - * (Mijireh is an offsite gateway which doesn't send an IPN. So when the user returns to EE from |
|
597 | - * mijireh, this method needs to be called so the Mijireh PM can ping Mijireh to know the status |
|
598 | - * of the payment). Fed a transaction because it's always assumed to be the last payment that |
|
599 | - * we're dealing with. Returns that last payment (if there is one) |
|
600 | - * |
|
601 | - * @param EE_Transaction $transaction |
|
602 | - * @return EE_Payment |
|
603 | - */ |
|
604 | - public function finalize_payment_for($transaction) |
|
605 | - { |
|
606 | - return $transaction->last_payment(); |
|
607 | - } |
|
608 | - |
|
609 | - |
|
610 | - /** |
|
611 | - * Whether or not this payment method's gateway supports sending refund requests |
|
612 | - * |
|
613 | - * @return boolean |
|
614 | - */ |
|
615 | - public function supports_sending_refunds() |
|
616 | - { |
|
617 | - if ($this->_gateway && $this->_gateway instanceof EE_Gateway) { |
|
618 | - return $this->_gateway->supports_sending_refunds(); |
|
619 | - } else { |
|
620 | - return false; |
|
621 | - } |
|
622 | - } |
|
623 | - |
|
624 | - |
|
625 | - /** |
|
626 | - * |
|
627 | - * @param EE_Payment $payment |
|
628 | - * @param array $refund_info |
|
629 | - * @throws EE_Error |
|
630 | - * @return EE_Payment |
|
631 | - */ |
|
632 | - public function process_refund(EE_Payment $payment, $refund_info = array()) |
|
633 | - { |
|
634 | - if ($this->_gateway && $this->_gateway instanceof EE_Gateway) { |
|
635 | - return $this->_gateway->do_direct_refund($payment, $refund_info); |
|
636 | - } else { |
|
637 | - throw new EE_Error( |
|
638 | - sprintf( |
|
639 | - esc_html__('Payment Method Type "%s" does not support sending refund requests', 'event_espresso'), |
|
640 | - get_class($this) |
|
641 | - ) |
|
642 | - ); |
|
643 | - } |
|
644 | - } |
|
645 | - |
|
646 | - |
|
647 | - /** |
|
648 | - * Returns one the class's constants onsite,offsite, or offline, depending on this |
|
649 | - * payment method's gateway. |
|
650 | - * |
|
651 | - * @return string |
|
652 | - * @throws EE_Error |
|
653 | - */ |
|
654 | - public function payment_occurs() |
|
655 | - { |
|
656 | - if (! $this->_gateway) { |
|
657 | - return EE_PMT_Base::offline; |
|
658 | - } elseif ($this->_gateway instanceof EE_Onsite_Gateway) { |
|
659 | - return EE_PMT_Base::onsite; |
|
660 | - } elseif ($this->_gateway instanceof EE_Offsite_Gateway) { |
|
661 | - return EE_PMT_Base::offsite; |
|
662 | - } else { |
|
663 | - throw new EE_Error( |
|
664 | - sprintf( |
|
665 | - esc_html__( |
|
666 | - "Payment method type '%s's gateway isn't an instance of EE_Onsite_Gateway, EE_Offsite_Gateway, or null. It must be one of those", |
|
667 | - "event_espresso" |
|
668 | - ), |
|
669 | - get_class($this) |
|
670 | - ) |
|
671 | - ); |
|
672 | - } |
|
673 | - } |
|
674 | - |
|
675 | - |
|
676 | - /** |
|
677 | - * For adding any html output ab ove the payment overview. |
|
678 | - * Many gateways won't want ot display anything, so this function just returns an empty string. |
|
679 | - * Other gateways may want to override this, such as offline gateways. |
|
680 | - * |
|
681 | - * @param EE_Payment $payment |
|
682 | - * @return string |
|
683 | - */ |
|
684 | - public function payment_overview_content(EE_Payment $payment) |
|
685 | - { |
|
686 | - return EEH_Template::display_template( |
|
687 | - EE_LIBRARIES . 'payment_methods/templates/payment_details_content.template.php', |
|
688 | - array('payment_method' => $this->_pm_instance, 'payment' => $payment), |
|
689 | - true |
|
690 | - ); |
|
691 | - } |
|
692 | - |
|
693 | - |
|
694 | - /** |
|
695 | - * @return array where keys are the help tab name, |
|
696 | - * values are: array { |
|
697 | - * @type string $title i18n name for the help tab |
|
698 | - * @type string $filename name of the file located in ./help_tabs/ (ie, in a folder next to this file) |
|
699 | - * @type array $template_args any arguments you want passed to the template file while rendering. |
|
700 | - * Keys will be variable names and values with be their values. |
|
701 | - */ |
|
702 | - public function help_tabs_config() |
|
703 | - { |
|
704 | - return array(); |
|
705 | - } |
|
706 | - |
|
707 | - |
|
708 | - /** |
|
709 | - * The system name for this PMT (eg AIM, Paypal_Pro, Invoice... what gets put into |
|
710 | - * the payment method's table's PMT_type column) |
|
711 | - * |
|
712 | - * @return string |
|
713 | - */ |
|
714 | - public function system_name() |
|
715 | - { |
|
716 | - $classname = get_class($this); |
|
717 | - return str_replace("EE_PMT_", '', $classname); |
|
718 | - } |
|
719 | - |
|
720 | - |
|
721 | - /** |
|
722 | - * A pretty i18n version of the PMT name. Often the same as the "pretty_name", but you can change it by overriding |
|
723 | - * this method. |
|
724 | - * @return string |
|
725 | - */ |
|
726 | - public function defaultFrontendName() |
|
727 | - { |
|
728 | - return $this->pretty_name(); |
|
729 | - } |
|
730 | - |
|
731 | - |
|
732 | - /** |
|
733 | - * A pretty i18n version of the PMT name |
|
734 | - * |
|
735 | - * @return string |
|
736 | - */ |
|
737 | - public function pretty_name() |
|
738 | - { |
|
739 | - return $this->_pretty_name; |
|
740 | - } |
|
741 | - |
|
742 | - |
|
743 | - /** |
|
744 | - * Gets the default absolute URL to the payment method type's button |
|
745 | - * |
|
746 | - * @return string |
|
747 | - */ |
|
748 | - public function default_button_url() |
|
749 | - { |
|
750 | - return $this->_default_button_url; |
|
751 | - } |
|
752 | - |
|
753 | - |
|
754 | - /** |
|
755 | - * Gets the gateway used by this payment method (if any) |
|
756 | - * |
|
757 | - * @return EE_Gateway |
|
758 | - */ |
|
759 | - public function get_gateway() |
|
760 | - { |
|
761 | - return $this->_gateway; |
|
762 | - } |
|
763 | - |
|
764 | - |
|
765 | - /** |
|
766 | - * @return string html for the link to a help tab |
|
767 | - */ |
|
768 | - public function get_help_tab_link() |
|
769 | - { |
|
770 | - return EEH_Template::get_help_tab_link( |
|
771 | - $this->get_help_tab_name(), |
|
772 | - 'espresso_payment_settings', |
|
773 | - 'default' |
|
774 | - ); |
|
775 | - } |
|
776 | - |
|
777 | - |
|
778 | - /** |
|
779 | - * Returns the name of the help tab for this PMT |
|
780 | - * |
|
781 | - * @return string |
|
782 | - */ |
|
783 | - public function get_help_tab_name() |
|
784 | - { |
|
785 | - return 'ee_' . strtolower($this->system_name()) . '_help_tab'; |
|
786 | - } |
|
787 | - |
|
788 | - /** |
|
789 | - * The name of the wp capability that should be associated with the usage of |
|
790 | - * this PMT by an admin |
|
791 | - * |
|
792 | - * @return string |
|
793 | - */ |
|
794 | - public function cap_name() |
|
795 | - { |
|
796 | - return 'ee_payment_method_' . strtolower($this->system_name()); |
|
797 | - } |
|
798 | - |
|
799 | - /** |
|
800 | - * Called by client code to tell the gateway that if it wants to change |
|
801 | - * the transaction or line items or registrations related to teh payment it already |
|
802 | - * processed (we think, but possibly not) that now's the time to do it. |
|
803 | - * It is expected that gateways will store any info they need for this on the PAY_details, |
|
804 | - * or maybe an extra meta value |
|
805 | - * |
|
806 | - * @param EE_Payment $payment |
|
807 | - * @return void |
|
808 | - */ |
|
809 | - public function update_txn_based_on_payment($payment) |
|
810 | - { |
|
811 | - if ($this->_gateway instanceof EE_Gateway) { |
|
812 | - $this->_gateway->update_txn_based_on_payment($payment); |
|
813 | - } |
|
814 | - } |
|
815 | - |
|
816 | - /** |
|
817 | - * Returns a string of HTML describing this payment method type for an admin, |
|
818 | - * primarily intended for them to read before activating it. |
|
819 | - * The easiest way to set this is to create a folder 'templates' alongside |
|
820 | - * your EE_PMT_{System_Name} file, and in it create a file named "{system_name}_intro.template.php". |
|
821 | - * Eg, if your payment method file is named "EE_PMT_Foo_Bar.pm.php", |
|
822 | - * then you'd create a file named "templates" in the same folder as it, and name the file |
|
823 | - * "foo_bar_intro.template.php", and its content will be returned by this method |
|
824 | - * |
|
825 | - * @return string |
|
826 | - */ |
|
827 | - public function introductory_html() |
|
828 | - { |
|
829 | - return EEH_Template::locate_template( |
|
830 | - $this->file_folder() . 'templates/' . strtolower($this->system_name()) . '_intro.template.php', |
|
831 | - array('pmt_obj' => $this, 'pm_instance' => $this->_pm_instance) |
|
832 | - ); |
|
833 | - } |
|
24 | + const onsite = 'on-site'; |
|
25 | + const offsite = 'off-site'; |
|
26 | + const offline = 'off-line'; |
|
27 | + |
|
28 | + /** |
|
29 | + * @var EE_Payment_Method |
|
30 | + */ |
|
31 | + protected $_pm_instance = null; |
|
32 | + |
|
33 | + /** |
|
34 | + * @var boolean |
|
35 | + */ |
|
36 | + protected $_requires_https = false; |
|
37 | + |
|
38 | + /** |
|
39 | + * @var boolean |
|
40 | + */ |
|
41 | + protected $_has_billing_form; |
|
42 | + |
|
43 | + /** |
|
44 | + * @var EE_Gateway |
|
45 | + */ |
|
46 | + protected $_gateway = null; |
|
47 | + |
|
48 | + /** |
|
49 | + * @var EE_Payment_Method_Form |
|
50 | + */ |
|
51 | + protected $_settings_form = null; |
|
52 | + |
|
53 | + /** |
|
54 | + * @var EE_Form_Section_Proper |
|
55 | + */ |
|
56 | + protected $_billing_form = null; |
|
57 | + |
|
58 | + /** |
|
59 | + * @var boolean |
|
60 | + */ |
|
61 | + protected $_cache_billing_form = true; |
|
62 | + |
|
63 | + /** |
|
64 | + * String of the absolute path to the folder containing this file, with a trailing slash. |
|
65 | + * eg '/public_html/wp-site/wp-content/plugins/event-espresso/payment_methods/Invoice/' |
|
66 | + * |
|
67 | + * @var string |
|
68 | + */ |
|
69 | + protected $_file_folder = null; |
|
70 | + |
|
71 | + /** |
|
72 | + * String to the absolute URL to this file (useful for getting its web-accessible resources |
|
73 | + * like images, js, or css) |
|
74 | + * |
|
75 | + * @var string |
|
76 | + */ |
|
77 | + protected $_file_url = null; |
|
78 | + |
|
79 | + /** |
|
80 | + * Pretty name for the payment method |
|
81 | + * |
|
82 | + * @var string |
|
83 | + */ |
|
84 | + protected $_pretty_name = null; |
|
85 | + |
|
86 | + /** |
|
87 | + * |
|
88 | + * @var string |
|
89 | + */ |
|
90 | + protected $_default_button_url = null; |
|
91 | + |
|
92 | + /** |
|
93 | + * |
|
94 | + * @var string |
|
95 | + */ |
|
96 | + protected $_default_description = null; |
|
97 | + |
|
98 | + |
|
99 | + /** |
|
100 | + * |
|
101 | + * @param EE_Payment_Method $pm_instance |
|
102 | + * @throws EE_Error |
|
103 | + * @return EE_PMT_Base |
|
104 | + */ |
|
105 | + public function __construct($pm_instance = null) |
|
106 | + { |
|
107 | + if ($pm_instance instanceof EE_Payment_Method) { |
|
108 | + $this->set_instance($pm_instance); |
|
109 | + } |
|
110 | + if ($this->_gateway) { |
|
111 | + $this->_gateway->set_payment_model(EEM_Payment::instance()); |
|
112 | + $this->_gateway->set_payment_log(EEM_Change_Log::instance()); |
|
113 | + $this->_gateway->set_template_helper(new EEH_Template()); |
|
114 | + $this->_gateway->set_line_item_helper(new EEH_Line_Item()); |
|
115 | + $this->_gateway->set_money_helper(new EEH_Money()); |
|
116 | + $this->_gateway->set_gateway_data_formatter(new GatewayDataFormatter()); |
|
117 | + $this->_gateway->set_unsupported_character_remover(new AsciiOnly()); |
|
118 | + do_action('AHEE__EE_PMT_Base___construct__done_initializing_gateway_class', $this, $this->_gateway); |
|
119 | + } |
|
120 | + if (! isset($this->_has_billing_form)) { |
|
121 | + // by default, On Site gateways have a billing form |
|
122 | + if ($this->payment_occurs() == EE_PMT_Base::onsite) { |
|
123 | + $this->set_has_billing_form(true); |
|
124 | + } else { |
|
125 | + $this->set_has_billing_form(false); |
|
126 | + } |
|
127 | + } |
|
128 | + |
|
129 | + if (! $this->_pretty_name) { |
|
130 | + throw new EE_Error( |
|
131 | + sprintf( |
|
132 | + esc_html__( |
|
133 | + "You must set the pretty name for the Payment Method Type in the constructor (_pretty_name), and please make it internationalized", |
|
134 | + "event_espresso" |
|
135 | + ) |
|
136 | + ) |
|
137 | + ); |
|
138 | + } |
|
139 | + // if the child didn't specify a default button, use the credit card one |
|
140 | + if ($this->_default_button_url === null) { |
|
141 | + $this->_default_button_url = EE_PLUGIN_DIR_URL . 'payment_methods/pay-by-credit-card.png'; |
|
142 | + } |
|
143 | + } |
|
144 | + |
|
145 | + |
|
146 | + /** |
|
147 | + * @param boolean $has_billing_form |
|
148 | + */ |
|
149 | + public function set_has_billing_form($has_billing_form) |
|
150 | + { |
|
151 | + $this->_has_billing_form = filter_var($has_billing_form, FILTER_VALIDATE_BOOLEAN); |
|
152 | + } |
|
153 | + |
|
154 | + |
|
155 | + /** |
|
156 | + * sets the file_folder property |
|
157 | + */ |
|
158 | + protected function _set_file_folder() |
|
159 | + { |
|
160 | + $reflector = new ReflectionClass(get_class($this)); |
|
161 | + $fn = $reflector->getFileName(); |
|
162 | + $this->_file_folder = dirname($fn) . '/'; |
|
163 | + } |
|
164 | + |
|
165 | + |
|
166 | + /** |
|
167 | + * sets the file URL with a trailing slash for this PMT |
|
168 | + */ |
|
169 | + protected function _set_file_url() |
|
170 | + { |
|
171 | + $plugins_dir_fixed = str_replace('\\', '/', WP_PLUGIN_DIR); |
|
172 | + $file_folder_fixed = str_replace('\\', '/', $this->file_folder()); |
|
173 | + $file_path = str_replace($plugins_dir_fixed, WP_PLUGIN_URL, $file_folder_fixed); |
|
174 | + $this->_file_url = set_url_scheme($file_path); |
|
175 | + } |
|
176 | + |
|
177 | + /** |
|
178 | + * Gets the default description on all payment methods of this type |
|
179 | + * |
|
180 | + * @return string |
|
181 | + */ |
|
182 | + public function default_description() |
|
183 | + { |
|
184 | + return $this->_default_description; |
|
185 | + } |
|
186 | + |
|
187 | + |
|
188 | + /** |
|
189 | + * Returns the folder containing the PMT child class, with a trailing slash |
|
190 | + * |
|
191 | + * @return string |
|
192 | + */ |
|
193 | + public function file_folder() |
|
194 | + { |
|
195 | + if (! $this->_file_folder) { |
|
196 | + $this->_set_file_folder(); |
|
197 | + } |
|
198 | + return $this->_file_folder; |
|
199 | + } |
|
200 | + |
|
201 | + |
|
202 | + /** |
|
203 | + * @return string |
|
204 | + */ |
|
205 | + public function file_url() |
|
206 | + { |
|
207 | + if (! $this->_file_url) { |
|
208 | + $this->_set_file_url(); |
|
209 | + } |
|
210 | + return $this->_file_url; |
|
211 | + } |
|
212 | + |
|
213 | + |
|
214 | + /** |
|
215 | + * Sets the payment method instance this payment method type is for. |
|
216 | + * Its important teh payment method instance is set before |
|
217 | + * |
|
218 | + * @param EE_Payment_Method $payment_method_instance |
|
219 | + */ |
|
220 | + public function set_instance($payment_method_instance) |
|
221 | + { |
|
222 | + $this->_pm_instance = $payment_method_instance; |
|
223 | + // if they have already requested the settings form, make sure its |
|
224 | + // data matches this model object |
|
225 | + if ($this->_settings_form) { |
|
226 | + $this->settings_form()->populate_model_obj($payment_method_instance); |
|
227 | + } |
|
228 | + if ($this->_gateway && $this->_gateway instanceof EE_Gateway) { |
|
229 | + $this->_gateway->set_settings($payment_method_instance->settings_array()); |
|
230 | + } |
|
231 | + } |
|
232 | + |
|
233 | + |
|
234 | + /** |
|
235 | + * Gets teh form for displaying to admins where they setup the payment method |
|
236 | + * |
|
237 | + * @return EE_Payment_Method_Form |
|
238 | + */ |
|
239 | + public function settings_form() |
|
240 | + { |
|
241 | + if (! $this->_settings_form) { |
|
242 | + $this->_settings_form = $this->generate_new_settings_form(); |
|
243 | + $this->_settings_form->set_payment_method_type($this); |
|
244 | + // if we have already assigned a model object to this pmt, make |
|
245 | + // sure its reflected in teh form we just generated |
|
246 | + if ($this->_pm_instance) { |
|
247 | + $this->_settings_form->populate_model_obj($this->_pm_instance); |
|
248 | + } |
|
249 | + } |
|
250 | + return $this->_settings_form; |
|
251 | + } |
|
252 | + |
|
253 | + |
|
254 | + /** |
|
255 | + * Gets the form for all the settings related to this payment method type |
|
256 | + * |
|
257 | + * @return EE_Payment_Method_Form |
|
258 | + */ |
|
259 | + abstract public function generate_new_settings_form(); |
|
260 | + |
|
261 | + |
|
262 | + /** |
|
263 | + * Sets the form for settings. This may be useful if we have already received |
|
264 | + * a form submission and have form data it in, and want to use it anytime we're showing |
|
265 | + * this payment method type's settings form later in the request |
|
266 | + * |
|
267 | + * @param EE_Payment_Method_Form $form |
|
268 | + */ |
|
269 | + public function set_settings_form($form) |
|
270 | + { |
|
271 | + $this->_settings_form = $form; |
|
272 | + } |
|
273 | + |
|
274 | + |
|
275 | + /** |
|
276 | + * @return boolean |
|
277 | + */ |
|
278 | + public function has_billing_form() |
|
279 | + { |
|
280 | + return $this->_has_billing_form; |
|
281 | + } |
|
282 | + |
|
283 | + |
|
284 | + /** |
|
285 | + * Gets the form for displaying to attendees where they can enter their billing info |
|
286 | + * which will be sent to teh gateway (can be null) |
|
287 | + * |
|
288 | + * @param \EE_Transaction $transaction |
|
289 | + * @param array $extra_args |
|
290 | + * @return \EE_Billing_Attendee_Info_Form|\EE_Billing_Info_Form|null |
|
291 | + */ |
|
292 | + public function billing_form(EE_Transaction $transaction = null, $extra_args = array()) |
|
293 | + { |
|
294 | + // has billing form already been regenerated ? or overwrite cache? |
|
295 | + if (! $this->_billing_form instanceof EE_Billing_Info_Form || ! $this->_cache_billing_form) { |
|
296 | + $this->_billing_form = $this->generate_new_billing_form($transaction, $extra_args); |
|
297 | + } |
|
298 | + // if we know who the attendee is, and this is a billing form |
|
299 | + // that uses attendee info, populate it |
|
300 | + if ( |
|
301 | + apply_filters( |
|
302 | + 'FHEE__populate_billing_form_fields_from_attendee', |
|
303 | + ($this->_billing_form instanceof EE_Billing_Attendee_Info_Form |
|
304 | + && $transaction instanceof EE_Transaction |
|
305 | + && $transaction->primary_registration() instanceof EE_Registration |
|
306 | + && $transaction->primary_registration()->attendee() instanceof EE_Attendee |
|
307 | + ), |
|
308 | + $this->_billing_form, |
|
309 | + $transaction |
|
310 | + ) |
|
311 | + ) { |
|
312 | + $this->_billing_form->populate_from_attendee($transaction->primary_registration()->attendee()); |
|
313 | + } |
|
314 | + return $this->_billing_form; |
|
315 | + } |
|
316 | + |
|
317 | + |
|
318 | + /** |
|
319 | + * Creates the billing form for this payment method type |
|
320 | + * |
|
321 | + * @param \EE_Transaction $transaction |
|
322 | + * @return \EE_Billing_Info_Form |
|
323 | + */ |
|
324 | + abstract public function generate_new_billing_form(EE_Transaction $transaction = null); |
|
325 | + |
|
326 | + |
|
327 | + /** |
|
328 | + * apply_billing_form_debug_settings |
|
329 | + * applies debug data to the form |
|
330 | + * |
|
331 | + * @param \EE_Billing_Info_Form $billing_form |
|
332 | + * @return \EE_Billing_Info_Form |
|
333 | + */ |
|
334 | + public function apply_billing_form_debug_settings(EE_Billing_Info_Form $billing_form) |
|
335 | + { |
|
336 | + return $billing_form; |
|
337 | + } |
|
338 | + |
|
339 | + |
|
340 | + /** |
|
341 | + * Sets the billing form for this payment method type. You may want to use this |
|
342 | + * if you have form |
|
343 | + * |
|
344 | + * @param EE_Payment_Method $form |
|
345 | + */ |
|
346 | + public function set_billing_form($form) |
|
347 | + { |
|
348 | + $this->_billing_form = $form; |
|
349 | + } |
|
350 | + |
|
351 | + |
|
352 | + /** |
|
353 | + * Returns whether or not this payment method requires HTTPS to be used |
|
354 | + * |
|
355 | + * @return boolean |
|
356 | + */ |
|
357 | + public function requires_https() |
|
358 | + { |
|
359 | + return $this->_requires_https; |
|
360 | + } |
|
361 | + |
|
362 | + |
|
363 | + /** |
|
364 | + * |
|
365 | + * @param EE_Transaction $transaction |
|
366 | + * @param float $amount |
|
367 | + * @param EE_Billing_Info_Form $billing_info |
|
368 | + * @param string $return_url |
|
369 | + * @param string $fail_url |
|
370 | + * @param string $method |
|
371 | + * @param bool $by_admin |
|
372 | + * @return EE_Payment |
|
373 | + * @throws EE_Error |
|
374 | + */ |
|
375 | + public function process_payment( |
|
376 | + EE_Transaction $transaction, |
|
377 | + $amount = null, |
|
378 | + $billing_info = null, |
|
379 | + $return_url = null, |
|
380 | + $fail_url = '', |
|
381 | + $method = 'CART', |
|
382 | + $by_admin = false |
|
383 | + ) { |
|
384 | + // @todo: add surcharge for the payment method, if any |
|
385 | + if ($this->_gateway) { |
|
386 | + // there is a gateway, so we're going to make a payment object |
|
387 | + // but wait! do they already have a payment in progress that we thought was failed? |
|
388 | + $duplicate_properties = array( |
|
389 | + 'STS_ID' => EEM_Payment::status_id_failed, |
|
390 | + 'TXN_ID' => $transaction->ID(), |
|
391 | + 'PMD_ID' => $this->_pm_instance->ID(), |
|
392 | + 'PAY_source' => $method, |
|
393 | + 'PAY_amount' => $amount !== null ? $amount : $transaction->remaining(), |
|
394 | + 'PAY_gateway_response' => null, |
|
395 | + ); |
|
396 | + $payment = EEM_Payment::instance()->get_one(array($duplicate_properties)); |
|
397 | + // if we didn't already have a payment in progress for the same thing, |
|
398 | + // then we actually want to make a new payment |
|
399 | + if (! $payment instanceof EE_Payment) { |
|
400 | + $payment = EE_Payment::new_instance( |
|
401 | + array_merge( |
|
402 | + $duplicate_properties, |
|
403 | + array( |
|
404 | + 'PAY_timestamp' => time(), |
|
405 | + 'PAY_txn_id_chq_nmbr' => null, |
|
406 | + 'PAY_po_number' => null, |
|
407 | + 'PAY_extra_accntng' => null, |
|
408 | + 'PAY_details' => null, |
|
409 | + ) |
|
410 | + ) |
|
411 | + ); |
|
412 | + } |
|
413 | + // make sure the payment has been saved to show we started it, and so it has an ID should the gateway try to log it |
|
414 | + $payment->save(); |
|
415 | + $billing_values = $this->_get_billing_values_from_form($billing_info); |
|
416 | + |
|
417 | + // Offsite Gateway |
|
418 | + if ($this->_gateway instanceof EE_Offsite_Gateway) { |
|
419 | + $payment = $this->_gateway->set_redirection_info( |
|
420 | + $payment, |
|
421 | + $billing_values, |
|
422 | + $return_url, |
|
423 | + EE_Config::instance()->core->txn_page_url( |
|
424 | + array( |
|
425 | + 'e_reg_url_link' => $transaction->primary_registration()->reg_url_link(), |
|
426 | + 'ee_payment_method' => $this->_pm_instance->slug(), |
|
427 | + ) |
|
428 | + ), |
|
429 | + $fail_url |
|
430 | + ); |
|
431 | + $payment->save(); |
|
432 | + // Onsite Gateway |
|
433 | + } elseif ($this->_gateway instanceof EE_Onsite_Gateway) { |
|
434 | + $payment = $this->_gateway->do_direct_payment($payment, $billing_values); |
|
435 | + $payment->save(); |
|
436 | + } else { |
|
437 | + throw new EE_Error( |
|
438 | + sprintf( |
|
439 | + esc_html__( |
|
440 | + 'Gateway for payment method type "%s" is "%s", not a subclass of either EE_Offsite_Gateway or EE_Onsite_Gateway, or null (to indicate NO gateway)', |
|
441 | + 'event_espresso' |
|
442 | + ), |
|
443 | + get_class($this), |
|
444 | + gettype($this->_gateway) |
|
445 | + ) |
|
446 | + ); |
|
447 | + } |
|
448 | + } else { |
|
449 | + // no gateway provided |
|
450 | + // there is no payment. Must be an offline gateway |
|
451 | + // create a payment object anyways, but dont save it |
|
452 | + $payment = EE_Payment::new_instance( |
|
453 | + array( |
|
454 | + 'STS_ID' => EEM_Payment::status_id_pending, |
|
455 | + 'TXN_ID' => $transaction->ID(), |
|
456 | + 'PMD_ID' => $transaction->payment_method_ID(), |
|
457 | + 'PAY_amount' => 0.00, |
|
458 | + 'PAY_timestamp' => time(), |
|
459 | + ) |
|
460 | + ); |
|
461 | + } |
|
462 | + |
|
463 | + // if there is billing info, clean it and save it now |
|
464 | + if ($billing_info instanceof EE_Billing_Attendee_Info_Form) { |
|
465 | + $this->_save_billing_info_to_attendee($billing_info, $transaction); |
|
466 | + } |
|
467 | + |
|
468 | + return $payment; |
|
469 | + } |
|
470 | + |
|
471 | + /** |
|
472 | + * Gets the values we want to pass onto the gateway. Normally these |
|
473 | + * are just the 'pretty' values, but there may be times the data may need |
|
474 | + * a little massaging. Proper subsections will become arrays of inputs |
|
475 | + * |
|
476 | + * @param EE_Billing_Info_Form $billing_form |
|
477 | + * @return array |
|
478 | + */ |
|
479 | + protected function _get_billing_values_from_form($billing_form) |
|
480 | + { |
|
481 | + if ($billing_form instanceof EE_Form_Section_Proper) { |
|
482 | + return $billing_form->input_pretty_values(true); |
|
483 | + } else { |
|
484 | + return null; |
|
485 | + } |
|
486 | + } |
|
487 | + |
|
488 | + |
|
489 | + /** |
|
490 | + * Handles an instant payment notification when the transaction is known (by default). |
|
491 | + * |
|
492 | + * @param array $req_data |
|
493 | + * @param EE_Transaction $transaction |
|
494 | + * @return EE_Payment |
|
495 | + * @throws EE_Error |
|
496 | + */ |
|
497 | + public function handle_ipn($req_data, $transaction) |
|
498 | + { |
|
499 | + $transaction = EEM_Transaction::instance()->ensure_is_obj($transaction); |
|
500 | + if (! $this->_gateway instanceof EE_Offsite_Gateway) { |
|
501 | + throw new EE_Error( |
|
502 | + sprintf( |
|
503 | + esc_html__("Could not handle IPN because '%s' is not an offsite gateway", "event_espresso"), |
|
504 | + print_r($this->_gateway, true) |
|
505 | + ) |
|
506 | + ); |
|
507 | + } |
|
508 | + $payment = $this->_gateway->handle_payment_update($req_data, $transaction); |
|
509 | + return $payment; |
|
510 | + } |
|
511 | + |
|
512 | + |
|
513 | + /** |
|
514 | + * Saves the billing info onto the attendee of the primary registrant on this transaction, and |
|
515 | + * cleans it first. |
|
516 | + * |
|
517 | + * @param EE_Billing_Attendee_Info_Form $billing_form |
|
518 | + * @param EE_Transaction $transaction |
|
519 | + * @return boolean success |
|
520 | + */ |
|
521 | + protected function _save_billing_info_to_attendee($billing_form, $transaction) |
|
522 | + { |
|
523 | + if (! $transaction || ! $transaction instanceof EE_Transaction) { |
|
524 | + EE_Error::add_error( |
|
525 | + esc_html__("Cannot save billing info because no transaction was specified", "event_espresso"), |
|
526 | + __FILE__, |
|
527 | + __FUNCTION__, |
|
528 | + __LINE__ |
|
529 | + ); |
|
530 | + return false; |
|
531 | + } |
|
532 | + $primary_reg = $transaction->primary_registration(); |
|
533 | + if (! $primary_reg) { |
|
534 | + EE_Error::add_error( |
|
535 | + esc_html__("Cannot save billing info because the transaction has no primary registration", "event_espresso"), |
|
536 | + __FILE__, |
|
537 | + __FUNCTION__, |
|
538 | + __LINE__ |
|
539 | + ); |
|
540 | + return false; |
|
541 | + } |
|
542 | + $attendee = $primary_reg->attendee(); |
|
543 | + if (! $attendee) { |
|
544 | + EE_Error::add_error( |
|
545 | + esc_html__( |
|
546 | + "Cannot save billing info because the transaction's primary registration has no attendee!", |
|
547 | + "event_espresso" |
|
548 | + ), |
|
549 | + __FILE__, |
|
550 | + __FUNCTION__, |
|
551 | + __LINE__ |
|
552 | + ); |
|
553 | + return false; |
|
554 | + } |
|
555 | + return $attendee->save_and_clean_billing_info_for_payment_method($billing_form, $transaction->payment_method()); |
|
556 | + } |
|
557 | + |
|
558 | + |
|
559 | + /** |
|
560 | + * Gets the payment this IPN is for. Children may often want to |
|
561 | + * override this to inspect the request |
|
562 | + * |
|
563 | + * @param EE_Transaction $transaction |
|
564 | + * @param array $req_data |
|
565 | + * @return EE_Payment |
|
566 | + */ |
|
567 | + protected function find_payment_for_ipn(EE_Transaction $transaction, $req_data = array()) |
|
568 | + { |
|
569 | + return $transaction->last_payment(); |
|
570 | + } |
|
571 | + |
|
572 | + |
|
573 | + /** |
|
574 | + * In case generic code cannot provide the payment processor with a specific payment method |
|
575 | + * and transaction, it will try calling this method on each activate payment method. |
|
576 | + * If the payment method is able to identify the request as being for it, it should fetch |
|
577 | + * the payment its for and return it. If not, it should throw an EE_Error to indicate it cannot |
|
578 | + * handle the IPN |
|
579 | + * |
|
580 | + * @param array $req_data |
|
581 | + * @return EE_Payment only if this payment method can find the info its needs from $req_data |
|
582 | + * and identifies the IPN as being for this payment method (not just fo ra payment method of this type) |
|
583 | + * @throws EE_Error |
|
584 | + */ |
|
585 | + public function handle_unclaimed_ipn($req_data = array()) |
|
586 | + { |
|
587 | + throw new EE_Error( |
|
588 | + sprintf(esc_html__("Payment Method '%s' cannot handle unclaimed IPNs", "event_espresso"), get_class($this)) |
|
589 | + ); |
|
590 | + } |
|
591 | + |
|
592 | + |
|
593 | + /** |
|
594 | + * Logic to be accomplished when the payment attempt is complete. |
|
595 | + * Most payment methods don't need to do anything at this point; but some, like Mijireh, do. |
|
596 | + * (Mijireh is an offsite gateway which doesn't send an IPN. So when the user returns to EE from |
|
597 | + * mijireh, this method needs to be called so the Mijireh PM can ping Mijireh to know the status |
|
598 | + * of the payment). Fed a transaction because it's always assumed to be the last payment that |
|
599 | + * we're dealing with. Returns that last payment (if there is one) |
|
600 | + * |
|
601 | + * @param EE_Transaction $transaction |
|
602 | + * @return EE_Payment |
|
603 | + */ |
|
604 | + public function finalize_payment_for($transaction) |
|
605 | + { |
|
606 | + return $transaction->last_payment(); |
|
607 | + } |
|
608 | + |
|
609 | + |
|
610 | + /** |
|
611 | + * Whether or not this payment method's gateway supports sending refund requests |
|
612 | + * |
|
613 | + * @return boolean |
|
614 | + */ |
|
615 | + public function supports_sending_refunds() |
|
616 | + { |
|
617 | + if ($this->_gateway && $this->_gateway instanceof EE_Gateway) { |
|
618 | + return $this->_gateway->supports_sending_refunds(); |
|
619 | + } else { |
|
620 | + return false; |
|
621 | + } |
|
622 | + } |
|
623 | + |
|
624 | + |
|
625 | + /** |
|
626 | + * |
|
627 | + * @param EE_Payment $payment |
|
628 | + * @param array $refund_info |
|
629 | + * @throws EE_Error |
|
630 | + * @return EE_Payment |
|
631 | + */ |
|
632 | + public function process_refund(EE_Payment $payment, $refund_info = array()) |
|
633 | + { |
|
634 | + if ($this->_gateway && $this->_gateway instanceof EE_Gateway) { |
|
635 | + return $this->_gateway->do_direct_refund($payment, $refund_info); |
|
636 | + } else { |
|
637 | + throw new EE_Error( |
|
638 | + sprintf( |
|
639 | + esc_html__('Payment Method Type "%s" does not support sending refund requests', 'event_espresso'), |
|
640 | + get_class($this) |
|
641 | + ) |
|
642 | + ); |
|
643 | + } |
|
644 | + } |
|
645 | + |
|
646 | + |
|
647 | + /** |
|
648 | + * Returns one the class's constants onsite,offsite, or offline, depending on this |
|
649 | + * payment method's gateway. |
|
650 | + * |
|
651 | + * @return string |
|
652 | + * @throws EE_Error |
|
653 | + */ |
|
654 | + public function payment_occurs() |
|
655 | + { |
|
656 | + if (! $this->_gateway) { |
|
657 | + return EE_PMT_Base::offline; |
|
658 | + } elseif ($this->_gateway instanceof EE_Onsite_Gateway) { |
|
659 | + return EE_PMT_Base::onsite; |
|
660 | + } elseif ($this->_gateway instanceof EE_Offsite_Gateway) { |
|
661 | + return EE_PMT_Base::offsite; |
|
662 | + } else { |
|
663 | + throw new EE_Error( |
|
664 | + sprintf( |
|
665 | + esc_html__( |
|
666 | + "Payment method type '%s's gateway isn't an instance of EE_Onsite_Gateway, EE_Offsite_Gateway, or null. It must be one of those", |
|
667 | + "event_espresso" |
|
668 | + ), |
|
669 | + get_class($this) |
|
670 | + ) |
|
671 | + ); |
|
672 | + } |
|
673 | + } |
|
674 | + |
|
675 | + |
|
676 | + /** |
|
677 | + * For adding any html output ab ove the payment overview. |
|
678 | + * Many gateways won't want ot display anything, so this function just returns an empty string. |
|
679 | + * Other gateways may want to override this, such as offline gateways. |
|
680 | + * |
|
681 | + * @param EE_Payment $payment |
|
682 | + * @return string |
|
683 | + */ |
|
684 | + public function payment_overview_content(EE_Payment $payment) |
|
685 | + { |
|
686 | + return EEH_Template::display_template( |
|
687 | + EE_LIBRARIES . 'payment_methods/templates/payment_details_content.template.php', |
|
688 | + array('payment_method' => $this->_pm_instance, 'payment' => $payment), |
|
689 | + true |
|
690 | + ); |
|
691 | + } |
|
692 | + |
|
693 | + |
|
694 | + /** |
|
695 | + * @return array where keys are the help tab name, |
|
696 | + * values are: array { |
|
697 | + * @type string $title i18n name for the help tab |
|
698 | + * @type string $filename name of the file located in ./help_tabs/ (ie, in a folder next to this file) |
|
699 | + * @type array $template_args any arguments you want passed to the template file while rendering. |
|
700 | + * Keys will be variable names and values with be their values. |
|
701 | + */ |
|
702 | + public function help_tabs_config() |
|
703 | + { |
|
704 | + return array(); |
|
705 | + } |
|
706 | + |
|
707 | + |
|
708 | + /** |
|
709 | + * The system name for this PMT (eg AIM, Paypal_Pro, Invoice... what gets put into |
|
710 | + * the payment method's table's PMT_type column) |
|
711 | + * |
|
712 | + * @return string |
|
713 | + */ |
|
714 | + public function system_name() |
|
715 | + { |
|
716 | + $classname = get_class($this); |
|
717 | + return str_replace("EE_PMT_", '', $classname); |
|
718 | + } |
|
719 | + |
|
720 | + |
|
721 | + /** |
|
722 | + * A pretty i18n version of the PMT name. Often the same as the "pretty_name", but you can change it by overriding |
|
723 | + * this method. |
|
724 | + * @return string |
|
725 | + */ |
|
726 | + public function defaultFrontendName() |
|
727 | + { |
|
728 | + return $this->pretty_name(); |
|
729 | + } |
|
730 | + |
|
731 | + |
|
732 | + /** |
|
733 | + * A pretty i18n version of the PMT name |
|
734 | + * |
|
735 | + * @return string |
|
736 | + */ |
|
737 | + public function pretty_name() |
|
738 | + { |
|
739 | + return $this->_pretty_name; |
|
740 | + } |
|
741 | + |
|
742 | + |
|
743 | + /** |
|
744 | + * Gets the default absolute URL to the payment method type's button |
|
745 | + * |
|
746 | + * @return string |
|
747 | + */ |
|
748 | + public function default_button_url() |
|
749 | + { |
|
750 | + return $this->_default_button_url; |
|
751 | + } |
|
752 | + |
|
753 | + |
|
754 | + /** |
|
755 | + * Gets the gateway used by this payment method (if any) |
|
756 | + * |
|
757 | + * @return EE_Gateway |
|
758 | + */ |
|
759 | + public function get_gateway() |
|
760 | + { |
|
761 | + return $this->_gateway; |
|
762 | + } |
|
763 | + |
|
764 | + |
|
765 | + /** |
|
766 | + * @return string html for the link to a help tab |
|
767 | + */ |
|
768 | + public function get_help_tab_link() |
|
769 | + { |
|
770 | + return EEH_Template::get_help_tab_link( |
|
771 | + $this->get_help_tab_name(), |
|
772 | + 'espresso_payment_settings', |
|
773 | + 'default' |
|
774 | + ); |
|
775 | + } |
|
776 | + |
|
777 | + |
|
778 | + /** |
|
779 | + * Returns the name of the help tab for this PMT |
|
780 | + * |
|
781 | + * @return string |
|
782 | + */ |
|
783 | + public function get_help_tab_name() |
|
784 | + { |
|
785 | + return 'ee_' . strtolower($this->system_name()) . '_help_tab'; |
|
786 | + } |
|
787 | + |
|
788 | + /** |
|
789 | + * The name of the wp capability that should be associated with the usage of |
|
790 | + * this PMT by an admin |
|
791 | + * |
|
792 | + * @return string |
|
793 | + */ |
|
794 | + public function cap_name() |
|
795 | + { |
|
796 | + return 'ee_payment_method_' . strtolower($this->system_name()); |
|
797 | + } |
|
798 | + |
|
799 | + /** |
|
800 | + * Called by client code to tell the gateway that if it wants to change |
|
801 | + * the transaction or line items or registrations related to teh payment it already |
|
802 | + * processed (we think, but possibly not) that now's the time to do it. |
|
803 | + * It is expected that gateways will store any info they need for this on the PAY_details, |
|
804 | + * or maybe an extra meta value |
|
805 | + * |
|
806 | + * @param EE_Payment $payment |
|
807 | + * @return void |
|
808 | + */ |
|
809 | + public function update_txn_based_on_payment($payment) |
|
810 | + { |
|
811 | + if ($this->_gateway instanceof EE_Gateway) { |
|
812 | + $this->_gateway->update_txn_based_on_payment($payment); |
|
813 | + } |
|
814 | + } |
|
815 | + |
|
816 | + /** |
|
817 | + * Returns a string of HTML describing this payment method type for an admin, |
|
818 | + * primarily intended for them to read before activating it. |
|
819 | + * The easiest way to set this is to create a folder 'templates' alongside |
|
820 | + * your EE_PMT_{System_Name} file, and in it create a file named "{system_name}_intro.template.php". |
|
821 | + * Eg, if your payment method file is named "EE_PMT_Foo_Bar.pm.php", |
|
822 | + * then you'd create a file named "templates" in the same folder as it, and name the file |
|
823 | + * "foo_bar_intro.template.php", and its content will be returned by this method |
|
824 | + * |
|
825 | + * @return string |
|
826 | + */ |
|
827 | + public function introductory_html() |
|
828 | + { |
|
829 | + return EEH_Template::locate_template( |
|
830 | + $this->file_folder() . 'templates/' . strtolower($this->system_name()) . '_intro.template.php', |
|
831 | + array('pmt_obj' => $this, 'pm_instance' => $this->_pm_instance) |
|
832 | + ); |
|
833 | + } |
|
834 | 834 | } |
@@ -50,7 +50,7 @@ discard block |
||
50 | 50 | */ |
51 | 51 | public function getModelVersionInfo() |
52 | 52 | { |
53 | - if (! $this->model_version_info) { |
|
53 | + if ( ! $this->model_version_info) { |
|
54 | 54 | throw new EE_Error( |
55 | 55 | sprintf( |
56 | 56 | esc_html__( |
@@ -95,7 +95,7 @@ discard block |
||
95 | 95 | */ |
96 | 96 | protected function validateModel($model_name) |
97 | 97 | { |
98 | - if (! $this->getModelVersionInfo()->isModelNameInThisVersion($model_name)) { |
|
98 | + if ( ! $this->getModelVersionInfo()->isModelNameInThisVersion($model_name)) { |
|
99 | 99 | throw new RestException( |
100 | 100 | 'endpoint_parsing_error', |
101 | 101 | sprintf( |
@@ -18,95 +18,95 @@ |
||
18 | 18 | */ |
19 | 19 | class Base extends Controller_Base |
20 | 20 | { |
21 | - /** |
|
22 | - * Holds reference to the model version info, which knows the requested version |
|
23 | - * |
|
24 | - * @var ModelVersionInfo |
|
25 | - */ |
|
26 | - protected $model_version_info; |
|
21 | + /** |
|
22 | + * Holds reference to the model version info, which knows the requested version |
|
23 | + * |
|
24 | + * @var ModelVersionInfo |
|
25 | + */ |
|
26 | + protected $model_version_info; |
|
27 | 27 | |
28 | 28 | |
29 | 29 | |
30 | - /** |
|
31 | - * Sets the version the user requested |
|
32 | - * |
|
33 | - * @param string $version eg '4.8' |
|
34 | - */ |
|
35 | - public function setRequestedVersion($version) |
|
36 | - { |
|
37 | - parent::setRequestedVersion($version); |
|
38 | - $this->model_version_info = new ModelVersionInfo($version); |
|
39 | - } |
|
30 | + /** |
|
31 | + * Sets the version the user requested |
|
32 | + * |
|
33 | + * @param string $version eg '4.8' |
|
34 | + */ |
|
35 | + public function setRequestedVersion($version) |
|
36 | + { |
|
37 | + parent::setRequestedVersion($version); |
|
38 | + $this->model_version_info = new ModelVersionInfo($version); |
|
39 | + } |
|
40 | 40 | |
41 | 41 | |
42 | 42 | |
43 | - /** |
|
44 | - * Gets the object that should be used for getting any info from the models, |
|
45 | - * because it's takes the requested and current core version into account |
|
46 | - * |
|
47 | - * @return \EventEspresso\core\libraries\rest_api\ModelVersionInfo |
|
48 | - * @throws EE_Error |
|
49 | - */ |
|
50 | - public function getModelVersionInfo() |
|
51 | - { |
|
52 | - if (! $this->model_version_info) { |
|
53 | - throw new EE_Error( |
|
54 | - sprintf( |
|
55 | - esc_html__( |
|
56 | - 'Cannot use model version info before setting the requested version in the controller', |
|
57 | - 'event_espresso' |
|
58 | - ) |
|
59 | - ) |
|
60 | - ); |
|
61 | - } |
|
62 | - return $this->model_version_info; |
|
63 | - } |
|
43 | + /** |
|
44 | + * Gets the object that should be used for getting any info from the models, |
|
45 | + * because it's takes the requested and current core version into account |
|
46 | + * |
|
47 | + * @return \EventEspresso\core\libraries\rest_api\ModelVersionInfo |
|
48 | + * @throws EE_Error |
|
49 | + */ |
|
50 | + public function getModelVersionInfo() |
|
51 | + { |
|
52 | + if (! $this->model_version_info) { |
|
53 | + throw new EE_Error( |
|
54 | + sprintf( |
|
55 | + esc_html__( |
|
56 | + 'Cannot use model version info before setting the requested version in the controller', |
|
57 | + 'event_espresso' |
|
58 | + ) |
|
59 | + ) |
|
60 | + ); |
|
61 | + } |
|
62 | + return $this->model_version_info; |
|
63 | + } |
|
64 | 64 | |
65 | 65 | |
66 | 66 | |
67 | - /** |
|
68 | - * Determines if $object is of one of the classes of $classes. Similar to |
|
69 | - * in_array(), except this checks if $object is a subclass of the classnames provided |
|
70 | - * in $classnames |
|
71 | - * |
|
72 | - * @param object $object |
|
73 | - * @param array $classnames |
|
74 | - * @return boolean |
|
75 | - */ |
|
76 | - public function isSubclassOfOne($object, $classnames) |
|
77 | - { |
|
78 | - foreach ($classnames as $classname) { |
|
79 | - if (is_a($object, $classname)) { |
|
80 | - return true; |
|
81 | - } |
|
82 | - } |
|
83 | - return false; |
|
84 | - } |
|
67 | + /** |
|
68 | + * Determines if $object is of one of the classes of $classes. Similar to |
|
69 | + * in_array(), except this checks if $object is a subclass of the classnames provided |
|
70 | + * in $classnames |
|
71 | + * |
|
72 | + * @param object $object |
|
73 | + * @param array $classnames |
|
74 | + * @return boolean |
|
75 | + */ |
|
76 | + public function isSubclassOfOne($object, $classnames) |
|
77 | + { |
|
78 | + foreach ($classnames as $classname) { |
|
79 | + if (is_a($object, $classname)) { |
|
80 | + return true; |
|
81 | + } |
|
82 | + } |
|
83 | + return false; |
|
84 | + } |
|
85 | 85 | |
86 | - /** |
|
87 | - * Verifies the model name provided was valid. If so, returns the model (as an object). Otherwise, throws an |
|
88 | - * exception. Must be called after `setRequestedVersion()`. |
|
89 | - * @since 4.9.76.p |
|
90 | - * @param $model_name |
|
91 | - * @return EEM_Base |
|
92 | - * @throws EE_Error |
|
93 | - * @throws RestException |
|
94 | - */ |
|
95 | - protected function validateModel($model_name) |
|
96 | - { |
|
97 | - if (! $this->getModelVersionInfo()->isModelNameInThisVersion($model_name)) { |
|
98 | - throw new RestException( |
|
99 | - 'endpoint_parsing_error', |
|
100 | - sprintf( |
|
101 | - esc_html__( |
|
102 | - 'There is no model for endpoint %s. Please contact event espresso support', |
|
103 | - 'event_espresso' |
|
104 | - ), |
|
105 | - $model_name |
|
106 | - ) |
|
107 | - ); |
|
108 | - } |
|
109 | - return $this->getModelVersionInfo()->loadModel($model_name); |
|
110 | - } |
|
86 | + /** |
|
87 | + * Verifies the model name provided was valid. If so, returns the model (as an object). Otherwise, throws an |
|
88 | + * exception. Must be called after `setRequestedVersion()`. |
|
89 | + * @since 4.9.76.p |
|
90 | + * @param $model_name |
|
91 | + * @return EEM_Base |
|
92 | + * @throws EE_Error |
|
93 | + * @throws RestException |
|
94 | + */ |
|
95 | + protected function validateModel($model_name) |
|
96 | + { |
|
97 | + if (! $this->getModelVersionInfo()->isModelNameInThisVersion($model_name)) { |
|
98 | + throw new RestException( |
|
99 | + 'endpoint_parsing_error', |
|
100 | + sprintf( |
|
101 | + esc_html__( |
|
102 | + 'There is no model for endpoint %s. Please contact event espresso support', |
|
103 | + 'event_espresso' |
|
104 | + ), |
|
105 | + $model_name |
|
106 | + ) |
|
107 | + ); |
|
108 | + } |
|
109 | + return $this->getModelVersionInfo()->loadModel($model_name); |
|
110 | + } |
|
111 | 111 | } |
112 | 112 | // End of file Base.php |
@@ -86,7 +86,7 @@ discard block |
||
86 | 86 | LoaderFactory::getLoader()->getNew('EventEspresso\core\libraries\rest_api\controllers\model\Read'); |
87 | 87 | try { |
88 | 88 | $controller->setRequestedVersion($version); |
89 | - if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) { |
|
89 | + if ( ! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) { |
|
90 | 90 | return $controller->sendResponse( |
91 | 91 | new WP_Error( |
92 | 92 | 'endpoint_parsing_error', |
@@ -128,7 +128,7 @@ discard block |
||
128 | 128 | LoaderFactory::getLoader()->getNew('EventEspresso\core\libraries\rest_api\controllers\model\Read'); |
129 | 129 | try { |
130 | 130 | $controller->setRequestedVersion($version); |
131 | - if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) { |
|
131 | + if ( ! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) { |
|
132 | 132 | return []; |
133 | 133 | } |
134 | 134 | // get the model for this version |
@@ -192,11 +192,11 @@ discard block |
||
192 | 192 | */ |
193 | 193 | protected function translateDefaultsForRestResponse($field_name, EE_Model_Field_Base $field, array $schema) |
194 | 194 | { |
195 | - if (isset($schema['properties'][ $field_name ]['default'])) { |
|
196 | - if (is_array($schema['properties'][ $field_name ]['default'])) { |
|
197 | - foreach ($schema['properties'][ $field_name ]['default'] as $default_key => $default_value) { |
|
195 | + if (isset($schema['properties'][$field_name]['default'])) { |
|
196 | + if (is_array($schema['properties'][$field_name]['default'])) { |
|
197 | + foreach ($schema['properties'][$field_name]['default'] as $default_key => $default_value) { |
|
198 | 198 | if ($default_key === 'raw') { |
199 | - $schema['properties'][ $field_name ]['default'][ $default_key ] = |
|
199 | + $schema['properties'][$field_name]['default'][$default_key] = |
|
200 | 200 | ModelDataTranslator::prepareFieldValueForJson( |
201 | 201 | $field, |
202 | 202 | $default_value, |
@@ -205,9 +205,9 @@ discard block |
||
205 | 205 | } |
206 | 206 | } |
207 | 207 | } else { |
208 | - $schema['properties'][ $field_name ]['default'] = ModelDataTranslator::prepareFieldValueForJson( |
|
208 | + $schema['properties'][$field_name]['default'] = ModelDataTranslator::prepareFieldValueForJson( |
|
209 | 209 | $field, |
210 | - $schema['properties'][ $field_name ]['default'], |
|
210 | + $schema['properties'][$field_name]['default'], |
|
211 | 211 | $this->getModelVersionInfo()->requestedVersion() |
212 | 212 | ); |
213 | 213 | } |
@@ -229,9 +229,9 @@ discard block |
||
229 | 229 | protected function maybeAddExtraFieldsToSchema($field_name, EE_Model_Field_Base $field, array $schema) |
230 | 230 | { |
231 | 231 | if ($field instanceof EE_Datetime_Field) { |
232 | - $schema['properties'][ $field_name . '_gmt' ] = $field->getSchema(); |
|
232 | + $schema['properties'][$field_name.'_gmt'] = $field->getSchema(); |
|
233 | 233 | // modify the description |
234 | - $schema['properties'][ $field_name . '_gmt' ]['description'] = sprintf( |
|
234 | + $schema['properties'][$field_name.'_gmt']['description'] = sprintf( |
|
235 | 235 | esc_html__('%s - the value for this field is in GMT.', 'event_espresso'), |
236 | 236 | wp_specialchars_decode($field->get_nicename(), ENT_QUOTES) |
237 | 237 | ); |
@@ -280,7 +280,7 @@ discard block |
||
280 | 280 | LoaderFactory::getLoader()->getNew('EventEspresso\core\libraries\rest_api\controllers\model\Read'); |
281 | 281 | try { |
282 | 282 | $controller->setRequestedVersion($version); |
283 | - if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) { |
|
283 | + if ( ! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) { |
|
284 | 284 | return $controller->sendResponse( |
285 | 285 | new WP_Error( |
286 | 286 | 'endpoint_parsing_error', |
@@ -360,7 +360,7 @@ discard block |
||
360 | 360 | public function getEntitiesFromModel($model, $request) |
361 | 361 | { |
362 | 362 | $query_params = $this->createModelQueryParams($model, $request->get_params()); |
363 | - if (! Capabilities::currentUserHasPartialAccessTo($model, $query_params['caps'])) { |
|
363 | + if ( ! Capabilities::currentUserHasPartialAccessTo($model, $query_params['caps'])) { |
|
364 | 364 | $model_name_plural = EEH_Inflector::pluralize_and_lower($model->get_this_model_name()); |
365 | 365 | throw new RestException( |
366 | 366 | sprintf('rest_%s_cannot_list', $model_name_plural), |
@@ -372,7 +372,7 @@ discard block |
||
372 | 372 | ['status' => 403] |
373 | 373 | ); |
374 | 374 | } |
375 | - if (! $request->get_header('no_rest_headers')) { |
|
375 | + if ( ! $request->get_header('no_rest_headers')) { |
|
376 | 376 | $this->setHeadersFromQueryParams($model, $query_params); |
377 | 377 | } |
378 | 378 | /** @type array $results */ |
@@ -413,7 +413,7 @@ discard block |
||
413 | 413 | $context = $this->validateContext($request->get_param('caps')); |
414 | 414 | $model = $relation->get_this_model(); |
415 | 415 | $related_model = $relation->get_other_model(); |
416 | - if (! isset($primary_model_query_params[0])) { |
|
416 | + if ( ! isset($primary_model_query_params[0])) { |
|
417 | 417 | $primary_model_query_params[0] = []; |
418 | 418 | } |
419 | 419 | // check if they can access the 1st model object |
@@ -477,13 +477,13 @@ discard block |
||
477 | 477 | ); |
478 | 478 | $query_params = $this->createModelQueryParams($relation->get_other_model(), $request->get_params()); |
479 | 479 | foreach ($primary_model_query_params[0] as $where_condition_key => $where_condition_value) { |
480 | - $query_params[0][ $relation->get_this_model()->get_this_model_name() |
|
480 | + $query_params[0][$relation->get_this_model()->get_this_model_name() |
|
481 | 481 | . '.' |
482 | - . $where_condition_key ] = $where_condition_value; |
|
482 | + . $where_condition_key] = $where_condition_value; |
|
483 | 483 | } |
484 | 484 | $query_params['default_where_conditions'] = 'none'; |
485 | 485 | $query_params['caps'] = $context; |
486 | - if (! $request->get_header('no_rest_headers')) { |
|
486 | + if ( ! $request->get_header('no_rest_headers')) { |
|
487 | 487 | $this->setHeadersFromQueryParams($relation->get_other_model(), $query_params); |
488 | 488 | } |
489 | 489 | /** @type array $results */ |
@@ -503,7 +503,7 @@ discard block |
||
503 | 503 | $result, |
504 | 504 | $request |
505 | 505 | ); |
506 | - $joined_result = array_merge($join_model_result, $nice_result); |
|
506 | + $joined_result = array_merge($join_model_result, $nice_result); |
|
507 | 507 | // but keep the meta stuff from the main model |
508 | 508 | if (isset($nice_result['meta'])) { |
509 | 509 | $joined_result['meta'] = $nice_result['meta']; |
@@ -535,7 +535,7 @@ discard block |
||
535 | 535 | */ |
536 | 536 | public function getEntitiesFromRelation($id, $relation, $request) |
537 | 537 | { |
538 | - if (! $relation->get_this_model()->has_primary_key_field()) { |
|
538 | + if ( ! $relation->get_this_model()->has_primary_key_field()) { |
|
539 | 539 | throw new EE_Error( |
540 | 540 | sprintf( |
541 | 541 | esc_html__( |
@@ -582,7 +582,7 @@ discard block |
||
582 | 582 | Capabilities::getMissingPermissionsString($model, $query_params['caps']) |
583 | 583 | ); |
584 | 584 | // normally the limit to a 2-part array, where the 2nd item is the limit |
585 | - if (! isset($query_params['limit'])) { |
|
585 | + if ( ! isset($query_params['limit'])) { |
|
586 | 586 | $query_params['limit'] = EED_Core_Rest_Api::get_default_query_limit(); |
587 | 587 | } |
588 | 588 | if (is_array($query_params['limit'])) { |
@@ -621,7 +621,7 @@ discard block |
||
621 | 621 | */ |
622 | 622 | public function createEntityFromWpdbResult($model, $db_row, $rest_request, $deprecated = null) |
623 | 623 | { |
624 | - if (! $rest_request instanceof WP_REST_Request) { |
|
624 | + if ( ! $rest_request instanceof WP_REST_Request) { |
|
625 | 625 | // ok so this was called in the old style, where the 3rd arg was |
626 | 626 | // $include, and the 4th arg was $context |
627 | 627 | // now setup the request just to avoid fatal errors, although we won't be able |
@@ -698,7 +698,7 @@ discard block |
||
698 | 698 | $rest_request, |
699 | 699 | $this |
700 | 700 | ); |
701 | - if (! $current_user_full_access_to_entity) { |
|
701 | + if ( ! $current_user_full_access_to_entity) { |
|
702 | 702 | $result_without_inaccessible_fields = Capabilities::filterOutInaccessibleEntityFields( |
703 | 703 | $entity_array, |
704 | 704 | $model, |
@@ -733,7 +733,7 @@ discard block |
||
733 | 733 | */ |
734 | 734 | protected function addProtectedProperty(EEM_Base $model, $results_so_far, $protected) |
735 | 735 | { |
736 | - if (! $model->hasPassword() || ! $protected) { |
|
736 | + if ( ! $model->hasPassword() || ! $protected) { |
|
737 | 737 | return $results_so_far; |
738 | 738 | } |
739 | 739 | $password_field = $model->getPasswordField(); |
@@ -782,8 +782,8 @@ discard block |
||
782 | 782 | if ($do_chevy_shuffle) { |
783 | 783 | global $post; |
784 | 784 | $old_post = $post; |
785 | - $post = get_post($result[ $model->primary_key_name() ]); |
|
786 | - if (! $post instanceof WP_Post) { |
|
785 | + $post = get_post($result[$model->primary_key_name()]); |
|
786 | + if ( ! $post instanceof WP_Post) { |
|
787 | 787 | // well that's weird, because $result is what we JUST fetched from the database |
788 | 788 | throw new RestException( |
789 | 789 | 'error_fetching_post_from_database_results', |
@@ -793,7 +793,7 @@ discard block |
||
793 | 793 | ) |
794 | 794 | ); |
795 | 795 | } |
796 | - $model_object_classname = 'EE_' . $model->get_this_model_name(); |
|
796 | + $model_object_classname = 'EE_'.$model->get_this_model_name(); |
|
797 | 797 | $post->{$model_object_classname} = EE_Registry::instance()->load_class( |
798 | 798 | $model_object_classname, |
799 | 799 | $result, |
@@ -804,14 +804,14 @@ discard block |
||
804 | 804 | foreach ($result as $field_name => $field_value) { |
805 | 805 | $field_obj = $model->field_settings_for($field_name); |
806 | 806 | if ($this->isSubclassOfOne($field_obj, $this->getModelVersionInfo()->fieldsIgnored())) { |
807 | - unset($result[ $field_name ]); |
|
807 | + unset($result[$field_name]); |
|
808 | 808 | } elseif ( |
809 | 809 | $this->isSubclassOfOne( |
810 | 810 | $field_obj, |
811 | 811 | $this->getModelVersionInfo()->fieldsThatHaveRenderedFormat() |
812 | 812 | ) |
813 | 813 | ) { |
814 | - $result[ $field_name ] = [ |
|
814 | + $result[$field_name] = [ |
|
815 | 815 | 'raw' => $this->prepareFieldObjValueForJson($field_obj, $field_value), |
816 | 816 | 'rendered' => $this->prepareFieldObjValueForJson($field_obj, $field_value, 'pretty'), |
817 | 817 | ]; |
@@ -821,7 +821,7 @@ discard block |
||
821 | 821 | $this->getModelVersionInfo()->fieldsThatHavePrettyFormat() |
822 | 822 | ) |
823 | 823 | ) { |
824 | - $result[ $field_name ] = [ |
|
824 | + $result[$field_name] = [ |
|
825 | 825 | 'raw' => $this->prepareFieldObjValueForJson($field_obj, $field_value), |
826 | 826 | 'pretty' => $this->prepareFieldObjValueForJson($field_obj, $field_value, 'pretty'), |
827 | 827 | ]; |
@@ -852,10 +852,10 @@ discard block |
||
852 | 852 | $this->getModelVersionInfo()->requestedVersion() |
853 | 853 | ); |
854 | 854 | } |
855 | - $result[ $field_name . '_gmt' ] = $gmt_date; |
|
856 | - $result[ $field_name ] = $local_date; |
|
855 | + $result[$field_name.'_gmt'] = $gmt_date; |
|
856 | + $result[$field_name] = $local_date; |
|
857 | 857 | } else { |
858 | - $result[ $field_name ] = $this->prepareFieldObjValueForJson($field_obj, $field_value); |
|
858 | + $result[$field_name] = $this->prepareFieldObjValueForJson($field_obj, $field_value); |
|
859 | 859 | } |
860 | 860 | } |
861 | 861 | if ($do_chevy_shuffle) { |
@@ -910,7 +910,7 @@ discard block |
||
910 | 910 | protected function addExtraFields(EEM_Base $model, $db_row, $entity_array) |
911 | 911 | { |
912 | 912 | if ($model instanceof EEM_CPT_Base) { |
913 | - $entity_array['link'] = get_permalink($db_row[ $model->get_primary_key_field()->get_qualified_column() ]); |
|
913 | + $entity_array['link'] = get_permalink($db_row[$model->get_primary_key_field()->get_qualified_column()]); |
|
914 | 914 | } |
915 | 915 | return $entity_array; |
916 | 916 | } |
@@ -937,7 +937,7 @@ discard block |
||
937 | 937 | 'href' => $this->getVersionedLinkTo( |
938 | 938 | EEH_Inflector::pluralize_and_lower($model->get_this_model_name()) |
939 | 939 | . '/' |
940 | - . $entity_array[ $model->primary_key_name() ] |
|
940 | + . $entity_array[$model->primary_key_name()] |
|
941 | 941 | ), |
942 | 942 | ], |
943 | 943 | ]; |
@@ -954,12 +954,12 @@ discard block |
||
954 | 954 | foreach ($this->getModelVersionInfo()->relationSettings($model) as $relation_name => $relation_obj) { |
955 | 955 | $related_model_part = |
956 | 956 | Read::getRelatedEntityName($relation_name, $relation_obj); |
957 | - $links[ EED_Core_Rest_Api::ee_api_link_namespace . $related_model_part ] = [ |
|
957 | + $links[EED_Core_Rest_Api::ee_api_link_namespace.$related_model_part] = [ |
|
958 | 958 | [ |
959 | 959 | 'href' => $this->getVersionedLinkTo( |
960 | 960 | EEH_Inflector::pluralize_and_lower($model->get_this_model_name()) |
961 | 961 | . '/' |
962 | - . $entity_array[ $model->primary_key_name() ] |
|
962 | + . $entity_array[$model->primary_key_name()] |
|
963 | 963 | . '/' |
964 | 964 | . $related_model_part |
965 | 965 | ), |
@@ -993,12 +993,12 @@ discard block |
||
993 | 993 | $included_items_protected = false |
994 | 994 | ) { |
995 | 995 | // if $db_row not included, hope the entity array has what we need |
996 | - if (! $db_row) { |
|
996 | + if ( ! $db_row) { |
|
997 | 997 | $db_row = $entity_array; |
998 | 998 | } |
999 | 999 | $relation_settings = $this->getModelVersionInfo()->relationSettings($model); |
1000 | 1000 | foreach ($relation_settings as $relation_name => $relation_obj) { |
1001 | - $related_fields_to_include = $this->explodeAndGetItemsPrefixedWith( |
|
1001 | + $related_fields_to_include = $this->explodeAndGetItemsPrefixedWith( |
|
1002 | 1002 | $rest_request->get_param('include'), |
1003 | 1003 | $relation_name |
1004 | 1004 | ); |
@@ -1026,7 +1026,7 @@ discard block |
||
1026 | 1026 | $model->deduce_fields_n_values_from_cols_n_values($db_row) |
1027 | 1027 | ) |
1028 | 1028 | ); |
1029 | - if (! $included_items_protected) { |
|
1029 | + if ( ! $included_items_protected) { |
|
1030 | 1030 | try { |
1031 | 1031 | $related_results = $this->getEntitiesFromRelationUsingModelQueryParams( |
1032 | 1032 | $primary_model_query_params, |
@@ -1047,7 +1047,7 @@ discard block |
||
1047 | 1047 | ? null |
1048 | 1048 | : []; |
1049 | 1049 | } |
1050 | - $entity_array[ Read::getRelatedEntityName($relation_name, $relation_obj) ] = $related_results; |
|
1050 | + $entity_array[Read::getRelatedEntityName($relation_name, $relation_obj)] = $related_results; |
|
1051 | 1051 | } |
1052 | 1052 | } |
1053 | 1053 | return $entity_array; |
@@ -1131,13 +1131,13 @@ discard block |
||
1131 | 1131 | $schema = $this->fields_calculator->getJsonSchemaForModel($model); |
1132 | 1132 | if ( |
1133 | 1133 | $row_is_protected |
1134 | - && isset($schema['properties'][ $field_to_calculate ]['protected']) |
|
1135 | - && $schema['properties'][ $field_to_calculate ]['protected'] |
|
1134 | + && isset($schema['properties'][$field_to_calculate]['protected']) |
|
1135 | + && $schema['properties'][$field_to_calculate]['protected'] |
|
1136 | 1136 | ) { |
1137 | 1137 | $calculated_value = null; |
1138 | 1138 | $protected_fields[] = $field_to_calculate; |
1139 | - if ($schema['properties'][ $field_to_calculate ]['type']) { |
|
1140 | - switch ($schema['properties'][ $field_to_calculate ]['type']) { |
|
1139 | + if ($schema['properties'][$field_to_calculate]['type']) { |
|
1140 | + switch ($schema['properties'][$field_to_calculate]['type']) { |
|
1141 | 1141 | case 'boolean': |
1142 | 1142 | $calculated_value = false; |
1143 | 1143 | break; |
@@ -1252,7 +1252,7 @@ discard block |
||
1252 | 1252 | */ |
1253 | 1253 | public function validateContext($context) |
1254 | 1254 | { |
1255 | - if (! $context) { |
|
1255 | + if ( ! $context) { |
|
1256 | 1256 | $context = EEM_Base::caps_read; |
1257 | 1257 | } |
1258 | 1258 | $valid_contexts = EEM_Base::valid_cap_contexts(); |
@@ -1277,7 +1277,7 @@ discard block |
||
1277 | 1277 | EEM_Base::default_where_conditions_minimum_all, |
1278 | 1278 | EEM_Base::default_where_conditions_minimum_others, |
1279 | 1279 | ]; |
1280 | - if (! $default_query_params) { |
|
1280 | + if ( ! $default_query_params) { |
|
1281 | 1281 | $default_query_params = EEM_Base::default_where_conditions_all; |
1282 | 1282 | } |
1283 | 1283 | if ( |
@@ -1363,14 +1363,14 @@ discard block |
||
1363 | 1363 | } |
1364 | 1364 | if (isset($query_params['limit'])) { |
1365 | 1365 | // limit should be either a string like '23' or '23,43', or an array with two items in it |
1366 | - if (! is_array($query_params['limit'])) { |
|
1366 | + if ( ! is_array($query_params['limit'])) { |
|
1367 | 1367 | $limit_array = explode(',', (string) $query_params['limit']); |
1368 | 1368 | } else { |
1369 | 1369 | $limit_array = $query_params['limit']; |
1370 | 1370 | } |
1371 | 1371 | $sanitized_limit = []; |
1372 | 1372 | foreach ($limit_array as $limit_part) { |
1373 | - if ($this->debug_mode && (! is_numeric($limit_part) || count($sanitized_limit) > 2)) { |
|
1373 | + if ($this->debug_mode && ( ! is_numeric($limit_part) || count($sanitized_limit) > 2)) { |
|
1374 | 1374 | throw new EE_Error( |
1375 | 1375 | sprintf( |
1376 | 1376 | esc_html__( |
@@ -1428,7 +1428,7 @@ discard block |
||
1428 | 1428 | { |
1429 | 1429 | $model_ready_query_params = []; |
1430 | 1430 | foreach ($query_params as $key => $value) { |
1431 | - $model_ready_query_params[ $key ] = is_array($value) |
|
1431 | + $model_ready_query_params[$key] = is_array($value) |
|
1432 | 1432 | ? $this->prepareRestQueryParamsKeyForModels($model, $value) |
1433 | 1433 | : $value; |
1434 | 1434 | } |
@@ -1447,9 +1447,9 @@ discard block |
||
1447 | 1447 | $model_ready_query_params = []; |
1448 | 1448 | foreach ($query_params as $key => $value) { |
1449 | 1449 | if (is_array($value)) { |
1450 | - $model_ready_query_params[ $key ] = $this->prepareRestQueryParamsValuesForModels($model, $value); |
|
1450 | + $model_ready_query_params[$key] = $this->prepareRestQueryParamsValuesForModels($model, $value); |
|
1451 | 1451 | } else { |
1452 | - $model_ready_query_params[ $key ] = $value; |
|
1452 | + $model_ready_query_params[$key] = $value; |
|
1453 | 1453 | } |
1454 | 1454 | } |
1455 | 1455 | return $model_ready_query_params; |
@@ -1481,17 +1481,17 @@ discard block |
||
1481 | 1481 | foreach ($exploded_contents as $item) { |
1482 | 1482 | $item = trim($item); |
1483 | 1483 | // if no prefix was provided, so we look for items with no "." in them |
1484 | - if (! $prefix) { |
|
1484 | + if ( ! $prefix) { |
|
1485 | 1485 | // does this item have a period? |
1486 | 1486 | if (strpos($item, '.') === false) { |
1487 | 1487 | // if not, then its what we're looking for |
1488 | 1488 | $contents_with_prefix[] = $item; |
1489 | 1489 | } |
1490 | - } elseif (strpos($item, $prefix . '.') === 0) { |
|
1490 | + } elseif (strpos($item, $prefix.'.') === 0) { |
|
1491 | 1491 | // this item has the prefix and a period, grab it |
1492 | 1492 | $contents_with_prefix[] = substr( |
1493 | 1493 | $item, |
1494 | - strpos($item, $prefix . '.') + strlen($prefix . '.') |
|
1494 | + strpos($item, $prefix.'.') + strlen($prefix.'.') |
|
1495 | 1495 | ); |
1496 | 1496 | } elseif ($item === $prefix) { |
1497 | 1497 | // this item is JUST the prefix |
@@ -1533,9 +1533,9 @@ discard block |
||
1533 | 1533 | if ($model_name) { |
1534 | 1534 | foreach ($includes as $field_to_include) { |
1535 | 1535 | $field_to_include = trim($field_to_include); |
1536 | - if (strpos($field_to_include, $model_name . '.') === 0) { |
|
1536 | + if (strpos($field_to_include, $model_name.'.') === 0) { |
|
1537 | 1537 | // found the model name at the exact start |
1538 | - $field_sans_model_name = str_replace($model_name . '.', '', $field_to_include); |
|
1538 | + $field_sans_model_name = str_replace($model_name.'.', '', $field_to_include); |
|
1539 | 1539 | $extracted_fields_to_include[] = $field_sans_model_name; |
1540 | 1540 | } elseif ($field_to_include == $model_name) { |
1541 | 1541 | $extracted_fields_to_include[] = '*'; |
@@ -1578,7 +1578,7 @@ discard block |
||
1578 | 1578 | $restricted_query_params['caps'] = $context; |
1579 | 1579 | $this->setDebugInfo('model query params', $restricted_query_params); |
1580 | 1580 | $model_rows = $model->get_all_wpdb_results($restricted_query_params); |
1581 | - if (! empty($model_rows)) { |
|
1581 | + if ( ! empty($model_rows)) { |
|
1582 | 1582 | return $this->createEntityFromWpdbResult( |
1583 | 1583 | $model, |
1584 | 1584 | reset($model_rows), |
@@ -1590,7 +1590,7 @@ discard block |
||
1590 | 1590 | if ($model->exists($query_params)) { |
1591 | 1591 | // you got shafted- it existed but we didn't want to tell you! |
1592 | 1592 | throw new RestException( |
1593 | - 'rest_user_cannot_' . $context, |
|
1593 | + 'rest_user_cannot_'.$context, |
|
1594 | 1594 | sprintf( |
1595 | 1595 | esc_html__('Sorry, you cannot %1$s this %2$s. Missing permissions are: %3$s', 'event_espresso'), |
1596 | 1596 | $context, |
@@ -1644,14 +1644,14 @@ discard block |
||
1644 | 1644 | // if this entity requires a password, they better give it and it better be right! |
1645 | 1645 | if ( |
1646 | 1646 | $model->hasPassword() |
1647 | - && $model_row[ $model->getPasswordField()->get_qualified_column() ] !== '' |
|
1647 | + && $model_row[$model->getPasswordField()->get_qualified_column()] !== '' |
|
1648 | 1648 | ) { |
1649 | 1649 | if (empty($request['password'])) { |
1650 | 1650 | throw new RestPasswordRequiredException(); |
1651 | 1651 | } |
1652 | 1652 | if ( |
1653 | 1653 | ! hash_equals( |
1654 | - $model_row[ $model->getPasswordField()->get_qualified_column() ], |
|
1654 | + $model_row[$model->getPasswordField()->get_qualified_column()], |
|
1655 | 1655 | $request['password'] |
1656 | 1656 | ) |
1657 | 1657 | ) { |
@@ -1665,12 +1665,12 @@ discard block |
||
1665 | 1665 | $password_supplied = $request->get_param('password'); |
1666 | 1666 | if (empty($password_supplied)) { |
1667 | 1667 | $query_params['exclude_protected'] = true; |
1668 | - if (! $model->exists($query_params)) { |
|
1668 | + if ( ! $model->exists($query_params)) { |
|
1669 | 1669 | throw new RestPasswordRequiredException(); |
1670 | 1670 | } |
1671 | 1671 | } else { |
1672 | - $query_params[0][ $model->modelChainAndPassword() ] = $password_supplied; |
|
1673 | - if (! $model->exists($query_params)) { |
|
1672 | + $query_params[0][$model->modelChainAndPassword()] = $password_supplied; |
|
1673 | + if ( ! $model->exists($query_params)) { |
|
1674 | 1674 | throw new RestPasswordIncorrectException(); |
1675 | 1675 | } |
1676 | 1676 | } |
@@ -49,1629 +49,1629 @@ |
||
49 | 49 | */ |
50 | 50 | class Read extends Base |
51 | 51 | { |
52 | - /** |
|
53 | - * @var CalculatedModelFields |
|
54 | - */ |
|
55 | - protected $fields_calculator; |
|
56 | - |
|
57 | - |
|
58 | - /** |
|
59 | - * Read constructor. |
|
60 | - * |
|
61 | - * @param CalculatedModelFields $fields_calculator |
|
62 | - */ |
|
63 | - public function __construct(CalculatedModelFields $fields_calculator) |
|
64 | - { |
|
65 | - parent::__construct(); |
|
66 | - $this->fields_calculator = $fields_calculator; |
|
67 | - } |
|
68 | - |
|
69 | - |
|
70 | - /** |
|
71 | - * Handles requests to get all (or a filtered subset) of entities for a particular model |
|
72 | - * |
|
73 | - * @param WP_REST_Request $request |
|
74 | - * @param string $version |
|
75 | - * @param string $model_name |
|
76 | - * @return WP_REST_Response|WP_Error |
|
77 | - * @throws InvalidArgumentException |
|
78 | - * @throws InvalidDataTypeException |
|
79 | - * @throws InvalidInterfaceException |
|
80 | - */ |
|
81 | - public static function handleRequestGetAll(WP_REST_Request $request, $version, $model_name) |
|
82 | - { |
|
83 | - $controller = |
|
84 | - LoaderFactory::getLoader()->getNew('EventEspresso\core\libraries\rest_api\controllers\model\Read'); |
|
85 | - try { |
|
86 | - $controller->setRequestedVersion($version); |
|
87 | - if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) { |
|
88 | - return $controller->sendResponse( |
|
89 | - new WP_Error( |
|
90 | - 'endpoint_parsing_error', |
|
91 | - sprintf( |
|
92 | - esc_html__( |
|
93 | - 'There is no model for endpoint %s. Please contact event espresso support', |
|
94 | - 'event_espresso' |
|
95 | - ), |
|
96 | - $model_name |
|
97 | - ) |
|
98 | - ) |
|
99 | - ); |
|
100 | - } |
|
101 | - return $controller->sendResponse( |
|
102 | - $controller->getEntitiesFromModel( |
|
103 | - $controller->getModelVersionInfo()->loadModel($model_name), |
|
104 | - $request |
|
105 | - ) |
|
106 | - ); |
|
107 | - } catch (Exception $e) { |
|
108 | - return $controller->sendResponse($e); |
|
109 | - } |
|
110 | - } |
|
111 | - |
|
112 | - |
|
113 | - /** |
|
114 | - * Prepares and returns schema for any OPTIONS request. |
|
115 | - * |
|
116 | - * @param string $version The API endpoint version being used. |
|
117 | - * @param string $model_name Something like `Event` or `Registration` |
|
118 | - * @return array |
|
119 | - * @throws InvalidArgumentException |
|
120 | - * @throws InvalidDataTypeException |
|
121 | - * @throws InvalidInterfaceException |
|
122 | - */ |
|
123 | - public static function handleSchemaRequest($version, $model_name) |
|
124 | - { |
|
125 | - $controller = |
|
126 | - LoaderFactory::getLoader()->getNew('EventEspresso\core\libraries\rest_api\controllers\model\Read'); |
|
127 | - try { |
|
128 | - $controller->setRequestedVersion($version); |
|
129 | - if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) { |
|
130 | - return []; |
|
131 | - } |
|
132 | - // get the model for this version |
|
133 | - $model = $controller->getModelVersionInfo()->loadModel($model_name); |
|
134 | - $model_schema = new JsonModelSchema( |
|
135 | - $model, |
|
136 | - LoaderFactory::getLoader()->getShared('EventEspresso\core\libraries\rest_api\CalculatedModelFields') |
|
137 | - ); |
|
138 | - return $model_schema->getModelSchemaForRelations( |
|
139 | - $controller->getModelVersionInfo()->relationSettings($model), |
|
140 | - $controller->customizeSchemaForRestResponse( |
|
141 | - $model, |
|
142 | - $model_schema->getModelSchemaForFields( |
|
143 | - $controller->getModelVersionInfo()->fieldsOnModelInThisVersion($model), |
|
144 | - $model_schema->getInitialSchemaStructure() |
|
145 | - ) |
|
146 | - ) |
|
147 | - ); |
|
148 | - } catch (Exception $e) { |
|
149 | - return []; |
|
150 | - } |
|
151 | - } |
|
152 | - |
|
153 | - |
|
154 | - /** |
|
155 | - * This loops through each field in the given schema for the model and does the following: |
|
156 | - * - add any extra fields that are REST API specific and related to existing fields. |
|
157 | - * - transform default values into the correct format for a REST API response. |
|
158 | - * |
|
159 | - * @param EEM_Base $model |
|
160 | - * @param array $schema |
|
161 | - * @return array The final schema. |
|
162 | - * @throws EE_Error |
|
163 | - * @throws EE_Error |
|
164 | - */ |
|
165 | - protected function customizeSchemaForRestResponse(EEM_Base $model, array $schema) |
|
166 | - { |
|
167 | - foreach ($this->getModelVersionInfo()->fieldsOnModelInThisVersion($model) as $field_name => $field) { |
|
168 | - $schema = $this->translateDefaultsForRestResponse( |
|
169 | - $field_name, |
|
170 | - $field, |
|
171 | - $this->maybeAddExtraFieldsToSchema($field_name, $field, $schema) |
|
172 | - ); |
|
173 | - } |
|
174 | - return $schema; |
|
175 | - } |
|
176 | - |
|
177 | - |
|
178 | - /** |
|
179 | - * This is used to ensure that the 'default' value set in the schema response is formatted correctly for the REST |
|
180 | - * response. |
|
181 | - * |
|
182 | - * @param $field_name |
|
183 | - * @param EE_Model_Field_Base $field |
|
184 | - * @param array $schema |
|
185 | - * @return array |
|
186 | - * @throws RestException if a default value has a PHP object, which we should never do |
|
187 | - * (but if we did, let's know about it ASAP, so let the exception bubble up) |
|
188 | - * @throws EE_Error |
|
189 | - * |
|
190 | - */ |
|
191 | - protected function translateDefaultsForRestResponse($field_name, EE_Model_Field_Base $field, array $schema) |
|
192 | - { |
|
193 | - if (isset($schema['properties'][ $field_name ]['default'])) { |
|
194 | - if (is_array($schema['properties'][ $field_name ]['default'])) { |
|
195 | - foreach ($schema['properties'][ $field_name ]['default'] as $default_key => $default_value) { |
|
196 | - if ($default_key === 'raw') { |
|
197 | - $schema['properties'][ $field_name ]['default'][ $default_key ] = |
|
198 | - ModelDataTranslator::prepareFieldValueForJson( |
|
199 | - $field, |
|
200 | - $default_value, |
|
201 | - $this->getModelVersionInfo()->requestedVersion() |
|
202 | - ); |
|
203 | - } |
|
204 | - } |
|
205 | - } else { |
|
206 | - $schema['properties'][ $field_name ]['default'] = ModelDataTranslator::prepareFieldValueForJson( |
|
207 | - $field, |
|
208 | - $schema['properties'][ $field_name ]['default'], |
|
209 | - $this->getModelVersionInfo()->requestedVersion() |
|
210 | - ); |
|
211 | - } |
|
212 | - } |
|
213 | - return $schema; |
|
214 | - } |
|
215 | - |
|
216 | - |
|
217 | - /** |
|
218 | - * Adds additional fields to the schema |
|
219 | - * The REST API returns a GMT value field for each datetime field in the resource. Thus the description about this |
|
220 | - * needs to be added to the schema. |
|
221 | - * |
|
222 | - * @param $field_name |
|
223 | - * @param EE_Model_Field_Base $field |
|
224 | - * @param array $schema |
|
225 | - * @return array |
|
226 | - */ |
|
227 | - protected function maybeAddExtraFieldsToSchema($field_name, EE_Model_Field_Base $field, array $schema) |
|
228 | - { |
|
229 | - if ($field instanceof EE_Datetime_Field) { |
|
230 | - $schema['properties'][ $field_name . '_gmt' ] = $field->getSchema(); |
|
231 | - // modify the description |
|
232 | - $schema['properties'][ $field_name . '_gmt' ]['description'] = sprintf( |
|
233 | - esc_html__('%s - the value for this field is in GMT.', 'event_espresso'), |
|
234 | - wp_specialchars_decode($field->get_nicename(), ENT_QUOTES) |
|
235 | - ); |
|
236 | - } |
|
237 | - return $schema; |
|
238 | - } |
|
239 | - |
|
240 | - |
|
241 | - /** |
|
242 | - * Used to figure out the route from the request when a `WP_REST_Request` object is not available |
|
243 | - * |
|
244 | - * @return string |
|
245 | - */ |
|
246 | - protected function getRouteFromRequest() |
|
247 | - { |
|
248 | - if ( |
|
249 | - isset($GLOBALS['wp']) |
|
250 | - && $GLOBALS['wp'] instanceof WP |
|
251 | - && isset($GLOBALS['wp']->query_vars['rest_route']) |
|
252 | - ) { |
|
253 | - return $GLOBALS['wp']->query_vars['rest_route']; |
|
254 | - } else { |
|
255 | - /** @var RequestInterface $request */ |
|
256 | - $request = LoaderFactory::getLoader()->getShared(RequestInterface::class); |
|
257 | - return $request->serverParamIsSet('PATH_INFO') |
|
258 | - ? $request->getServerParam('PATH_INFO') |
|
259 | - : '/'; |
|
260 | - } |
|
261 | - } |
|
262 | - |
|
263 | - |
|
264 | - /** |
|
265 | - * Gets a single entity related to the model indicated in the path and its id |
|
266 | - * |
|
267 | - * @param WP_REST_Request $request |
|
268 | - * @param string $version |
|
269 | - * @param string $model_name |
|
270 | - * @return WP_REST_Response|WP_Error |
|
271 | - * @throws InvalidDataTypeException |
|
272 | - * @throws InvalidInterfaceException |
|
273 | - * @throws InvalidArgumentException |
|
274 | - */ |
|
275 | - public static function handleRequestGetOne(WP_REST_Request $request, $version, $model_name) |
|
276 | - { |
|
277 | - $controller = |
|
278 | - LoaderFactory::getLoader()->getNew('EventEspresso\core\libraries\rest_api\controllers\model\Read'); |
|
279 | - try { |
|
280 | - $controller->setRequestedVersion($version); |
|
281 | - if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) { |
|
282 | - return $controller->sendResponse( |
|
283 | - new WP_Error( |
|
284 | - 'endpoint_parsing_error', |
|
285 | - sprintf( |
|
286 | - esc_html__( |
|
287 | - 'There is no model for endpoint %s. Please contact event espresso support', |
|
288 | - 'event_espresso' |
|
289 | - ), |
|
290 | - $model_name |
|
291 | - ) |
|
292 | - ) |
|
293 | - ); |
|
294 | - } |
|
295 | - return $controller->sendResponse( |
|
296 | - $controller->getEntityFromModel( |
|
297 | - $controller->getModelVersionInfo()->loadModel($model_name), |
|
298 | - $request |
|
299 | - ) |
|
300 | - ); |
|
301 | - } catch (Exception $e) { |
|
302 | - return $controller->sendResponse($e); |
|
303 | - } |
|
304 | - } |
|
305 | - |
|
306 | - |
|
307 | - /** |
|
308 | - * Gets all the related entities (or if its a belongs-to relation just the one) |
|
309 | - * to the item with the given id |
|
310 | - * |
|
311 | - * @param WP_REST_Request $request |
|
312 | - * @param string $version |
|
313 | - * @param string $model_name |
|
314 | - * @param string $related_model_name |
|
315 | - * @return WP_REST_Response|WP_Error |
|
316 | - * @throws InvalidDataTypeException |
|
317 | - * @throws InvalidInterfaceException |
|
318 | - * @throws InvalidArgumentException |
|
319 | - */ |
|
320 | - public static function handleRequestGetRelated( |
|
321 | - WP_REST_Request $request, |
|
322 | - $version, |
|
323 | - $model_name, |
|
324 | - $related_model_name |
|
325 | - ) { |
|
326 | - $controller = |
|
327 | - LoaderFactory::getLoader()->getNew('EventEspresso\core\libraries\rest_api\controllers\model\Read'); |
|
328 | - try { |
|
329 | - $controller->setRequestedVersion($version); |
|
330 | - $main_model = $controller->validateModel($model_name); |
|
331 | - $controller->validateModel($related_model_name); |
|
332 | - return $controller->sendResponse( |
|
333 | - $controller->getEntitiesFromRelation( |
|
334 | - $request->get_param('id'), |
|
335 | - $main_model->related_settings_for($related_model_name), |
|
336 | - $request |
|
337 | - ) |
|
338 | - ); |
|
339 | - } catch (Exception $e) { |
|
340 | - return $controller->sendResponse($e); |
|
341 | - } |
|
342 | - } |
|
343 | - |
|
344 | - |
|
345 | - /** |
|
346 | - * Gets a collection for the given model and filters |
|
347 | - * |
|
348 | - * @param EEM_Base $model |
|
349 | - * @param WP_REST_Request $request |
|
350 | - * @return array |
|
351 | - * @throws EE_Error |
|
352 | - * @throws InvalidArgumentException |
|
353 | - * @throws InvalidDataTypeException |
|
354 | - * @throws InvalidInterfaceException |
|
355 | - * @throws ReflectionException |
|
356 | - * @throws RestException |
|
357 | - */ |
|
358 | - public function getEntitiesFromModel($model, $request) |
|
359 | - { |
|
360 | - $query_params = $this->createModelQueryParams($model, $request->get_params()); |
|
361 | - if (! Capabilities::currentUserHasPartialAccessTo($model, $query_params['caps'])) { |
|
362 | - $model_name_plural = EEH_Inflector::pluralize_and_lower($model->get_this_model_name()); |
|
363 | - throw new RestException( |
|
364 | - sprintf('rest_%s_cannot_list', $model_name_plural), |
|
365 | - sprintf( |
|
366 | - esc_html__('Sorry, you are not allowed to list %1$s. Missing permissions: %2$s', 'event_espresso'), |
|
367 | - $model_name_plural, |
|
368 | - Capabilities::getMissingPermissionsString($model, $query_params['caps']) |
|
369 | - ), |
|
370 | - ['status' => 403] |
|
371 | - ); |
|
372 | - } |
|
373 | - if (! $request->get_header('no_rest_headers')) { |
|
374 | - $this->setHeadersFromQueryParams($model, $query_params); |
|
375 | - } |
|
376 | - /** @type array $results */ |
|
377 | - $results = $model->get_all_wpdb_results($query_params); |
|
378 | - $nice_results = []; |
|
379 | - foreach ($results as $result) { |
|
380 | - $nice_results[] = $this->createEntityFromWpdbResult( |
|
381 | - $model, |
|
382 | - $result, |
|
383 | - $request |
|
384 | - ); |
|
385 | - } |
|
386 | - return $nice_results; |
|
387 | - } |
|
388 | - |
|
389 | - |
|
390 | - /** |
|
391 | - * Gets the collection for given relation object |
|
392 | - * The same as Read::get_entities_from_model(), except if the relation |
|
393 | - * is a HABTM relation, in which case it merges any non-foreign-key fields from |
|
394 | - * the join-model-object into the results |
|
395 | - * |
|
396 | - * @param array $primary_model_query_params query params for finding the item from which |
|
397 | - * relations will be based |
|
398 | - * @param EE_Model_Relation_Base $relation |
|
399 | - * @param WP_REST_Request $request |
|
400 | - * @return array |
|
401 | - * @throws EE_Error |
|
402 | - * @throws InvalidArgumentException |
|
403 | - * @throws InvalidDataTypeException |
|
404 | - * @throws InvalidInterfaceException |
|
405 | - * @throws ReflectionException |
|
406 | - * @throws RestException |
|
407 | - * @throws ModelConfigurationException |
|
408 | - */ |
|
409 | - protected function getEntitiesFromRelationUsingModelQueryParams($primary_model_query_params, $relation, $request) |
|
410 | - { |
|
411 | - $context = $this->validateContext($request->get_param('caps')); |
|
412 | - $model = $relation->get_this_model(); |
|
413 | - $related_model = $relation->get_other_model(); |
|
414 | - if (! isset($primary_model_query_params[0])) { |
|
415 | - $primary_model_query_params[0] = []; |
|
416 | - } |
|
417 | - // check if they can access the 1st model object |
|
418 | - $primary_model_query_params = [ |
|
419 | - 0 => $primary_model_query_params[0], |
|
420 | - 'limit' => 1, |
|
421 | - ]; |
|
422 | - if ($model instanceof EEM_Soft_Delete_Base) { |
|
423 | - $primary_model_query_params = $model->alter_query_params_so_deleted_and_undeleted_items_included( |
|
424 | - $primary_model_query_params |
|
425 | - ); |
|
426 | - } |
|
427 | - $restricted_query_params = $primary_model_query_params; |
|
428 | - $restricted_query_params['caps'] = $context; |
|
429 | - $restricted_query_params['limit'] = 1; |
|
430 | - $this->setDebugInfo('main model query params', $restricted_query_params); |
|
431 | - $this->setDebugInfo('missing caps', Capabilities::getMissingPermissionsString($related_model, $context)); |
|
432 | - $primary_model_rows = $model->get_all_wpdb_results($restricted_query_params); |
|
433 | - $primary_model_row = null; |
|
434 | - if (is_array($primary_model_rows)) { |
|
435 | - $primary_model_row = reset($primary_model_rows); |
|
436 | - } |
|
437 | - if ( |
|
438 | - ! ( |
|
439 | - $primary_model_row |
|
440 | - && Capabilities::currentUserHasPartialAccessTo($related_model, $context) |
|
441 | - ) |
|
442 | - ) { |
|
443 | - if ($relation instanceof EE_Belongs_To_Relation) { |
|
444 | - $related_model_name_maybe_plural = strtolower($related_model->get_this_model_name()); |
|
445 | - } else { |
|
446 | - $related_model_name_maybe_plural = EEH_Inflector::pluralize_and_lower( |
|
447 | - $related_model->get_this_model_name() |
|
448 | - ); |
|
449 | - } |
|
450 | - throw new RestException( |
|
451 | - sprintf('rest_%s_cannot_list', $related_model_name_maybe_plural), |
|
452 | - sprintf( |
|
453 | - esc_html__( |
|
454 | - 'Sorry, you are not allowed to list %1$s related to %2$s. Missing permissions: %3$s', |
|
455 | - 'event_espresso' |
|
456 | - ), |
|
457 | - $related_model_name_maybe_plural, |
|
458 | - $relation->get_this_model()->get_this_model_name(), |
|
459 | - implode( |
|
460 | - ',', |
|
461 | - array_keys( |
|
462 | - Capabilities::getMissingPermissions($related_model, $context) |
|
463 | - ) |
|
464 | - ) |
|
465 | - ), |
|
466 | - ['status' => 403] |
|
467 | - ); |
|
468 | - } |
|
469 | - |
|
470 | - $this->checkPassword( |
|
471 | - $model, |
|
472 | - $primary_model_row, |
|
473 | - $restricted_query_params, |
|
474 | - $request |
|
475 | - ); |
|
476 | - $query_params = $this->createModelQueryParams($relation->get_other_model(), $request->get_params()); |
|
477 | - foreach ($primary_model_query_params[0] as $where_condition_key => $where_condition_value) { |
|
478 | - $query_params[0][ $relation->get_this_model()->get_this_model_name() |
|
479 | - . '.' |
|
480 | - . $where_condition_key ] = $where_condition_value; |
|
481 | - } |
|
482 | - $query_params['default_where_conditions'] = 'none'; |
|
483 | - $query_params['caps'] = $context; |
|
484 | - if (! $request->get_header('no_rest_headers')) { |
|
485 | - $this->setHeadersFromQueryParams($relation->get_other_model(), $query_params); |
|
486 | - } |
|
487 | - /** @type array $results */ |
|
488 | - $results = $relation->get_other_model()->get_all_wpdb_results($query_params); |
|
489 | - $nice_results = []; |
|
490 | - foreach ($results as $result) { |
|
491 | - $nice_result = $this->createEntityFromWpdbResult( |
|
492 | - $relation->get_other_model(), |
|
493 | - $result, |
|
494 | - $request |
|
495 | - ); |
|
496 | - if ($relation instanceof EE_HABTM_Relation) { |
|
497 | - // put the unusual stuff (properties from the HABTM relation) first, and make sure |
|
498 | - // if there are conflicts we prefer the properties from the main model |
|
499 | - $join_model_result = $this->createEntityFromWpdbResult( |
|
500 | - $relation->get_join_model(), |
|
501 | - $result, |
|
502 | - $request |
|
503 | - ); |
|
504 | - $joined_result = array_merge($join_model_result, $nice_result); |
|
505 | - // but keep the meta stuff from the main model |
|
506 | - if (isset($nice_result['meta'])) { |
|
507 | - $joined_result['meta'] = $nice_result['meta']; |
|
508 | - } |
|
509 | - $nice_result = $joined_result; |
|
510 | - } |
|
511 | - $nice_results[] = $nice_result; |
|
512 | - } |
|
513 | - if ($relation instanceof EE_Belongs_To_Relation) { |
|
514 | - return array_shift($nice_results); |
|
515 | - } else { |
|
516 | - return $nice_results; |
|
517 | - } |
|
518 | - } |
|
519 | - |
|
520 | - |
|
521 | - /** |
|
522 | - * Gets the collection for given relation object |
|
523 | - * The same as Read::get_entities_from_model(), except if the relation |
|
524 | - * is a HABTM relation, in which case it merges any non-foreign-key fields from |
|
525 | - * the join-model-object into the results |
|
526 | - * |
|
527 | - * @param string $id the ID of the thing we are fetching related stuff from |
|
528 | - * @param EE_Model_Relation_Base $relation |
|
529 | - * @param WP_REST_Request $request |
|
530 | - * @return array |
|
531 | - * @throws EE_Error |
|
532 | - * @throws ReflectionException |
|
533 | - */ |
|
534 | - public function getEntitiesFromRelation($id, $relation, $request) |
|
535 | - { |
|
536 | - if (! $relation->get_this_model()->has_primary_key_field()) { |
|
537 | - throw new EE_Error( |
|
538 | - sprintf( |
|
539 | - esc_html__( |
|
540 | - // @codingStandardsIgnoreStart |
|
541 | - 'Read::get_entities_from_relation should only be called from a model with a primary key, it was called from %1$s', |
|
542 | - // @codingStandardsIgnoreEnd |
|
543 | - 'event_espresso' |
|
544 | - ), |
|
545 | - $relation->get_this_model()->get_this_model_name() |
|
546 | - ) |
|
547 | - ); |
|
548 | - } |
|
549 | - // can we edit that main item? |
|
550 | - // if not, show nothing but an error |
|
551 | - // otherwise, please proceed |
|
552 | - return $this->getEntitiesFromRelationUsingModelQueryParams( |
|
553 | - [ |
|
554 | - [ |
|
555 | - $relation->get_this_model()->primary_key_name() => $id, |
|
556 | - ], |
|
557 | - ], |
|
558 | - $relation, |
|
559 | - $request |
|
560 | - ); |
|
561 | - } |
|
562 | - |
|
563 | - |
|
564 | - /** |
|
565 | - * Sets the headers that are based on the model and query params, |
|
566 | - * like the total records. This should only be called on the original request |
|
567 | - * from the client, not on subsequent internal |
|
568 | - * |
|
569 | - * @param EEM_Base $model |
|
570 | - * @param array $query_params |
|
571 | - * @return void |
|
572 | - * @throws EE_Error |
|
573 | - * @throws EE_Error |
|
574 | - */ |
|
575 | - protected function setHeadersFromQueryParams($model, $query_params) |
|
576 | - { |
|
577 | - $this->setDebugInfo('model query params', $query_params); |
|
578 | - $this->setDebugInfo( |
|
579 | - 'missing caps', |
|
580 | - Capabilities::getMissingPermissionsString($model, $query_params['caps']) |
|
581 | - ); |
|
582 | - // normally the limit to a 2-part array, where the 2nd item is the limit |
|
583 | - if (! isset($query_params['limit'])) { |
|
584 | - $query_params['limit'] = EED_Core_Rest_Api::get_default_query_limit(); |
|
585 | - } |
|
586 | - if (is_array($query_params['limit'])) { |
|
587 | - $limit_parts = $query_params['limit']; |
|
588 | - } else { |
|
589 | - $limit_parts = explode(',', $query_params['limit']); |
|
590 | - if (count($limit_parts) == 1) { |
|
591 | - $limit_parts = [0, $limit_parts[0]]; |
|
592 | - } |
|
593 | - } |
|
594 | - // remove the group by and having parts of the query, as those will |
|
595 | - // make the sql query return an array of values, instead of just a single value |
|
596 | - unset($query_params['group_by'], $query_params['having'], $query_params['limit']); |
|
597 | - $count = $model->count($query_params, null, true); |
|
598 | - $pages = $count / $limit_parts[1]; |
|
599 | - $this->setResponseHeader('Total', $count, false); |
|
600 | - $this->setResponseHeader('PageSize', $limit_parts[1], false); |
|
601 | - $this->setResponseHeader('TotalPages', ceil($pages), false); |
|
602 | - } |
|
603 | - |
|
604 | - |
|
605 | - /** |
|
606 | - * Changes database results into REST API entities |
|
607 | - * |
|
608 | - * @param EEM_Base $model |
|
609 | - * @param array $db_row like results from $wpdb->get_results() |
|
610 | - * @param WP_REST_Request $rest_request |
|
611 | - * @param string $deprecated no longer used |
|
612 | - * @return array ready for being converted into json for sending to client |
|
613 | - * @throws EE_Error |
|
614 | - * @throws RestException |
|
615 | - * @throws InvalidDataTypeException |
|
616 | - * @throws InvalidInterfaceException |
|
617 | - * @throws InvalidArgumentException |
|
618 | - * @throws ReflectionException |
|
619 | - */ |
|
620 | - public function createEntityFromWpdbResult($model, $db_row, $rest_request, $deprecated = null) |
|
621 | - { |
|
622 | - if (! $rest_request instanceof WP_REST_Request) { |
|
623 | - // ok so this was called in the old style, where the 3rd arg was |
|
624 | - // $include, and the 4th arg was $context |
|
625 | - // now setup the request just to avoid fatal errors, although we won't be able |
|
626 | - // to truly make use of it because it's kinda devoid of info |
|
627 | - $rest_request = new WP_REST_Request(); |
|
628 | - $rest_request->set_param('include', $rest_request); |
|
629 | - $rest_request->set_param('caps', $deprecated); |
|
630 | - } |
|
631 | - if ($rest_request->get_param('caps') == null) { |
|
632 | - $rest_request->set_param('caps', EEM_Base::caps_read); |
|
633 | - } |
|
634 | - $current_user_full_access_to_entity = $model->currentUserCan( |
|
635 | - EEM_Base::caps_read_admin, |
|
636 | - $model->deduce_fields_n_values_from_cols_n_values($db_row) |
|
637 | - ); |
|
638 | - $entity_array = $this->createBareEntityFromWpdbResults($model, $db_row); |
|
639 | - $entity_array = $this->addExtraFields($model, $db_row, $entity_array); |
|
640 | - $entity_array['_links'] = $this->getEntityLinks($model, $db_row, $entity_array); |
|
641 | - // when it's a regular read request for a model with a password and the password wasn't provided |
|
642 | - // remove the password protected fields |
|
643 | - $has_protected_fields = false; |
|
644 | - try { |
|
645 | - $this->checkPassword( |
|
646 | - $model, |
|
647 | - $db_row, |
|
648 | - $model->alter_query_params_to_restrict_by_ID( |
|
649 | - $model->get_index_primary_key_string( |
|
650 | - $model->deduce_fields_n_values_from_cols_n_values($db_row) |
|
651 | - ) |
|
652 | - ), |
|
653 | - $rest_request |
|
654 | - ); |
|
655 | - } catch (RestPasswordRequiredException $e) { |
|
656 | - if ($model->hasPassword()) { |
|
657 | - // just remove protected fields |
|
658 | - $has_protected_fields = true; |
|
659 | - $entity_array = Capabilities::filterOutPasswordProtectedFields( |
|
660 | - $entity_array, |
|
661 | - $model, |
|
662 | - $this->getModelVersionInfo() |
|
663 | - ); |
|
664 | - } else { |
|
665 | - // that's a problem. None of this should be accessible if no password was provided |
|
666 | - throw $e; |
|
667 | - } |
|
668 | - } |
|
669 | - |
|
670 | - $entity_array['_calculated_fields'] = |
|
671 | - $this->getEntityCalculations($model, $db_row, $rest_request, $has_protected_fields); |
|
672 | - $entity_array = apply_filters( |
|
673 | - 'FHEE__Read__create_entity_from_wpdb_results__entity_before_including_requested_models', |
|
674 | - $entity_array, |
|
675 | - $model, |
|
676 | - $rest_request->get_param('caps'), |
|
677 | - $rest_request, |
|
678 | - $this |
|
679 | - ); |
|
680 | - // add an empty protected property for now. If it's still around after we remove everything the request didn't |
|
681 | - // want, we'll populate it then. k? |
|
682 | - $entity_array['_protected'] = []; |
|
683 | - // remove any properties the request didn't want. This way _protected won't bother mentioning them |
|
684 | - $entity_array = $this->includeOnlyRequestedProperties($model, $rest_request, $entity_array); |
|
685 | - $entity_array = |
|
686 | - $this->includeRequestedModels($model, $rest_request, $entity_array, $db_row, $has_protected_fields); |
|
687 | - // if they still wanted the _protected property, add it. |
|
688 | - if (isset($entity_array['_protected'])) { |
|
689 | - $entity_array = $this->addProtectedProperty($model, $entity_array, $has_protected_fields); |
|
690 | - } |
|
691 | - $entity_array = apply_filters( |
|
692 | - 'FHEE__Read__create_entity_from_wpdb_results__entity_before_inaccessible_field_removal', |
|
693 | - $entity_array, |
|
694 | - $model, |
|
695 | - $rest_request->get_param('caps'), |
|
696 | - $rest_request, |
|
697 | - $this |
|
698 | - ); |
|
699 | - if (! $current_user_full_access_to_entity) { |
|
700 | - $result_without_inaccessible_fields = Capabilities::filterOutInaccessibleEntityFields( |
|
701 | - $entity_array, |
|
702 | - $model, |
|
703 | - $rest_request->get_param('caps'), |
|
704 | - $this->getModelVersionInfo() |
|
705 | - ); |
|
706 | - } else { |
|
707 | - $result_without_inaccessible_fields = $entity_array; |
|
708 | - } |
|
709 | - $this->setDebugInfo( |
|
710 | - 'inaccessible fields', |
|
711 | - array_keys(array_diff_key((array) $entity_array, (array) $result_without_inaccessible_fields)) |
|
712 | - ); |
|
713 | - return apply_filters( |
|
714 | - 'FHEE__Read__create_entity_from_wpdb_results__entity_return', |
|
715 | - $result_without_inaccessible_fields, |
|
716 | - $model, |
|
717 | - $rest_request->get_param('caps') |
|
718 | - ); |
|
719 | - } |
|
720 | - |
|
721 | - |
|
722 | - /** |
|
723 | - * Returns an array describing which fields can be protected, and which actually were removed this request |
|
724 | - * |
|
725 | - * @param EEM_Base $model |
|
726 | - * @param array $results_so_far |
|
727 | - * @param bool $protected |
|
728 | - * @return array results |
|
729 | - * @throws EE_Error |
|
730 | - * @since 4.9.74.p |
|
731 | - */ |
|
732 | - protected function addProtectedProperty(EEM_Base $model, $results_so_far, $protected) |
|
733 | - { |
|
734 | - if (! $model->hasPassword() || ! $protected) { |
|
735 | - return $results_so_far; |
|
736 | - } |
|
737 | - $password_field = $model->getPasswordField(); |
|
738 | - $all_protected = array_merge( |
|
739 | - [$password_field->get_name()], |
|
740 | - $password_field->protectedFields() |
|
741 | - ); |
|
742 | - $fields_included = array_keys($results_so_far); |
|
743 | - $fields_included = array_intersect( |
|
744 | - $all_protected, |
|
745 | - $fields_included |
|
746 | - ); |
|
747 | - foreach ($fields_included as $field_name) { |
|
748 | - $results_so_far['_protected'][] = $field_name; |
|
749 | - } |
|
750 | - return $results_so_far; |
|
751 | - } |
|
752 | - |
|
753 | - |
|
754 | - /** |
|
755 | - * Creates a REST entity array (JSON object we're going to return in the response, but |
|
756 | - * for now still a PHP array, but soon enough we'll call json_encode on it, don't worry), |
|
757 | - * from $wpdb->get_row( $sql, ARRAY_A) |
|
758 | - * |
|
759 | - * @param EEM_Base $model |
|
760 | - * @param array $db_row |
|
761 | - * @return array entity mostly ready for converting to JSON and sending in the response |
|
762 | - * @throws EE_Error |
|
763 | - * @throws ReflectionException |
|
764 | - * @throws RestException |
|
765 | - */ |
|
766 | - protected function createBareEntityFromWpdbResults(EEM_Base $model, $db_row) |
|
767 | - { |
|
768 | - $result = $model->deduce_fields_n_values_from_cols_n_values($db_row); |
|
769 | - $result = array_intersect_key( |
|
770 | - $result, |
|
771 | - $this->getModelVersionInfo()->fieldsOnModelInThisVersion($model) |
|
772 | - ); |
|
773 | - // if this is a CPT, we need to set the global $post to it, |
|
774 | - // otherwise shortcodes etc won't work properly while rendering it |
|
775 | - if ($model instanceof EEM_CPT_Base) { |
|
776 | - $do_chevy_shuffle = true; |
|
777 | - } else { |
|
778 | - $do_chevy_shuffle = false; |
|
779 | - } |
|
780 | - if ($do_chevy_shuffle) { |
|
781 | - global $post; |
|
782 | - $old_post = $post; |
|
783 | - $post = get_post($result[ $model->primary_key_name() ]); |
|
784 | - if (! $post instanceof WP_Post) { |
|
785 | - // well that's weird, because $result is what we JUST fetched from the database |
|
786 | - throw new RestException( |
|
787 | - 'error_fetching_post_from_database_results', |
|
788 | - esc_html__( |
|
789 | - 'An item was retrieved from the database but it\'s not a WP_Post like it should be.', |
|
790 | - 'event_espresso' |
|
791 | - ) |
|
792 | - ); |
|
793 | - } |
|
794 | - $model_object_classname = 'EE_' . $model->get_this_model_name(); |
|
795 | - $post->{$model_object_classname} = EE_Registry::instance()->load_class( |
|
796 | - $model_object_classname, |
|
797 | - $result, |
|
798 | - false, |
|
799 | - false |
|
800 | - ); |
|
801 | - } |
|
802 | - foreach ($result as $field_name => $field_value) { |
|
803 | - $field_obj = $model->field_settings_for($field_name); |
|
804 | - if ($this->isSubclassOfOne($field_obj, $this->getModelVersionInfo()->fieldsIgnored())) { |
|
805 | - unset($result[ $field_name ]); |
|
806 | - } elseif ( |
|
807 | - $this->isSubclassOfOne( |
|
808 | - $field_obj, |
|
809 | - $this->getModelVersionInfo()->fieldsThatHaveRenderedFormat() |
|
810 | - ) |
|
811 | - ) { |
|
812 | - $result[ $field_name ] = [ |
|
813 | - 'raw' => $this->prepareFieldObjValueForJson($field_obj, $field_value), |
|
814 | - 'rendered' => $this->prepareFieldObjValueForJson($field_obj, $field_value, 'pretty'), |
|
815 | - ]; |
|
816 | - } elseif ( |
|
817 | - $this->isSubclassOfOne( |
|
818 | - $field_obj, |
|
819 | - $this->getModelVersionInfo()->fieldsThatHavePrettyFormat() |
|
820 | - ) |
|
821 | - ) { |
|
822 | - $result[ $field_name ] = [ |
|
823 | - 'raw' => $this->prepareFieldObjValueForJson($field_obj, $field_value), |
|
824 | - 'pretty' => $this->prepareFieldObjValueForJson($field_obj, $field_value, 'pretty'), |
|
825 | - ]; |
|
826 | - } elseif ($field_obj instanceof EE_Datetime_Field) { |
|
827 | - $field_value = $field_obj->prepare_for_set_from_db($field_value); |
|
828 | - // if the value is null, but we're not supposed to permit null, then set to the field's default |
|
829 | - if (is_null($field_value)) { |
|
830 | - $field_value = $field_obj->getDefaultDateTimeObj(); |
|
831 | - } |
|
832 | - if (is_null($field_value)) { |
|
833 | - $gmt_date = $local_date = ModelDataTranslator::prepareFieldValuesForJson( |
|
834 | - $field_obj, |
|
835 | - $field_value, |
|
836 | - $this->getModelVersionInfo()->requestedVersion() |
|
837 | - ); |
|
838 | - } else { |
|
839 | - $timezone = $field_value->getTimezone(); |
|
840 | - EEH_DTT_Helper::setTimezone($field_value, new DateTimeZone('UTC')); |
|
841 | - $gmt_date = ModelDataTranslator::prepareFieldValuesForJson( |
|
842 | - $field_obj, |
|
843 | - $field_value, |
|
844 | - $this->getModelVersionInfo()->requestedVersion() |
|
845 | - ); |
|
846 | - EEH_DTT_Helper::setTimezone($field_value, $timezone); |
|
847 | - $local_date = ModelDataTranslator::prepareFieldValuesForJson( |
|
848 | - $field_obj, |
|
849 | - $field_value, |
|
850 | - $this->getModelVersionInfo()->requestedVersion() |
|
851 | - ); |
|
852 | - } |
|
853 | - $result[ $field_name . '_gmt' ] = $gmt_date; |
|
854 | - $result[ $field_name ] = $local_date; |
|
855 | - } else { |
|
856 | - $result[ $field_name ] = $this->prepareFieldObjValueForJson($field_obj, $field_value); |
|
857 | - } |
|
858 | - } |
|
859 | - if ($do_chevy_shuffle) { |
|
860 | - $post = $old_post; |
|
861 | - } |
|
862 | - return $result; |
|
863 | - } |
|
864 | - |
|
865 | - |
|
866 | - /** |
|
867 | - * Takes a value all the way from the DB representation, to the model object's representation, to the |
|
868 | - * user-facing PHP representation, to the REST API representation. (Assumes you've already taken from the DB |
|
869 | - * representation using $field_obj->prepare_for_set_from_db()) |
|
870 | - * |
|
871 | - * @param EE_Model_Field_Base $field_obj |
|
872 | - * @param mixed $value as it's stored on a model object |
|
873 | - * @param string $format valid values are 'normal' (default), 'pretty', 'datetime_obj' |
|
874 | - * @return array |
|
875 | - * @throws RestException if $value contains a PHP object |
|
876 | - * @throws EE_Error |
|
877 | - */ |
|
878 | - protected function prepareFieldObjValueForJson(EE_Model_Field_Base $field_obj, $value, $format = 'normal') |
|
879 | - { |
|
880 | - $value = $field_obj->prepare_for_set_from_db($value); |
|
881 | - switch ($format) { |
|
882 | - case 'pretty': |
|
883 | - $value = $field_obj->prepare_for_pretty_echoing($value); |
|
884 | - break; |
|
885 | - case 'normal': |
|
886 | - default: |
|
887 | - $value = $field_obj->prepare_for_get($value); |
|
888 | - break; |
|
889 | - } |
|
890 | - return ModelDataTranslator::prepareFieldValuesForJson( |
|
891 | - $field_obj, |
|
892 | - $value, |
|
893 | - $this->getModelVersionInfo()->requestedVersion() |
|
894 | - ); |
|
895 | - } |
|
896 | - |
|
897 | - |
|
898 | - /** |
|
899 | - * Adds a few extra fields to the entity response |
|
900 | - * |
|
901 | - * @param EEM_Base $model |
|
902 | - * @param array $db_row |
|
903 | - * @param array $entity_array |
|
904 | - * @return array modified entity |
|
905 | - * @throws EE_Error |
|
906 | - * @throws EE_Error |
|
907 | - */ |
|
908 | - protected function addExtraFields(EEM_Base $model, $db_row, $entity_array) |
|
909 | - { |
|
910 | - if ($model instanceof EEM_CPT_Base) { |
|
911 | - $entity_array['link'] = get_permalink($db_row[ $model->get_primary_key_field()->get_qualified_column() ]); |
|
912 | - } |
|
913 | - return $entity_array; |
|
914 | - } |
|
915 | - |
|
916 | - |
|
917 | - /** |
|
918 | - * Gets links we want to add to the response |
|
919 | - * |
|
920 | - * @param EEM_Base $model |
|
921 | - * @param array $db_row |
|
922 | - * @param array $entity_array |
|
923 | - * @return array the _links item in the entity |
|
924 | - * @throws EE_Error |
|
925 | - * @throws EE_Error |
|
926 | - * @global WP_REST_Server $wp_rest_server |
|
927 | - */ |
|
928 | - protected function getEntityLinks($model, $db_row, $entity_array) |
|
929 | - { |
|
930 | - // add basic links |
|
931 | - $links = []; |
|
932 | - if ($model->has_primary_key_field()) { |
|
933 | - $links['self'] = [ |
|
934 | - [ |
|
935 | - 'href' => $this->getVersionedLinkTo( |
|
936 | - EEH_Inflector::pluralize_and_lower($model->get_this_model_name()) |
|
937 | - . '/' |
|
938 | - . $entity_array[ $model->primary_key_name() ] |
|
939 | - ), |
|
940 | - ], |
|
941 | - ]; |
|
942 | - } |
|
943 | - $links['collection'] = [ |
|
944 | - [ |
|
945 | - 'href' => $this->getVersionedLinkTo( |
|
946 | - EEH_Inflector::pluralize_and_lower($model->get_this_model_name()) |
|
947 | - ), |
|
948 | - ], |
|
949 | - ]; |
|
950 | - // add links to related models |
|
951 | - if ($model->has_primary_key_field()) { |
|
952 | - foreach ($this->getModelVersionInfo()->relationSettings($model) as $relation_name => $relation_obj) { |
|
953 | - $related_model_part = |
|
954 | - Read::getRelatedEntityName($relation_name, $relation_obj); |
|
955 | - $links[ EED_Core_Rest_Api::ee_api_link_namespace . $related_model_part ] = [ |
|
956 | - [ |
|
957 | - 'href' => $this->getVersionedLinkTo( |
|
958 | - EEH_Inflector::pluralize_and_lower($model->get_this_model_name()) |
|
959 | - . '/' |
|
960 | - . $entity_array[ $model->primary_key_name() ] |
|
961 | - . '/' |
|
962 | - . $related_model_part |
|
963 | - ), |
|
964 | - 'single' => $relation_obj instanceof EE_Belongs_To_Relation, |
|
965 | - ], |
|
966 | - ]; |
|
967 | - } |
|
968 | - } |
|
969 | - return $links; |
|
970 | - } |
|
971 | - |
|
972 | - |
|
973 | - /** |
|
974 | - * Adds the included models indicated in the request to the entity provided |
|
975 | - * |
|
976 | - * @param EEM_Base $model |
|
977 | - * @param WP_REST_Request $rest_request |
|
978 | - * @param array $entity_array |
|
979 | - * @param array $db_row |
|
980 | - * @param boolean $included_items_protected if the original item is password protected, don't include any |
|
981 | - * related models. |
|
982 | - * @return array the modified entity |
|
983 | - * @throws EE_Error |
|
984 | - * @throws ReflectionException |
|
985 | - */ |
|
986 | - protected function includeRequestedModels( |
|
987 | - EEM_Base $model, |
|
988 | - WP_REST_Request $rest_request, |
|
989 | - $entity_array, |
|
990 | - $db_row = [], |
|
991 | - $included_items_protected = false |
|
992 | - ) { |
|
993 | - // if $db_row not included, hope the entity array has what we need |
|
994 | - if (! $db_row) { |
|
995 | - $db_row = $entity_array; |
|
996 | - } |
|
997 | - $relation_settings = $this->getModelVersionInfo()->relationSettings($model); |
|
998 | - foreach ($relation_settings as $relation_name => $relation_obj) { |
|
999 | - $related_fields_to_include = $this->explodeAndGetItemsPrefixedWith( |
|
1000 | - $rest_request->get_param('include'), |
|
1001 | - $relation_name |
|
1002 | - ); |
|
1003 | - $related_fields_to_calculate = $this->explodeAndGetItemsPrefixedWith( |
|
1004 | - $rest_request->get_param('calculate'), |
|
1005 | - $relation_name |
|
1006 | - ); |
|
1007 | - // did they specify they wanted to include a related model, or |
|
1008 | - // specific fields from a related model? |
|
1009 | - // or did they specify to calculate a field from a related model? |
|
1010 | - if ($related_fields_to_include || $related_fields_to_calculate) { |
|
1011 | - // if so, we should include at least some part of the related model |
|
1012 | - $pretend_related_request = new WP_REST_Request(); |
|
1013 | - $pretend_related_request->set_query_params( |
|
1014 | - [ |
|
1015 | - 'caps' => $rest_request->get_param('caps'), |
|
1016 | - 'include' => $related_fields_to_include, |
|
1017 | - 'calculate' => $related_fields_to_calculate, |
|
1018 | - 'password' => $rest_request->get_param('password'), |
|
1019 | - ] |
|
1020 | - ); |
|
1021 | - $pretend_related_request->add_header('no_rest_headers', true); |
|
1022 | - $primary_model_query_params = $model->alter_query_params_to_restrict_by_ID( |
|
1023 | - $model->get_index_primary_key_string( |
|
1024 | - $model->deduce_fields_n_values_from_cols_n_values($db_row) |
|
1025 | - ) |
|
1026 | - ); |
|
1027 | - if (! $included_items_protected) { |
|
1028 | - try { |
|
1029 | - $related_results = $this->getEntitiesFromRelationUsingModelQueryParams( |
|
1030 | - $primary_model_query_params, |
|
1031 | - $relation_obj, |
|
1032 | - $pretend_related_request |
|
1033 | - ); |
|
1034 | - } catch (RestException $e) { |
|
1035 | - $related_results = null; |
|
1036 | - } |
|
1037 | - } else { |
|
1038 | - // they're protected, hide them. |
|
1039 | - $related_results = null; |
|
1040 | - $entity_array['_protected'][] = Read::getRelatedEntityName($relation_name, $relation_obj); |
|
1041 | - } |
|
1042 | - if ($related_results instanceof WP_Error || $related_results === null) { |
|
1043 | - $related_results = |
|
1044 | - $relation_obj instanceof EE_Belongs_To_Relation |
|
1045 | - ? null |
|
1046 | - : []; |
|
1047 | - } |
|
1048 | - $entity_array[ Read::getRelatedEntityName($relation_name, $relation_obj) ] = $related_results; |
|
1049 | - } |
|
1050 | - } |
|
1051 | - return $entity_array; |
|
1052 | - } |
|
1053 | - |
|
1054 | - |
|
1055 | - /** |
|
1056 | - * If the user has requested only specific properties (including meta properties like _links or _protected) |
|
1057 | - * remove everything else. |
|
1058 | - * |
|
1059 | - * @param EEM_Base $model |
|
1060 | - * @param WP_REST_Request $rest_request |
|
1061 | - * @param $entity_array |
|
1062 | - * @return array |
|
1063 | - * @throws EE_Error |
|
1064 | - * @since 4.9.74.p |
|
1065 | - */ |
|
1066 | - protected function includeOnlyRequestedProperties( |
|
1067 | - EEM_Base $model, |
|
1068 | - WP_REST_Request $rest_request, |
|
1069 | - $entity_array |
|
1070 | - ) { |
|
1071 | - |
|
1072 | - $includes_for_this_model = $this->explodeAndGetItemsPrefixedWith($rest_request->get_param('include'), ''); |
|
1073 | - $includes_for_this_model = $this->removeModelNamesFromArray($includes_for_this_model); |
|
1074 | - // if they passed in * or didn't specify any includes, return everything |
|
1075 | - if ( |
|
1076 | - ! in_array('*', $includes_for_this_model) |
|
1077 | - && ! empty($includes_for_this_model) |
|
1078 | - ) { |
|
1079 | - if ($model->has_primary_key_field()) { |
|
1080 | - // always include the primary key. ya just gotta know that at least |
|
1081 | - $includes_for_this_model[] = $model->primary_key_name(); |
|
1082 | - } |
|
1083 | - if ($this->explodeAndGetItemsPrefixedWith($rest_request->get_param('calculate'), '')) { |
|
1084 | - $includes_for_this_model[] = '_calculated_fields'; |
|
1085 | - } |
|
1086 | - $entity_array = array_intersect_key($entity_array, array_flip($includes_for_this_model)); |
|
1087 | - } |
|
1088 | - return $entity_array; |
|
1089 | - } |
|
1090 | - |
|
1091 | - |
|
1092 | - /** |
|
1093 | - * Returns a new array with all the names of models removed. Eg |
|
1094 | - * array( 'Event', 'Datetime.*', 'foobar' ) would become array( 'Datetime.*', 'foobar' ) |
|
1095 | - * |
|
1096 | - * @param array $arr |
|
1097 | - * @return array |
|
1098 | - */ |
|
1099 | - private function removeModelNamesFromArray($arr) |
|
1100 | - { |
|
1101 | - return array_diff($arr, array_keys(EE_Registry::instance()->non_abstract_db_models)); |
|
1102 | - } |
|
1103 | - |
|
1104 | - |
|
1105 | - /** |
|
1106 | - * Gets the calculated fields for the response |
|
1107 | - * |
|
1108 | - * @param EEM_Base $model |
|
1109 | - * @param array $wpdb_row |
|
1110 | - * @param WP_REST_Request $rest_request |
|
1111 | - * @param boolean $row_is_protected whether this row is password protected or not |
|
1112 | - * @return stdClass the _calculations item in the entity |
|
1113 | - * @throws RestException if a default value has a PHP object, which should never do (and if we |
|
1114 | - * @throws EE_Error |
|
1115 | - * did, let's know about it ASAP, so let the exception bubble up) |
|
1116 | - */ |
|
1117 | - protected function getEntityCalculations($model, $wpdb_row, $rest_request, $row_is_protected = false) |
|
1118 | - { |
|
1119 | - $calculated_fields = $this->explodeAndGetItemsPrefixedWith( |
|
1120 | - $rest_request->get_param('calculate'), |
|
1121 | - '' |
|
1122 | - ); |
|
1123 | - // note: setting calculate=* doesn't do anything |
|
1124 | - $calculated_fields_to_return = new stdClass(); |
|
1125 | - $protected_fields = []; |
|
1126 | - foreach ($calculated_fields as $field_to_calculate) { |
|
1127 | - try { |
|
1128 | - // it's password protected, so they shouldn't be able to read this. Remove the value |
|
1129 | - $schema = $this->fields_calculator->getJsonSchemaForModel($model); |
|
1130 | - if ( |
|
1131 | - $row_is_protected |
|
1132 | - && isset($schema['properties'][ $field_to_calculate ]['protected']) |
|
1133 | - && $schema['properties'][ $field_to_calculate ]['protected'] |
|
1134 | - ) { |
|
1135 | - $calculated_value = null; |
|
1136 | - $protected_fields[] = $field_to_calculate; |
|
1137 | - if ($schema['properties'][ $field_to_calculate ]['type']) { |
|
1138 | - switch ($schema['properties'][ $field_to_calculate ]['type']) { |
|
1139 | - case 'boolean': |
|
1140 | - $calculated_value = false; |
|
1141 | - break; |
|
1142 | - case 'integer': |
|
1143 | - $calculated_value = 0; |
|
1144 | - break; |
|
1145 | - case 'string': |
|
1146 | - $calculated_value = ''; |
|
1147 | - break; |
|
1148 | - case 'array': |
|
1149 | - $calculated_value = []; |
|
1150 | - break; |
|
1151 | - case 'object': |
|
1152 | - $calculated_value = new stdClass(); |
|
1153 | - break; |
|
1154 | - } |
|
1155 | - } |
|
1156 | - } else { |
|
1157 | - $calculated_value = ModelDataTranslator::prepareFieldValueForJson( |
|
1158 | - null, |
|
1159 | - $this->fields_calculator->retrieveCalculatedFieldValue( |
|
1160 | - $model, |
|
1161 | - $field_to_calculate, |
|
1162 | - $wpdb_row, |
|
1163 | - $rest_request, |
|
1164 | - $this |
|
1165 | - ), |
|
1166 | - $this->getModelVersionInfo()->requestedVersion() |
|
1167 | - ); |
|
1168 | - } |
|
1169 | - $calculated_fields_to_return->{$field_to_calculate} = $calculated_value; |
|
1170 | - } catch (RestException $e) { |
|
1171 | - // if we don't have permission to read it, just leave it out. but let devs know about the problem |
|
1172 | - $this->setResponseHeader( |
|
1173 | - 'Notices-Field-Calculation-Errors[' |
|
1174 | - . $e->getStringCode() |
|
1175 | - . '][' |
|
1176 | - . $model->get_this_model_name() |
|
1177 | - . '][' |
|
1178 | - . $field_to_calculate |
|
1179 | - . ']', |
|
1180 | - $e->getMessage(), |
|
1181 | - true |
|
1182 | - ); |
|
1183 | - } |
|
1184 | - } |
|
1185 | - $calculated_fields_to_return->_protected = $protected_fields; |
|
1186 | - return $calculated_fields_to_return; |
|
1187 | - } |
|
1188 | - |
|
1189 | - |
|
1190 | - /** |
|
1191 | - * Gets the full URL to the resource, taking the requested version into account |
|
1192 | - * |
|
1193 | - * @param string $link_part_after_version_and_slash eg "events/10/datetimes" |
|
1194 | - * @return string url eg "http://mysite.com/wp-json/ee/v4.6/events/10/datetimes" |
|
1195 | - * @throws EE_Error |
|
1196 | - * @throws EE_Error |
|
1197 | - */ |
|
1198 | - public function getVersionedLinkTo($link_part_after_version_and_slash) |
|
1199 | - { |
|
1200 | - return rest_url( |
|
1201 | - EED_Core_Rest_Api::get_versioned_route_to( |
|
1202 | - $link_part_after_version_and_slash, |
|
1203 | - $this->getModelVersionInfo()->requestedVersion() |
|
1204 | - ) |
|
1205 | - ); |
|
1206 | - } |
|
1207 | - |
|
1208 | - |
|
1209 | - /** |
|
1210 | - * Gets the correct lowercase name for the relation in the API according |
|
1211 | - * to the relation's type |
|
1212 | - * |
|
1213 | - * @param string $relation_name |
|
1214 | - * @param EE_Model_Relation_Base $relation_obj |
|
1215 | - * @return string |
|
1216 | - */ |
|
1217 | - public static function getRelatedEntityName($relation_name, $relation_obj) |
|
1218 | - { |
|
1219 | - if ($relation_obj instanceof EE_Belongs_To_Relation) { |
|
1220 | - return strtolower($relation_name); |
|
1221 | - } else { |
|
1222 | - return EEH_Inflector::pluralize_and_lower($relation_name); |
|
1223 | - } |
|
1224 | - } |
|
1225 | - |
|
1226 | - |
|
1227 | - /** |
|
1228 | - * Gets the one model object with the specified id for the specified model |
|
1229 | - * |
|
1230 | - * @param EEM_Base $model |
|
1231 | - * @param WP_REST_Request $request |
|
1232 | - * @return array |
|
1233 | - * @throws EE_Error |
|
1234 | - * @throws EE_Error |
|
1235 | - * @throws ReflectionException |
|
1236 | - */ |
|
1237 | - public function getEntityFromModel($model, $request) |
|
1238 | - { |
|
1239 | - $context = $this->validateContext($request->get_param('caps')); |
|
1240 | - return $this->getOneOrReportPermissionError($model, $request, $context); |
|
1241 | - } |
|
1242 | - |
|
1243 | - |
|
1244 | - /** |
|
1245 | - * If a context is provided which isn't valid, maybe it was added in a future |
|
1246 | - * version so just treat it as a default read |
|
1247 | - * |
|
1248 | - * @param string $context |
|
1249 | - * @return string array key of EEM_Base::cap_contexts_to_cap_action_map() |
|
1250 | - */ |
|
1251 | - public function validateContext($context) |
|
1252 | - { |
|
1253 | - if (! $context) { |
|
1254 | - $context = EEM_Base::caps_read; |
|
1255 | - } |
|
1256 | - $valid_contexts = EEM_Base::valid_cap_contexts(); |
|
1257 | - if (in_array($context, $valid_contexts)) { |
|
1258 | - return $context; |
|
1259 | - } else { |
|
1260 | - return EEM_Base::caps_read; |
|
1261 | - } |
|
1262 | - } |
|
1263 | - |
|
1264 | - |
|
1265 | - /** |
|
1266 | - * Verifies the passed in value is an allowable default where conditions value. |
|
1267 | - * |
|
1268 | - * @param $default_query_params |
|
1269 | - * @return string |
|
1270 | - */ |
|
1271 | - public function validateDefaultQueryParams($default_query_params) |
|
1272 | - { |
|
1273 | - $valid_default_where_conditions_for_api_calls = [ |
|
1274 | - EEM_Base::default_where_conditions_all, |
|
1275 | - EEM_Base::default_where_conditions_minimum_all, |
|
1276 | - EEM_Base::default_where_conditions_minimum_others, |
|
1277 | - ]; |
|
1278 | - if (! $default_query_params) { |
|
1279 | - $default_query_params = EEM_Base::default_where_conditions_all; |
|
1280 | - } |
|
1281 | - if ( |
|
1282 | - in_array( |
|
1283 | - $default_query_params, |
|
1284 | - $valid_default_where_conditions_for_api_calls, |
|
1285 | - true |
|
1286 | - ) |
|
1287 | - ) { |
|
1288 | - return $default_query_params; |
|
1289 | - } |
|
1290 | - return EEM_Base::default_where_conditions_all; |
|
1291 | - } |
|
1292 | - |
|
1293 | - |
|
1294 | - /** |
|
1295 | - * Translates API filter get parameter into model query params @see |
|
1296 | - * https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md#0-where-conditions. |
|
1297 | - * Note: right now the query parameter keys for fields (and related fields) can be left as-is, but it's quite |
|
1298 | - * possible this will change someday. Also, this method's contents might be candidate for moving to |
|
1299 | - * Model_Data_Translator |
|
1300 | - * |
|
1301 | - * @param EEM_Base $model |
|
1302 | - * @param array $query_params |
|
1303 | - * @return array model query params (@see |
|
1304 | - * https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md#0-where-conditions) |
|
1305 | - * or FALSE to indicate that absolutely no results should be returned |
|
1306 | - * @throws EE_Error |
|
1307 | - * @throws RestException |
|
1308 | - */ |
|
1309 | - public function createModelQueryParams($model, $query_params) |
|
1310 | - { |
|
1311 | - $model_query_params = []; |
|
1312 | - if (isset($query_params['where'])) { |
|
1313 | - $model_query_params[0] = ModelDataTranslator::prepareConditionsQueryParamsForModels( |
|
1314 | - $query_params['where'], |
|
1315 | - $model, |
|
1316 | - $this->getModelVersionInfo()->requestedVersion() |
|
1317 | - ); |
|
1318 | - } |
|
1319 | - if (isset($query_params['order_by'])) { |
|
1320 | - $order_by = $query_params['order_by']; |
|
1321 | - } elseif (isset($query_params['orderby'])) { |
|
1322 | - $order_by = $query_params['orderby']; |
|
1323 | - } else { |
|
1324 | - $order_by = null; |
|
1325 | - } |
|
1326 | - if ($order_by !== null) { |
|
1327 | - if (is_array($order_by)) { |
|
1328 | - $order_by = ModelDataTranslator::prepareFieldNamesInArrayKeysFromJson($order_by); |
|
1329 | - } else { |
|
1330 | - // it's a single item |
|
1331 | - $order_by = ModelDataTranslator::prepareFieldNameFromJson($order_by); |
|
1332 | - } |
|
1333 | - $model_query_params['order_by'] = $order_by; |
|
1334 | - } |
|
1335 | - if (isset($query_params['group_by'])) { |
|
1336 | - $group_by = $query_params['group_by']; |
|
1337 | - } elseif (isset($query_params['groupby'])) { |
|
1338 | - $group_by = $query_params['groupby']; |
|
1339 | - } else { |
|
1340 | - $group_by = array_keys($model->get_combined_primary_key_fields()); |
|
1341 | - } |
|
1342 | - // make sure they're all real names |
|
1343 | - if (is_array($group_by)) { |
|
1344 | - $group_by = ModelDataTranslator::prepareFieldNamesFromJson($group_by); |
|
1345 | - } |
|
1346 | - if ($group_by !== null) { |
|
1347 | - $model_query_params['group_by'] = $group_by; |
|
1348 | - } |
|
1349 | - if (isset($query_params['having'])) { |
|
1350 | - $model_query_params['having'] = ModelDataTranslator::prepareConditionsQueryParamsForModels( |
|
1351 | - $query_params['having'], |
|
1352 | - $model, |
|
1353 | - $this->getModelVersionInfo()->requestedVersion() |
|
1354 | - ); |
|
1355 | - } |
|
1356 | - if (isset($query_params['order'])) { |
|
1357 | - $model_query_params['order'] = $query_params['order']; |
|
1358 | - } |
|
1359 | - if (isset($query_params['mine'])) { |
|
1360 | - $model_query_params = $model->alter_query_params_to_only_include_mine($model_query_params); |
|
1361 | - } |
|
1362 | - if (isset($query_params['limit'])) { |
|
1363 | - // limit should be either a string like '23' or '23,43', or an array with two items in it |
|
1364 | - if (! is_array($query_params['limit'])) { |
|
1365 | - $limit_array = explode(',', (string) $query_params['limit']); |
|
1366 | - } else { |
|
1367 | - $limit_array = $query_params['limit']; |
|
1368 | - } |
|
1369 | - $sanitized_limit = []; |
|
1370 | - foreach ($limit_array as $limit_part) { |
|
1371 | - if ($this->debug_mode && (! is_numeric($limit_part) || count($sanitized_limit) > 2)) { |
|
1372 | - throw new EE_Error( |
|
1373 | - sprintf( |
|
1374 | - esc_html__( |
|
1375 | - // @codingStandardsIgnoreStart |
|
1376 | - 'An invalid limit filter was provided. It was: %s. If the EE4 JSON REST API weren\'t in debug mode, this message would not appear.', |
|
1377 | - // @codingStandardsIgnoreEnd |
|
1378 | - 'event_espresso' |
|
1379 | - ), |
|
1380 | - wp_json_encode($query_params['limit']) |
|
1381 | - ) |
|
1382 | - ); |
|
1383 | - } |
|
1384 | - $sanitized_limit[] = (int) $limit_part; |
|
1385 | - } |
|
1386 | - $model_query_params['limit'] = implode(',', $sanitized_limit); |
|
1387 | - } else { |
|
1388 | - $model_query_params['limit'] = EED_Core_Rest_Api::get_default_query_limit(); |
|
1389 | - } |
|
1390 | - if (isset($query_params['caps'])) { |
|
1391 | - $model_query_params['caps'] = $this->validateContext($query_params['caps']); |
|
1392 | - } else { |
|
1393 | - $model_query_params['caps'] = EEM_Base::caps_read; |
|
1394 | - } |
|
1395 | - if (isset($query_params['default_where_conditions'])) { |
|
1396 | - $model_query_params['default_where_conditions'] = $this->validateDefaultQueryParams( |
|
1397 | - $query_params['default_where_conditions'] |
|
1398 | - ); |
|
1399 | - } |
|
1400 | - // if this is a model protected by a password on another model, exclude the password protected |
|
1401 | - // entities by default. But if they passed in a password, try to show them all. If the password is wrong, |
|
1402 | - // though, they'll get an error (see Read::createEntityFromWpdbResult() which calls Read::checkPassword) |
|
1403 | - if ( |
|
1404 | - ! $model->hasPassword() |
|
1405 | - && $model->restrictedByRelatedModelPassword() |
|
1406 | - && $model_query_params['caps'] === EEM_Base::caps_read |
|
1407 | - ) { |
|
1408 | - if (empty($query_params['password'])) { |
|
1409 | - $model_query_params['exclude_protected'] = true; |
|
1410 | - } |
|
1411 | - } |
|
1412 | - |
|
1413 | - return apply_filters('FHEE__Read__create_model_query_params', $model_query_params, $query_params, $model); |
|
1414 | - } |
|
1415 | - |
|
1416 | - |
|
1417 | - /** |
|
1418 | - * Changes the REST-style query params for use in the models |
|
1419 | - * |
|
1420 | - * @param EEM_Base $model |
|
1421 | - * @param array $query_params sub-array from @see EEM_Base::get_all() |
|
1422 | - * @return array |
|
1423 | - * @deprecated |
|
1424 | - */ |
|
1425 | - public function prepareRestQueryParamsKeyForModels($model, $query_params) |
|
1426 | - { |
|
1427 | - $model_ready_query_params = []; |
|
1428 | - foreach ($query_params as $key => $value) { |
|
1429 | - $model_ready_query_params[ $key ] = is_array($value) |
|
1430 | - ? $this->prepareRestQueryParamsKeyForModels($model, $value) |
|
1431 | - : $value; |
|
1432 | - } |
|
1433 | - return $model_ready_query_params; |
|
1434 | - } |
|
1435 | - |
|
1436 | - |
|
1437 | - /** |
|
1438 | - * @param $model |
|
1439 | - * @param $query_params |
|
1440 | - * @return array |
|
1441 | - * @deprecated instead use ModelDataTranslator::prepareFieldValuesFromJson() |
|
1442 | - */ |
|
1443 | - public function prepareRestQueryParamsValuesForModels($model, $query_params) |
|
1444 | - { |
|
1445 | - $model_ready_query_params = []; |
|
1446 | - foreach ($query_params as $key => $value) { |
|
1447 | - if (is_array($value)) { |
|
1448 | - $model_ready_query_params[ $key ] = $this->prepareRestQueryParamsValuesForModels($model, $value); |
|
1449 | - } else { |
|
1450 | - $model_ready_query_params[ $key ] = $value; |
|
1451 | - } |
|
1452 | - } |
|
1453 | - return $model_ready_query_params; |
|
1454 | - } |
|
1455 | - |
|
1456 | - |
|
1457 | - /** |
|
1458 | - * Explodes the string on commas, and only returns items with $prefix followed by a period. |
|
1459 | - * If no prefix is specified, returns items with no period. |
|
1460 | - * |
|
1461 | - * @param string|array $string_to_explode eg "jibba,jabba, blah, blah, blah" or array('jibba', 'jabba' ) |
|
1462 | - * @param string $prefix "Event" or "foobar" |
|
1463 | - * @return array $string_to_exploded exploded on COMMAS, and if a prefix was specified |
|
1464 | - * we only return strings starting with that and a period; if no prefix was |
|
1465 | - * specified we return all items containing NO periods |
|
1466 | - */ |
|
1467 | - public function explodeAndGetItemsPrefixedWith($string_to_explode, $prefix) |
|
1468 | - { |
|
1469 | - if (is_string($string_to_explode)) { |
|
1470 | - $exploded_contents = explode(',', $string_to_explode); |
|
1471 | - } elseif (is_array($string_to_explode)) { |
|
1472 | - $exploded_contents = $string_to_explode; |
|
1473 | - } else { |
|
1474 | - $exploded_contents = []; |
|
1475 | - } |
|
1476 | - // if the string was empty, we want an empty array |
|
1477 | - $exploded_contents = array_filter($exploded_contents); |
|
1478 | - $contents_with_prefix = []; |
|
1479 | - foreach ($exploded_contents as $item) { |
|
1480 | - $item = trim($item); |
|
1481 | - // if no prefix was provided, so we look for items with no "." in them |
|
1482 | - if (! $prefix) { |
|
1483 | - // does this item have a period? |
|
1484 | - if (strpos($item, '.') === false) { |
|
1485 | - // if not, then its what we're looking for |
|
1486 | - $contents_with_prefix[] = $item; |
|
1487 | - } |
|
1488 | - } elseif (strpos($item, $prefix . '.') === 0) { |
|
1489 | - // this item has the prefix and a period, grab it |
|
1490 | - $contents_with_prefix[] = substr( |
|
1491 | - $item, |
|
1492 | - strpos($item, $prefix . '.') + strlen($prefix . '.') |
|
1493 | - ); |
|
1494 | - } elseif ($item === $prefix) { |
|
1495 | - // this item is JUST the prefix |
|
1496 | - // so let's grab everything after, which is a blank string |
|
1497 | - $contents_with_prefix[] = ''; |
|
1498 | - } |
|
1499 | - } |
|
1500 | - return $contents_with_prefix; |
|
1501 | - } |
|
1502 | - |
|
1503 | - |
|
1504 | - /** |
|
1505 | - * @param string $include_string @see Read:handle_request_get_all |
|
1506 | - * @param string $model_name |
|
1507 | - * @return array of fields for this model. If $model_name is provided, then |
|
1508 | - * the fields for that model, with the model's name removed from each. |
|
1509 | - * If $include_string was blank or '*' returns an empty array |
|
1510 | - * @throws EE_Error |
|
1511 | - * @throws EE_Error |
|
1512 | - * @deprecated since 4.8.36.rc.001 You should instead use Read::explode_and_get_items_prefixed_with. |
|
1513 | - * Deprecated because its return values were really quite confusing- sometimes it |
|
1514 | - * returned an empty array (when the include string was blank or '*') or sometimes it |
|
1515 | - * returned array('*') (when you provided a model and a model of that kind was |
|
1516 | - * found). Parses the $include_string so we fetch all the field names relating to |
|
1517 | - * THIS model |
|
1518 | - * (ie have NO period in them), or for the provided model (ie start with the model |
|
1519 | - * name and then a period). |
|
1520 | - */ |
|
1521 | - public function extractIncludesForThisModel($include_string, $model_name = null) |
|
1522 | - { |
|
1523 | - if (is_array($include_string)) { |
|
1524 | - $include_string = implode(',', $include_string); |
|
1525 | - } |
|
1526 | - if ($include_string === '*' || $include_string === '') { |
|
1527 | - return []; |
|
1528 | - } |
|
1529 | - $includes = explode(',', $include_string); |
|
1530 | - $extracted_fields_to_include = []; |
|
1531 | - if ($model_name) { |
|
1532 | - foreach ($includes as $field_to_include) { |
|
1533 | - $field_to_include = trim($field_to_include); |
|
1534 | - if (strpos($field_to_include, $model_name . '.') === 0) { |
|
1535 | - // found the model name at the exact start |
|
1536 | - $field_sans_model_name = str_replace($model_name . '.', '', $field_to_include); |
|
1537 | - $extracted_fields_to_include[] = $field_sans_model_name; |
|
1538 | - } elseif ($field_to_include == $model_name) { |
|
1539 | - $extracted_fields_to_include[] = '*'; |
|
1540 | - } |
|
1541 | - } |
|
1542 | - } else { |
|
1543 | - // look for ones with no period |
|
1544 | - foreach ($includes as $field_to_include) { |
|
1545 | - $field_to_include = trim($field_to_include); |
|
1546 | - if ( |
|
1547 | - strpos($field_to_include, '.') === false |
|
1548 | - && ! $this->getModelVersionInfo()->isModelNameInThisVersion($field_to_include) |
|
1549 | - ) { |
|
1550 | - $extracted_fields_to_include[] = $field_to_include; |
|
1551 | - } |
|
1552 | - } |
|
1553 | - } |
|
1554 | - return $extracted_fields_to_include; |
|
1555 | - } |
|
1556 | - |
|
1557 | - |
|
1558 | - /** |
|
1559 | - * Gets the single item using the model according to the request in the context given, otherwise |
|
1560 | - * returns that it's inaccessible to the current user |
|
1561 | - * |
|
1562 | - * @param EEM_Base $model |
|
1563 | - * @param WP_REST_Request $request |
|
1564 | - * @param null $context |
|
1565 | - * @return array |
|
1566 | - * @throws EE_Error |
|
1567 | - * @throws ReflectionException |
|
1568 | - */ |
|
1569 | - public function getOneOrReportPermissionError(EEM_Base $model, WP_REST_Request $request, $context = null) |
|
1570 | - { |
|
1571 | - $query_params = [[$model->primary_key_name() => $request->get_param('id')], 'limit' => 1]; |
|
1572 | - if ($model instanceof EEM_Soft_Delete_Base) { |
|
1573 | - $query_params = $model->alter_query_params_so_deleted_and_undeleted_items_included($query_params); |
|
1574 | - } |
|
1575 | - $restricted_query_params = $query_params; |
|
1576 | - $restricted_query_params['caps'] = $context; |
|
1577 | - $this->setDebugInfo('model query params', $restricted_query_params); |
|
1578 | - $model_rows = $model->get_all_wpdb_results($restricted_query_params); |
|
1579 | - if (! empty($model_rows)) { |
|
1580 | - return $this->createEntityFromWpdbResult( |
|
1581 | - $model, |
|
1582 | - reset($model_rows), |
|
1583 | - $request |
|
1584 | - ); |
|
1585 | - } else { |
|
1586 | - // ok let's test to see if we WOULD have found it, had we not had restrictions from missing capabilities |
|
1587 | - $lowercase_model_name = strtolower($model->get_this_model_name()); |
|
1588 | - if ($model->exists($query_params)) { |
|
1589 | - // you got shafted- it existed but we didn't want to tell you! |
|
1590 | - throw new RestException( |
|
1591 | - 'rest_user_cannot_' . $context, |
|
1592 | - sprintf( |
|
1593 | - esc_html__('Sorry, you cannot %1$s this %2$s. Missing permissions are: %3$s', 'event_espresso'), |
|
1594 | - $context, |
|
1595 | - $lowercase_model_name, |
|
1596 | - Capabilities::getMissingPermissionsString( |
|
1597 | - $model, |
|
1598 | - $context |
|
1599 | - ) |
|
1600 | - ), |
|
1601 | - ['status' => 403] |
|
1602 | - ); |
|
1603 | - } else { |
|
1604 | - // it's not you. It just doesn't exist |
|
1605 | - throw new RestException( |
|
1606 | - sprintf('rest_%s_invalid_id', $lowercase_model_name), |
|
1607 | - sprintf(esc_html__('Invalid %s ID.', 'event_espresso'), $lowercase_model_name), |
|
1608 | - ['status' => 404] |
|
1609 | - ); |
|
1610 | - } |
|
1611 | - } |
|
1612 | - } |
|
1613 | - |
|
1614 | - |
|
1615 | - /** |
|
1616 | - * Checks that if this content requires a password to be read, that it's been provided and is correct. |
|
1617 | - * |
|
1618 | - * @param EEM_Base $model |
|
1619 | - * @param array $model_row |
|
1620 | - * @param array $query_params Adds 'default_where_conditions' => 'minimum' |
|
1621 | - * to ensure we don't confuse trashed with password protected. |
|
1622 | - * @param WP_REST_Request $request |
|
1623 | - * @throws EE_Error |
|
1624 | - * @throws InvalidArgumentException |
|
1625 | - * @throws InvalidDataTypeException |
|
1626 | - * @throws InvalidInterfaceException |
|
1627 | - * @throws RestPasswordRequiredException |
|
1628 | - * @throws RestPasswordIncorrectException |
|
1629 | - * @throws ModelConfigurationException |
|
1630 | - * @throws ReflectionException |
|
1631 | - * @since 4.9.74.p |
|
1632 | - */ |
|
1633 | - protected function checkPassword(EEM_Base $model, $model_row, $query_params, WP_REST_Request $request) |
|
1634 | - { |
|
1635 | - $query_params['default_where_conditions'] = 'minimum'; |
|
1636 | - // stuff is only "protected" for front-end requests. Elsewhere, you either get full permission to access the object |
|
1637 | - // or you don't. |
|
1638 | - $request_caps = $request->get_param('caps'); |
|
1639 | - if (isset($request_caps) && $request_caps !== EEM_Base::caps_read) { |
|
1640 | - return; |
|
1641 | - } |
|
1642 | - // if this entity requires a password, they better give it and it better be right! |
|
1643 | - if ( |
|
1644 | - $model->hasPassword() |
|
1645 | - && $model_row[ $model->getPasswordField()->get_qualified_column() ] !== '' |
|
1646 | - ) { |
|
1647 | - if (empty($request['password'])) { |
|
1648 | - throw new RestPasswordRequiredException(); |
|
1649 | - } |
|
1650 | - if ( |
|
1651 | - ! hash_equals( |
|
1652 | - $model_row[ $model->getPasswordField()->get_qualified_column() ], |
|
1653 | - $request['password'] |
|
1654 | - ) |
|
1655 | - ) { |
|
1656 | - throw new RestPasswordIncorrectException(); |
|
1657 | - } |
|
1658 | - } elseif ( |
|
1659 | - // wait! maybe this content is password protected |
|
1660 | - $model->restrictedByRelatedModelPassword() |
|
1661 | - && $request->get_param('caps') === EEM_Base::caps_read |
|
1662 | - ) { |
|
1663 | - $password_supplied = $request->get_param('password'); |
|
1664 | - if (empty($password_supplied)) { |
|
1665 | - $query_params['exclude_protected'] = true; |
|
1666 | - if (! $model->exists($query_params)) { |
|
1667 | - throw new RestPasswordRequiredException(); |
|
1668 | - } |
|
1669 | - } else { |
|
1670 | - $query_params[0][ $model->modelChainAndPassword() ] = $password_supplied; |
|
1671 | - if (! $model->exists($query_params)) { |
|
1672 | - throw new RestPasswordIncorrectException(); |
|
1673 | - } |
|
1674 | - } |
|
1675 | - } |
|
1676 | - } |
|
52 | + /** |
|
53 | + * @var CalculatedModelFields |
|
54 | + */ |
|
55 | + protected $fields_calculator; |
|
56 | + |
|
57 | + |
|
58 | + /** |
|
59 | + * Read constructor. |
|
60 | + * |
|
61 | + * @param CalculatedModelFields $fields_calculator |
|
62 | + */ |
|
63 | + public function __construct(CalculatedModelFields $fields_calculator) |
|
64 | + { |
|
65 | + parent::__construct(); |
|
66 | + $this->fields_calculator = $fields_calculator; |
|
67 | + } |
|
68 | + |
|
69 | + |
|
70 | + /** |
|
71 | + * Handles requests to get all (or a filtered subset) of entities for a particular model |
|
72 | + * |
|
73 | + * @param WP_REST_Request $request |
|
74 | + * @param string $version |
|
75 | + * @param string $model_name |
|
76 | + * @return WP_REST_Response|WP_Error |
|
77 | + * @throws InvalidArgumentException |
|
78 | + * @throws InvalidDataTypeException |
|
79 | + * @throws InvalidInterfaceException |
|
80 | + */ |
|
81 | + public static function handleRequestGetAll(WP_REST_Request $request, $version, $model_name) |
|
82 | + { |
|
83 | + $controller = |
|
84 | + LoaderFactory::getLoader()->getNew('EventEspresso\core\libraries\rest_api\controllers\model\Read'); |
|
85 | + try { |
|
86 | + $controller->setRequestedVersion($version); |
|
87 | + if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) { |
|
88 | + return $controller->sendResponse( |
|
89 | + new WP_Error( |
|
90 | + 'endpoint_parsing_error', |
|
91 | + sprintf( |
|
92 | + esc_html__( |
|
93 | + 'There is no model for endpoint %s. Please contact event espresso support', |
|
94 | + 'event_espresso' |
|
95 | + ), |
|
96 | + $model_name |
|
97 | + ) |
|
98 | + ) |
|
99 | + ); |
|
100 | + } |
|
101 | + return $controller->sendResponse( |
|
102 | + $controller->getEntitiesFromModel( |
|
103 | + $controller->getModelVersionInfo()->loadModel($model_name), |
|
104 | + $request |
|
105 | + ) |
|
106 | + ); |
|
107 | + } catch (Exception $e) { |
|
108 | + return $controller->sendResponse($e); |
|
109 | + } |
|
110 | + } |
|
111 | + |
|
112 | + |
|
113 | + /** |
|
114 | + * Prepares and returns schema for any OPTIONS request. |
|
115 | + * |
|
116 | + * @param string $version The API endpoint version being used. |
|
117 | + * @param string $model_name Something like `Event` or `Registration` |
|
118 | + * @return array |
|
119 | + * @throws InvalidArgumentException |
|
120 | + * @throws InvalidDataTypeException |
|
121 | + * @throws InvalidInterfaceException |
|
122 | + */ |
|
123 | + public static function handleSchemaRequest($version, $model_name) |
|
124 | + { |
|
125 | + $controller = |
|
126 | + LoaderFactory::getLoader()->getNew('EventEspresso\core\libraries\rest_api\controllers\model\Read'); |
|
127 | + try { |
|
128 | + $controller->setRequestedVersion($version); |
|
129 | + if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) { |
|
130 | + return []; |
|
131 | + } |
|
132 | + // get the model for this version |
|
133 | + $model = $controller->getModelVersionInfo()->loadModel($model_name); |
|
134 | + $model_schema = new JsonModelSchema( |
|
135 | + $model, |
|
136 | + LoaderFactory::getLoader()->getShared('EventEspresso\core\libraries\rest_api\CalculatedModelFields') |
|
137 | + ); |
|
138 | + return $model_schema->getModelSchemaForRelations( |
|
139 | + $controller->getModelVersionInfo()->relationSettings($model), |
|
140 | + $controller->customizeSchemaForRestResponse( |
|
141 | + $model, |
|
142 | + $model_schema->getModelSchemaForFields( |
|
143 | + $controller->getModelVersionInfo()->fieldsOnModelInThisVersion($model), |
|
144 | + $model_schema->getInitialSchemaStructure() |
|
145 | + ) |
|
146 | + ) |
|
147 | + ); |
|
148 | + } catch (Exception $e) { |
|
149 | + return []; |
|
150 | + } |
|
151 | + } |
|
152 | + |
|
153 | + |
|
154 | + /** |
|
155 | + * This loops through each field in the given schema for the model and does the following: |
|
156 | + * - add any extra fields that are REST API specific and related to existing fields. |
|
157 | + * - transform default values into the correct format for a REST API response. |
|
158 | + * |
|
159 | + * @param EEM_Base $model |
|
160 | + * @param array $schema |
|
161 | + * @return array The final schema. |
|
162 | + * @throws EE_Error |
|
163 | + * @throws EE_Error |
|
164 | + */ |
|
165 | + protected function customizeSchemaForRestResponse(EEM_Base $model, array $schema) |
|
166 | + { |
|
167 | + foreach ($this->getModelVersionInfo()->fieldsOnModelInThisVersion($model) as $field_name => $field) { |
|
168 | + $schema = $this->translateDefaultsForRestResponse( |
|
169 | + $field_name, |
|
170 | + $field, |
|
171 | + $this->maybeAddExtraFieldsToSchema($field_name, $field, $schema) |
|
172 | + ); |
|
173 | + } |
|
174 | + return $schema; |
|
175 | + } |
|
176 | + |
|
177 | + |
|
178 | + /** |
|
179 | + * This is used to ensure that the 'default' value set in the schema response is formatted correctly for the REST |
|
180 | + * response. |
|
181 | + * |
|
182 | + * @param $field_name |
|
183 | + * @param EE_Model_Field_Base $field |
|
184 | + * @param array $schema |
|
185 | + * @return array |
|
186 | + * @throws RestException if a default value has a PHP object, which we should never do |
|
187 | + * (but if we did, let's know about it ASAP, so let the exception bubble up) |
|
188 | + * @throws EE_Error |
|
189 | + * |
|
190 | + */ |
|
191 | + protected function translateDefaultsForRestResponse($field_name, EE_Model_Field_Base $field, array $schema) |
|
192 | + { |
|
193 | + if (isset($schema['properties'][ $field_name ]['default'])) { |
|
194 | + if (is_array($schema['properties'][ $field_name ]['default'])) { |
|
195 | + foreach ($schema['properties'][ $field_name ]['default'] as $default_key => $default_value) { |
|
196 | + if ($default_key === 'raw') { |
|
197 | + $schema['properties'][ $field_name ]['default'][ $default_key ] = |
|
198 | + ModelDataTranslator::prepareFieldValueForJson( |
|
199 | + $field, |
|
200 | + $default_value, |
|
201 | + $this->getModelVersionInfo()->requestedVersion() |
|
202 | + ); |
|
203 | + } |
|
204 | + } |
|
205 | + } else { |
|
206 | + $schema['properties'][ $field_name ]['default'] = ModelDataTranslator::prepareFieldValueForJson( |
|
207 | + $field, |
|
208 | + $schema['properties'][ $field_name ]['default'], |
|
209 | + $this->getModelVersionInfo()->requestedVersion() |
|
210 | + ); |
|
211 | + } |
|
212 | + } |
|
213 | + return $schema; |
|
214 | + } |
|
215 | + |
|
216 | + |
|
217 | + /** |
|
218 | + * Adds additional fields to the schema |
|
219 | + * The REST API returns a GMT value field for each datetime field in the resource. Thus the description about this |
|
220 | + * needs to be added to the schema. |
|
221 | + * |
|
222 | + * @param $field_name |
|
223 | + * @param EE_Model_Field_Base $field |
|
224 | + * @param array $schema |
|
225 | + * @return array |
|
226 | + */ |
|
227 | + protected function maybeAddExtraFieldsToSchema($field_name, EE_Model_Field_Base $field, array $schema) |
|
228 | + { |
|
229 | + if ($field instanceof EE_Datetime_Field) { |
|
230 | + $schema['properties'][ $field_name . '_gmt' ] = $field->getSchema(); |
|
231 | + // modify the description |
|
232 | + $schema['properties'][ $field_name . '_gmt' ]['description'] = sprintf( |
|
233 | + esc_html__('%s - the value for this field is in GMT.', 'event_espresso'), |
|
234 | + wp_specialchars_decode($field->get_nicename(), ENT_QUOTES) |
|
235 | + ); |
|
236 | + } |
|
237 | + return $schema; |
|
238 | + } |
|
239 | + |
|
240 | + |
|
241 | + /** |
|
242 | + * Used to figure out the route from the request when a `WP_REST_Request` object is not available |
|
243 | + * |
|
244 | + * @return string |
|
245 | + */ |
|
246 | + protected function getRouteFromRequest() |
|
247 | + { |
|
248 | + if ( |
|
249 | + isset($GLOBALS['wp']) |
|
250 | + && $GLOBALS['wp'] instanceof WP |
|
251 | + && isset($GLOBALS['wp']->query_vars['rest_route']) |
|
252 | + ) { |
|
253 | + return $GLOBALS['wp']->query_vars['rest_route']; |
|
254 | + } else { |
|
255 | + /** @var RequestInterface $request */ |
|
256 | + $request = LoaderFactory::getLoader()->getShared(RequestInterface::class); |
|
257 | + return $request->serverParamIsSet('PATH_INFO') |
|
258 | + ? $request->getServerParam('PATH_INFO') |
|
259 | + : '/'; |
|
260 | + } |
|
261 | + } |
|
262 | + |
|
263 | + |
|
264 | + /** |
|
265 | + * Gets a single entity related to the model indicated in the path and its id |
|
266 | + * |
|
267 | + * @param WP_REST_Request $request |
|
268 | + * @param string $version |
|
269 | + * @param string $model_name |
|
270 | + * @return WP_REST_Response|WP_Error |
|
271 | + * @throws InvalidDataTypeException |
|
272 | + * @throws InvalidInterfaceException |
|
273 | + * @throws InvalidArgumentException |
|
274 | + */ |
|
275 | + public static function handleRequestGetOne(WP_REST_Request $request, $version, $model_name) |
|
276 | + { |
|
277 | + $controller = |
|
278 | + LoaderFactory::getLoader()->getNew('EventEspresso\core\libraries\rest_api\controllers\model\Read'); |
|
279 | + try { |
|
280 | + $controller->setRequestedVersion($version); |
|
281 | + if (! $controller->getModelVersionInfo()->isModelNameInThisVersion($model_name)) { |
|
282 | + return $controller->sendResponse( |
|
283 | + new WP_Error( |
|
284 | + 'endpoint_parsing_error', |
|
285 | + sprintf( |
|
286 | + esc_html__( |
|
287 | + 'There is no model for endpoint %s. Please contact event espresso support', |
|
288 | + 'event_espresso' |
|
289 | + ), |
|
290 | + $model_name |
|
291 | + ) |
|
292 | + ) |
|
293 | + ); |
|
294 | + } |
|
295 | + return $controller->sendResponse( |
|
296 | + $controller->getEntityFromModel( |
|
297 | + $controller->getModelVersionInfo()->loadModel($model_name), |
|
298 | + $request |
|
299 | + ) |
|
300 | + ); |
|
301 | + } catch (Exception $e) { |
|
302 | + return $controller->sendResponse($e); |
|
303 | + } |
|
304 | + } |
|
305 | + |
|
306 | + |
|
307 | + /** |
|
308 | + * Gets all the related entities (or if its a belongs-to relation just the one) |
|
309 | + * to the item with the given id |
|
310 | + * |
|
311 | + * @param WP_REST_Request $request |
|
312 | + * @param string $version |
|
313 | + * @param string $model_name |
|
314 | + * @param string $related_model_name |
|
315 | + * @return WP_REST_Response|WP_Error |
|
316 | + * @throws InvalidDataTypeException |
|
317 | + * @throws InvalidInterfaceException |
|
318 | + * @throws InvalidArgumentException |
|
319 | + */ |
|
320 | + public static function handleRequestGetRelated( |
|
321 | + WP_REST_Request $request, |
|
322 | + $version, |
|
323 | + $model_name, |
|
324 | + $related_model_name |
|
325 | + ) { |
|
326 | + $controller = |
|
327 | + LoaderFactory::getLoader()->getNew('EventEspresso\core\libraries\rest_api\controllers\model\Read'); |
|
328 | + try { |
|
329 | + $controller->setRequestedVersion($version); |
|
330 | + $main_model = $controller->validateModel($model_name); |
|
331 | + $controller->validateModel($related_model_name); |
|
332 | + return $controller->sendResponse( |
|
333 | + $controller->getEntitiesFromRelation( |
|
334 | + $request->get_param('id'), |
|
335 | + $main_model->related_settings_for($related_model_name), |
|
336 | + $request |
|
337 | + ) |
|
338 | + ); |
|
339 | + } catch (Exception $e) { |
|
340 | + return $controller->sendResponse($e); |
|
341 | + } |
|
342 | + } |
|
343 | + |
|
344 | + |
|
345 | + /** |
|
346 | + * Gets a collection for the given model and filters |
|
347 | + * |
|
348 | + * @param EEM_Base $model |
|
349 | + * @param WP_REST_Request $request |
|
350 | + * @return array |
|
351 | + * @throws EE_Error |
|
352 | + * @throws InvalidArgumentException |
|
353 | + * @throws InvalidDataTypeException |
|
354 | + * @throws InvalidInterfaceException |
|
355 | + * @throws ReflectionException |
|
356 | + * @throws RestException |
|
357 | + */ |
|
358 | + public function getEntitiesFromModel($model, $request) |
|
359 | + { |
|
360 | + $query_params = $this->createModelQueryParams($model, $request->get_params()); |
|
361 | + if (! Capabilities::currentUserHasPartialAccessTo($model, $query_params['caps'])) { |
|
362 | + $model_name_plural = EEH_Inflector::pluralize_and_lower($model->get_this_model_name()); |
|
363 | + throw new RestException( |
|
364 | + sprintf('rest_%s_cannot_list', $model_name_plural), |
|
365 | + sprintf( |
|
366 | + esc_html__('Sorry, you are not allowed to list %1$s. Missing permissions: %2$s', 'event_espresso'), |
|
367 | + $model_name_plural, |
|
368 | + Capabilities::getMissingPermissionsString($model, $query_params['caps']) |
|
369 | + ), |
|
370 | + ['status' => 403] |
|
371 | + ); |
|
372 | + } |
|
373 | + if (! $request->get_header('no_rest_headers')) { |
|
374 | + $this->setHeadersFromQueryParams($model, $query_params); |
|
375 | + } |
|
376 | + /** @type array $results */ |
|
377 | + $results = $model->get_all_wpdb_results($query_params); |
|
378 | + $nice_results = []; |
|
379 | + foreach ($results as $result) { |
|
380 | + $nice_results[] = $this->createEntityFromWpdbResult( |
|
381 | + $model, |
|
382 | + $result, |
|
383 | + $request |
|
384 | + ); |
|
385 | + } |
|
386 | + return $nice_results; |
|
387 | + } |
|
388 | + |
|
389 | + |
|
390 | + /** |
|
391 | + * Gets the collection for given relation object |
|
392 | + * The same as Read::get_entities_from_model(), except if the relation |
|
393 | + * is a HABTM relation, in which case it merges any non-foreign-key fields from |
|
394 | + * the join-model-object into the results |
|
395 | + * |
|
396 | + * @param array $primary_model_query_params query params for finding the item from which |
|
397 | + * relations will be based |
|
398 | + * @param EE_Model_Relation_Base $relation |
|
399 | + * @param WP_REST_Request $request |
|
400 | + * @return array |
|
401 | + * @throws EE_Error |
|
402 | + * @throws InvalidArgumentException |
|
403 | + * @throws InvalidDataTypeException |
|
404 | + * @throws InvalidInterfaceException |
|
405 | + * @throws ReflectionException |
|
406 | + * @throws RestException |
|
407 | + * @throws ModelConfigurationException |
|
408 | + */ |
|
409 | + protected function getEntitiesFromRelationUsingModelQueryParams($primary_model_query_params, $relation, $request) |
|
410 | + { |
|
411 | + $context = $this->validateContext($request->get_param('caps')); |
|
412 | + $model = $relation->get_this_model(); |
|
413 | + $related_model = $relation->get_other_model(); |
|
414 | + if (! isset($primary_model_query_params[0])) { |
|
415 | + $primary_model_query_params[0] = []; |
|
416 | + } |
|
417 | + // check if they can access the 1st model object |
|
418 | + $primary_model_query_params = [ |
|
419 | + 0 => $primary_model_query_params[0], |
|
420 | + 'limit' => 1, |
|
421 | + ]; |
|
422 | + if ($model instanceof EEM_Soft_Delete_Base) { |
|
423 | + $primary_model_query_params = $model->alter_query_params_so_deleted_and_undeleted_items_included( |
|
424 | + $primary_model_query_params |
|
425 | + ); |
|
426 | + } |
|
427 | + $restricted_query_params = $primary_model_query_params; |
|
428 | + $restricted_query_params['caps'] = $context; |
|
429 | + $restricted_query_params['limit'] = 1; |
|
430 | + $this->setDebugInfo('main model query params', $restricted_query_params); |
|
431 | + $this->setDebugInfo('missing caps', Capabilities::getMissingPermissionsString($related_model, $context)); |
|
432 | + $primary_model_rows = $model->get_all_wpdb_results($restricted_query_params); |
|
433 | + $primary_model_row = null; |
|
434 | + if (is_array($primary_model_rows)) { |
|
435 | + $primary_model_row = reset($primary_model_rows); |
|
436 | + } |
|
437 | + if ( |
|
438 | + ! ( |
|
439 | + $primary_model_row |
|
440 | + && Capabilities::currentUserHasPartialAccessTo($related_model, $context) |
|
441 | + ) |
|
442 | + ) { |
|
443 | + if ($relation instanceof EE_Belongs_To_Relation) { |
|
444 | + $related_model_name_maybe_plural = strtolower($related_model->get_this_model_name()); |
|
445 | + } else { |
|
446 | + $related_model_name_maybe_plural = EEH_Inflector::pluralize_and_lower( |
|
447 | + $related_model->get_this_model_name() |
|
448 | + ); |
|
449 | + } |
|
450 | + throw new RestException( |
|
451 | + sprintf('rest_%s_cannot_list', $related_model_name_maybe_plural), |
|
452 | + sprintf( |
|
453 | + esc_html__( |
|
454 | + 'Sorry, you are not allowed to list %1$s related to %2$s. Missing permissions: %3$s', |
|
455 | + 'event_espresso' |
|
456 | + ), |
|
457 | + $related_model_name_maybe_plural, |
|
458 | + $relation->get_this_model()->get_this_model_name(), |
|
459 | + implode( |
|
460 | + ',', |
|
461 | + array_keys( |
|
462 | + Capabilities::getMissingPermissions($related_model, $context) |
|
463 | + ) |
|
464 | + ) |
|
465 | + ), |
|
466 | + ['status' => 403] |
|
467 | + ); |
|
468 | + } |
|
469 | + |
|
470 | + $this->checkPassword( |
|
471 | + $model, |
|
472 | + $primary_model_row, |
|
473 | + $restricted_query_params, |
|
474 | + $request |
|
475 | + ); |
|
476 | + $query_params = $this->createModelQueryParams($relation->get_other_model(), $request->get_params()); |
|
477 | + foreach ($primary_model_query_params[0] as $where_condition_key => $where_condition_value) { |
|
478 | + $query_params[0][ $relation->get_this_model()->get_this_model_name() |
|
479 | + . '.' |
|
480 | + . $where_condition_key ] = $where_condition_value; |
|
481 | + } |
|
482 | + $query_params['default_where_conditions'] = 'none'; |
|
483 | + $query_params['caps'] = $context; |
|
484 | + if (! $request->get_header('no_rest_headers')) { |
|
485 | + $this->setHeadersFromQueryParams($relation->get_other_model(), $query_params); |
|
486 | + } |
|
487 | + /** @type array $results */ |
|
488 | + $results = $relation->get_other_model()->get_all_wpdb_results($query_params); |
|
489 | + $nice_results = []; |
|
490 | + foreach ($results as $result) { |
|
491 | + $nice_result = $this->createEntityFromWpdbResult( |
|
492 | + $relation->get_other_model(), |
|
493 | + $result, |
|
494 | + $request |
|
495 | + ); |
|
496 | + if ($relation instanceof EE_HABTM_Relation) { |
|
497 | + // put the unusual stuff (properties from the HABTM relation) first, and make sure |
|
498 | + // if there are conflicts we prefer the properties from the main model |
|
499 | + $join_model_result = $this->createEntityFromWpdbResult( |
|
500 | + $relation->get_join_model(), |
|
501 | + $result, |
|
502 | + $request |
|
503 | + ); |
|
504 | + $joined_result = array_merge($join_model_result, $nice_result); |
|
505 | + // but keep the meta stuff from the main model |
|
506 | + if (isset($nice_result['meta'])) { |
|
507 | + $joined_result['meta'] = $nice_result['meta']; |
|
508 | + } |
|
509 | + $nice_result = $joined_result; |
|
510 | + } |
|
511 | + $nice_results[] = $nice_result; |
|
512 | + } |
|
513 | + if ($relation instanceof EE_Belongs_To_Relation) { |
|
514 | + return array_shift($nice_results); |
|
515 | + } else { |
|
516 | + return $nice_results; |
|
517 | + } |
|
518 | + } |
|
519 | + |
|
520 | + |
|
521 | + /** |
|
522 | + * Gets the collection for given relation object |
|
523 | + * The same as Read::get_entities_from_model(), except if the relation |
|
524 | + * is a HABTM relation, in which case it merges any non-foreign-key fields from |
|
525 | + * the join-model-object into the results |
|
526 | + * |
|
527 | + * @param string $id the ID of the thing we are fetching related stuff from |
|
528 | + * @param EE_Model_Relation_Base $relation |
|
529 | + * @param WP_REST_Request $request |
|
530 | + * @return array |
|
531 | + * @throws EE_Error |
|
532 | + * @throws ReflectionException |
|
533 | + */ |
|
534 | + public function getEntitiesFromRelation($id, $relation, $request) |
|
535 | + { |
|
536 | + if (! $relation->get_this_model()->has_primary_key_field()) { |
|
537 | + throw new EE_Error( |
|
538 | + sprintf( |
|
539 | + esc_html__( |
|
540 | + // @codingStandardsIgnoreStart |
|
541 | + 'Read::get_entities_from_relation should only be called from a model with a primary key, it was called from %1$s', |
|
542 | + // @codingStandardsIgnoreEnd |
|
543 | + 'event_espresso' |
|
544 | + ), |
|
545 | + $relation->get_this_model()->get_this_model_name() |
|
546 | + ) |
|
547 | + ); |
|
548 | + } |
|
549 | + // can we edit that main item? |
|
550 | + // if not, show nothing but an error |
|
551 | + // otherwise, please proceed |
|
552 | + return $this->getEntitiesFromRelationUsingModelQueryParams( |
|
553 | + [ |
|
554 | + [ |
|
555 | + $relation->get_this_model()->primary_key_name() => $id, |
|
556 | + ], |
|
557 | + ], |
|
558 | + $relation, |
|
559 | + $request |
|
560 | + ); |
|
561 | + } |
|
562 | + |
|
563 | + |
|
564 | + /** |
|
565 | + * Sets the headers that are based on the model and query params, |
|
566 | + * like the total records. This should only be called on the original request |
|
567 | + * from the client, not on subsequent internal |
|
568 | + * |
|
569 | + * @param EEM_Base $model |
|
570 | + * @param array $query_params |
|
571 | + * @return void |
|
572 | + * @throws EE_Error |
|
573 | + * @throws EE_Error |
|
574 | + */ |
|
575 | + protected function setHeadersFromQueryParams($model, $query_params) |
|
576 | + { |
|
577 | + $this->setDebugInfo('model query params', $query_params); |
|
578 | + $this->setDebugInfo( |
|
579 | + 'missing caps', |
|
580 | + Capabilities::getMissingPermissionsString($model, $query_params['caps']) |
|
581 | + ); |
|
582 | + // normally the limit to a 2-part array, where the 2nd item is the limit |
|
583 | + if (! isset($query_params['limit'])) { |
|
584 | + $query_params['limit'] = EED_Core_Rest_Api::get_default_query_limit(); |
|
585 | + } |
|
586 | + if (is_array($query_params['limit'])) { |
|
587 | + $limit_parts = $query_params['limit']; |
|
588 | + } else { |
|
589 | + $limit_parts = explode(',', $query_params['limit']); |
|
590 | + if (count($limit_parts) == 1) { |
|
591 | + $limit_parts = [0, $limit_parts[0]]; |
|
592 | + } |
|
593 | + } |
|
594 | + // remove the group by and having parts of the query, as those will |
|
595 | + // make the sql query return an array of values, instead of just a single value |
|
596 | + unset($query_params['group_by'], $query_params['having'], $query_params['limit']); |
|
597 | + $count = $model->count($query_params, null, true); |
|
598 | + $pages = $count / $limit_parts[1]; |
|
599 | + $this->setResponseHeader('Total', $count, false); |
|
600 | + $this->setResponseHeader('PageSize', $limit_parts[1], false); |
|
601 | + $this->setResponseHeader('TotalPages', ceil($pages), false); |
|
602 | + } |
|
603 | + |
|
604 | + |
|
605 | + /** |
|
606 | + * Changes database results into REST API entities |
|
607 | + * |
|
608 | + * @param EEM_Base $model |
|
609 | + * @param array $db_row like results from $wpdb->get_results() |
|
610 | + * @param WP_REST_Request $rest_request |
|
611 | + * @param string $deprecated no longer used |
|
612 | + * @return array ready for being converted into json for sending to client |
|
613 | + * @throws EE_Error |
|
614 | + * @throws RestException |
|
615 | + * @throws InvalidDataTypeException |
|
616 | + * @throws InvalidInterfaceException |
|
617 | + * @throws InvalidArgumentException |
|
618 | + * @throws ReflectionException |
|
619 | + */ |
|
620 | + public function createEntityFromWpdbResult($model, $db_row, $rest_request, $deprecated = null) |
|
621 | + { |
|
622 | + if (! $rest_request instanceof WP_REST_Request) { |
|
623 | + // ok so this was called in the old style, where the 3rd arg was |
|
624 | + // $include, and the 4th arg was $context |
|
625 | + // now setup the request just to avoid fatal errors, although we won't be able |
|
626 | + // to truly make use of it because it's kinda devoid of info |
|
627 | + $rest_request = new WP_REST_Request(); |
|
628 | + $rest_request->set_param('include', $rest_request); |
|
629 | + $rest_request->set_param('caps', $deprecated); |
|
630 | + } |
|
631 | + if ($rest_request->get_param('caps') == null) { |
|
632 | + $rest_request->set_param('caps', EEM_Base::caps_read); |
|
633 | + } |
|
634 | + $current_user_full_access_to_entity = $model->currentUserCan( |
|
635 | + EEM_Base::caps_read_admin, |
|
636 | + $model->deduce_fields_n_values_from_cols_n_values($db_row) |
|
637 | + ); |
|
638 | + $entity_array = $this->createBareEntityFromWpdbResults($model, $db_row); |
|
639 | + $entity_array = $this->addExtraFields($model, $db_row, $entity_array); |
|
640 | + $entity_array['_links'] = $this->getEntityLinks($model, $db_row, $entity_array); |
|
641 | + // when it's a regular read request for a model with a password and the password wasn't provided |
|
642 | + // remove the password protected fields |
|
643 | + $has_protected_fields = false; |
|
644 | + try { |
|
645 | + $this->checkPassword( |
|
646 | + $model, |
|
647 | + $db_row, |
|
648 | + $model->alter_query_params_to_restrict_by_ID( |
|
649 | + $model->get_index_primary_key_string( |
|
650 | + $model->deduce_fields_n_values_from_cols_n_values($db_row) |
|
651 | + ) |
|
652 | + ), |
|
653 | + $rest_request |
|
654 | + ); |
|
655 | + } catch (RestPasswordRequiredException $e) { |
|
656 | + if ($model->hasPassword()) { |
|
657 | + // just remove protected fields |
|
658 | + $has_protected_fields = true; |
|
659 | + $entity_array = Capabilities::filterOutPasswordProtectedFields( |
|
660 | + $entity_array, |
|
661 | + $model, |
|
662 | + $this->getModelVersionInfo() |
|
663 | + ); |
|
664 | + } else { |
|
665 | + // that's a problem. None of this should be accessible if no password was provided |
|
666 | + throw $e; |
|
667 | + } |
|
668 | + } |
|
669 | + |
|
670 | + $entity_array['_calculated_fields'] = |
|
671 | + $this->getEntityCalculations($model, $db_row, $rest_request, $has_protected_fields); |
|
672 | + $entity_array = apply_filters( |
|
673 | + 'FHEE__Read__create_entity_from_wpdb_results__entity_before_including_requested_models', |
|
674 | + $entity_array, |
|
675 | + $model, |
|
676 | + $rest_request->get_param('caps'), |
|
677 | + $rest_request, |
|
678 | + $this |
|
679 | + ); |
|
680 | + // add an empty protected property for now. If it's still around after we remove everything the request didn't |
|
681 | + // want, we'll populate it then. k? |
|
682 | + $entity_array['_protected'] = []; |
|
683 | + // remove any properties the request didn't want. This way _protected won't bother mentioning them |
|
684 | + $entity_array = $this->includeOnlyRequestedProperties($model, $rest_request, $entity_array); |
|
685 | + $entity_array = |
|
686 | + $this->includeRequestedModels($model, $rest_request, $entity_array, $db_row, $has_protected_fields); |
|
687 | + // if they still wanted the _protected property, add it. |
|
688 | + if (isset($entity_array['_protected'])) { |
|
689 | + $entity_array = $this->addProtectedProperty($model, $entity_array, $has_protected_fields); |
|
690 | + } |
|
691 | + $entity_array = apply_filters( |
|
692 | + 'FHEE__Read__create_entity_from_wpdb_results__entity_before_inaccessible_field_removal', |
|
693 | + $entity_array, |
|
694 | + $model, |
|
695 | + $rest_request->get_param('caps'), |
|
696 | + $rest_request, |
|
697 | + $this |
|
698 | + ); |
|
699 | + if (! $current_user_full_access_to_entity) { |
|
700 | + $result_without_inaccessible_fields = Capabilities::filterOutInaccessibleEntityFields( |
|
701 | + $entity_array, |
|
702 | + $model, |
|
703 | + $rest_request->get_param('caps'), |
|
704 | + $this->getModelVersionInfo() |
|
705 | + ); |
|
706 | + } else { |
|
707 | + $result_without_inaccessible_fields = $entity_array; |
|
708 | + } |
|
709 | + $this->setDebugInfo( |
|
710 | + 'inaccessible fields', |
|
711 | + array_keys(array_diff_key((array) $entity_array, (array) $result_without_inaccessible_fields)) |
|
712 | + ); |
|
713 | + return apply_filters( |
|
714 | + 'FHEE__Read__create_entity_from_wpdb_results__entity_return', |
|
715 | + $result_without_inaccessible_fields, |
|
716 | + $model, |
|
717 | + $rest_request->get_param('caps') |
|
718 | + ); |
|
719 | + } |
|
720 | + |
|
721 | + |
|
722 | + /** |
|
723 | + * Returns an array describing which fields can be protected, and which actually were removed this request |
|
724 | + * |
|
725 | + * @param EEM_Base $model |
|
726 | + * @param array $results_so_far |
|
727 | + * @param bool $protected |
|
728 | + * @return array results |
|
729 | + * @throws EE_Error |
|
730 | + * @since 4.9.74.p |
|
731 | + */ |
|
732 | + protected function addProtectedProperty(EEM_Base $model, $results_so_far, $protected) |
|
733 | + { |
|
734 | + if (! $model->hasPassword() || ! $protected) { |
|
735 | + return $results_so_far; |
|
736 | + } |
|
737 | + $password_field = $model->getPasswordField(); |
|
738 | + $all_protected = array_merge( |
|
739 | + [$password_field->get_name()], |
|
740 | + $password_field->protectedFields() |
|
741 | + ); |
|
742 | + $fields_included = array_keys($results_so_far); |
|
743 | + $fields_included = array_intersect( |
|
744 | + $all_protected, |
|
745 | + $fields_included |
|
746 | + ); |
|
747 | + foreach ($fields_included as $field_name) { |
|
748 | + $results_so_far['_protected'][] = $field_name; |
|
749 | + } |
|
750 | + return $results_so_far; |
|
751 | + } |
|
752 | + |
|
753 | + |
|
754 | + /** |
|
755 | + * Creates a REST entity array (JSON object we're going to return in the response, but |
|
756 | + * for now still a PHP array, but soon enough we'll call json_encode on it, don't worry), |
|
757 | + * from $wpdb->get_row( $sql, ARRAY_A) |
|
758 | + * |
|
759 | + * @param EEM_Base $model |
|
760 | + * @param array $db_row |
|
761 | + * @return array entity mostly ready for converting to JSON and sending in the response |
|
762 | + * @throws EE_Error |
|
763 | + * @throws ReflectionException |
|
764 | + * @throws RestException |
|
765 | + */ |
|
766 | + protected function createBareEntityFromWpdbResults(EEM_Base $model, $db_row) |
|
767 | + { |
|
768 | + $result = $model->deduce_fields_n_values_from_cols_n_values($db_row); |
|
769 | + $result = array_intersect_key( |
|
770 | + $result, |
|
771 | + $this->getModelVersionInfo()->fieldsOnModelInThisVersion($model) |
|
772 | + ); |
|
773 | + // if this is a CPT, we need to set the global $post to it, |
|
774 | + // otherwise shortcodes etc won't work properly while rendering it |
|
775 | + if ($model instanceof EEM_CPT_Base) { |
|
776 | + $do_chevy_shuffle = true; |
|
777 | + } else { |
|
778 | + $do_chevy_shuffle = false; |
|
779 | + } |
|
780 | + if ($do_chevy_shuffle) { |
|
781 | + global $post; |
|
782 | + $old_post = $post; |
|
783 | + $post = get_post($result[ $model->primary_key_name() ]); |
|
784 | + if (! $post instanceof WP_Post) { |
|
785 | + // well that's weird, because $result is what we JUST fetched from the database |
|
786 | + throw new RestException( |
|
787 | + 'error_fetching_post_from_database_results', |
|
788 | + esc_html__( |
|
789 | + 'An item was retrieved from the database but it\'s not a WP_Post like it should be.', |
|
790 | + 'event_espresso' |
|
791 | + ) |
|
792 | + ); |
|
793 | + } |
|
794 | + $model_object_classname = 'EE_' . $model->get_this_model_name(); |
|
795 | + $post->{$model_object_classname} = EE_Registry::instance()->load_class( |
|
796 | + $model_object_classname, |
|
797 | + $result, |
|
798 | + false, |
|
799 | + false |
|
800 | + ); |
|
801 | + } |
|
802 | + foreach ($result as $field_name => $field_value) { |
|
803 | + $field_obj = $model->field_settings_for($field_name); |
|
804 | + if ($this->isSubclassOfOne($field_obj, $this->getModelVersionInfo()->fieldsIgnored())) { |
|
805 | + unset($result[ $field_name ]); |
|
806 | + } elseif ( |
|
807 | + $this->isSubclassOfOne( |
|
808 | + $field_obj, |
|
809 | + $this->getModelVersionInfo()->fieldsThatHaveRenderedFormat() |
|
810 | + ) |
|
811 | + ) { |
|
812 | + $result[ $field_name ] = [ |
|
813 | + 'raw' => $this->prepareFieldObjValueForJson($field_obj, $field_value), |
|
814 | + 'rendered' => $this->prepareFieldObjValueForJson($field_obj, $field_value, 'pretty'), |
|
815 | + ]; |
|
816 | + } elseif ( |
|
817 | + $this->isSubclassOfOne( |
|
818 | + $field_obj, |
|
819 | + $this->getModelVersionInfo()->fieldsThatHavePrettyFormat() |
|
820 | + ) |
|
821 | + ) { |
|
822 | + $result[ $field_name ] = [ |
|
823 | + 'raw' => $this->prepareFieldObjValueForJson($field_obj, $field_value), |
|
824 | + 'pretty' => $this->prepareFieldObjValueForJson($field_obj, $field_value, 'pretty'), |
|
825 | + ]; |
|
826 | + } elseif ($field_obj instanceof EE_Datetime_Field) { |
|
827 | + $field_value = $field_obj->prepare_for_set_from_db($field_value); |
|
828 | + // if the value is null, but we're not supposed to permit null, then set to the field's default |
|
829 | + if (is_null($field_value)) { |
|
830 | + $field_value = $field_obj->getDefaultDateTimeObj(); |
|
831 | + } |
|
832 | + if (is_null($field_value)) { |
|
833 | + $gmt_date = $local_date = ModelDataTranslator::prepareFieldValuesForJson( |
|
834 | + $field_obj, |
|
835 | + $field_value, |
|
836 | + $this->getModelVersionInfo()->requestedVersion() |
|
837 | + ); |
|
838 | + } else { |
|
839 | + $timezone = $field_value->getTimezone(); |
|
840 | + EEH_DTT_Helper::setTimezone($field_value, new DateTimeZone('UTC')); |
|
841 | + $gmt_date = ModelDataTranslator::prepareFieldValuesForJson( |
|
842 | + $field_obj, |
|
843 | + $field_value, |
|
844 | + $this->getModelVersionInfo()->requestedVersion() |
|
845 | + ); |
|
846 | + EEH_DTT_Helper::setTimezone($field_value, $timezone); |
|
847 | + $local_date = ModelDataTranslator::prepareFieldValuesForJson( |
|
848 | + $field_obj, |
|
849 | + $field_value, |
|
850 | + $this->getModelVersionInfo()->requestedVersion() |
|
851 | + ); |
|
852 | + } |
|
853 | + $result[ $field_name . '_gmt' ] = $gmt_date; |
|
854 | + $result[ $field_name ] = $local_date; |
|
855 | + } else { |
|
856 | + $result[ $field_name ] = $this->prepareFieldObjValueForJson($field_obj, $field_value); |
|
857 | + } |
|
858 | + } |
|
859 | + if ($do_chevy_shuffle) { |
|
860 | + $post = $old_post; |
|
861 | + } |
|
862 | + return $result; |
|
863 | + } |
|
864 | + |
|
865 | + |
|
866 | + /** |
|
867 | + * Takes a value all the way from the DB representation, to the model object's representation, to the |
|
868 | + * user-facing PHP representation, to the REST API representation. (Assumes you've already taken from the DB |
|
869 | + * representation using $field_obj->prepare_for_set_from_db()) |
|
870 | + * |
|
871 | + * @param EE_Model_Field_Base $field_obj |
|
872 | + * @param mixed $value as it's stored on a model object |
|
873 | + * @param string $format valid values are 'normal' (default), 'pretty', 'datetime_obj' |
|
874 | + * @return array |
|
875 | + * @throws RestException if $value contains a PHP object |
|
876 | + * @throws EE_Error |
|
877 | + */ |
|
878 | + protected function prepareFieldObjValueForJson(EE_Model_Field_Base $field_obj, $value, $format = 'normal') |
|
879 | + { |
|
880 | + $value = $field_obj->prepare_for_set_from_db($value); |
|
881 | + switch ($format) { |
|
882 | + case 'pretty': |
|
883 | + $value = $field_obj->prepare_for_pretty_echoing($value); |
|
884 | + break; |
|
885 | + case 'normal': |
|
886 | + default: |
|
887 | + $value = $field_obj->prepare_for_get($value); |
|
888 | + break; |
|
889 | + } |
|
890 | + return ModelDataTranslator::prepareFieldValuesForJson( |
|
891 | + $field_obj, |
|
892 | + $value, |
|
893 | + $this->getModelVersionInfo()->requestedVersion() |
|
894 | + ); |
|
895 | + } |
|
896 | + |
|
897 | + |
|
898 | + /** |
|
899 | + * Adds a few extra fields to the entity response |
|
900 | + * |
|
901 | + * @param EEM_Base $model |
|
902 | + * @param array $db_row |
|
903 | + * @param array $entity_array |
|
904 | + * @return array modified entity |
|
905 | + * @throws EE_Error |
|
906 | + * @throws EE_Error |
|
907 | + */ |
|
908 | + protected function addExtraFields(EEM_Base $model, $db_row, $entity_array) |
|
909 | + { |
|
910 | + if ($model instanceof EEM_CPT_Base) { |
|
911 | + $entity_array['link'] = get_permalink($db_row[ $model->get_primary_key_field()->get_qualified_column() ]); |
|
912 | + } |
|
913 | + return $entity_array; |
|
914 | + } |
|
915 | + |
|
916 | + |
|
917 | + /** |
|
918 | + * Gets links we want to add to the response |
|
919 | + * |
|
920 | + * @param EEM_Base $model |
|
921 | + * @param array $db_row |
|
922 | + * @param array $entity_array |
|
923 | + * @return array the _links item in the entity |
|
924 | + * @throws EE_Error |
|
925 | + * @throws EE_Error |
|
926 | + * @global WP_REST_Server $wp_rest_server |
|
927 | + */ |
|
928 | + protected function getEntityLinks($model, $db_row, $entity_array) |
|
929 | + { |
|
930 | + // add basic links |
|
931 | + $links = []; |
|
932 | + if ($model->has_primary_key_field()) { |
|
933 | + $links['self'] = [ |
|
934 | + [ |
|
935 | + 'href' => $this->getVersionedLinkTo( |
|
936 | + EEH_Inflector::pluralize_and_lower($model->get_this_model_name()) |
|
937 | + . '/' |
|
938 | + . $entity_array[ $model->primary_key_name() ] |
|
939 | + ), |
|
940 | + ], |
|
941 | + ]; |
|
942 | + } |
|
943 | + $links['collection'] = [ |
|
944 | + [ |
|
945 | + 'href' => $this->getVersionedLinkTo( |
|
946 | + EEH_Inflector::pluralize_and_lower($model->get_this_model_name()) |
|
947 | + ), |
|
948 | + ], |
|
949 | + ]; |
|
950 | + // add links to related models |
|
951 | + if ($model->has_primary_key_field()) { |
|
952 | + foreach ($this->getModelVersionInfo()->relationSettings($model) as $relation_name => $relation_obj) { |
|
953 | + $related_model_part = |
|
954 | + Read::getRelatedEntityName($relation_name, $relation_obj); |
|
955 | + $links[ EED_Core_Rest_Api::ee_api_link_namespace . $related_model_part ] = [ |
|
956 | + [ |
|
957 | + 'href' => $this->getVersionedLinkTo( |
|
958 | + EEH_Inflector::pluralize_and_lower($model->get_this_model_name()) |
|
959 | + . '/' |
|
960 | + . $entity_array[ $model->primary_key_name() ] |
|
961 | + . '/' |
|
962 | + . $related_model_part |
|
963 | + ), |
|
964 | + 'single' => $relation_obj instanceof EE_Belongs_To_Relation, |
|
965 | + ], |
|
966 | + ]; |
|
967 | + } |
|
968 | + } |
|
969 | + return $links; |
|
970 | + } |
|
971 | + |
|
972 | + |
|
973 | + /** |
|
974 | + * Adds the included models indicated in the request to the entity provided |
|
975 | + * |
|
976 | + * @param EEM_Base $model |
|
977 | + * @param WP_REST_Request $rest_request |
|
978 | + * @param array $entity_array |
|
979 | + * @param array $db_row |
|
980 | + * @param boolean $included_items_protected if the original item is password protected, don't include any |
|
981 | + * related models. |
|
982 | + * @return array the modified entity |
|
983 | + * @throws EE_Error |
|
984 | + * @throws ReflectionException |
|
985 | + */ |
|
986 | + protected function includeRequestedModels( |
|
987 | + EEM_Base $model, |
|
988 | + WP_REST_Request $rest_request, |
|
989 | + $entity_array, |
|
990 | + $db_row = [], |
|
991 | + $included_items_protected = false |
|
992 | + ) { |
|
993 | + // if $db_row not included, hope the entity array has what we need |
|
994 | + if (! $db_row) { |
|
995 | + $db_row = $entity_array; |
|
996 | + } |
|
997 | + $relation_settings = $this->getModelVersionInfo()->relationSettings($model); |
|
998 | + foreach ($relation_settings as $relation_name => $relation_obj) { |
|
999 | + $related_fields_to_include = $this->explodeAndGetItemsPrefixedWith( |
|
1000 | + $rest_request->get_param('include'), |
|
1001 | + $relation_name |
|
1002 | + ); |
|
1003 | + $related_fields_to_calculate = $this->explodeAndGetItemsPrefixedWith( |
|
1004 | + $rest_request->get_param('calculate'), |
|
1005 | + $relation_name |
|
1006 | + ); |
|
1007 | + // did they specify they wanted to include a related model, or |
|
1008 | + // specific fields from a related model? |
|
1009 | + // or did they specify to calculate a field from a related model? |
|
1010 | + if ($related_fields_to_include || $related_fields_to_calculate) { |
|
1011 | + // if so, we should include at least some part of the related model |
|
1012 | + $pretend_related_request = new WP_REST_Request(); |
|
1013 | + $pretend_related_request->set_query_params( |
|
1014 | + [ |
|
1015 | + 'caps' => $rest_request->get_param('caps'), |
|
1016 | + 'include' => $related_fields_to_include, |
|
1017 | + 'calculate' => $related_fields_to_calculate, |
|
1018 | + 'password' => $rest_request->get_param('password'), |
|
1019 | + ] |
|
1020 | + ); |
|
1021 | + $pretend_related_request->add_header('no_rest_headers', true); |
|
1022 | + $primary_model_query_params = $model->alter_query_params_to_restrict_by_ID( |
|
1023 | + $model->get_index_primary_key_string( |
|
1024 | + $model->deduce_fields_n_values_from_cols_n_values($db_row) |
|
1025 | + ) |
|
1026 | + ); |
|
1027 | + if (! $included_items_protected) { |
|
1028 | + try { |
|
1029 | + $related_results = $this->getEntitiesFromRelationUsingModelQueryParams( |
|
1030 | + $primary_model_query_params, |
|
1031 | + $relation_obj, |
|
1032 | + $pretend_related_request |
|
1033 | + ); |
|
1034 | + } catch (RestException $e) { |
|
1035 | + $related_results = null; |
|
1036 | + } |
|
1037 | + } else { |
|
1038 | + // they're protected, hide them. |
|
1039 | + $related_results = null; |
|
1040 | + $entity_array['_protected'][] = Read::getRelatedEntityName($relation_name, $relation_obj); |
|
1041 | + } |
|
1042 | + if ($related_results instanceof WP_Error || $related_results === null) { |
|
1043 | + $related_results = |
|
1044 | + $relation_obj instanceof EE_Belongs_To_Relation |
|
1045 | + ? null |
|
1046 | + : []; |
|
1047 | + } |
|
1048 | + $entity_array[ Read::getRelatedEntityName($relation_name, $relation_obj) ] = $related_results; |
|
1049 | + } |
|
1050 | + } |
|
1051 | + return $entity_array; |
|
1052 | + } |
|
1053 | + |
|
1054 | + |
|
1055 | + /** |
|
1056 | + * If the user has requested only specific properties (including meta properties like _links or _protected) |
|
1057 | + * remove everything else. |
|
1058 | + * |
|
1059 | + * @param EEM_Base $model |
|
1060 | + * @param WP_REST_Request $rest_request |
|
1061 | + * @param $entity_array |
|
1062 | + * @return array |
|
1063 | + * @throws EE_Error |
|
1064 | + * @since 4.9.74.p |
|
1065 | + */ |
|
1066 | + protected function includeOnlyRequestedProperties( |
|
1067 | + EEM_Base $model, |
|
1068 | + WP_REST_Request $rest_request, |
|
1069 | + $entity_array |
|
1070 | + ) { |
|
1071 | + |
|
1072 | + $includes_for_this_model = $this->explodeAndGetItemsPrefixedWith($rest_request->get_param('include'), ''); |
|
1073 | + $includes_for_this_model = $this->removeModelNamesFromArray($includes_for_this_model); |
|
1074 | + // if they passed in * or didn't specify any includes, return everything |
|
1075 | + if ( |
|
1076 | + ! in_array('*', $includes_for_this_model) |
|
1077 | + && ! empty($includes_for_this_model) |
|
1078 | + ) { |
|
1079 | + if ($model->has_primary_key_field()) { |
|
1080 | + // always include the primary key. ya just gotta know that at least |
|
1081 | + $includes_for_this_model[] = $model->primary_key_name(); |
|
1082 | + } |
|
1083 | + if ($this->explodeAndGetItemsPrefixedWith($rest_request->get_param('calculate'), '')) { |
|
1084 | + $includes_for_this_model[] = '_calculated_fields'; |
|
1085 | + } |
|
1086 | + $entity_array = array_intersect_key($entity_array, array_flip($includes_for_this_model)); |
|
1087 | + } |
|
1088 | + return $entity_array; |
|
1089 | + } |
|
1090 | + |
|
1091 | + |
|
1092 | + /** |
|
1093 | + * Returns a new array with all the names of models removed. Eg |
|
1094 | + * array( 'Event', 'Datetime.*', 'foobar' ) would become array( 'Datetime.*', 'foobar' ) |
|
1095 | + * |
|
1096 | + * @param array $arr |
|
1097 | + * @return array |
|
1098 | + */ |
|
1099 | + private function removeModelNamesFromArray($arr) |
|
1100 | + { |
|
1101 | + return array_diff($arr, array_keys(EE_Registry::instance()->non_abstract_db_models)); |
|
1102 | + } |
|
1103 | + |
|
1104 | + |
|
1105 | + /** |
|
1106 | + * Gets the calculated fields for the response |
|
1107 | + * |
|
1108 | + * @param EEM_Base $model |
|
1109 | + * @param array $wpdb_row |
|
1110 | + * @param WP_REST_Request $rest_request |
|
1111 | + * @param boolean $row_is_protected whether this row is password protected or not |
|
1112 | + * @return stdClass the _calculations item in the entity |
|
1113 | + * @throws RestException if a default value has a PHP object, which should never do (and if we |
|
1114 | + * @throws EE_Error |
|
1115 | + * did, let's know about it ASAP, so let the exception bubble up) |
|
1116 | + */ |
|
1117 | + protected function getEntityCalculations($model, $wpdb_row, $rest_request, $row_is_protected = false) |
|
1118 | + { |
|
1119 | + $calculated_fields = $this->explodeAndGetItemsPrefixedWith( |
|
1120 | + $rest_request->get_param('calculate'), |
|
1121 | + '' |
|
1122 | + ); |
|
1123 | + // note: setting calculate=* doesn't do anything |
|
1124 | + $calculated_fields_to_return = new stdClass(); |
|
1125 | + $protected_fields = []; |
|
1126 | + foreach ($calculated_fields as $field_to_calculate) { |
|
1127 | + try { |
|
1128 | + // it's password protected, so they shouldn't be able to read this. Remove the value |
|
1129 | + $schema = $this->fields_calculator->getJsonSchemaForModel($model); |
|
1130 | + if ( |
|
1131 | + $row_is_protected |
|
1132 | + && isset($schema['properties'][ $field_to_calculate ]['protected']) |
|
1133 | + && $schema['properties'][ $field_to_calculate ]['protected'] |
|
1134 | + ) { |
|
1135 | + $calculated_value = null; |
|
1136 | + $protected_fields[] = $field_to_calculate; |
|
1137 | + if ($schema['properties'][ $field_to_calculate ]['type']) { |
|
1138 | + switch ($schema['properties'][ $field_to_calculate ]['type']) { |
|
1139 | + case 'boolean': |
|
1140 | + $calculated_value = false; |
|
1141 | + break; |
|
1142 | + case 'integer': |
|
1143 | + $calculated_value = 0; |
|
1144 | + break; |
|
1145 | + case 'string': |
|
1146 | + $calculated_value = ''; |
|
1147 | + break; |
|
1148 | + case 'array': |
|
1149 | + $calculated_value = []; |
|
1150 | + break; |
|
1151 | + case 'object': |
|
1152 | + $calculated_value = new stdClass(); |
|
1153 | + break; |
|
1154 | + } |
|
1155 | + } |
|
1156 | + } else { |
|
1157 | + $calculated_value = ModelDataTranslator::prepareFieldValueForJson( |
|
1158 | + null, |
|
1159 | + $this->fields_calculator->retrieveCalculatedFieldValue( |
|
1160 | + $model, |
|
1161 | + $field_to_calculate, |
|
1162 | + $wpdb_row, |
|
1163 | + $rest_request, |
|
1164 | + $this |
|
1165 | + ), |
|
1166 | + $this->getModelVersionInfo()->requestedVersion() |
|
1167 | + ); |
|
1168 | + } |
|
1169 | + $calculated_fields_to_return->{$field_to_calculate} = $calculated_value; |
|
1170 | + } catch (RestException $e) { |
|
1171 | + // if we don't have permission to read it, just leave it out. but let devs know about the problem |
|
1172 | + $this->setResponseHeader( |
|
1173 | + 'Notices-Field-Calculation-Errors[' |
|
1174 | + . $e->getStringCode() |
|
1175 | + . '][' |
|
1176 | + . $model->get_this_model_name() |
|
1177 | + . '][' |
|
1178 | + . $field_to_calculate |
|
1179 | + . ']', |
|
1180 | + $e->getMessage(), |
|
1181 | + true |
|
1182 | + ); |
|
1183 | + } |
|
1184 | + } |
|
1185 | + $calculated_fields_to_return->_protected = $protected_fields; |
|
1186 | + return $calculated_fields_to_return; |
|
1187 | + } |
|
1188 | + |
|
1189 | + |
|
1190 | + /** |
|
1191 | + * Gets the full URL to the resource, taking the requested version into account |
|
1192 | + * |
|
1193 | + * @param string $link_part_after_version_and_slash eg "events/10/datetimes" |
|
1194 | + * @return string url eg "http://mysite.com/wp-json/ee/v4.6/events/10/datetimes" |
|
1195 | + * @throws EE_Error |
|
1196 | + * @throws EE_Error |
|
1197 | + */ |
|
1198 | + public function getVersionedLinkTo($link_part_after_version_and_slash) |
|
1199 | + { |
|
1200 | + return rest_url( |
|
1201 | + EED_Core_Rest_Api::get_versioned_route_to( |
|
1202 | + $link_part_after_version_and_slash, |
|
1203 | + $this->getModelVersionInfo()->requestedVersion() |
|
1204 | + ) |
|
1205 | + ); |
|
1206 | + } |
|
1207 | + |
|
1208 | + |
|
1209 | + /** |
|
1210 | + * Gets the correct lowercase name for the relation in the API according |
|
1211 | + * to the relation's type |
|
1212 | + * |
|
1213 | + * @param string $relation_name |
|
1214 | + * @param EE_Model_Relation_Base $relation_obj |
|
1215 | + * @return string |
|
1216 | + */ |
|
1217 | + public static function getRelatedEntityName($relation_name, $relation_obj) |
|
1218 | + { |
|
1219 | + if ($relation_obj instanceof EE_Belongs_To_Relation) { |
|
1220 | + return strtolower($relation_name); |
|
1221 | + } else { |
|
1222 | + return EEH_Inflector::pluralize_and_lower($relation_name); |
|
1223 | + } |
|
1224 | + } |
|
1225 | + |
|
1226 | + |
|
1227 | + /** |
|
1228 | + * Gets the one model object with the specified id for the specified model |
|
1229 | + * |
|
1230 | + * @param EEM_Base $model |
|
1231 | + * @param WP_REST_Request $request |
|
1232 | + * @return array |
|
1233 | + * @throws EE_Error |
|
1234 | + * @throws EE_Error |
|
1235 | + * @throws ReflectionException |
|
1236 | + */ |
|
1237 | + public function getEntityFromModel($model, $request) |
|
1238 | + { |
|
1239 | + $context = $this->validateContext($request->get_param('caps')); |
|
1240 | + return $this->getOneOrReportPermissionError($model, $request, $context); |
|
1241 | + } |
|
1242 | + |
|
1243 | + |
|
1244 | + /** |
|
1245 | + * If a context is provided which isn't valid, maybe it was added in a future |
|
1246 | + * version so just treat it as a default read |
|
1247 | + * |
|
1248 | + * @param string $context |
|
1249 | + * @return string array key of EEM_Base::cap_contexts_to_cap_action_map() |
|
1250 | + */ |
|
1251 | + public function validateContext($context) |
|
1252 | + { |
|
1253 | + if (! $context) { |
|
1254 | + $context = EEM_Base::caps_read; |
|
1255 | + } |
|
1256 | + $valid_contexts = EEM_Base::valid_cap_contexts(); |
|
1257 | + if (in_array($context, $valid_contexts)) { |
|
1258 | + return $context; |
|
1259 | + } else { |
|
1260 | + return EEM_Base::caps_read; |
|
1261 | + } |
|
1262 | + } |
|
1263 | + |
|
1264 | + |
|
1265 | + /** |
|
1266 | + * Verifies the passed in value is an allowable default where conditions value. |
|
1267 | + * |
|
1268 | + * @param $default_query_params |
|
1269 | + * @return string |
|
1270 | + */ |
|
1271 | + public function validateDefaultQueryParams($default_query_params) |
|
1272 | + { |
|
1273 | + $valid_default_where_conditions_for_api_calls = [ |
|
1274 | + EEM_Base::default_where_conditions_all, |
|
1275 | + EEM_Base::default_where_conditions_minimum_all, |
|
1276 | + EEM_Base::default_where_conditions_minimum_others, |
|
1277 | + ]; |
|
1278 | + if (! $default_query_params) { |
|
1279 | + $default_query_params = EEM_Base::default_where_conditions_all; |
|
1280 | + } |
|
1281 | + if ( |
|
1282 | + in_array( |
|
1283 | + $default_query_params, |
|
1284 | + $valid_default_where_conditions_for_api_calls, |
|
1285 | + true |
|
1286 | + ) |
|
1287 | + ) { |
|
1288 | + return $default_query_params; |
|
1289 | + } |
|
1290 | + return EEM_Base::default_where_conditions_all; |
|
1291 | + } |
|
1292 | + |
|
1293 | + |
|
1294 | + /** |
|
1295 | + * Translates API filter get parameter into model query params @see |
|
1296 | + * https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md#0-where-conditions. |
|
1297 | + * Note: right now the query parameter keys for fields (and related fields) can be left as-is, but it's quite |
|
1298 | + * possible this will change someday. Also, this method's contents might be candidate for moving to |
|
1299 | + * Model_Data_Translator |
|
1300 | + * |
|
1301 | + * @param EEM_Base $model |
|
1302 | + * @param array $query_params |
|
1303 | + * @return array model query params (@see |
|
1304 | + * https://github.com/eventespresso/event-espresso-core/tree/master/docs/G--Model-System/model-query-params.md#0-where-conditions) |
|
1305 | + * or FALSE to indicate that absolutely no results should be returned |
|
1306 | + * @throws EE_Error |
|
1307 | + * @throws RestException |
|
1308 | + */ |
|
1309 | + public function createModelQueryParams($model, $query_params) |
|
1310 | + { |
|
1311 | + $model_query_params = []; |
|
1312 | + if (isset($query_params['where'])) { |
|
1313 | + $model_query_params[0] = ModelDataTranslator::prepareConditionsQueryParamsForModels( |
|
1314 | + $query_params['where'], |
|
1315 | + $model, |
|
1316 | + $this->getModelVersionInfo()->requestedVersion() |
|
1317 | + ); |
|
1318 | + } |
|
1319 | + if (isset($query_params['order_by'])) { |
|
1320 | + $order_by = $query_params['order_by']; |
|
1321 | + } elseif (isset($query_params['orderby'])) { |
|
1322 | + $order_by = $query_params['orderby']; |
|
1323 | + } else { |
|
1324 | + $order_by = null; |
|
1325 | + } |
|
1326 | + if ($order_by !== null) { |
|
1327 | + if (is_array($order_by)) { |
|
1328 | + $order_by = ModelDataTranslator::prepareFieldNamesInArrayKeysFromJson($order_by); |
|
1329 | + } else { |
|
1330 | + // it's a single item |
|
1331 | + $order_by = ModelDataTranslator::prepareFieldNameFromJson($order_by); |
|
1332 | + } |
|
1333 | + $model_query_params['order_by'] = $order_by; |
|
1334 | + } |
|
1335 | + if (isset($query_params['group_by'])) { |
|
1336 | + $group_by = $query_params['group_by']; |
|
1337 | + } elseif (isset($query_params['groupby'])) { |
|
1338 | + $group_by = $query_params['groupby']; |
|
1339 | + } else { |
|
1340 | + $group_by = array_keys($model->get_combined_primary_key_fields()); |
|
1341 | + } |
|
1342 | + // make sure they're all real names |
|
1343 | + if (is_array($group_by)) { |
|
1344 | + $group_by = ModelDataTranslator::prepareFieldNamesFromJson($group_by); |
|
1345 | + } |
|
1346 | + if ($group_by !== null) { |
|
1347 | + $model_query_params['group_by'] = $group_by; |
|
1348 | + } |
|
1349 | + if (isset($query_params['having'])) { |
|
1350 | + $model_query_params['having'] = ModelDataTranslator::prepareConditionsQueryParamsForModels( |
|
1351 | + $query_params['having'], |
|
1352 | + $model, |
|
1353 | + $this->getModelVersionInfo()->requestedVersion() |
|
1354 | + ); |
|
1355 | + } |
|
1356 | + if (isset($query_params['order'])) { |
|
1357 | + $model_query_params['order'] = $query_params['order']; |
|
1358 | + } |
|
1359 | + if (isset($query_params['mine'])) { |
|
1360 | + $model_query_params = $model->alter_query_params_to_only_include_mine($model_query_params); |
|
1361 | + } |
|
1362 | + if (isset($query_params['limit'])) { |
|
1363 | + // limit should be either a string like '23' or '23,43', or an array with two items in it |
|
1364 | + if (! is_array($query_params['limit'])) { |
|
1365 | + $limit_array = explode(',', (string) $query_params['limit']); |
|
1366 | + } else { |
|
1367 | + $limit_array = $query_params['limit']; |
|
1368 | + } |
|
1369 | + $sanitized_limit = []; |
|
1370 | + foreach ($limit_array as $limit_part) { |
|
1371 | + if ($this->debug_mode && (! is_numeric($limit_part) || count($sanitized_limit) > 2)) { |
|
1372 | + throw new EE_Error( |
|
1373 | + sprintf( |
|
1374 | + esc_html__( |
|
1375 | + // @codingStandardsIgnoreStart |
|
1376 | + 'An invalid limit filter was provided. It was: %s. If the EE4 JSON REST API weren\'t in debug mode, this message would not appear.', |
|
1377 | + // @codingStandardsIgnoreEnd |
|
1378 | + 'event_espresso' |
|
1379 | + ), |
|
1380 | + wp_json_encode($query_params['limit']) |
|
1381 | + ) |
|
1382 | + ); |
|
1383 | + } |
|
1384 | + $sanitized_limit[] = (int) $limit_part; |
|
1385 | + } |
|
1386 | + $model_query_params['limit'] = implode(',', $sanitized_limit); |
|
1387 | + } else { |
|
1388 | + $model_query_params['limit'] = EED_Core_Rest_Api::get_default_query_limit(); |
|
1389 | + } |
|
1390 | + if (isset($query_params['caps'])) { |
|
1391 | + $model_query_params['caps'] = $this->validateContext($query_params['caps']); |
|
1392 | + } else { |
|
1393 | + $model_query_params['caps'] = EEM_Base::caps_read; |
|
1394 | + } |
|
1395 | + if (isset($query_params['default_where_conditions'])) { |
|
1396 | + $model_query_params['default_where_conditions'] = $this->validateDefaultQueryParams( |
|
1397 | + $query_params['default_where_conditions'] |
|
1398 | + ); |
|
1399 | + } |
|
1400 | + // if this is a model protected by a password on another model, exclude the password protected |
|
1401 | + // entities by default. But if they passed in a password, try to show them all. If the password is wrong, |
|
1402 | + // though, they'll get an error (see Read::createEntityFromWpdbResult() which calls Read::checkPassword) |
|
1403 | + if ( |
|
1404 | + ! $model->hasPassword() |
|
1405 | + && $model->restrictedByRelatedModelPassword() |
|
1406 | + && $model_query_params['caps'] === EEM_Base::caps_read |
|
1407 | + ) { |
|
1408 | + if (empty($query_params['password'])) { |
|
1409 | + $model_query_params['exclude_protected'] = true; |
|
1410 | + } |
|
1411 | + } |
|
1412 | + |
|
1413 | + return apply_filters('FHEE__Read__create_model_query_params', $model_query_params, $query_params, $model); |
|
1414 | + } |
|
1415 | + |
|
1416 | + |
|
1417 | + /** |
|
1418 | + * Changes the REST-style query params for use in the models |
|
1419 | + * |
|
1420 | + * @param EEM_Base $model |
|
1421 | + * @param array $query_params sub-array from @see EEM_Base::get_all() |
|
1422 | + * @return array |
|
1423 | + * @deprecated |
|
1424 | + */ |
|
1425 | + public function prepareRestQueryParamsKeyForModels($model, $query_params) |
|
1426 | + { |
|
1427 | + $model_ready_query_params = []; |
|
1428 | + foreach ($query_params as $key => $value) { |
|
1429 | + $model_ready_query_params[ $key ] = is_array($value) |
|
1430 | + ? $this->prepareRestQueryParamsKeyForModels($model, $value) |
|
1431 | + : $value; |
|
1432 | + } |
|
1433 | + return $model_ready_query_params; |
|
1434 | + } |
|
1435 | + |
|
1436 | + |
|
1437 | + /** |
|
1438 | + * @param $model |
|
1439 | + * @param $query_params |
|
1440 | + * @return array |
|
1441 | + * @deprecated instead use ModelDataTranslator::prepareFieldValuesFromJson() |
|
1442 | + */ |
|
1443 | + public function prepareRestQueryParamsValuesForModels($model, $query_params) |
|
1444 | + { |
|
1445 | + $model_ready_query_params = []; |
|
1446 | + foreach ($query_params as $key => $value) { |
|
1447 | + if (is_array($value)) { |
|
1448 | + $model_ready_query_params[ $key ] = $this->prepareRestQueryParamsValuesForModels($model, $value); |
|
1449 | + } else { |
|
1450 | + $model_ready_query_params[ $key ] = $value; |
|
1451 | + } |
|
1452 | + } |
|
1453 | + return $model_ready_query_params; |
|
1454 | + } |
|
1455 | + |
|
1456 | + |
|
1457 | + /** |
|
1458 | + * Explodes the string on commas, and only returns items with $prefix followed by a period. |
|
1459 | + * If no prefix is specified, returns items with no period. |
|
1460 | + * |
|
1461 | + * @param string|array $string_to_explode eg "jibba,jabba, blah, blah, blah" or array('jibba', 'jabba' ) |
|
1462 | + * @param string $prefix "Event" or "foobar" |
|
1463 | + * @return array $string_to_exploded exploded on COMMAS, and if a prefix was specified |
|
1464 | + * we only return strings starting with that and a period; if no prefix was |
|
1465 | + * specified we return all items containing NO periods |
|
1466 | + */ |
|
1467 | + public function explodeAndGetItemsPrefixedWith($string_to_explode, $prefix) |
|
1468 | + { |
|
1469 | + if (is_string($string_to_explode)) { |
|
1470 | + $exploded_contents = explode(',', $string_to_explode); |
|
1471 | + } elseif (is_array($string_to_explode)) { |
|
1472 | + $exploded_contents = $string_to_explode; |
|
1473 | + } else { |
|
1474 | + $exploded_contents = []; |
|
1475 | + } |
|
1476 | + // if the string was empty, we want an empty array |
|
1477 | + $exploded_contents = array_filter($exploded_contents); |
|
1478 | + $contents_with_prefix = []; |
|
1479 | + foreach ($exploded_contents as $item) { |
|
1480 | + $item = trim($item); |
|
1481 | + // if no prefix was provided, so we look for items with no "." in them |
|
1482 | + if (! $prefix) { |
|
1483 | + // does this item have a period? |
|
1484 | + if (strpos($item, '.') === false) { |
|
1485 | + // if not, then its what we're looking for |
|
1486 | + $contents_with_prefix[] = $item; |
|
1487 | + } |
|
1488 | + } elseif (strpos($item, $prefix . '.') === 0) { |
|
1489 | + // this item has the prefix and a period, grab it |
|
1490 | + $contents_with_prefix[] = substr( |
|
1491 | + $item, |
|
1492 | + strpos($item, $prefix . '.') + strlen($prefix . '.') |
|
1493 | + ); |
|
1494 | + } elseif ($item === $prefix) { |
|
1495 | + // this item is JUST the prefix |
|
1496 | + // so let's grab everything after, which is a blank string |
|
1497 | + $contents_with_prefix[] = ''; |
|
1498 | + } |
|
1499 | + } |
|
1500 | + return $contents_with_prefix; |
|
1501 | + } |
|
1502 | + |
|
1503 | + |
|
1504 | + /** |
|
1505 | + * @param string $include_string @see Read:handle_request_get_all |
|
1506 | + * @param string $model_name |
|
1507 | + * @return array of fields for this model. If $model_name is provided, then |
|
1508 | + * the fields for that model, with the model's name removed from each. |
|
1509 | + * If $include_string was blank or '*' returns an empty array |
|
1510 | + * @throws EE_Error |
|
1511 | + * @throws EE_Error |
|
1512 | + * @deprecated since 4.8.36.rc.001 You should instead use Read::explode_and_get_items_prefixed_with. |
|
1513 | + * Deprecated because its return values were really quite confusing- sometimes it |
|
1514 | + * returned an empty array (when the include string was blank or '*') or sometimes it |
|
1515 | + * returned array('*') (when you provided a model and a model of that kind was |
|
1516 | + * found). Parses the $include_string so we fetch all the field names relating to |
|
1517 | + * THIS model |
|
1518 | + * (ie have NO period in them), or for the provided model (ie start with the model |
|
1519 | + * name and then a period). |
|
1520 | + */ |
|
1521 | + public function extractIncludesForThisModel($include_string, $model_name = null) |
|
1522 | + { |
|
1523 | + if (is_array($include_string)) { |
|
1524 | + $include_string = implode(',', $include_string); |
|
1525 | + } |
|
1526 | + if ($include_string === '*' || $include_string === '') { |
|
1527 | + return []; |
|
1528 | + } |
|
1529 | + $includes = explode(',', $include_string); |
|
1530 | + $extracted_fields_to_include = []; |
|
1531 | + if ($model_name) { |
|
1532 | + foreach ($includes as $field_to_include) { |
|
1533 | + $field_to_include = trim($field_to_include); |
|
1534 | + if (strpos($field_to_include, $model_name . '.') === 0) { |
|
1535 | + // found the model name at the exact start |
|
1536 | + $field_sans_model_name = str_replace($model_name . '.', '', $field_to_include); |
|
1537 | + $extracted_fields_to_include[] = $field_sans_model_name; |
|
1538 | + } elseif ($field_to_include == $model_name) { |
|
1539 | + $extracted_fields_to_include[] = '*'; |
|
1540 | + } |
|
1541 | + } |
|
1542 | + } else { |
|
1543 | + // look for ones with no period |
|
1544 | + foreach ($includes as $field_to_include) { |
|
1545 | + $field_to_include = trim($field_to_include); |
|
1546 | + if ( |
|
1547 | + strpos($field_to_include, '.') === false |
|
1548 | + && ! $this->getModelVersionInfo()->isModelNameInThisVersion($field_to_include) |
|
1549 | + ) { |
|
1550 | + $extracted_fields_to_include[] = $field_to_include; |
|
1551 | + } |
|
1552 | + } |
|
1553 | + } |
|
1554 | + return $extracted_fields_to_include; |
|
1555 | + } |
|
1556 | + |
|
1557 | + |
|
1558 | + /** |
|
1559 | + * Gets the single item using the model according to the request in the context given, otherwise |
|
1560 | + * returns that it's inaccessible to the current user |
|
1561 | + * |
|
1562 | + * @param EEM_Base $model |
|
1563 | + * @param WP_REST_Request $request |
|
1564 | + * @param null $context |
|
1565 | + * @return array |
|
1566 | + * @throws EE_Error |
|
1567 | + * @throws ReflectionException |
|
1568 | + */ |
|
1569 | + public function getOneOrReportPermissionError(EEM_Base $model, WP_REST_Request $request, $context = null) |
|
1570 | + { |
|
1571 | + $query_params = [[$model->primary_key_name() => $request->get_param('id')], 'limit' => 1]; |
|
1572 | + if ($model instanceof EEM_Soft_Delete_Base) { |
|
1573 | + $query_params = $model->alter_query_params_so_deleted_and_undeleted_items_included($query_params); |
|
1574 | + } |
|
1575 | + $restricted_query_params = $query_params; |
|
1576 | + $restricted_query_params['caps'] = $context; |
|
1577 | + $this->setDebugInfo('model query params', $restricted_query_params); |
|
1578 | + $model_rows = $model->get_all_wpdb_results($restricted_query_params); |
|
1579 | + if (! empty($model_rows)) { |
|
1580 | + return $this->createEntityFromWpdbResult( |
|
1581 | + $model, |
|
1582 | + reset($model_rows), |
|
1583 | + $request |
|
1584 | + ); |
|
1585 | + } else { |
|
1586 | + // ok let's test to see if we WOULD have found it, had we not had restrictions from missing capabilities |
|
1587 | + $lowercase_model_name = strtolower($model->get_this_model_name()); |
|
1588 | + if ($model->exists($query_params)) { |
|
1589 | + // you got shafted- it existed but we didn't want to tell you! |
|
1590 | + throw new RestException( |
|
1591 | + 'rest_user_cannot_' . $context, |
|
1592 | + sprintf( |
|
1593 | + esc_html__('Sorry, you cannot %1$s this %2$s. Missing permissions are: %3$s', 'event_espresso'), |
|
1594 | + $context, |
|
1595 | + $lowercase_model_name, |
|
1596 | + Capabilities::getMissingPermissionsString( |
|
1597 | + $model, |
|
1598 | + $context |
|
1599 | + ) |
|
1600 | + ), |
|
1601 | + ['status' => 403] |
|
1602 | + ); |
|
1603 | + } else { |
|
1604 | + // it's not you. It just doesn't exist |
|
1605 | + throw new RestException( |
|
1606 | + sprintf('rest_%s_invalid_id', $lowercase_model_name), |
|
1607 | + sprintf(esc_html__('Invalid %s ID.', 'event_espresso'), $lowercase_model_name), |
|
1608 | + ['status' => 404] |
|
1609 | + ); |
|
1610 | + } |
|
1611 | + } |
|
1612 | + } |
|
1613 | + |
|
1614 | + |
|
1615 | + /** |
|
1616 | + * Checks that if this content requires a password to be read, that it's been provided and is correct. |
|
1617 | + * |
|
1618 | + * @param EEM_Base $model |
|
1619 | + * @param array $model_row |
|
1620 | + * @param array $query_params Adds 'default_where_conditions' => 'minimum' |
|
1621 | + * to ensure we don't confuse trashed with password protected. |
|
1622 | + * @param WP_REST_Request $request |
|
1623 | + * @throws EE_Error |
|
1624 | + * @throws InvalidArgumentException |
|
1625 | + * @throws InvalidDataTypeException |
|
1626 | + * @throws InvalidInterfaceException |
|
1627 | + * @throws RestPasswordRequiredException |
|
1628 | + * @throws RestPasswordIncorrectException |
|
1629 | + * @throws ModelConfigurationException |
|
1630 | + * @throws ReflectionException |
|
1631 | + * @since 4.9.74.p |
|
1632 | + */ |
|
1633 | + protected function checkPassword(EEM_Base $model, $model_row, $query_params, WP_REST_Request $request) |
|
1634 | + { |
|
1635 | + $query_params['default_where_conditions'] = 'minimum'; |
|
1636 | + // stuff is only "protected" for front-end requests. Elsewhere, you either get full permission to access the object |
|
1637 | + // or you don't. |
|
1638 | + $request_caps = $request->get_param('caps'); |
|
1639 | + if (isset($request_caps) && $request_caps !== EEM_Base::caps_read) { |
|
1640 | + return; |
|
1641 | + } |
|
1642 | + // if this entity requires a password, they better give it and it better be right! |
|
1643 | + if ( |
|
1644 | + $model->hasPassword() |
|
1645 | + && $model_row[ $model->getPasswordField()->get_qualified_column() ] !== '' |
|
1646 | + ) { |
|
1647 | + if (empty($request['password'])) { |
|
1648 | + throw new RestPasswordRequiredException(); |
|
1649 | + } |
|
1650 | + if ( |
|
1651 | + ! hash_equals( |
|
1652 | + $model_row[ $model->getPasswordField()->get_qualified_column() ], |
|
1653 | + $request['password'] |
|
1654 | + ) |
|
1655 | + ) { |
|
1656 | + throw new RestPasswordIncorrectException(); |
|
1657 | + } |
|
1658 | + } elseif ( |
|
1659 | + // wait! maybe this content is password protected |
|
1660 | + $model->restrictedByRelatedModelPassword() |
|
1661 | + && $request->get_param('caps') === EEM_Base::caps_read |
|
1662 | + ) { |
|
1663 | + $password_supplied = $request->get_param('password'); |
|
1664 | + if (empty($password_supplied)) { |
|
1665 | + $query_params['exclude_protected'] = true; |
|
1666 | + if (! $model->exists($query_params)) { |
|
1667 | + throw new RestPasswordRequiredException(); |
|
1668 | + } |
|
1669 | + } else { |
|
1670 | + $query_params[0][ $model->modelChainAndPassword() ] = $password_supplied; |
|
1671 | + if (! $model->exists($query_params)) { |
|
1672 | + throw new RestPasswordIncorrectException(); |
|
1673 | + } |
|
1674 | + } |
|
1675 | + } |
|
1676 | + } |
|
1677 | 1677 | } |