@@ -505,7 +505,7 @@ |
||
| 505 | 505 | * |
| 506 | 506 | * @param string $value string to evaluate |
| 507 | 507 | * @param array $valid_shortcodes array of shortcodes that are acceptable. |
| 508 | - * @return mixed (bool|string) return either a list of invalid shortcodes OR false if the shortcodes validate. |
|
| 508 | + * @return false|string (bool|string) return either a list of invalid shortcodes OR false if the shortcodes validate. |
|
| 509 | 509 | */ |
| 510 | 510 | protected function _invalid_shortcodes($value, $valid_shortcodes) |
| 511 | 511 | { |
@@ -20,626 +20,626 @@ |
||
| 20 | 20 | { |
| 21 | 21 | |
| 22 | 22 | |
| 23 | - /** |
|
| 24 | - * These properties just hold the name for the Messenger and Message Type (defined by child classes). |
|
| 25 | - * These are used for retrieving objects etc. |
|
| 26 | - * |
|
| 27 | - * @var string |
|
| 28 | - */ |
|
| 29 | - protected $_m_name; |
|
| 30 | - protected $_mt_name; |
|
| 31 | - |
|
| 32 | - |
|
| 33 | - /** |
|
| 34 | - * This will hold any error messages from the validation process. |
|
| 35 | - * The _errors property holds an associative array of error messages |
|
| 36 | - * listing the field as the key and the message as the value. |
|
| 37 | - * |
|
| 38 | - * @var array() |
|
| 39 | - */ |
|
| 40 | - private $_errors = array(); |
|
| 41 | - |
|
| 42 | - |
|
| 43 | - /** |
|
| 44 | - * holds an array of fields being validated |
|
| 45 | - * |
|
| 46 | - * @var array |
|
| 47 | - */ |
|
| 48 | - protected $_fields; |
|
| 49 | - |
|
| 50 | - |
|
| 51 | - /** |
|
| 52 | - * this will hold the incoming context |
|
| 53 | - * |
|
| 54 | - * @var string |
|
| 55 | - */ |
|
| 56 | - protected $_context; |
|
| 57 | - |
|
| 58 | - |
|
| 59 | - /** |
|
| 60 | - * this holds an array of fields and the relevant validation information |
|
| 61 | - * that the incoming fields data get validated against. |
|
| 62 | - * This gets setup in the _set_props() method. |
|
| 63 | - * |
|
| 64 | - * @var array |
|
| 65 | - */ |
|
| 66 | - protected $_validators; |
|
| 67 | - |
|
| 68 | - |
|
| 69 | - /** |
|
| 70 | - * holds the messenger object |
|
| 71 | - * |
|
| 72 | - * @var object |
|
| 73 | - */ |
|
| 74 | - protected $_messenger; |
|
| 75 | - |
|
| 76 | - |
|
| 77 | - /** |
|
| 78 | - * holds the message type object |
|
| 79 | - * |
|
| 80 | - * @var object |
|
| 81 | - */ |
|
| 82 | - protected $_message_type; |
|
| 83 | - |
|
| 84 | - |
|
| 85 | - /** |
|
| 86 | - * will hold any valid_shortcode modifications made by the _modify_validator() method. |
|
| 87 | - * |
|
| 88 | - * @var array |
|
| 89 | - */ |
|
| 90 | - protected $_valid_shortcodes_modifier; |
|
| 91 | - |
|
| 92 | - |
|
| 93 | - /** |
|
| 94 | - * There may be times where a message type wants to include a shortcode group but exclude specific |
|
| 95 | - * shortcodes. If that's the case then it can set this property as an array of shortcodes to exclude and |
|
| 96 | - * they will not be allowed. |
|
| 97 | - * Array should be indexed by field and values are an array of specific shortcodes to exclude. |
|
| 98 | - * |
|
| 99 | - * @var array |
|
| 100 | - */ |
|
| 101 | - protected $_specific_shortcode_excludes = array(); |
|
| 102 | - |
|
| 103 | - |
|
| 104 | - /** |
|
| 105 | - * Runs the validator using the incoming fields array as the fields/values to check. |
|
| 106 | - * |
|
| 107 | - * @param array $fields The fields sent by the EEM object. |
|
| 108 | - * @param $context |
|
| 109 | - * @throws EE_Error |
|
| 110 | - * @throws ReflectionException |
|
| 111 | - */ |
|
| 112 | - public function __construct($fields, $context) |
|
| 113 | - { |
|
| 114 | - //check that _m_name and _mt_name have been set by child class otherwise we get out. |
|
| 115 | - if (empty($this->_m_name) || empty($this->_mt_name)) { |
|
| 116 | - throw new EE_Error( |
|
| 117 | - esc_html__( |
|
| 118 | - 'EE_Messages_Validator child classes MUST set the $_m_name and $_mt_name property. Check that the child class is doing this', |
|
| 119 | - 'event_espresso' |
|
| 120 | - ) |
|
| 121 | - ); |
|
| 122 | - } |
|
| 123 | - $this->_fields = $fields; |
|
| 124 | - $this->_context = $context; |
|
| 125 | - |
|
| 126 | - //load messenger and message_type objects and the related shortcode objects. |
|
| 127 | - $this->_load_objects(); |
|
| 128 | - |
|
| 129 | - |
|
| 130 | - //modify any messenger/message_type specific validation instructions. This is what child classes define. |
|
| 131 | - $this->_modify_validator(); |
|
| 132 | - |
|
| 133 | - |
|
| 134 | - //let's set validators property |
|
| 135 | - $this->_set_validators(); |
|
| 136 | - } |
|
| 137 | - |
|
| 138 | - |
|
| 139 | - /** |
|
| 140 | - * Child classes instantiate this and use it to modify the _validator_config array property |
|
| 141 | - * for the messenger using messengers set_validate_config() method. |
|
| 142 | - * This is so we can specify specific validation instructions for a messenger/message_type combo |
|
| 143 | - * that aren't handled by the defaults setup in the messenger. |
|
| 144 | - * |
|
| 145 | - * @abstract |
|
| 146 | - * @access protected |
|
| 147 | - * @return void |
|
| 148 | - */ |
|
| 149 | - abstract protected function _modify_validator(); |
|
| 150 | - |
|
| 151 | - |
|
| 152 | - /** |
|
| 153 | - * loads all objects used by validator |
|
| 154 | - * |
|
| 155 | - * @access private |
|
| 156 | - * @throws \EE_Error |
|
| 157 | - */ |
|
| 158 | - private function _load_objects() |
|
| 159 | - { |
|
| 160 | - //load messenger |
|
| 161 | - $messenger = ucwords(str_replace('_', ' ', $this->_m_name)); |
|
| 162 | - $messenger = str_replace(' ', '_', $messenger); |
|
| 163 | - $messenger = 'EE_' . $messenger . '_messenger'; |
|
| 164 | - |
|
| 165 | - if (! class_exists($messenger)) { |
|
| 166 | - throw new EE_Error( |
|
| 167 | - sprintf( |
|
| 168 | - esc_html__('There is no messenger class for the given string (%s)', 'event_espresso'), |
|
| 169 | - $this->_m_name |
|
| 170 | - ) |
|
| 171 | - ); |
|
| 172 | - } |
|
| 173 | - |
|
| 174 | - $this->_messenger = new $messenger(); |
|
| 175 | - |
|
| 176 | - //load message type |
|
| 177 | - $message_type = ucwords(str_replace('_', ' ', $this->_mt_name)); |
|
| 178 | - $message_type = str_replace(' ', '_', $message_type); |
|
| 179 | - $message_type = 'EE_' . $message_type . '_message_type'; |
|
| 180 | - |
|
| 181 | - if (! class_exists($message_type)) { |
|
| 182 | - throw new EE_Error( |
|
| 183 | - sprintf( |
|
| 184 | - esc_html__('There is no message type class for the given string (%s)', 'event_espresso'), |
|
| 185 | - $this->_mt_name |
|
| 186 | - ) |
|
| 187 | - ); |
|
| 188 | - } |
|
| 189 | - |
|
| 190 | - $this->_message_type = new $message_type(); |
|
| 191 | - } |
|
| 192 | - |
|
| 193 | - |
|
| 194 | - /** |
|
| 195 | - * used to set the $_validators property |
|
| 196 | - * |
|
| 197 | - * @access private |
|
| 198 | - * @return void |
|
| 199 | - * @throws ReflectionException |
|
| 200 | - */ |
|
| 201 | - private function _set_validators() |
|
| 202 | - { |
|
| 203 | - // let's get all valid shortcodes from mt and message type |
|
| 204 | - // (messenger will have its set in the _validator_config property for the messenger) |
|
| 205 | - $mt_codes = $this->_message_type->get_valid_shortcodes(); |
|
| 206 | - |
|
| 207 | - |
|
| 208 | - //get messenger validator_config |
|
| 209 | - $msgr_validator = $this->_messenger->get_validator_config(); |
|
| 210 | - |
|
| 211 | - |
|
| 212 | - //we only want the valid shortcodes for the given context! |
|
| 213 | - $context = $this->_context; |
|
| 214 | - $mt_codes = $mt_codes[$context]; |
|
| 215 | - |
|
| 216 | - // in this first loop we're just getting all shortcode group indexes from the msgr_validator |
|
| 217 | - // into a single array (so we can get the appropriate shortcode objects for the groups) |
|
| 218 | - $shortcode_groups = $mt_codes; |
|
| 219 | - $groups_per_field = array(); |
|
| 220 | - |
|
| 221 | - foreach ($msgr_validator as $field => $config) { |
|
| 222 | - if (empty($config) || ! isset($config['shortcodes'])) { |
|
| 223 | - continue; |
|
| 224 | - } //Nothing to see here. |
|
| 225 | - $groups_per_field[$field] = array_intersect($config['shortcodes'], $mt_codes); |
|
| 226 | - $shortcode_groups = array_merge($config['shortcodes'], $shortcode_groups); |
|
| 227 | - } |
|
| 228 | - |
|
| 229 | - $shortcode_groups = array_unique($shortcode_groups); |
|
| 230 | - |
|
| 231 | - // okay now we've got our groups. |
|
| 232 | - // Let's get the codes from the objects into an array indexed by group for easy retrieval later. |
|
| 233 | - $codes_from_objs = array(); |
|
| 234 | - |
|
| 235 | - foreach ($shortcode_groups as $group) { |
|
| 236 | - $ref = ucwords(str_replace('_', ' ', $group)); |
|
| 237 | - $ref = str_replace(' ', '_', $ref); |
|
| 238 | - $classname = 'EE_' . $ref . '_Shortcodes'; |
|
| 239 | - if (class_exists($classname)) { |
|
| 240 | - $a = new ReflectionClass($classname); |
|
| 241 | - $obj = $a->newInstance(); |
|
| 242 | - $codes_from_objs[$group] = $obj->get_shortcodes(); |
|
| 243 | - } |
|
| 244 | - } |
|
| 245 | - |
|
| 246 | - |
|
| 247 | - //let's just replace the $mt shortcode group indexes with the actual shortcodes (unique) |
|
| 248 | - $final_mt_codes = array(); |
|
| 249 | - foreach ($mt_codes as $group) { |
|
| 250 | - $final_mt_codes = array_merge($final_mt_codes, $codes_from_objs[$group]); |
|
| 251 | - } |
|
| 252 | - |
|
| 253 | - $mt_codes = $final_mt_codes; |
|
| 254 | - |
|
| 255 | - |
|
| 256 | - // k now in this next loop we're going to loop through $msgr_validator again |
|
| 257 | - // and setup the _validators property from the data we've setup so far. |
|
| 258 | - foreach ($msgr_validator as $field => $config) { |
|
| 259 | - //if required shortcode is not in our list of codes for the given field, then we skip this field. |
|
| 260 | - $required = isset($config['required']) |
|
| 261 | - ? array_intersect($config['required'], array_keys($mt_codes)) |
|
| 262 | - : true; |
|
| 263 | - if (empty($required)) { |
|
| 264 | - continue; |
|
| 265 | - } |
|
| 266 | - |
|
| 267 | - //If we have an override then we use it to indicate the codes we want. |
|
| 268 | - if (isset($this->_valid_shortcodes_modifier[$context][$field])) { |
|
| 269 | - $this->_validators[$field]['shortcodes'] = $this->_reassemble_valid_shortcodes_from_group( |
|
| 270 | - $this->_valid_shortcodes_modifier[$context][$field], |
|
| 271 | - $codes_from_objs |
|
| 272 | - ); |
|
| 273 | - } //if we have specific shortcodes for a field then we need to use them |
|
| 274 | - elseif (isset($groups_per_field[$field])) { |
|
| 275 | - $this->_validators[$field]['shortcodes'] = $this->_reassemble_valid_shortcodes_from_group( |
|
| 276 | - $groups_per_field[$field], |
|
| 277 | - $codes_from_objs |
|
| 278 | - ); |
|
| 279 | - } //if empty config then we're assuming we're just going to use the shortcodes from the message type context |
|
| 280 | - elseif (empty($config)) { |
|
| 281 | - $this->_validators[$field]['shortcodes'] = $mt_codes; |
|
| 282 | - } //if we have specific shortcodes then we need to use them |
|
| 283 | - elseif (isset($config['specific_shortcodes'])) { |
|
| 284 | - $this->_validators[$field]['shortcodes'] = $config['specific_shortcodes']; |
|
| 285 | - } //otherwise the shortcodes are what is set by the messenger for that field |
|
| 286 | - else { |
|
| 287 | - foreach ($config['shortcodes'] as $group) { |
|
| 288 | - $this->_validators[$field]['shortcodes'] = isset($this->_validators[$field]['shortcodes']) |
|
| 289 | - ? array_merge($this->_validators[$field]['shortcodes'], $codes_from_objs[$group]) |
|
| 290 | - : $codes_from_objs[$group]; |
|
| 291 | - } |
|
| 292 | - } |
|
| 293 | - |
|
| 294 | - //now let's just make sure that any excluded specific shortcodes are removed. |
|
| 295 | - $specific_excludes = $this->get_specific_shortcode_excludes(); |
|
| 296 | - if (isset($specific_excludes[$field])) { |
|
| 297 | - foreach ($specific_excludes[$field] as $sex) { |
|
| 298 | - if (isset($this->_validators[$field]['shortcodes'][$sex])) { |
|
| 299 | - unset($this->_validators[$field]['shortcodes'][$sex]); |
|
| 300 | - } |
|
| 301 | - } |
|
| 302 | - } |
|
| 303 | - |
|
| 304 | - //hey! don't forget to include the type if present! |
|
| 305 | - $this->_validators[$field]['type'] = isset($config['type']) ? $config['type'] : null; |
|
| 306 | - } |
|
| 307 | - } |
|
| 308 | - |
|
| 309 | - |
|
| 310 | - /** |
|
| 311 | - * This just returns the validators property that contains information |
|
| 312 | - * about the various shortcodes and their availability with each field |
|
| 313 | - * |
|
| 314 | - * @return array |
|
| 315 | - */ |
|
| 316 | - public function get_validators() |
|
| 317 | - { |
|
| 318 | - return $this->_validators; |
|
| 319 | - } |
|
| 320 | - |
|
| 321 | - |
|
| 322 | - /** |
|
| 323 | - * This simply returns the specific shortcode_excludes property that is set. |
|
| 324 | - * |
|
| 325 | - * @since 4.5.0 |
|
| 326 | - * @return array |
|
| 327 | - */ |
|
| 328 | - public function get_specific_shortcode_excludes() |
|
| 329 | - { |
|
| 330 | - //specific validator filter |
|
| 331 | - $shortcode_excludes = apply_filters( |
|
| 332 | - 'FHEE__' . get_class($this) . '__get_specific_shortcode_excludes;', |
|
| 333 | - $this->_specific_shortcode_excludes, |
|
| 334 | - $this->_context |
|
| 335 | - ); |
|
| 336 | - //global filter |
|
| 337 | - return apply_filters( |
|
| 338 | - 'FHEE__EE_Messages_Validator__get_specific_shortcode_excludes', |
|
| 339 | - $shortcode_excludes, |
|
| 340 | - $this->_context, |
|
| 341 | - $this |
|
| 342 | - ); |
|
| 343 | - } |
|
| 344 | - |
|
| 345 | - |
|
| 346 | - /** |
|
| 347 | - * This is the main method that handles validation |
|
| 348 | - * What it does is loop through the _fields (the ones that get validated) |
|
| 349 | - * and checks them against the shortcodes array for the field and the 'type' indicated by the |
|
| 350 | - * |
|
| 351 | - * @access public |
|
| 352 | - * @return mixed (bool|array) if errors present we return the array otherwise true |
|
| 353 | - */ |
|
| 354 | - public function validate() |
|
| 355 | - { |
|
| 356 | - //some defaults |
|
| 357 | - $template_fields = $this->_messenger->get_template_fields(); |
|
| 358 | - //loop through the fields and check! |
|
| 359 | - foreach ($this->_fields as $field => $value) { |
|
| 360 | - $this->_errors[$field] = array(); |
|
| 361 | - $err_msg = ''; |
|
| 362 | - $field_label = ''; |
|
| 363 | - //if field is not present in the _validators array then we continue |
|
| 364 | - if (! isset($this->_validators[$field])) { |
|
| 365 | - unset($this->_errors[$field]); |
|
| 366 | - continue; |
|
| 367 | - } |
|
| 368 | - |
|
| 369 | - //get the translated field label! |
|
| 370 | - //first check if it's in the main fields list |
|
| 371 | - if (isset($template_fields[$field])) { |
|
| 372 | - if (empty($template_fields[$field])) { |
|
| 373 | - $field_label = $field; |
|
| 374 | - } //most likely the field is found in the 'extra' array. |
|
| 375 | - else { |
|
| 376 | - $field_label = $template_fields[$field]['label']; |
|
| 377 | - } |
|
| 378 | - } |
|
| 379 | - |
|
| 380 | - // if field label is empty OR is equal to the current field |
|
| 381 | - // then we need to loop through the 'extra' fields in the template_fields config (if present) |
|
| 382 | - if (isset($template_fields['extra']) && (empty($field_label) || $field_label === $field)) { |
|
| 383 | - foreach ($template_fields['extra'] as $main_field => $secondary_field) { |
|
| 384 | - foreach ($secondary_field as $name => $values) { |
|
| 385 | - if ($name === $field) { |
|
| 386 | - $field_label = $values['label']; |
|
| 387 | - } |
|
| 388 | - |
|
| 389 | - // if we've got a 'main' secondary field, let's see if that matches what field we're on |
|
| 390 | - // which means it contains the label for this field. |
|
| 391 | - if ($name === 'main' && $main_field === $field_label) { |
|
| 392 | - $field_label = $values['label']; |
|
| 393 | - } |
|
| 394 | - } |
|
| 395 | - } |
|
| 396 | - } |
|
| 397 | - |
|
| 398 | - //field is present. Let's validate shortcodes first (but only if shortcodes present). |
|
| 399 | - if (isset($this->_validators[$field]['shortcodes']) |
|
| 400 | - && ! empty($this->_validators[$field]['shortcodes']) |
|
| 401 | - ) { |
|
| 402 | - $invalid_shortcodes = $this->_invalid_shortcodes($value, $this->_validators[$field]['shortcodes']); |
|
| 403 | - // if true then that means there is a returned error message |
|
| 404 | - // that we'll need to add to the _errors array for this field. |
|
| 405 | - if ($invalid_shortcodes) { |
|
| 406 | - $v_s = array_keys($this->_validators[$field]['shortcodes']); |
|
| 407 | - $err_msg = sprintf( |
|
| 408 | - esc_html__( |
|
| 409 | - '%3$sThe following shortcodes were found in the "%1$s" field that ARE not valid: %2$s%4$s', |
|
| 410 | - 'event_espresso' |
|
| 411 | - ), |
|
| 412 | - '<strong>' . $field_label . '</strong>', |
|
| 413 | - $invalid_shortcodes, |
|
| 414 | - '<p>', |
|
| 415 | - '</p >' |
|
| 416 | - ); |
|
| 417 | - $err_msg .= sprintf( |
|
| 418 | - esc_html__('%2$sValid shortcodes for this field are: %1$s%3$s', 'event_espresso'), |
|
| 419 | - implode(', ', $v_s), |
|
| 420 | - '<strong>', |
|
| 421 | - '</strong>' |
|
| 422 | - ); |
|
| 423 | - } |
|
| 424 | - } |
|
| 425 | - |
|
| 426 | - //if there's a "type" to be validated then let's do that too. |
|
| 427 | - if (isset($this->_validators[$field]['type']) && ! empty($this->_validators[$field]['type'])) { |
|
| 428 | - switch ($this->_validators[$field]['type']) { |
|
| 429 | - case 'number': |
|
| 430 | - if (! is_numeric($value)) { |
|
| 431 | - $err_msg .= sprintf( |
|
| 432 | - esc_html__( |
|
| 433 | - '%3$sThe %1$s field is supposed to be a number. The value given (%2$s) is not. Please double-check and make sure the field contains a number%4$s', |
|
| 434 | - 'event_espresso' |
|
| 435 | - ), |
|
| 436 | - $field_label, |
|
| 437 | - $value, |
|
| 438 | - '<p>', |
|
| 439 | - '</p >' |
|
| 440 | - ); |
|
| 441 | - } |
|
| 442 | - break; |
|
| 443 | - case 'email': |
|
| 444 | - $valid_email = $this->_validate_email($value); |
|
| 445 | - if (! $valid_email) { |
|
| 446 | - $err_msg .= htmlentities( |
|
| 447 | - sprintf( |
|
| 448 | - esc_html__( |
|
| 449 | - 'The %1$s field has at least one string that is not a valid email address record. Valid emails are in the format: "Name <[email protected]>" or "[email protected]" and multiple emails can be separated by a comma.' |
|
| 450 | - ), |
|
| 451 | - $field_label |
|
| 452 | - |
|
| 453 | - ) |
|
| 454 | - ); |
|
| 455 | - } |
|
| 456 | - break; |
|
| 457 | - default: |
|
| 458 | - break; |
|
| 459 | - } |
|
| 460 | - } |
|
| 461 | - |
|
| 462 | - //if $err_msg isn't empty let's setup the _errors array for this field. |
|
| 463 | - if (! empty($err_msg)) { |
|
| 464 | - $this->_errors[$field]['msg'] = $err_msg; |
|
| 465 | - } else { |
|
| 466 | - unset($this->_errors[$field]); |
|
| 467 | - } |
|
| 468 | - } |
|
| 469 | - |
|
| 470 | - // if we have ANY errors, then we want to make sure we return the values |
|
| 471 | - // for ALL the fields so the user doesn't have to retype them all. |
|
| 472 | - if (! empty($this->_errors)) { |
|
| 473 | - foreach ($this->_fields as $field => $value) { |
|
| 474 | - $this->_errors[$field]['value'] = stripslashes($value); |
|
| 475 | - } |
|
| 476 | - } |
|
| 477 | - |
|
| 478 | - //return any errors or just TRUE if everything validates |
|
| 479 | - return empty($this->_errors) ? true : $this->_errors; |
|
| 480 | - } |
|
| 481 | - |
|
| 482 | - |
|
| 483 | - /** |
|
| 484 | - * Reassembles and returns an array of valid shortcodes |
|
| 485 | - * given the array of groups and array of shortcodes indexed by group. |
|
| 486 | - * |
|
| 487 | - * @param array $groups array of shortcode groups that we want shortcodes for |
|
| 488 | - * @param array $codes_from_objs All the codes available. |
|
| 489 | - * @return array an array of actual shortcodes (that will be used for validation). |
|
| 490 | - */ |
|
| 491 | - private function _reassemble_valid_shortcodes_from_group($groups, $codes_from_objs) |
|
| 492 | - { |
|
| 493 | - $shortcodes = array(); |
|
| 494 | - foreach ($groups as $group) { |
|
| 495 | - $shortcodes = array_merge($shortcodes, $codes_from_objs[$group]); |
|
| 496 | - } |
|
| 497 | - return $shortcodes; |
|
| 498 | - } |
|
| 499 | - |
|
| 500 | - |
|
| 501 | - /** |
|
| 502 | - * Validates a string against a list of accepted shortcodes |
|
| 503 | - * This function takes in an array of shortcodes |
|
| 504 | - * and makes sure that the given string ONLY contains shortcodes in that array. |
|
| 505 | - * |
|
| 506 | - * @param string $value string to evaluate |
|
| 507 | - * @param array $valid_shortcodes array of shortcodes that are acceptable. |
|
| 508 | - * @return mixed (bool|string) return either a list of invalid shortcodes OR false if the shortcodes validate. |
|
| 509 | - */ |
|
| 510 | - protected function _invalid_shortcodes($value, $valid_shortcodes) |
|
| 511 | - { |
|
| 512 | - //first we need to go through the string and get the shortcodes in the string |
|
| 513 | - preg_match_all('/(\[.+?\])/', $value, $matches); |
|
| 514 | - $incoming_shortcodes = (array)$matches[0]; |
|
| 515 | - |
|
| 516 | - //get a diff of the shortcodes in the string vs the valid shortcodes |
|
| 517 | - $diff = array_diff($incoming_shortcodes, array_keys($valid_shortcodes)); |
|
| 518 | - |
|
| 519 | - //we need to account for custom codes so let's loop through the diff and remove any of those type of codes |
|
| 520 | - foreach ($diff as $ind => $code) { |
|
| 521 | - if (preg_match('/(\[[A-Za-z0-9\_]+_\*)/', $code)) { |
|
| 522 | - //strip the shortcode so we just have the BASE string (i.e. [ANSWER_*] ) |
|
| 523 | - $dynamic_sc = preg_replace('/(_\*+.+)/', '_*]', $code); |
|
| 524 | - //does this exist in the $valid_shortcodes? If so then unset. |
|
| 525 | - if (isset($valid_shortcodes[$dynamic_sc])) { |
|
| 526 | - unset($diff[$ind]); |
|
| 527 | - } |
|
| 528 | - } |
|
| 529 | - } |
|
| 530 | - |
|
| 531 | - if (empty($diff)) { |
|
| 532 | - return false; |
|
| 533 | - } //there is no diff, we have no invalid shortcodes, so return |
|
| 534 | - |
|
| 535 | - //made it here? then let's assemble the error message |
|
| 536 | - $invalid_shortcodes = implode('</strong>,<strong>', $diff); |
|
| 537 | - $invalid_shortcodes = '<strong>' . $invalid_shortcodes . '</strong>'; |
|
| 538 | - return $invalid_shortcodes; |
|
| 539 | - } |
|
| 540 | - |
|
| 541 | - |
|
| 542 | - /** |
|
| 543 | - * Validates an incoming string and makes sure we have valid emails in the string. |
|
| 544 | - * |
|
| 545 | - * @param string $value incoming value to validate |
|
| 546 | - * @return bool true if the string validates, false if it doesn't |
|
| 547 | - */ |
|
| 548 | - protected function _validate_email($value) |
|
| 549 | - { |
|
| 550 | - $validate = true; |
|
| 551 | - $or_val = $value; |
|
| 552 | - |
|
| 553 | - // empty strings will validate because this is how a message template |
|
| 554 | - // for a particular context can be "turned off" (if there is no email then no message) |
|
| 555 | - if (empty($value)) { |
|
| 556 | - return $validate; |
|
| 557 | - } |
|
| 558 | - |
|
| 559 | - // first determine if there ARE any shortcodes. |
|
| 560 | - // If there are shortcodes and then later we find that there were no other valid emails |
|
| 561 | - // but the field isn't empty... |
|
| 562 | - // that means we've got extra commas that were left after stripping out shortcodes so probably still valid. |
|
| 563 | - $has_shortcodes = preg_match('/(\[.+?\])/', $value); |
|
| 564 | - |
|
| 565 | - //first we need to strip out all the shortcodes! |
|
| 566 | - $value = preg_replace('/(\[.+?\])/', '', $value); |
|
| 567 | - |
|
| 568 | - // if original value is not empty and new value is, then we've parsed out a shortcode |
|
| 569 | - // and we now have an empty string which DOES validate. |
|
| 570 | - // We also validate complete empty field for email because |
|
| 571 | - // its possible that this message is being "turned off" for a particular context |
|
| 572 | - |
|
| 573 | - |
|
| 574 | - if (! empty($or_val) && empty($value)) { |
|
| 575 | - return $validate; |
|
| 576 | - } |
|
| 577 | - |
|
| 578 | - //trim any commas from beginning and end of string ( after whitespace trimmed ); |
|
| 579 | - $value = trim(trim($value), ','); |
|
| 580 | - |
|
| 581 | - |
|
| 582 | - //next we need to split up the string if its comma delimited. |
|
| 583 | - $emails = explode(',', $value); |
|
| 584 | - $empty = false; //used to indicate that there is an empty comma. |
|
| 585 | - //now let's loop through the emails and do our checks |
|
| 586 | - foreach ($emails as $email) { |
|
| 587 | - if (empty($email)) { |
|
| 588 | - $empty = true; |
|
| 589 | - continue; |
|
| 590 | - } |
|
| 591 | - |
|
| 592 | - //trim whitespace |
|
| 593 | - $email = trim($email); |
|
| 594 | - //either its of type "[email protected]", or its of type "fname lname <[email protected]>" |
|
| 595 | - if (is_email($email)) { |
|
| 596 | - continue; |
|
| 597 | - } |
|
| 598 | - $matches = array(); |
|
| 599 | - $validate = preg_match('/(.*)<(.+)>/', $email, $matches) ? true : false; |
|
| 600 | - if ($validate && is_email($matches[2])) { |
|
| 601 | - continue; |
|
| 602 | - } |
|
| 603 | - return false; |
|
| 604 | - } |
|
| 605 | - |
|
| 606 | - $validate = $empty && ! $has_shortcodes ? false : $validate; |
|
| 607 | - |
|
| 608 | - return $validate; |
|
| 609 | - } |
|
| 610 | - |
|
| 611 | - |
|
| 612 | - /** |
|
| 613 | - * Magic getter |
|
| 614 | - * Using this to provide back compat with add-ons referencing deprecated properties. |
|
| 615 | - * |
|
| 616 | - * @param string $property Property being requested |
|
| 617 | - * @throws Exception |
|
| 618 | - * @return mixed |
|
| 619 | - */ |
|
| 620 | - public function __get($property) |
|
| 621 | - { |
|
| 622 | - $expected_properties_map = array( |
|
| 623 | - /** |
|
| 624 | - * @deprecated 4.9.0 |
|
| 625 | - */ |
|
| 626 | - '_MSGR' => '_messenger', |
|
| 627 | - /** |
|
| 628 | - * @deprecated 4.9.0 |
|
| 629 | - */ |
|
| 630 | - '_MSGTYP' => '_message_type', |
|
| 631 | - ); |
|
| 632 | - |
|
| 633 | - if (isset($expected_properties_map[$property])) { |
|
| 634 | - return $this->{$expected_properties_map[$property]}; |
|
| 635 | - } |
|
| 636 | - |
|
| 637 | - throw new Exception( |
|
| 638 | - sprintf( |
|
| 639 | - esc_html__('The property %1$s being requested on %2$s does not exist', 'event_espresso'), |
|
| 640 | - $property, |
|
| 641 | - get_class($this) |
|
| 642 | - ) |
|
| 643 | - ); |
|
| 644 | - } |
|
| 23 | + /** |
|
| 24 | + * These properties just hold the name for the Messenger and Message Type (defined by child classes). |
|
| 25 | + * These are used for retrieving objects etc. |
|
| 26 | + * |
|
| 27 | + * @var string |
|
| 28 | + */ |
|
| 29 | + protected $_m_name; |
|
| 30 | + protected $_mt_name; |
|
| 31 | + |
|
| 32 | + |
|
| 33 | + /** |
|
| 34 | + * This will hold any error messages from the validation process. |
|
| 35 | + * The _errors property holds an associative array of error messages |
|
| 36 | + * listing the field as the key and the message as the value. |
|
| 37 | + * |
|
| 38 | + * @var array() |
|
| 39 | + */ |
|
| 40 | + private $_errors = array(); |
|
| 41 | + |
|
| 42 | + |
|
| 43 | + /** |
|
| 44 | + * holds an array of fields being validated |
|
| 45 | + * |
|
| 46 | + * @var array |
|
| 47 | + */ |
|
| 48 | + protected $_fields; |
|
| 49 | + |
|
| 50 | + |
|
| 51 | + /** |
|
| 52 | + * this will hold the incoming context |
|
| 53 | + * |
|
| 54 | + * @var string |
|
| 55 | + */ |
|
| 56 | + protected $_context; |
|
| 57 | + |
|
| 58 | + |
|
| 59 | + /** |
|
| 60 | + * this holds an array of fields and the relevant validation information |
|
| 61 | + * that the incoming fields data get validated against. |
|
| 62 | + * This gets setup in the _set_props() method. |
|
| 63 | + * |
|
| 64 | + * @var array |
|
| 65 | + */ |
|
| 66 | + protected $_validators; |
|
| 67 | + |
|
| 68 | + |
|
| 69 | + /** |
|
| 70 | + * holds the messenger object |
|
| 71 | + * |
|
| 72 | + * @var object |
|
| 73 | + */ |
|
| 74 | + protected $_messenger; |
|
| 75 | + |
|
| 76 | + |
|
| 77 | + /** |
|
| 78 | + * holds the message type object |
|
| 79 | + * |
|
| 80 | + * @var object |
|
| 81 | + */ |
|
| 82 | + protected $_message_type; |
|
| 83 | + |
|
| 84 | + |
|
| 85 | + /** |
|
| 86 | + * will hold any valid_shortcode modifications made by the _modify_validator() method. |
|
| 87 | + * |
|
| 88 | + * @var array |
|
| 89 | + */ |
|
| 90 | + protected $_valid_shortcodes_modifier; |
|
| 91 | + |
|
| 92 | + |
|
| 93 | + /** |
|
| 94 | + * There may be times where a message type wants to include a shortcode group but exclude specific |
|
| 95 | + * shortcodes. If that's the case then it can set this property as an array of shortcodes to exclude and |
|
| 96 | + * they will not be allowed. |
|
| 97 | + * Array should be indexed by field and values are an array of specific shortcodes to exclude. |
|
| 98 | + * |
|
| 99 | + * @var array |
|
| 100 | + */ |
|
| 101 | + protected $_specific_shortcode_excludes = array(); |
|
| 102 | + |
|
| 103 | + |
|
| 104 | + /** |
|
| 105 | + * Runs the validator using the incoming fields array as the fields/values to check. |
|
| 106 | + * |
|
| 107 | + * @param array $fields The fields sent by the EEM object. |
|
| 108 | + * @param $context |
|
| 109 | + * @throws EE_Error |
|
| 110 | + * @throws ReflectionException |
|
| 111 | + */ |
|
| 112 | + public function __construct($fields, $context) |
|
| 113 | + { |
|
| 114 | + //check that _m_name and _mt_name have been set by child class otherwise we get out. |
|
| 115 | + if (empty($this->_m_name) || empty($this->_mt_name)) { |
|
| 116 | + throw new EE_Error( |
|
| 117 | + esc_html__( |
|
| 118 | + 'EE_Messages_Validator child classes MUST set the $_m_name and $_mt_name property. Check that the child class is doing this', |
|
| 119 | + 'event_espresso' |
|
| 120 | + ) |
|
| 121 | + ); |
|
| 122 | + } |
|
| 123 | + $this->_fields = $fields; |
|
| 124 | + $this->_context = $context; |
|
| 125 | + |
|
| 126 | + //load messenger and message_type objects and the related shortcode objects. |
|
| 127 | + $this->_load_objects(); |
|
| 128 | + |
|
| 129 | + |
|
| 130 | + //modify any messenger/message_type specific validation instructions. This is what child classes define. |
|
| 131 | + $this->_modify_validator(); |
|
| 132 | + |
|
| 133 | + |
|
| 134 | + //let's set validators property |
|
| 135 | + $this->_set_validators(); |
|
| 136 | + } |
|
| 137 | + |
|
| 138 | + |
|
| 139 | + /** |
|
| 140 | + * Child classes instantiate this and use it to modify the _validator_config array property |
|
| 141 | + * for the messenger using messengers set_validate_config() method. |
|
| 142 | + * This is so we can specify specific validation instructions for a messenger/message_type combo |
|
| 143 | + * that aren't handled by the defaults setup in the messenger. |
|
| 144 | + * |
|
| 145 | + * @abstract |
|
| 146 | + * @access protected |
|
| 147 | + * @return void |
|
| 148 | + */ |
|
| 149 | + abstract protected function _modify_validator(); |
|
| 150 | + |
|
| 151 | + |
|
| 152 | + /** |
|
| 153 | + * loads all objects used by validator |
|
| 154 | + * |
|
| 155 | + * @access private |
|
| 156 | + * @throws \EE_Error |
|
| 157 | + */ |
|
| 158 | + private function _load_objects() |
|
| 159 | + { |
|
| 160 | + //load messenger |
|
| 161 | + $messenger = ucwords(str_replace('_', ' ', $this->_m_name)); |
|
| 162 | + $messenger = str_replace(' ', '_', $messenger); |
|
| 163 | + $messenger = 'EE_' . $messenger . '_messenger'; |
|
| 164 | + |
|
| 165 | + if (! class_exists($messenger)) { |
|
| 166 | + throw new EE_Error( |
|
| 167 | + sprintf( |
|
| 168 | + esc_html__('There is no messenger class for the given string (%s)', 'event_espresso'), |
|
| 169 | + $this->_m_name |
|
| 170 | + ) |
|
| 171 | + ); |
|
| 172 | + } |
|
| 173 | + |
|
| 174 | + $this->_messenger = new $messenger(); |
|
| 175 | + |
|
| 176 | + //load message type |
|
| 177 | + $message_type = ucwords(str_replace('_', ' ', $this->_mt_name)); |
|
| 178 | + $message_type = str_replace(' ', '_', $message_type); |
|
| 179 | + $message_type = 'EE_' . $message_type . '_message_type'; |
|
| 180 | + |
|
| 181 | + if (! class_exists($message_type)) { |
|
| 182 | + throw new EE_Error( |
|
| 183 | + sprintf( |
|
| 184 | + esc_html__('There is no message type class for the given string (%s)', 'event_espresso'), |
|
| 185 | + $this->_mt_name |
|
| 186 | + ) |
|
| 187 | + ); |
|
| 188 | + } |
|
| 189 | + |
|
| 190 | + $this->_message_type = new $message_type(); |
|
| 191 | + } |
|
| 192 | + |
|
| 193 | + |
|
| 194 | + /** |
|
| 195 | + * used to set the $_validators property |
|
| 196 | + * |
|
| 197 | + * @access private |
|
| 198 | + * @return void |
|
| 199 | + * @throws ReflectionException |
|
| 200 | + */ |
|
| 201 | + private function _set_validators() |
|
| 202 | + { |
|
| 203 | + // let's get all valid shortcodes from mt and message type |
|
| 204 | + // (messenger will have its set in the _validator_config property for the messenger) |
|
| 205 | + $mt_codes = $this->_message_type->get_valid_shortcodes(); |
|
| 206 | + |
|
| 207 | + |
|
| 208 | + //get messenger validator_config |
|
| 209 | + $msgr_validator = $this->_messenger->get_validator_config(); |
|
| 210 | + |
|
| 211 | + |
|
| 212 | + //we only want the valid shortcodes for the given context! |
|
| 213 | + $context = $this->_context; |
|
| 214 | + $mt_codes = $mt_codes[$context]; |
|
| 215 | + |
|
| 216 | + // in this first loop we're just getting all shortcode group indexes from the msgr_validator |
|
| 217 | + // into a single array (so we can get the appropriate shortcode objects for the groups) |
|
| 218 | + $shortcode_groups = $mt_codes; |
|
| 219 | + $groups_per_field = array(); |
|
| 220 | + |
|
| 221 | + foreach ($msgr_validator as $field => $config) { |
|
| 222 | + if (empty($config) || ! isset($config['shortcodes'])) { |
|
| 223 | + continue; |
|
| 224 | + } //Nothing to see here. |
|
| 225 | + $groups_per_field[$field] = array_intersect($config['shortcodes'], $mt_codes); |
|
| 226 | + $shortcode_groups = array_merge($config['shortcodes'], $shortcode_groups); |
|
| 227 | + } |
|
| 228 | + |
|
| 229 | + $shortcode_groups = array_unique($shortcode_groups); |
|
| 230 | + |
|
| 231 | + // okay now we've got our groups. |
|
| 232 | + // Let's get the codes from the objects into an array indexed by group for easy retrieval later. |
|
| 233 | + $codes_from_objs = array(); |
|
| 234 | + |
|
| 235 | + foreach ($shortcode_groups as $group) { |
|
| 236 | + $ref = ucwords(str_replace('_', ' ', $group)); |
|
| 237 | + $ref = str_replace(' ', '_', $ref); |
|
| 238 | + $classname = 'EE_' . $ref . '_Shortcodes'; |
|
| 239 | + if (class_exists($classname)) { |
|
| 240 | + $a = new ReflectionClass($classname); |
|
| 241 | + $obj = $a->newInstance(); |
|
| 242 | + $codes_from_objs[$group] = $obj->get_shortcodes(); |
|
| 243 | + } |
|
| 244 | + } |
|
| 245 | + |
|
| 246 | + |
|
| 247 | + //let's just replace the $mt shortcode group indexes with the actual shortcodes (unique) |
|
| 248 | + $final_mt_codes = array(); |
|
| 249 | + foreach ($mt_codes as $group) { |
|
| 250 | + $final_mt_codes = array_merge($final_mt_codes, $codes_from_objs[$group]); |
|
| 251 | + } |
|
| 252 | + |
|
| 253 | + $mt_codes = $final_mt_codes; |
|
| 254 | + |
|
| 255 | + |
|
| 256 | + // k now in this next loop we're going to loop through $msgr_validator again |
|
| 257 | + // and setup the _validators property from the data we've setup so far. |
|
| 258 | + foreach ($msgr_validator as $field => $config) { |
|
| 259 | + //if required shortcode is not in our list of codes for the given field, then we skip this field. |
|
| 260 | + $required = isset($config['required']) |
|
| 261 | + ? array_intersect($config['required'], array_keys($mt_codes)) |
|
| 262 | + : true; |
|
| 263 | + if (empty($required)) { |
|
| 264 | + continue; |
|
| 265 | + } |
|
| 266 | + |
|
| 267 | + //If we have an override then we use it to indicate the codes we want. |
|
| 268 | + if (isset($this->_valid_shortcodes_modifier[$context][$field])) { |
|
| 269 | + $this->_validators[$field]['shortcodes'] = $this->_reassemble_valid_shortcodes_from_group( |
|
| 270 | + $this->_valid_shortcodes_modifier[$context][$field], |
|
| 271 | + $codes_from_objs |
|
| 272 | + ); |
|
| 273 | + } //if we have specific shortcodes for a field then we need to use them |
|
| 274 | + elseif (isset($groups_per_field[$field])) { |
|
| 275 | + $this->_validators[$field]['shortcodes'] = $this->_reassemble_valid_shortcodes_from_group( |
|
| 276 | + $groups_per_field[$field], |
|
| 277 | + $codes_from_objs |
|
| 278 | + ); |
|
| 279 | + } //if empty config then we're assuming we're just going to use the shortcodes from the message type context |
|
| 280 | + elseif (empty($config)) { |
|
| 281 | + $this->_validators[$field]['shortcodes'] = $mt_codes; |
|
| 282 | + } //if we have specific shortcodes then we need to use them |
|
| 283 | + elseif (isset($config['specific_shortcodes'])) { |
|
| 284 | + $this->_validators[$field]['shortcodes'] = $config['specific_shortcodes']; |
|
| 285 | + } //otherwise the shortcodes are what is set by the messenger for that field |
|
| 286 | + else { |
|
| 287 | + foreach ($config['shortcodes'] as $group) { |
|
| 288 | + $this->_validators[$field]['shortcodes'] = isset($this->_validators[$field]['shortcodes']) |
|
| 289 | + ? array_merge($this->_validators[$field]['shortcodes'], $codes_from_objs[$group]) |
|
| 290 | + : $codes_from_objs[$group]; |
|
| 291 | + } |
|
| 292 | + } |
|
| 293 | + |
|
| 294 | + //now let's just make sure that any excluded specific shortcodes are removed. |
|
| 295 | + $specific_excludes = $this->get_specific_shortcode_excludes(); |
|
| 296 | + if (isset($specific_excludes[$field])) { |
|
| 297 | + foreach ($specific_excludes[$field] as $sex) { |
|
| 298 | + if (isset($this->_validators[$field]['shortcodes'][$sex])) { |
|
| 299 | + unset($this->_validators[$field]['shortcodes'][$sex]); |
|
| 300 | + } |
|
| 301 | + } |
|
| 302 | + } |
|
| 303 | + |
|
| 304 | + //hey! don't forget to include the type if present! |
|
| 305 | + $this->_validators[$field]['type'] = isset($config['type']) ? $config['type'] : null; |
|
| 306 | + } |
|
| 307 | + } |
|
| 308 | + |
|
| 309 | + |
|
| 310 | + /** |
|
| 311 | + * This just returns the validators property that contains information |
|
| 312 | + * about the various shortcodes and their availability with each field |
|
| 313 | + * |
|
| 314 | + * @return array |
|
| 315 | + */ |
|
| 316 | + public function get_validators() |
|
| 317 | + { |
|
| 318 | + return $this->_validators; |
|
| 319 | + } |
|
| 320 | + |
|
| 321 | + |
|
| 322 | + /** |
|
| 323 | + * This simply returns the specific shortcode_excludes property that is set. |
|
| 324 | + * |
|
| 325 | + * @since 4.5.0 |
|
| 326 | + * @return array |
|
| 327 | + */ |
|
| 328 | + public function get_specific_shortcode_excludes() |
|
| 329 | + { |
|
| 330 | + //specific validator filter |
|
| 331 | + $shortcode_excludes = apply_filters( |
|
| 332 | + 'FHEE__' . get_class($this) . '__get_specific_shortcode_excludes;', |
|
| 333 | + $this->_specific_shortcode_excludes, |
|
| 334 | + $this->_context |
|
| 335 | + ); |
|
| 336 | + //global filter |
|
| 337 | + return apply_filters( |
|
| 338 | + 'FHEE__EE_Messages_Validator__get_specific_shortcode_excludes', |
|
| 339 | + $shortcode_excludes, |
|
| 340 | + $this->_context, |
|
| 341 | + $this |
|
| 342 | + ); |
|
| 343 | + } |
|
| 344 | + |
|
| 345 | + |
|
| 346 | + /** |
|
| 347 | + * This is the main method that handles validation |
|
| 348 | + * What it does is loop through the _fields (the ones that get validated) |
|
| 349 | + * and checks them against the shortcodes array for the field and the 'type' indicated by the |
|
| 350 | + * |
|
| 351 | + * @access public |
|
| 352 | + * @return mixed (bool|array) if errors present we return the array otherwise true |
|
| 353 | + */ |
|
| 354 | + public function validate() |
|
| 355 | + { |
|
| 356 | + //some defaults |
|
| 357 | + $template_fields = $this->_messenger->get_template_fields(); |
|
| 358 | + //loop through the fields and check! |
|
| 359 | + foreach ($this->_fields as $field => $value) { |
|
| 360 | + $this->_errors[$field] = array(); |
|
| 361 | + $err_msg = ''; |
|
| 362 | + $field_label = ''; |
|
| 363 | + //if field is not present in the _validators array then we continue |
|
| 364 | + if (! isset($this->_validators[$field])) { |
|
| 365 | + unset($this->_errors[$field]); |
|
| 366 | + continue; |
|
| 367 | + } |
|
| 368 | + |
|
| 369 | + //get the translated field label! |
|
| 370 | + //first check if it's in the main fields list |
|
| 371 | + if (isset($template_fields[$field])) { |
|
| 372 | + if (empty($template_fields[$field])) { |
|
| 373 | + $field_label = $field; |
|
| 374 | + } //most likely the field is found in the 'extra' array. |
|
| 375 | + else { |
|
| 376 | + $field_label = $template_fields[$field]['label']; |
|
| 377 | + } |
|
| 378 | + } |
|
| 379 | + |
|
| 380 | + // if field label is empty OR is equal to the current field |
|
| 381 | + // then we need to loop through the 'extra' fields in the template_fields config (if present) |
|
| 382 | + if (isset($template_fields['extra']) && (empty($field_label) || $field_label === $field)) { |
|
| 383 | + foreach ($template_fields['extra'] as $main_field => $secondary_field) { |
|
| 384 | + foreach ($secondary_field as $name => $values) { |
|
| 385 | + if ($name === $field) { |
|
| 386 | + $field_label = $values['label']; |
|
| 387 | + } |
|
| 388 | + |
|
| 389 | + // if we've got a 'main' secondary field, let's see if that matches what field we're on |
|
| 390 | + // which means it contains the label for this field. |
|
| 391 | + if ($name === 'main' && $main_field === $field_label) { |
|
| 392 | + $field_label = $values['label']; |
|
| 393 | + } |
|
| 394 | + } |
|
| 395 | + } |
|
| 396 | + } |
|
| 397 | + |
|
| 398 | + //field is present. Let's validate shortcodes first (but only if shortcodes present). |
|
| 399 | + if (isset($this->_validators[$field]['shortcodes']) |
|
| 400 | + && ! empty($this->_validators[$field]['shortcodes']) |
|
| 401 | + ) { |
|
| 402 | + $invalid_shortcodes = $this->_invalid_shortcodes($value, $this->_validators[$field]['shortcodes']); |
|
| 403 | + // if true then that means there is a returned error message |
|
| 404 | + // that we'll need to add to the _errors array for this field. |
|
| 405 | + if ($invalid_shortcodes) { |
|
| 406 | + $v_s = array_keys($this->_validators[$field]['shortcodes']); |
|
| 407 | + $err_msg = sprintf( |
|
| 408 | + esc_html__( |
|
| 409 | + '%3$sThe following shortcodes were found in the "%1$s" field that ARE not valid: %2$s%4$s', |
|
| 410 | + 'event_espresso' |
|
| 411 | + ), |
|
| 412 | + '<strong>' . $field_label . '</strong>', |
|
| 413 | + $invalid_shortcodes, |
|
| 414 | + '<p>', |
|
| 415 | + '</p >' |
|
| 416 | + ); |
|
| 417 | + $err_msg .= sprintf( |
|
| 418 | + esc_html__('%2$sValid shortcodes for this field are: %1$s%3$s', 'event_espresso'), |
|
| 419 | + implode(', ', $v_s), |
|
| 420 | + '<strong>', |
|
| 421 | + '</strong>' |
|
| 422 | + ); |
|
| 423 | + } |
|
| 424 | + } |
|
| 425 | + |
|
| 426 | + //if there's a "type" to be validated then let's do that too. |
|
| 427 | + if (isset($this->_validators[$field]['type']) && ! empty($this->_validators[$field]['type'])) { |
|
| 428 | + switch ($this->_validators[$field]['type']) { |
|
| 429 | + case 'number': |
|
| 430 | + if (! is_numeric($value)) { |
|
| 431 | + $err_msg .= sprintf( |
|
| 432 | + esc_html__( |
|
| 433 | + '%3$sThe %1$s field is supposed to be a number. The value given (%2$s) is not. Please double-check and make sure the field contains a number%4$s', |
|
| 434 | + 'event_espresso' |
|
| 435 | + ), |
|
| 436 | + $field_label, |
|
| 437 | + $value, |
|
| 438 | + '<p>', |
|
| 439 | + '</p >' |
|
| 440 | + ); |
|
| 441 | + } |
|
| 442 | + break; |
|
| 443 | + case 'email': |
|
| 444 | + $valid_email = $this->_validate_email($value); |
|
| 445 | + if (! $valid_email) { |
|
| 446 | + $err_msg .= htmlentities( |
|
| 447 | + sprintf( |
|
| 448 | + esc_html__( |
|
| 449 | + 'The %1$s field has at least one string that is not a valid email address record. Valid emails are in the format: "Name <[email protected]>" or "[email protected]" and multiple emails can be separated by a comma.' |
|
| 450 | + ), |
|
| 451 | + $field_label |
|
| 452 | + |
|
| 453 | + ) |
|
| 454 | + ); |
|
| 455 | + } |
|
| 456 | + break; |
|
| 457 | + default: |
|
| 458 | + break; |
|
| 459 | + } |
|
| 460 | + } |
|
| 461 | + |
|
| 462 | + //if $err_msg isn't empty let's setup the _errors array for this field. |
|
| 463 | + if (! empty($err_msg)) { |
|
| 464 | + $this->_errors[$field]['msg'] = $err_msg; |
|
| 465 | + } else { |
|
| 466 | + unset($this->_errors[$field]); |
|
| 467 | + } |
|
| 468 | + } |
|
| 469 | + |
|
| 470 | + // if we have ANY errors, then we want to make sure we return the values |
|
| 471 | + // for ALL the fields so the user doesn't have to retype them all. |
|
| 472 | + if (! empty($this->_errors)) { |
|
| 473 | + foreach ($this->_fields as $field => $value) { |
|
| 474 | + $this->_errors[$field]['value'] = stripslashes($value); |
|
| 475 | + } |
|
| 476 | + } |
|
| 477 | + |
|
| 478 | + //return any errors or just TRUE if everything validates |
|
| 479 | + return empty($this->_errors) ? true : $this->_errors; |
|
| 480 | + } |
|
| 481 | + |
|
| 482 | + |
|
| 483 | + /** |
|
| 484 | + * Reassembles and returns an array of valid shortcodes |
|
| 485 | + * given the array of groups and array of shortcodes indexed by group. |
|
| 486 | + * |
|
| 487 | + * @param array $groups array of shortcode groups that we want shortcodes for |
|
| 488 | + * @param array $codes_from_objs All the codes available. |
|
| 489 | + * @return array an array of actual shortcodes (that will be used for validation). |
|
| 490 | + */ |
|
| 491 | + private function _reassemble_valid_shortcodes_from_group($groups, $codes_from_objs) |
|
| 492 | + { |
|
| 493 | + $shortcodes = array(); |
|
| 494 | + foreach ($groups as $group) { |
|
| 495 | + $shortcodes = array_merge($shortcodes, $codes_from_objs[$group]); |
|
| 496 | + } |
|
| 497 | + return $shortcodes; |
|
| 498 | + } |
|
| 499 | + |
|
| 500 | + |
|
| 501 | + /** |
|
| 502 | + * Validates a string against a list of accepted shortcodes |
|
| 503 | + * This function takes in an array of shortcodes |
|
| 504 | + * and makes sure that the given string ONLY contains shortcodes in that array. |
|
| 505 | + * |
|
| 506 | + * @param string $value string to evaluate |
|
| 507 | + * @param array $valid_shortcodes array of shortcodes that are acceptable. |
|
| 508 | + * @return mixed (bool|string) return either a list of invalid shortcodes OR false if the shortcodes validate. |
|
| 509 | + */ |
|
| 510 | + protected function _invalid_shortcodes($value, $valid_shortcodes) |
|
| 511 | + { |
|
| 512 | + //first we need to go through the string and get the shortcodes in the string |
|
| 513 | + preg_match_all('/(\[.+?\])/', $value, $matches); |
|
| 514 | + $incoming_shortcodes = (array)$matches[0]; |
|
| 515 | + |
|
| 516 | + //get a diff of the shortcodes in the string vs the valid shortcodes |
|
| 517 | + $diff = array_diff($incoming_shortcodes, array_keys($valid_shortcodes)); |
|
| 518 | + |
|
| 519 | + //we need to account for custom codes so let's loop through the diff and remove any of those type of codes |
|
| 520 | + foreach ($diff as $ind => $code) { |
|
| 521 | + if (preg_match('/(\[[A-Za-z0-9\_]+_\*)/', $code)) { |
|
| 522 | + //strip the shortcode so we just have the BASE string (i.e. [ANSWER_*] ) |
|
| 523 | + $dynamic_sc = preg_replace('/(_\*+.+)/', '_*]', $code); |
|
| 524 | + //does this exist in the $valid_shortcodes? If so then unset. |
|
| 525 | + if (isset($valid_shortcodes[$dynamic_sc])) { |
|
| 526 | + unset($diff[$ind]); |
|
| 527 | + } |
|
| 528 | + } |
|
| 529 | + } |
|
| 530 | + |
|
| 531 | + if (empty($diff)) { |
|
| 532 | + return false; |
|
| 533 | + } //there is no diff, we have no invalid shortcodes, so return |
|
| 534 | + |
|
| 535 | + //made it here? then let's assemble the error message |
|
| 536 | + $invalid_shortcodes = implode('</strong>,<strong>', $diff); |
|
| 537 | + $invalid_shortcodes = '<strong>' . $invalid_shortcodes . '</strong>'; |
|
| 538 | + return $invalid_shortcodes; |
|
| 539 | + } |
|
| 540 | + |
|
| 541 | + |
|
| 542 | + /** |
|
| 543 | + * Validates an incoming string and makes sure we have valid emails in the string. |
|
| 544 | + * |
|
| 545 | + * @param string $value incoming value to validate |
|
| 546 | + * @return bool true if the string validates, false if it doesn't |
|
| 547 | + */ |
|
| 548 | + protected function _validate_email($value) |
|
| 549 | + { |
|
| 550 | + $validate = true; |
|
| 551 | + $or_val = $value; |
|
| 552 | + |
|
| 553 | + // empty strings will validate because this is how a message template |
|
| 554 | + // for a particular context can be "turned off" (if there is no email then no message) |
|
| 555 | + if (empty($value)) { |
|
| 556 | + return $validate; |
|
| 557 | + } |
|
| 558 | + |
|
| 559 | + // first determine if there ARE any shortcodes. |
|
| 560 | + // If there are shortcodes and then later we find that there were no other valid emails |
|
| 561 | + // but the field isn't empty... |
|
| 562 | + // that means we've got extra commas that were left after stripping out shortcodes so probably still valid. |
|
| 563 | + $has_shortcodes = preg_match('/(\[.+?\])/', $value); |
|
| 564 | + |
|
| 565 | + //first we need to strip out all the shortcodes! |
|
| 566 | + $value = preg_replace('/(\[.+?\])/', '', $value); |
|
| 567 | + |
|
| 568 | + // if original value is not empty and new value is, then we've parsed out a shortcode |
|
| 569 | + // and we now have an empty string which DOES validate. |
|
| 570 | + // We also validate complete empty field for email because |
|
| 571 | + // its possible that this message is being "turned off" for a particular context |
|
| 572 | + |
|
| 573 | + |
|
| 574 | + if (! empty($or_val) && empty($value)) { |
|
| 575 | + return $validate; |
|
| 576 | + } |
|
| 577 | + |
|
| 578 | + //trim any commas from beginning and end of string ( after whitespace trimmed ); |
|
| 579 | + $value = trim(trim($value), ','); |
|
| 580 | + |
|
| 581 | + |
|
| 582 | + //next we need to split up the string if its comma delimited. |
|
| 583 | + $emails = explode(',', $value); |
|
| 584 | + $empty = false; //used to indicate that there is an empty comma. |
|
| 585 | + //now let's loop through the emails and do our checks |
|
| 586 | + foreach ($emails as $email) { |
|
| 587 | + if (empty($email)) { |
|
| 588 | + $empty = true; |
|
| 589 | + continue; |
|
| 590 | + } |
|
| 591 | + |
|
| 592 | + //trim whitespace |
|
| 593 | + $email = trim($email); |
|
| 594 | + //either its of type "[email protected]", or its of type "fname lname <[email protected]>" |
|
| 595 | + if (is_email($email)) { |
|
| 596 | + continue; |
|
| 597 | + } |
|
| 598 | + $matches = array(); |
|
| 599 | + $validate = preg_match('/(.*)<(.+)>/', $email, $matches) ? true : false; |
|
| 600 | + if ($validate && is_email($matches[2])) { |
|
| 601 | + continue; |
|
| 602 | + } |
|
| 603 | + return false; |
|
| 604 | + } |
|
| 605 | + |
|
| 606 | + $validate = $empty && ! $has_shortcodes ? false : $validate; |
|
| 607 | + |
|
| 608 | + return $validate; |
|
| 609 | + } |
|
| 610 | + |
|
| 611 | + |
|
| 612 | + /** |
|
| 613 | + * Magic getter |
|
| 614 | + * Using this to provide back compat with add-ons referencing deprecated properties. |
|
| 615 | + * |
|
| 616 | + * @param string $property Property being requested |
|
| 617 | + * @throws Exception |
|
| 618 | + * @return mixed |
|
| 619 | + */ |
|
| 620 | + public function __get($property) |
|
| 621 | + { |
|
| 622 | + $expected_properties_map = array( |
|
| 623 | + /** |
|
| 624 | + * @deprecated 4.9.0 |
|
| 625 | + */ |
|
| 626 | + '_MSGR' => '_messenger', |
|
| 627 | + /** |
|
| 628 | + * @deprecated 4.9.0 |
|
| 629 | + */ |
|
| 630 | + '_MSGTYP' => '_message_type', |
|
| 631 | + ); |
|
| 632 | + |
|
| 633 | + if (isset($expected_properties_map[$property])) { |
|
| 634 | + return $this->{$expected_properties_map[$property]}; |
|
| 635 | + } |
|
| 636 | + |
|
| 637 | + throw new Exception( |
|
| 638 | + sprintf( |
|
| 639 | + esc_html__('The property %1$s being requested on %2$s does not exist', 'event_espresso'), |
|
| 640 | + $property, |
|
| 641 | + get_class($this) |
|
| 642 | + ) |
|
| 643 | + ); |
|
| 644 | + } |
|
| 645 | 645 | } |
@@ -160,9 +160,9 @@ discard block |
||
| 160 | 160 | //load messenger |
| 161 | 161 | $messenger = ucwords(str_replace('_', ' ', $this->_m_name)); |
| 162 | 162 | $messenger = str_replace(' ', '_', $messenger); |
| 163 | - $messenger = 'EE_' . $messenger . '_messenger'; |
|
| 163 | + $messenger = 'EE_'.$messenger.'_messenger'; |
|
| 164 | 164 | |
| 165 | - if (! class_exists($messenger)) { |
|
| 165 | + if ( ! class_exists($messenger)) { |
|
| 166 | 166 | throw new EE_Error( |
| 167 | 167 | sprintf( |
| 168 | 168 | esc_html__('There is no messenger class for the given string (%s)', 'event_espresso'), |
@@ -176,9 +176,9 @@ discard block |
||
| 176 | 176 | //load message type |
| 177 | 177 | $message_type = ucwords(str_replace('_', ' ', $this->_mt_name)); |
| 178 | 178 | $message_type = str_replace(' ', '_', $message_type); |
| 179 | - $message_type = 'EE_' . $message_type . '_message_type'; |
|
| 179 | + $message_type = 'EE_'.$message_type.'_message_type'; |
|
| 180 | 180 | |
| 181 | - if (! class_exists($message_type)) { |
|
| 181 | + if ( ! class_exists($message_type)) { |
|
| 182 | 182 | throw new EE_Error( |
| 183 | 183 | sprintf( |
| 184 | 184 | esc_html__('There is no message type class for the given string (%s)', 'event_espresso'), |
@@ -235,7 +235,7 @@ discard block |
||
| 235 | 235 | foreach ($shortcode_groups as $group) { |
| 236 | 236 | $ref = ucwords(str_replace('_', ' ', $group)); |
| 237 | 237 | $ref = str_replace(' ', '_', $ref); |
| 238 | - $classname = 'EE_' . $ref . '_Shortcodes'; |
|
| 238 | + $classname = 'EE_'.$ref.'_Shortcodes'; |
|
| 239 | 239 | if (class_exists($classname)) { |
| 240 | 240 | $a = new ReflectionClass($classname); |
| 241 | 241 | $obj = $a->newInstance(); |
@@ -329,7 +329,7 @@ discard block |
||
| 329 | 329 | { |
| 330 | 330 | //specific validator filter |
| 331 | 331 | $shortcode_excludes = apply_filters( |
| 332 | - 'FHEE__' . get_class($this) . '__get_specific_shortcode_excludes;', |
|
| 332 | + 'FHEE__'.get_class($this).'__get_specific_shortcode_excludes;', |
|
| 333 | 333 | $this->_specific_shortcode_excludes, |
| 334 | 334 | $this->_context |
| 335 | 335 | ); |
@@ -361,7 +361,7 @@ discard block |
||
| 361 | 361 | $err_msg = ''; |
| 362 | 362 | $field_label = ''; |
| 363 | 363 | //if field is not present in the _validators array then we continue |
| 364 | - if (! isset($this->_validators[$field])) { |
|
| 364 | + if ( ! isset($this->_validators[$field])) { |
|
| 365 | 365 | unset($this->_errors[$field]); |
| 366 | 366 | continue; |
| 367 | 367 | } |
@@ -409,7 +409,7 @@ discard block |
||
| 409 | 409 | '%3$sThe following shortcodes were found in the "%1$s" field that ARE not valid: %2$s%4$s', |
| 410 | 410 | 'event_espresso' |
| 411 | 411 | ), |
| 412 | - '<strong>' . $field_label . '</strong>', |
|
| 412 | + '<strong>'.$field_label.'</strong>', |
|
| 413 | 413 | $invalid_shortcodes, |
| 414 | 414 | '<p>', |
| 415 | 415 | '</p >' |
@@ -427,7 +427,7 @@ discard block |
||
| 427 | 427 | if (isset($this->_validators[$field]['type']) && ! empty($this->_validators[$field]['type'])) { |
| 428 | 428 | switch ($this->_validators[$field]['type']) { |
| 429 | 429 | case 'number': |
| 430 | - if (! is_numeric($value)) { |
|
| 430 | + if ( ! is_numeric($value)) { |
|
| 431 | 431 | $err_msg .= sprintf( |
| 432 | 432 | esc_html__( |
| 433 | 433 | '%3$sThe %1$s field is supposed to be a number. The value given (%2$s) is not. Please double-check and make sure the field contains a number%4$s', |
@@ -442,7 +442,7 @@ discard block |
||
| 442 | 442 | break; |
| 443 | 443 | case 'email': |
| 444 | 444 | $valid_email = $this->_validate_email($value); |
| 445 | - if (! $valid_email) { |
|
| 445 | + if ( ! $valid_email) { |
|
| 446 | 446 | $err_msg .= htmlentities( |
| 447 | 447 | sprintf( |
| 448 | 448 | esc_html__( |
@@ -460,7 +460,7 @@ discard block |
||
| 460 | 460 | } |
| 461 | 461 | |
| 462 | 462 | //if $err_msg isn't empty let's setup the _errors array for this field. |
| 463 | - if (! empty($err_msg)) { |
|
| 463 | + if ( ! empty($err_msg)) { |
|
| 464 | 464 | $this->_errors[$field]['msg'] = $err_msg; |
| 465 | 465 | } else { |
| 466 | 466 | unset($this->_errors[$field]); |
@@ -469,7 +469,7 @@ discard block |
||
| 469 | 469 | |
| 470 | 470 | // if we have ANY errors, then we want to make sure we return the values |
| 471 | 471 | // for ALL the fields so the user doesn't have to retype them all. |
| 472 | - if (! empty($this->_errors)) { |
|
| 472 | + if ( ! empty($this->_errors)) { |
|
| 473 | 473 | foreach ($this->_fields as $field => $value) { |
| 474 | 474 | $this->_errors[$field]['value'] = stripslashes($value); |
| 475 | 475 | } |
@@ -511,7 +511,7 @@ discard block |
||
| 511 | 511 | { |
| 512 | 512 | //first we need to go through the string and get the shortcodes in the string |
| 513 | 513 | preg_match_all('/(\[.+?\])/', $value, $matches); |
| 514 | - $incoming_shortcodes = (array)$matches[0]; |
|
| 514 | + $incoming_shortcodes = (array) $matches[0]; |
|
| 515 | 515 | |
| 516 | 516 | //get a diff of the shortcodes in the string vs the valid shortcodes |
| 517 | 517 | $diff = array_diff($incoming_shortcodes, array_keys($valid_shortcodes)); |
@@ -534,7 +534,7 @@ discard block |
||
| 534 | 534 | |
| 535 | 535 | //made it here? then let's assemble the error message |
| 536 | 536 | $invalid_shortcodes = implode('</strong>,<strong>', $diff); |
| 537 | - $invalid_shortcodes = '<strong>' . $invalid_shortcodes . '</strong>'; |
|
| 537 | + $invalid_shortcodes = '<strong>'.$invalid_shortcodes.'</strong>'; |
|
| 538 | 538 | return $invalid_shortcodes; |
| 539 | 539 | } |
| 540 | 540 | |
@@ -571,7 +571,7 @@ discard block |
||
| 571 | 571 | // its possible that this message is being "turned off" for a particular context |
| 572 | 572 | |
| 573 | 573 | |
| 574 | - if (! empty($or_val) && empty($value)) { |
|
| 574 | + if ( ! empty($or_val) && empty($value)) { |
|
| 575 | 575 | return $validate; |
| 576 | 576 | } |
| 577 | 577 | |