@@ -16,806 +16,806 @@ |
||
| 16 | 16 | */ |
| 17 | 17 | class EE_Transaction_Shortcodes extends EE_Shortcodes |
| 18 | 18 | { |
| 19 | - /** |
|
| 20 | - * @var EE_Payment_Method|null $_invoice_pm the invoice payment method for use in invoices etc |
|
| 21 | - */ |
|
| 22 | - protected ?EE_Payment_Method $_invoice_pm = null; |
|
| 23 | - |
|
| 24 | - |
|
| 25 | - protected function _init_props() |
|
| 26 | - { |
|
| 27 | - $this->label = esc_html__('Transaction Shortcodes', 'event_espresso'); |
|
| 28 | - $this->description = esc_html__('All shortcodes specific to transaction related data', 'event_espresso'); |
|
| 29 | - $this->_shortcodes = [ |
|
| 30 | - '[TXN_ID]' => esc_html__('The transaction id for the purchase.', 'event_espresso'), |
|
| 31 | - '[PAYMENT_URL]' => esc_html__( |
|
| 32 | - 'This is a link to make a payment for the event', |
|
| 33 | - 'event_espresso' |
|
| 34 | - ), |
|
| 35 | - '[PAYMENT_LINK_IF_NEEDED_*]' => esc_html__( |
|
| 36 | - 'This is a special dynamic shortcode that allows one to insert a payment link conditional on there being amount owing on the transaction. Three params are available on this shortcode:', |
|
| 37 | - 'event_espresso' |
|
| 38 | - ) |
|
| 39 | - . '<ul>' |
|
| 40 | - . '<li>' |
|
| 41 | - . sprintf( |
|
| 42 | - esc_html__( |
|
| 43 | - '%sclass:%s This can be used to indicate css class is given to the containing css element (default is "callout").', |
|
| 44 | - 'event_espresso' |
|
| 45 | - ), |
|
| 46 | - '<strong>', |
|
| 47 | - '</strong>' |
|
| 48 | - ) |
|
| 49 | - . '</li>' |
|
| 50 | - . '<li>' |
|
| 51 | - . sprintf( |
|
| 52 | - esc_html__( |
|
| 53 | - '%scustom_text:%s This should be a sprintf format text string (with %%s for where the hyperlink tags go) that is used for the generated link text (The default is "You can %%smake a payment here »%%s.)', |
|
| 54 | - 'event_espresso' |
|
| 55 | - ), |
|
| 56 | - '<strong>', |
|
| 57 | - '</strong>' |
|
| 58 | - ) |
|
| 59 | - . '</li>' |
|
| 60 | - . '<li>' |
|
| 61 | - . sprintf( |
|
| 62 | - esc_html__( |
|
| 63 | - '%scontainer_tag:%s Use this to indicate what container tag you want surrounding the payment link (default is "p").', |
|
| 64 | - 'event_espresso' |
|
| 65 | - ), |
|
| 66 | - '<strong>', |
|
| 67 | - '</strong>' |
|
| 68 | - ) |
|
| 69 | - . '</li>' |
|
| 70 | - . '</ul>', |
|
| 71 | - '[PAYMENT_DUE_DATE_*]' => esc_html__( |
|
| 72 | - 'This is a special dynamic shortcode that allows one to output a payment due date. It will only result in a date shown if there is money owing. Three parameters are available on this shortcode:', |
|
| 73 | - 'event_espresso' |
|
| 74 | - ) |
|
| 75 | - . '<ul>' |
|
| 76 | - . '<li>' |
|
| 77 | - . sprintf( |
|
| 78 | - esc_html__( |
|
| 79 | - '%sformat:%s This is used to indicate what format the date is in. Default is whatever is set as date formats for your website.', |
|
| 80 | - 'event_espresso' |
|
| 81 | - ), |
|
| 82 | - '<strong>', |
|
| 83 | - '</strong>' |
|
| 84 | - ) |
|
| 85 | - . '</li>' |
|
| 86 | - . '<li>' |
|
| 87 | - . sprintf( |
|
| 88 | - esc_html__( |
|
| 89 | - '%sdays_until_due:%s This is the number of days form the transaction creation date that the payment is due. Defaults to 30.', |
|
| 90 | - 'event_espresso' |
|
| 91 | - ), |
|
| 92 | - '<strong>', |
|
| 93 | - '</strong>' |
|
| 94 | - ) |
|
| 95 | - . '</li>' |
|
| 96 | - . '<li>' |
|
| 97 | - . sprintf( |
|
| 98 | - esc_html__( |
|
| 99 | - '%sprefix_text:%s You can use this to indicate what text will prefix the date string. Defaults to "Payment in full due by:"', |
|
| 100 | - 'event_espresso' |
|
| 101 | - ), |
|
| 102 | - '<strong>', |
|
| 103 | - '</strong>' |
|
| 104 | - ) |
|
| 105 | - . '</li>', |
|
| 106 | - '[INVOICE_LINK]' => esc_html__( |
|
| 107 | - 'This is a full html link to the invoice. Add download=true to link directly to download.', |
|
| 108 | - 'event_espresso' |
|
| 109 | - ), |
|
| 110 | - '[INVOICE_URL]' => esc_html__( |
|
| 111 | - 'This is just the url for the invoice. Add download=true to link directly to download.', |
|
| 112 | - 'event_espresso' |
|
| 113 | - ), |
|
| 114 | - '[INVOICE_LOGO_URL]' => esc_html__( |
|
| 115 | - 'This returns the url for the logo uploaded via the invoice settings page.', |
|
| 116 | - 'event_espresso' |
|
| 117 | - ), |
|
| 118 | - '[INVOICE_LOGO]' => esc_html__( |
|
| 119 | - 'This returns the logo uploaded via the invoice settings page wrapped in img_tags and with a "logo screen" classes. The image size is also set in the img tags automatically to match the uploaded logo.', |
|
| 120 | - 'event_espresso' |
|
| 121 | - ), |
|
| 122 | - '[INVOICE_PAYEE_NAME]' => esc_html__( |
|
| 123 | - 'This will parse to either: the value of the "Company Name" field in the invoice payment method settings; if that is blank, then the value of the Company Name in the "Your Organization Settings", if that is blank then an empty string.', |
|
| 124 | - 'event_espresso' |
|
| 125 | - ), |
|
| 126 | - '[INVOICE_PAYEE_ADDRESS]' => esc_html__( |
|
| 127 | - 'This will parse to either: the value of the "Company Address" field in the invoice payment method settings; if that is blank, then the value of the Company Address in the "Your Organization Settings", if that is blank then an empty string.', |
|
| 128 | - 'event_espresso' |
|
| 129 | - ), |
|
| 130 | - '[INVOICE_PAYMENT_INSTRUCTIONS]' => esc_html__( |
|
| 131 | - 'This will parse to the value of the "Payment Instructions" field found on the Invoice payment methods settings page', |
|
| 132 | - 'event_espresso' |
|
| 133 | - ), |
|
| 134 | - '[INVOICE_PAYEE_EMAIL]' => esc_html__( |
|
| 135 | - 'This will parse to either: the value of the "Company Email" field in the invoice payment method settings; if that is blank, then the value of the Company Email in the "Your Organization Settings", if that is blank then an empty string.', |
|
| 136 | - 'event_espresso' |
|
| 137 | - ), |
|
| 138 | - '[INVOICE_PAYEE_TAX_NUMBER_*]' => sprintf( |
|
| 139 | - esc_html__( |
|
| 140 | - 'This will parse to either: the value of the "Company Tax Number" field in the invoice payment method settings; if that is blank, then the value of the Company Tax Number in the "Your Organization Settings", if that is blank then an empty string. Note this is also a special dynamic shortcode. You can use the "prefix" parameter to indicate what text you want to use as a prefix before this tax number. It defaults to "VAT/Tax Number:". To change this prefix you do the following format for this shortcode: %1$s[INVOICE_PAYEE_TAX_NUMBER_* prefix="GST:"]%2$s and that will output: GST: 12345t56. If you have no tax number in your settings, then no prefix will be output either.', |
|
| 141 | - 'event_espresso' |
|
| 142 | - ), |
|
| 143 | - '<code>', |
|
| 144 | - '</code>' |
|
| 145 | - ), |
|
| 146 | - '[TOTAL_COST]' => esc_html__('The total cost for the transaction', 'event_espresso'), |
|
| 147 | - '[TXN_STATUS]' => esc_html__( |
|
| 148 | - 'The transaction status for the transaction.', |
|
| 149 | - 'event_espresso' |
|
| 150 | - ), |
|
| 151 | - '[TXN_STATUS_ID]' => esc_html__( |
|
| 152 | - 'The ID representing the transaction status as saved in the db. This tends to be useful for including with css classes for styling certain statuses differently from others.', |
|
| 153 | - 'event_espresso' |
|
| 154 | - ), |
|
| 155 | - '[PAYMENT_STATUS]' => esc_html__( |
|
| 156 | - 'The transaction status for the transaction. This parses to the same value as the [TXN_STATUS] shortcode and still remains here for legacy support.', |
|
| 157 | - 'event_espresso' |
|
| 158 | - ), |
|
| 159 | - '[PAYMENT_GATEWAY]' => esc_html__( |
|
| 160 | - 'The payment gateway used for the transaction', |
|
| 161 | - 'event_espresso' |
|
| 162 | - ), |
|
| 163 | - '[AMOUNT_PAID]' => esc_html__( |
|
| 164 | - 'The amount paid or refunded. This will only have a value if there was a payment or refund at the time of generating the message.', |
|
| 165 | - 'event_espresso' |
|
| 166 | - ), |
|
| 167 | - '[LAST_AMOUNT_PAID]' => esc_html__( |
|
| 168 | - 'This is the last payment or refund made on the transaction related to the message being generated.', |
|
| 169 | - 'event_espresso' |
|
| 170 | - ), |
|
| 171 | - '[TOTAL_AMOUNT_PAID]' => esc_html__( |
|
| 172 | - 'This parses to the total amount paid over all payments', |
|
| 173 | - 'event_espresso' |
|
| 174 | - ), |
|
| 175 | - '[TOTAL_OWING]' => esc_html__( |
|
| 176 | - 'The total owing on a transaction with no attributes.', |
|
| 177 | - 'event_espresso' |
|
| 178 | - ), |
|
| 179 | - '[TXN_SUBTOTAL]' => esc_html__('The subtotal for all txn line items.', 'event_espresso'), |
|
| 180 | - '[TXN_TAX_SUBTOTAL]' => esc_html__('The subtotal for all tax line items.', 'event_espresso'), |
|
| 181 | - '[OWING_STATUS_MESSAGE_*]' => esc_html__( |
|
| 182 | - 'A dynamic shortcode for adjusting how total owing gets shown. The acceptable attributes on the shortcode are:', |
|
| 183 | - 'event_espresso' |
|
| 184 | - ) |
|
| 185 | - . '<p></ul>' |
|
| 186 | - . '<li><strong>still_owing</strong>:' |
|
| 187 | - . esc_html__( |
|
| 188 | - 'If the transaction is not paid in full, then whatever is set for this attribute is shown (otherwise its just the amount owing). The default is:', |
|
| 189 | - 'event_espresso' |
|
| 190 | - ) |
|
| 191 | - . sprintf( |
|
| 192 | - esc_html__('%sPlease make a payment.%s', 'event_espresso'), |
|
| 193 | - '<a href="[PAYMENT_URL]" class="noPrint">', |
|
| 194 | - '</a>' |
|
| 195 | - ) |
|
| 196 | - . '</li>' |
|
| 197 | - . |
|
| 198 | - '<li><strong>none_owing</strong>:' |
|
| 199 | - . esc_html__( |
|
| 200 | - 'If the transaction is paid in full, then you can indicate how this gets displayed. Note, that it defaults to just be the total owing.', |
|
| 201 | - 'event_espresso' |
|
| 202 | - ) |
|
| 203 | - . '</li></ul></p>', |
|
| 204 | - '[TXN_TOTAL_TICKETS]' => esc_html__( |
|
| 205 | - 'The total number of all tickets purchased in a transaction', |
|
| 206 | - 'event_espresso' |
|
| 207 | - ), |
|
| 208 | - '[TKT_QTY_PURCHASED]' => sprintf( |
|
| 209 | - esc_html__( |
|
| 210 | - 'The total number of all tickets purchased in a transaction. %1$sNOTE: This shortcode is good to use in the "[TICKET_LIST]" field but has been deprecated from all other contexts in favor of the more explicit [TXN_TOTAL_TICKETS] shortcode.%2$s', |
|
| 211 | - 'event_espresso' |
|
| 212 | - ), |
|
| 213 | - '<strong>', |
|
| 214 | - '</strong>' |
|
| 215 | - ), |
|
| 216 | - '[TRANSACTION_ADMIN_URL]' => esc_html__( |
|
| 217 | - 'The url to the admin page for this transaction', |
|
| 218 | - 'event_espresso' |
|
| 219 | - ), |
|
| 220 | - '[RECEIPT_URL]' => esc_html__( |
|
| 221 | - 'This parses to the generated url for retrieving the receipt for the transaction. Add download=true to link directly to download.', |
|
| 222 | - 'event_espresso' |
|
| 223 | - ), |
|
| 224 | - '[INVOICE_RECEIPT_SWITCHER_URL]' => esc_html__( |
|
| 225 | - 'This parses to the url that will switch to the receipt if an invoice is displayed, and switch to the invoice if receipt is displayed. If a message type OTHER than invoice or receipt is displayed then this will just return the url for the invoice. If the related message type is not active then will parse to an empty string.', |
|
| 226 | - 'event_espresso' |
|
| 227 | - ), |
|
| 228 | - '[INVOICE_RECEIPT_SWITCHER_BUTTON]' => sprintf( |
|
| 229 | - esc_html__( |
|
| 230 | - 'The same as %1$s%2$s except this returns the html for a button linked to the invoice or receipt.', |
|
| 231 | - 'event_espresso' |
|
| 232 | - ), |
|
| 233 | - '<code>[INVOICE_RECEIPT_SWITCHER_URL]', |
|
| 234 | - '</code>' |
|
| 235 | - ), |
|
| 236 | - '[LAST_PAYMENT_TRANSACTION_ID]' => esc_html__( |
|
| 237 | - 'This will output the value of the payment transaction id for the last payment made on the transaction. Note, if a specific payment was included for message generation, that will be used when parsing the shortcode.', |
|
| 238 | - 'event_espresso' |
|
| 239 | - ), |
|
| 240 | - ]; |
|
| 241 | - } |
|
| 242 | - |
|
| 243 | - |
|
| 244 | - /** |
|
| 245 | - * @param string $shortcode the shortcode to be parsed. |
|
| 246 | - * @return string parsed shortcode |
|
| 247 | - * @throws EE_Error |
|
| 248 | - * @throws InvalidArgumentException |
|
| 249 | - * @throws ReflectionException |
|
| 250 | - * @throws InvalidDataTypeException |
|
| 251 | - * @throws InvalidInterfaceException |
|
| 252 | - */ |
|
| 253 | - protected function _parser($shortcode) |
|
| 254 | - { |
|
| 255 | - // attempt to get the transaction. Since this is potentially used in more fields, we may have to look in the |
|
| 256 | - // _extra_data for the transaction. |
|
| 257 | - $transaction = $this->_data->txn instanceof EE_Transaction ? $this->_data->txn : null; |
|
| 258 | - $transaction = ! $transaction instanceof EE_Transaction |
|
| 259 | - && is_array($this->_extra_data) |
|
| 260 | - && isset($this->_extra_data['data']) |
|
| 261 | - && $this->_extra_data['data'] instanceof EE_Messages_Addressee |
|
| 262 | - ? $this->_extra_data['data']->txn |
|
| 263 | - : $transaction; |
|
| 264 | - if (! $transaction instanceof EE_Transaction) { |
|
| 265 | - return ''; |
|
| 266 | - } |
|
| 267 | - // payment |
|
| 268 | - $payment = $this->_data->payment instanceof EE_Payment ? $this->_data->payment : null; |
|
| 269 | - $payment = ! $payment instanceof EE_Payment |
|
| 270 | - && is_array($this->_extra_data) |
|
| 271 | - && isset($this->_extra_data['data']) |
|
| 272 | - && $this->_extra_data['data'] instanceof EE_Messages_Addressee |
|
| 273 | - ? $this->_extra_data['data']->payment |
|
| 274 | - : $payment; |
|
| 275 | - |
|
| 276 | - switch ($shortcode) { |
|
| 277 | - case '[TXN_ID]': |
|
| 278 | - return $transaction->ID(); |
|
| 279 | - |
|
| 280 | - case '[PAYMENT_URL]': |
|
| 281 | - $payment_url = $transaction->payment_overview_url(); |
|
| 282 | - return empty($payment_url) |
|
| 283 | - ? esc_html__('http://dummypaymenturlforpreview.com', 'event_espresso') |
|
| 284 | - : $payment_url; |
|
| 285 | - |
|
| 286 | - case strpos($shortcode, '[INVOICE_LINK') !== false : |
|
| 287 | - // any attributes? |
|
| 288 | - $attrs = $this->_get_shortcode_attrs($shortcode); |
|
| 289 | - // downloading PDF or HTML? |
|
| 290 | - $messenger = isset($attrs['download']) ? 'pdf' : 'html'; |
|
| 291 | - $invoice_url = $transaction->invoice_url($messenger); |
|
| 292 | - $invoice_url = empty($invoice_url) ? 'http://dummyinvoicelinksforpreview.com' : $invoice_url; |
|
| 293 | - return sprintf( |
|
| 294 | - esc_html__('%sClick here for Invoice%s', 'event_espresso'), |
|
| 295 | - '<a href="' . $invoice_url . '">', |
|
| 296 | - '</a>' |
|
| 297 | - ); |
|
| 298 | - |
|
| 299 | - case strpos($shortcode, '[INVOICE_URL') !== false : |
|
| 300 | - // any attributes? |
|
| 301 | - $attrs = $this->_get_shortcode_attrs($shortcode); |
|
| 302 | - // downloading PDF or HTML? |
|
| 303 | - $messenger = isset($attrs['download']) ? 'pdf' : 'html'; |
|
| 304 | - $invoice_url = $transaction->invoice_url($messenger); |
|
| 305 | - return empty($invoice_url) ? 'http://dummyinvoicelinksforpreview.com' : $invoice_url; |
|
| 306 | - |
|
| 307 | - case '[INVOICE_LOGO_URL]': |
|
| 308 | - return $this->_get_invoice_logo(); |
|
| 309 | - |
|
| 310 | - case '[INVOICE_LOGO]': |
|
| 311 | - return $this->_get_invoice_logo(true); |
|
| 312 | - |
|
| 313 | - case '[INVOICE_PAYEE_NAME]': |
|
| 314 | - return $this->_get_invoice_payee_name(); |
|
| 315 | - |
|
| 316 | - case '[INVOICE_PAYEE_ADDRESS]': |
|
| 317 | - return $this->_get_invoice_payee_address(); |
|
| 318 | - |
|
| 319 | - case '[INVOICE_PAYMENT_INSTRUCTIONS]': |
|
| 320 | - return $this->_get_invoice_payment_instructions(); |
|
| 321 | - |
|
| 322 | - case '[INVOICE_PAYEE_EMAIL]': |
|
| 323 | - return $this->_get_invoice_payee_email(); |
|
| 324 | - |
|
| 325 | - case '[TOTAL_COST]': |
|
| 326 | - $total = $transaction->total(); |
|
| 327 | - return ! empty($total) ? EEH_Template::format_currency($total) : ''; |
|
| 328 | - |
|
| 329 | - // note the [payment_status] shortcode is kind of misleading because payment status might be different |
|
| 330 | - // from txn status so I'm adding this here for clarity. |
|
| 331 | - case '[PAYMENT_STATUS]': |
|
| 332 | - case '[TXN_STATUS]': |
|
| 333 | - $status = $transaction->pretty_status(); |
|
| 334 | - return ! empty($status) ? $status : esc_html__('Unknown', 'event_espresso'); |
|
| 335 | - |
|
| 336 | - case '[TXN_STATUS_ID]': |
|
| 337 | - return $transaction->status_ID(); |
|
| 338 | - |
|
| 339 | - case '[PAYMENT_GATEWAY]': |
|
| 340 | - return $this->_get_payment_gateway($transaction); |
|
| 341 | - |
|
| 342 | - case '[AMOUNT_PAID]': |
|
| 343 | - return $payment instanceof EE_Payment |
|
| 344 | - ? EEH_Template::format_currency($payment->amount()) |
|
| 345 | - : EEH_Template::format_currency(0); |
|
| 346 | - |
|
| 347 | - case '[LAST_AMOUNT_PAID]': |
|
| 348 | - $last_payment = $transaction->last_payment(); |
|
| 349 | - return $last_payment instanceof EE_Payment |
|
| 350 | - ? EEH_Template::format_currency($last_payment->amount()) |
|
| 351 | - : EEH_Template::format_currency(0); |
|
| 352 | - |
|
| 353 | - case '[TOTAL_AMOUNT_PAID]': |
|
| 354 | - return EEH_Template::format_currency($transaction->paid()); |
|
| 355 | - |
|
| 356 | - case '[TOTAL_OWING]': |
|
| 357 | - $total_owing = $transaction->remaining(); |
|
| 358 | - return EEH_Template::format_currency($total_owing); |
|
| 359 | - |
|
| 360 | - case '[TXN_SUBTOTAL]': |
|
| 361 | - return EEH_Template::format_currency($this->_get_subtotal()); |
|
| 362 | - |
|
| 363 | - case '[TXN_TAX_SUBTOTAL]': |
|
| 364 | - return EEH_Template::format_currency($this->_get_subtotal(true)); |
|
| 365 | - |
|
| 366 | - case '[TKT_QTY_PURCHASED]': |
|
| 367 | - case '[TXN_TOTAL_TICKETS]': |
|
| 368 | - return $this->_data->total_ticket_count; |
|
| 369 | - |
|
| 370 | - case '[TRANSACTION_ADMIN_URL]': |
|
| 371 | - require_once EE_CORE . 'admin/EE_Admin_Page.core.php'; |
|
| 372 | - $query_args = [ |
|
| 373 | - 'page' => 'espresso_transactions', |
|
| 374 | - 'action' => 'view_transaction', |
|
| 375 | - 'TXN_ID' => $transaction->ID(), |
|
| 376 | - ]; |
|
| 377 | - return EE_Admin_Page::add_query_args_and_nonce($query_args, admin_url('admin.php')); |
|
| 378 | - |
|
| 379 | - case strpos($shortcode, '[RECEIPT_URL') !== false : |
|
| 380 | - // get primary_registration |
|
| 381 | - $reg = $this->_data->primary_reg_obj; |
|
| 382 | - if (! $reg instanceof EE_Registration) { |
|
| 383 | - return ''; |
|
| 384 | - } |
|
| 385 | - // any attributes? |
|
| 386 | - $attrs = $this->_get_shortcode_attrs($shortcode); |
|
| 387 | - // downloading PDF or HTML? |
|
| 388 | - $messenger = isset($attrs['download']) ? 'pdf' : 'html'; |
|
| 389 | - return $reg->receipt_url($messenger); |
|
| 390 | - |
|
| 391 | - case '[INVOICE_RECEIPT_SWITCHER_URL]': |
|
| 392 | - return $this->_get_invoice_receipt_switcher(false); |
|
| 393 | - |
|
| 394 | - case '[INVOICE_RECEIPT_SWITCHER_BUTTON]': |
|
| 395 | - return $this->_get_invoice_receipt_switcher(); |
|
| 396 | - |
|
| 397 | - case '[LAST_PAYMENT_TRANSACTION_ID]': |
|
| 398 | - $id = ''; |
|
| 399 | - $payment = $payment instanceof EE_Payment && $payment->ID() !== 0 |
|
| 400 | - ? $payment |
|
| 401 | - : $transaction->last_payment(); |
|
| 402 | - if ($payment instanceof EE_Payment) { |
|
| 403 | - $id = $payment->txn_id_chq_nmbr(); |
|
| 404 | - } |
|
| 405 | - return $id; |
|
| 406 | - } |
|
| 407 | - |
|
| 408 | - |
|
| 409 | - if (strpos($shortcode, '[OWING_STATUS_MESSAGE_*') !== false) { |
|
| 410 | - return $this->_get_custom_total_owing($shortcode); |
|
| 411 | - } |
|
| 412 | - if (strpos($shortcode, '[INVOICE_PAYEE_TAX_NUMBER_*') !== false) { |
|
| 413 | - return $this->_get_invoice_payee_tax_number($shortcode); |
|
| 414 | - } |
|
| 415 | - if (strpos($shortcode, '[PAYMENT_LINK_IF_NEEDED_*') !== false) { |
|
| 416 | - return $this->_get_payment_link_if_needed($shortcode); |
|
| 417 | - } |
|
| 418 | - if (strpos($shortcode, '[PAYMENT_DUE_DATE_*') !== false) { |
|
| 419 | - return $this->_get_payment_due_date($shortcode, $transaction); |
|
| 420 | - } |
|
| 421 | - return ''; |
|
| 422 | - } |
|
| 423 | - |
|
| 424 | - |
|
| 425 | - /** |
|
| 426 | - * parser for the [OWING_STATUS_MESSAGE_*] attribute type shortcode |
|
| 427 | - * |
|
| 428 | - * @param string $shortcode the incoming shortcode |
|
| 429 | - * @return string parsed. |
|
| 430 | - * @throws EE_Error |
|
| 431 | - * @throws ReflectionException |
|
| 432 | - * @since 4.5.0 |
|
| 433 | - */ |
|
| 434 | - private function _get_custom_total_owing($shortcode) |
|
| 435 | - { |
|
| 436 | - $valid_shortcodes = ['transaction']; |
|
| 437 | - $attrs = $this->_get_shortcode_attrs($shortcode); |
|
| 438 | - // ensure default is set. |
|
| 439 | - $addressee = $this->_data instanceof EE_Messages_Addressee ? $this->_data : null; |
|
| 440 | - $total_owing = $addressee instanceof EE_Messages_Addressee && $addressee->txn instanceof EE_Transaction |
|
| 441 | - ? $addressee->txn->remaining() |
|
| 442 | - : 0; |
|
| 443 | - if ($total_owing > 0) { |
|
| 444 | - $owing_content = ! empty($attrs['still_owing']) |
|
| 445 | - ? $attrs['still_owing'] |
|
| 446 | - : sprintf( |
|
| 447 | - esc_html__('%sPlease make a payment.%s', 'event_espresso'), |
|
| 448 | - '<a href="[PAYMENT_URL]" class="noPrint">', |
|
| 449 | - '</a>' |
|
| 450 | - ); |
|
| 451 | - $owing_content = $this->_shortcode_helper->parse_message_template( |
|
| 452 | - $owing_content, |
|
| 453 | - $addressee, |
|
| 454 | - $valid_shortcodes, |
|
| 455 | - $this->_message_type, |
|
| 456 | - $this->_messenger, |
|
| 457 | - $this->_message |
|
| 458 | - ); |
|
| 459 | - } else { |
|
| 460 | - $owing_content = ! empty($attrs['none_owing']) ? $attrs['none_owing'] : ''; |
|
| 461 | - } |
|
| 462 | - return $owing_content; |
|
| 463 | - } |
|
| 464 | - |
|
| 465 | - |
|
| 466 | - /** |
|
| 467 | - * @param EE_Transaction $transaction |
|
| 468 | - * @return string |
|
| 469 | - * @throws EE_Error |
|
| 470 | - * @throws ReflectionException |
|
| 471 | - */ |
|
| 472 | - private function _get_payment_gateway($transaction) |
|
| 473 | - { |
|
| 474 | - $payment_method = $transaction instanceof EE_Transaction ? $transaction->payment_method() : null; |
|
| 475 | - return $payment_method instanceof EE_Payment_Method ? $payment_method->name() : ''; |
|
| 476 | - } |
|
| 477 | - |
|
| 478 | - |
|
| 479 | - /** |
|
| 480 | - * This retrieves a logo to be used for the invoice from whatever is set on the invoice logo settings page. If its |
|
| 481 | - * not present then the organization logo is used if its found (set on the organization settings page). |
|
| 482 | - * |
|
| 483 | - * @param bool $img_tags TRUE means to return with the img tag wrappers. False just returns the url to the image. |
|
| 484 | - * @return string url or html |
|
| 485 | - * @throws EE_Error |
|
| 486 | - * @throws InvalidArgumentException |
|
| 487 | - * @throws InvalidDataTypeException |
|
| 488 | - * @throws InvalidInterfaceException |
|
| 489 | - * @throws ReflectionException |
|
| 490 | - * @since 4.5.0 |
|
| 491 | - */ |
|
| 492 | - private function _get_invoice_logo(bool $img_tags = false): string |
|
| 493 | - { |
|
| 494 | - $invoice_logo_url = ''; |
|
| 495 | - // try to get the invoice payment method's logo for this transaction image first |
|
| 496 | - $payment_method = $this->_get_invoice_payment_method(); |
|
| 497 | - if ($payment_method instanceof EE_Payment_Method) { |
|
| 498 | - $invoice_logo_url = $payment_method->get_extra_meta('pdf_logo_image', true); |
|
| 499 | - } |
|
| 500 | - if (empty($invoice_logo_url)) { |
|
| 501 | - $invoice_logo_url = EE_Registry::instance()->CFG->organization->logo_url; |
|
| 502 | - } |
|
| 503 | - if (empty($invoice_logo_url)) { |
|
| 504 | - return ''; |
|
| 505 | - } |
|
| 506 | - if (! $img_tags) { |
|
| 507 | - return $invoice_logo_url; |
|
| 508 | - } |
|
| 509 | - $invoice_logo_url = esc_url_raw($invoice_logo_url); |
|
| 510 | - // image tags have been requested. |
|
| 511 | - $image_size = @getimagesize($invoice_logo_url); |
|
| 512 | - $image_width_attr = ''; |
|
| 513 | - // if image is wider than 300px, set the width to 300 |
|
| 514 | - if ($image_size !== false) { |
|
| 515 | - $image_width = min($image_size[0], 300); |
|
| 516 | - $image_width = esc_attr($image_width); |
|
| 517 | - $image_width_attr = " width='$image_width'"; |
|
| 518 | - } |
|
| 519 | - return '<img class="logo screen" src="' . $invoice_logo_url . '"' . $image_width_attr . ' alt="logo" />'; |
|
| 520 | - } |
|
| 521 | - |
|
| 522 | - |
|
| 523 | - /** |
|
| 524 | - * Used to retrieve the appropriate content for the invoice payee name shortcode |
|
| 525 | - * |
|
| 526 | - * @return string |
|
| 527 | - * @throws EE_Error |
|
| 528 | - * @throws InvalidArgumentException |
|
| 529 | - * @throws InvalidDataTypeException |
|
| 530 | - * @throws InvalidInterfaceException |
|
| 531 | - * @throws ReflectionException |
|
| 532 | - * @since 4.5.0 |
|
| 533 | - */ |
|
| 534 | - private function _get_invoice_payee_name() |
|
| 535 | - { |
|
| 536 | - $payment_method = $this->_get_invoice_payment_method(); |
|
| 537 | - $payee_name = $payment_method instanceof EE_Payment_Method |
|
| 538 | - ? $payment_method->get_extra_meta('pdf_payee_name', true) |
|
| 539 | - : null; |
|
| 540 | - return empty($payee_name) ? EE_Registry::instance()->CFG->organization->get_pretty('name') : $payee_name; |
|
| 541 | - } |
|
| 542 | - |
|
| 543 | - |
|
| 544 | - /** |
|
| 545 | - * gets the default invoice payment method, but has a filter so it can be overridden |
|
| 546 | - * |
|
| 547 | - * @return EE_Payment_Method|null |
|
| 548 | - * @throws EE_Error |
|
| 549 | - * @throws InvalidArgumentException |
|
| 550 | - * @throws InvalidDataTypeException |
|
| 551 | - * @throws InvalidInterfaceException |
|
| 552 | - * @throws ReflectionException |
|
| 553 | - */ |
|
| 554 | - private function _get_invoice_payment_method() |
|
| 555 | - { |
|
| 556 | - if (! $this->_invoice_pm instanceof EE_Payment_Method) { |
|
| 557 | - $transaction = $this->_data->txn instanceof EE_Transaction ? $this->_data->txn : null; |
|
| 558 | - $transaction = ! $transaction instanceof EE_Transaction |
|
| 559 | - && is_array($this->_extra_data) |
|
| 560 | - && isset($this->_extra_data['data']) |
|
| 561 | - && $this->_extra_data['data'] instanceof EE_Messages_Addressee |
|
| 562 | - ? $this->_extra_data['data']->txn |
|
| 563 | - : $transaction; |
|
| 564 | - // get the invoice payment method, and remember it for the next call too |
|
| 565 | - $this->_invoice_pm = apply_filters( |
|
| 566 | - 'FHEE__EE_Transaction_Shortcodes__get_payment_method__default', |
|
| 567 | - EEM_Payment_Method::instance()->get_one_of_type('Invoice'), |
|
| 568 | - $transaction |
|
| 569 | - ); |
|
| 570 | - } |
|
| 571 | - return $this->_invoice_pm; |
|
| 572 | - } |
|
| 573 | - |
|
| 574 | - |
|
| 575 | - /** |
|
| 576 | - * Used to retrieve the appropriate content for the invoice payee email shortcode |
|
| 577 | - * |
|
| 578 | - * @return string |
|
| 579 | - * @throws EE_Error |
|
| 580 | - * @throws InvalidArgumentException |
|
| 581 | - * @throws InvalidDataTypeException |
|
| 582 | - * @throws InvalidInterfaceException |
|
| 583 | - * @throws ReflectionException |
|
| 584 | - * @since 4.5.0 |
|
| 585 | - */ |
|
| 586 | - private function _get_invoice_payee_email() |
|
| 587 | - { |
|
| 588 | - $payment_method = $this->_get_invoice_payment_method(); |
|
| 589 | - $payee_email = $payment_method instanceof EE_Payment_Method |
|
| 590 | - ? $payment_method->get_extra_meta('pdf_payee_email', true) |
|
| 591 | - : null; |
|
| 592 | - return empty($payee_email) |
|
| 593 | - ? EE_Registry::instance()->CFG->organization->get_pretty('email') |
|
| 594 | - : $payee_email; |
|
| 595 | - } |
|
| 596 | - |
|
| 597 | - |
|
| 598 | - /** |
|
| 599 | - * Used to retrieve the appropriate content for the invoice payee tax number shortcode |
|
| 600 | - * |
|
| 601 | - * @param string $shortcode |
|
| 602 | - * @return string |
|
| 603 | - * @throws EE_Error |
|
| 604 | - * @throws InvalidArgumentException |
|
| 605 | - * @throws InvalidDataTypeException |
|
| 606 | - * @throws InvalidInterfaceException |
|
| 607 | - * @throws ReflectionException |
|
| 608 | - * @since 4.5.0 |
|
| 609 | - */ |
|
| 610 | - private function _get_invoice_payee_tax_number($shortcode) |
|
| 611 | - { |
|
| 612 | - $payee_tax_number = null; |
|
| 613 | - $payment_method = $this->_get_invoice_payment_method(); |
|
| 614 | - if ($payment_method instanceof EE_Payment_Method) { |
|
| 615 | - $payee_tax_number = $payment_method->get_extra_meta('pdf_payee_tax_number', true); |
|
| 616 | - } |
|
| 617 | - $payee_tax_number = empty($payee_tax_number) ? EE_Registry::instance()->CFG->organization->vat |
|
| 618 | - : $payee_tax_number; |
|
| 619 | - if (empty($payee_tax_number)) { |
|
| 620 | - return ''; |
|
| 621 | - } |
|
| 622 | - // any attributes? |
|
| 623 | - $attrs = $this->_get_shortcode_attrs($shortcode); |
|
| 624 | - // prefix? |
|
| 625 | - $prefix = $attrs['prefix'] ?? esc_html__('VAT/Tax Number: ', 'event_espresso'); |
|
| 626 | - return $prefix . $payee_tax_number; |
|
| 627 | - } |
|
| 628 | - |
|
| 629 | - |
|
| 630 | - /** |
|
| 631 | - * Used to retrieve the appropriate content for the invoice payee address shortcode. |
|
| 632 | - * |
|
| 633 | - * @return string |
|
| 634 | - * @throws EE_Error |
|
| 635 | - * @throws InvalidArgumentException |
|
| 636 | - * @throws ReflectionException |
|
| 637 | - * @throws InvalidDataTypeException |
|
| 638 | - * @throws InvalidInterfaceException |
|
| 639 | - * @since 4.5.0 |
|
| 640 | - */ |
|
| 641 | - private function _get_invoice_payee_address() |
|
| 642 | - { |
|
| 643 | - $payee_address = null; |
|
| 644 | - $payment_method = $this->_get_invoice_payment_method(); |
|
| 645 | - if ($payment_method instanceof EE_Payment_Method) { |
|
| 646 | - $payee_address = $payment_method->get_extra_meta('pdf_payee_address', true); |
|
| 647 | - } |
|
| 648 | - if (empty($payee_address)) { |
|
| 649 | - $organization = EE_Registry::instance()->CFG->organization; |
|
| 650 | - $payee_address = $organization->get_pretty('address_1') . '<br>'; |
|
| 651 | - $payee_address .= ! empty($organization->address_2) |
|
| 652 | - ? $organization->get_pretty('address_2') . '<br>' |
|
| 653 | - : ''; |
|
| 654 | - $payee_address .= $organization->get_pretty('city') . '<br>'; |
|
| 655 | - // state |
|
| 656 | - $state = EE_Registry::instance()->load_model('State')->get_one_by_ID($organization->STA_ID); |
|
| 657 | - $payee_address .= $state instanceof EE_State ? $state->name() : ''; |
|
| 658 | - // Country |
|
| 659 | - $payee_address .= ! empty($organization->CNT_ISO) ? ', ' . $organization->CNT_ISO . '<br>' : ''; |
|
| 660 | - $payee_address .= ! empty($organization->zip) ? $organization->zip : ''; |
|
| 661 | - } |
|
| 662 | - return $payee_address; |
|
| 663 | - } |
|
| 664 | - |
|
| 665 | - |
|
| 666 | - /** |
|
| 667 | - * Used to retrieve the appropriate content for the invoice payment instructions shortcode. |
|
| 668 | - * |
|
| 669 | - * @return string |
|
| 670 | - * @throws EE_Error |
|
| 671 | - * @throws InvalidArgumentException |
|
| 672 | - * @throws InvalidDataTypeException |
|
| 673 | - * @throws InvalidInterfaceException |
|
| 674 | - * @throws ReflectionException |
|
| 675 | - * @since 4.5.0 |
|
| 676 | - */ |
|
| 677 | - private function _get_invoice_payment_instructions() |
|
| 678 | - { |
|
| 679 | - $payment_method = $this->_get_invoice_payment_method(); |
|
| 680 | - return ($payment_method instanceof EE_Payment_Method) |
|
| 681 | - ? $payment_method->get_extra_meta('pdf_instructions', true) |
|
| 682 | - : ''; |
|
| 683 | - } |
|
| 684 | - |
|
| 685 | - |
|
| 686 | - /** |
|
| 687 | - * get invoice/receipt switch button or url. |
|
| 688 | - * |
|
| 689 | - * @param bool $button true (default) returns the html for a button, false just returns the url. |
|
| 690 | - * @return string |
|
| 691 | - */ |
|
| 692 | - protected function _get_invoice_receipt_switcher($button = true) |
|
| 693 | - { |
|
| 694 | - $reg = $this->_data->primary_reg_obj; |
|
| 695 | - $message_type = $this->_extra_data['message_type'] ?? ''; |
|
| 696 | - if (! $reg instanceof EE_Registration || empty($message_type)) { |
|
| 697 | - return ''; |
|
| 698 | - } |
|
| 699 | - $switch_to_invoice = ! $message_type instanceof EE_Invoice_message_type; |
|
| 700 | - $switch_to_label = $switch_to_invoice && ! $message_type instanceof EE_Receipt_message_type |
|
| 701 | - ? esc_html__('View Invoice', 'event_espresso') |
|
| 702 | - : esc_html__('Switch to Invoice', 'event_espresso'); |
|
| 703 | - $switch_to_label = |
|
| 704 | - ! $switch_to_invoice ? esc_html__('Switch to Receipt', 'event_espresso') : $switch_to_label; |
|
| 705 | - $switch_to_url = $switch_to_invoice ? $reg->invoice_url() : $reg->receipt_url(); |
|
| 706 | - if (! $button) { |
|
| 707 | - return $switch_to_url; |
|
| 708 | - } |
|
| 709 | - if (! empty($switch_to_url)) { |
|
| 710 | - return ' |
|
| 19 | + /** |
|
| 20 | + * @var EE_Payment_Method|null $_invoice_pm the invoice payment method for use in invoices etc |
|
| 21 | + */ |
|
| 22 | + protected ?EE_Payment_Method $_invoice_pm = null; |
|
| 23 | + |
|
| 24 | + |
|
| 25 | + protected function _init_props() |
|
| 26 | + { |
|
| 27 | + $this->label = esc_html__('Transaction Shortcodes', 'event_espresso'); |
|
| 28 | + $this->description = esc_html__('All shortcodes specific to transaction related data', 'event_espresso'); |
|
| 29 | + $this->_shortcodes = [ |
|
| 30 | + '[TXN_ID]' => esc_html__('The transaction id for the purchase.', 'event_espresso'), |
|
| 31 | + '[PAYMENT_URL]' => esc_html__( |
|
| 32 | + 'This is a link to make a payment for the event', |
|
| 33 | + 'event_espresso' |
|
| 34 | + ), |
|
| 35 | + '[PAYMENT_LINK_IF_NEEDED_*]' => esc_html__( |
|
| 36 | + 'This is a special dynamic shortcode that allows one to insert a payment link conditional on there being amount owing on the transaction. Three params are available on this shortcode:', |
|
| 37 | + 'event_espresso' |
|
| 38 | + ) |
|
| 39 | + . '<ul>' |
|
| 40 | + . '<li>' |
|
| 41 | + . sprintf( |
|
| 42 | + esc_html__( |
|
| 43 | + '%sclass:%s This can be used to indicate css class is given to the containing css element (default is "callout").', |
|
| 44 | + 'event_espresso' |
|
| 45 | + ), |
|
| 46 | + '<strong>', |
|
| 47 | + '</strong>' |
|
| 48 | + ) |
|
| 49 | + . '</li>' |
|
| 50 | + . '<li>' |
|
| 51 | + . sprintf( |
|
| 52 | + esc_html__( |
|
| 53 | + '%scustom_text:%s This should be a sprintf format text string (with %%s for where the hyperlink tags go) that is used for the generated link text (The default is "You can %%smake a payment here »%%s.)', |
|
| 54 | + 'event_espresso' |
|
| 55 | + ), |
|
| 56 | + '<strong>', |
|
| 57 | + '</strong>' |
|
| 58 | + ) |
|
| 59 | + . '</li>' |
|
| 60 | + . '<li>' |
|
| 61 | + . sprintf( |
|
| 62 | + esc_html__( |
|
| 63 | + '%scontainer_tag:%s Use this to indicate what container tag you want surrounding the payment link (default is "p").', |
|
| 64 | + 'event_espresso' |
|
| 65 | + ), |
|
| 66 | + '<strong>', |
|
| 67 | + '</strong>' |
|
| 68 | + ) |
|
| 69 | + . '</li>' |
|
| 70 | + . '</ul>', |
|
| 71 | + '[PAYMENT_DUE_DATE_*]' => esc_html__( |
|
| 72 | + 'This is a special dynamic shortcode that allows one to output a payment due date. It will only result in a date shown if there is money owing. Three parameters are available on this shortcode:', |
|
| 73 | + 'event_espresso' |
|
| 74 | + ) |
|
| 75 | + . '<ul>' |
|
| 76 | + . '<li>' |
|
| 77 | + . sprintf( |
|
| 78 | + esc_html__( |
|
| 79 | + '%sformat:%s This is used to indicate what format the date is in. Default is whatever is set as date formats for your website.', |
|
| 80 | + 'event_espresso' |
|
| 81 | + ), |
|
| 82 | + '<strong>', |
|
| 83 | + '</strong>' |
|
| 84 | + ) |
|
| 85 | + . '</li>' |
|
| 86 | + . '<li>' |
|
| 87 | + . sprintf( |
|
| 88 | + esc_html__( |
|
| 89 | + '%sdays_until_due:%s This is the number of days form the transaction creation date that the payment is due. Defaults to 30.', |
|
| 90 | + 'event_espresso' |
|
| 91 | + ), |
|
| 92 | + '<strong>', |
|
| 93 | + '</strong>' |
|
| 94 | + ) |
|
| 95 | + . '</li>' |
|
| 96 | + . '<li>' |
|
| 97 | + . sprintf( |
|
| 98 | + esc_html__( |
|
| 99 | + '%sprefix_text:%s You can use this to indicate what text will prefix the date string. Defaults to "Payment in full due by:"', |
|
| 100 | + 'event_espresso' |
|
| 101 | + ), |
|
| 102 | + '<strong>', |
|
| 103 | + '</strong>' |
|
| 104 | + ) |
|
| 105 | + . '</li>', |
|
| 106 | + '[INVOICE_LINK]' => esc_html__( |
|
| 107 | + 'This is a full html link to the invoice. Add download=true to link directly to download.', |
|
| 108 | + 'event_espresso' |
|
| 109 | + ), |
|
| 110 | + '[INVOICE_URL]' => esc_html__( |
|
| 111 | + 'This is just the url for the invoice. Add download=true to link directly to download.', |
|
| 112 | + 'event_espresso' |
|
| 113 | + ), |
|
| 114 | + '[INVOICE_LOGO_URL]' => esc_html__( |
|
| 115 | + 'This returns the url for the logo uploaded via the invoice settings page.', |
|
| 116 | + 'event_espresso' |
|
| 117 | + ), |
|
| 118 | + '[INVOICE_LOGO]' => esc_html__( |
|
| 119 | + 'This returns the logo uploaded via the invoice settings page wrapped in img_tags and with a "logo screen" classes. The image size is also set in the img tags automatically to match the uploaded logo.', |
|
| 120 | + 'event_espresso' |
|
| 121 | + ), |
|
| 122 | + '[INVOICE_PAYEE_NAME]' => esc_html__( |
|
| 123 | + 'This will parse to either: the value of the "Company Name" field in the invoice payment method settings; if that is blank, then the value of the Company Name in the "Your Organization Settings", if that is blank then an empty string.', |
|
| 124 | + 'event_espresso' |
|
| 125 | + ), |
|
| 126 | + '[INVOICE_PAYEE_ADDRESS]' => esc_html__( |
|
| 127 | + 'This will parse to either: the value of the "Company Address" field in the invoice payment method settings; if that is blank, then the value of the Company Address in the "Your Organization Settings", if that is blank then an empty string.', |
|
| 128 | + 'event_espresso' |
|
| 129 | + ), |
|
| 130 | + '[INVOICE_PAYMENT_INSTRUCTIONS]' => esc_html__( |
|
| 131 | + 'This will parse to the value of the "Payment Instructions" field found on the Invoice payment methods settings page', |
|
| 132 | + 'event_espresso' |
|
| 133 | + ), |
|
| 134 | + '[INVOICE_PAYEE_EMAIL]' => esc_html__( |
|
| 135 | + 'This will parse to either: the value of the "Company Email" field in the invoice payment method settings; if that is blank, then the value of the Company Email in the "Your Organization Settings", if that is blank then an empty string.', |
|
| 136 | + 'event_espresso' |
|
| 137 | + ), |
|
| 138 | + '[INVOICE_PAYEE_TAX_NUMBER_*]' => sprintf( |
|
| 139 | + esc_html__( |
|
| 140 | + 'This will parse to either: the value of the "Company Tax Number" field in the invoice payment method settings; if that is blank, then the value of the Company Tax Number in the "Your Organization Settings", if that is blank then an empty string. Note this is also a special dynamic shortcode. You can use the "prefix" parameter to indicate what text you want to use as a prefix before this tax number. It defaults to "VAT/Tax Number:". To change this prefix you do the following format for this shortcode: %1$s[INVOICE_PAYEE_TAX_NUMBER_* prefix="GST:"]%2$s and that will output: GST: 12345t56. If you have no tax number in your settings, then no prefix will be output either.', |
|
| 141 | + 'event_espresso' |
|
| 142 | + ), |
|
| 143 | + '<code>', |
|
| 144 | + '</code>' |
|
| 145 | + ), |
|
| 146 | + '[TOTAL_COST]' => esc_html__('The total cost for the transaction', 'event_espresso'), |
|
| 147 | + '[TXN_STATUS]' => esc_html__( |
|
| 148 | + 'The transaction status for the transaction.', |
|
| 149 | + 'event_espresso' |
|
| 150 | + ), |
|
| 151 | + '[TXN_STATUS_ID]' => esc_html__( |
|
| 152 | + 'The ID representing the transaction status as saved in the db. This tends to be useful for including with css classes for styling certain statuses differently from others.', |
|
| 153 | + 'event_espresso' |
|
| 154 | + ), |
|
| 155 | + '[PAYMENT_STATUS]' => esc_html__( |
|
| 156 | + 'The transaction status for the transaction. This parses to the same value as the [TXN_STATUS] shortcode and still remains here for legacy support.', |
|
| 157 | + 'event_espresso' |
|
| 158 | + ), |
|
| 159 | + '[PAYMENT_GATEWAY]' => esc_html__( |
|
| 160 | + 'The payment gateway used for the transaction', |
|
| 161 | + 'event_espresso' |
|
| 162 | + ), |
|
| 163 | + '[AMOUNT_PAID]' => esc_html__( |
|
| 164 | + 'The amount paid or refunded. This will only have a value if there was a payment or refund at the time of generating the message.', |
|
| 165 | + 'event_espresso' |
|
| 166 | + ), |
|
| 167 | + '[LAST_AMOUNT_PAID]' => esc_html__( |
|
| 168 | + 'This is the last payment or refund made on the transaction related to the message being generated.', |
|
| 169 | + 'event_espresso' |
|
| 170 | + ), |
|
| 171 | + '[TOTAL_AMOUNT_PAID]' => esc_html__( |
|
| 172 | + 'This parses to the total amount paid over all payments', |
|
| 173 | + 'event_espresso' |
|
| 174 | + ), |
|
| 175 | + '[TOTAL_OWING]' => esc_html__( |
|
| 176 | + 'The total owing on a transaction with no attributes.', |
|
| 177 | + 'event_espresso' |
|
| 178 | + ), |
|
| 179 | + '[TXN_SUBTOTAL]' => esc_html__('The subtotal for all txn line items.', 'event_espresso'), |
|
| 180 | + '[TXN_TAX_SUBTOTAL]' => esc_html__('The subtotal for all tax line items.', 'event_espresso'), |
|
| 181 | + '[OWING_STATUS_MESSAGE_*]' => esc_html__( |
|
| 182 | + 'A dynamic shortcode for adjusting how total owing gets shown. The acceptable attributes on the shortcode are:', |
|
| 183 | + 'event_espresso' |
|
| 184 | + ) |
|
| 185 | + . '<p></ul>' |
|
| 186 | + . '<li><strong>still_owing</strong>:' |
|
| 187 | + . esc_html__( |
|
| 188 | + 'If the transaction is not paid in full, then whatever is set for this attribute is shown (otherwise its just the amount owing). The default is:', |
|
| 189 | + 'event_espresso' |
|
| 190 | + ) |
|
| 191 | + . sprintf( |
|
| 192 | + esc_html__('%sPlease make a payment.%s', 'event_espresso'), |
|
| 193 | + '<a href="[PAYMENT_URL]" class="noPrint">', |
|
| 194 | + '</a>' |
|
| 195 | + ) |
|
| 196 | + . '</li>' |
|
| 197 | + . |
|
| 198 | + '<li><strong>none_owing</strong>:' |
|
| 199 | + . esc_html__( |
|
| 200 | + 'If the transaction is paid in full, then you can indicate how this gets displayed. Note, that it defaults to just be the total owing.', |
|
| 201 | + 'event_espresso' |
|
| 202 | + ) |
|
| 203 | + . '</li></ul></p>', |
|
| 204 | + '[TXN_TOTAL_TICKETS]' => esc_html__( |
|
| 205 | + 'The total number of all tickets purchased in a transaction', |
|
| 206 | + 'event_espresso' |
|
| 207 | + ), |
|
| 208 | + '[TKT_QTY_PURCHASED]' => sprintf( |
|
| 209 | + esc_html__( |
|
| 210 | + 'The total number of all tickets purchased in a transaction. %1$sNOTE: This shortcode is good to use in the "[TICKET_LIST]" field but has been deprecated from all other contexts in favor of the more explicit [TXN_TOTAL_TICKETS] shortcode.%2$s', |
|
| 211 | + 'event_espresso' |
|
| 212 | + ), |
|
| 213 | + '<strong>', |
|
| 214 | + '</strong>' |
|
| 215 | + ), |
|
| 216 | + '[TRANSACTION_ADMIN_URL]' => esc_html__( |
|
| 217 | + 'The url to the admin page for this transaction', |
|
| 218 | + 'event_espresso' |
|
| 219 | + ), |
|
| 220 | + '[RECEIPT_URL]' => esc_html__( |
|
| 221 | + 'This parses to the generated url for retrieving the receipt for the transaction. Add download=true to link directly to download.', |
|
| 222 | + 'event_espresso' |
|
| 223 | + ), |
|
| 224 | + '[INVOICE_RECEIPT_SWITCHER_URL]' => esc_html__( |
|
| 225 | + 'This parses to the url that will switch to the receipt if an invoice is displayed, and switch to the invoice if receipt is displayed. If a message type OTHER than invoice or receipt is displayed then this will just return the url for the invoice. If the related message type is not active then will parse to an empty string.', |
|
| 226 | + 'event_espresso' |
|
| 227 | + ), |
|
| 228 | + '[INVOICE_RECEIPT_SWITCHER_BUTTON]' => sprintf( |
|
| 229 | + esc_html__( |
|
| 230 | + 'The same as %1$s%2$s except this returns the html for a button linked to the invoice or receipt.', |
|
| 231 | + 'event_espresso' |
|
| 232 | + ), |
|
| 233 | + '<code>[INVOICE_RECEIPT_SWITCHER_URL]', |
|
| 234 | + '</code>' |
|
| 235 | + ), |
|
| 236 | + '[LAST_PAYMENT_TRANSACTION_ID]' => esc_html__( |
|
| 237 | + 'This will output the value of the payment transaction id for the last payment made on the transaction. Note, if a specific payment was included for message generation, that will be used when parsing the shortcode.', |
|
| 238 | + 'event_espresso' |
|
| 239 | + ), |
|
| 240 | + ]; |
|
| 241 | + } |
|
| 242 | + |
|
| 243 | + |
|
| 244 | + /** |
|
| 245 | + * @param string $shortcode the shortcode to be parsed. |
|
| 246 | + * @return string parsed shortcode |
|
| 247 | + * @throws EE_Error |
|
| 248 | + * @throws InvalidArgumentException |
|
| 249 | + * @throws ReflectionException |
|
| 250 | + * @throws InvalidDataTypeException |
|
| 251 | + * @throws InvalidInterfaceException |
|
| 252 | + */ |
|
| 253 | + protected function _parser($shortcode) |
|
| 254 | + { |
|
| 255 | + // attempt to get the transaction. Since this is potentially used in more fields, we may have to look in the |
|
| 256 | + // _extra_data for the transaction. |
|
| 257 | + $transaction = $this->_data->txn instanceof EE_Transaction ? $this->_data->txn : null; |
|
| 258 | + $transaction = ! $transaction instanceof EE_Transaction |
|
| 259 | + && is_array($this->_extra_data) |
|
| 260 | + && isset($this->_extra_data['data']) |
|
| 261 | + && $this->_extra_data['data'] instanceof EE_Messages_Addressee |
|
| 262 | + ? $this->_extra_data['data']->txn |
|
| 263 | + : $transaction; |
|
| 264 | + if (! $transaction instanceof EE_Transaction) { |
|
| 265 | + return ''; |
|
| 266 | + } |
|
| 267 | + // payment |
|
| 268 | + $payment = $this->_data->payment instanceof EE_Payment ? $this->_data->payment : null; |
|
| 269 | + $payment = ! $payment instanceof EE_Payment |
|
| 270 | + && is_array($this->_extra_data) |
|
| 271 | + && isset($this->_extra_data['data']) |
|
| 272 | + && $this->_extra_data['data'] instanceof EE_Messages_Addressee |
|
| 273 | + ? $this->_extra_data['data']->payment |
|
| 274 | + : $payment; |
|
| 275 | + |
|
| 276 | + switch ($shortcode) { |
|
| 277 | + case '[TXN_ID]': |
|
| 278 | + return $transaction->ID(); |
|
| 279 | + |
|
| 280 | + case '[PAYMENT_URL]': |
|
| 281 | + $payment_url = $transaction->payment_overview_url(); |
|
| 282 | + return empty($payment_url) |
|
| 283 | + ? esc_html__('http://dummypaymenturlforpreview.com', 'event_espresso') |
|
| 284 | + : $payment_url; |
|
| 285 | + |
|
| 286 | + case strpos($shortcode, '[INVOICE_LINK') !== false : |
|
| 287 | + // any attributes? |
|
| 288 | + $attrs = $this->_get_shortcode_attrs($shortcode); |
|
| 289 | + // downloading PDF or HTML? |
|
| 290 | + $messenger = isset($attrs['download']) ? 'pdf' : 'html'; |
|
| 291 | + $invoice_url = $transaction->invoice_url($messenger); |
|
| 292 | + $invoice_url = empty($invoice_url) ? 'http://dummyinvoicelinksforpreview.com' : $invoice_url; |
|
| 293 | + return sprintf( |
|
| 294 | + esc_html__('%sClick here for Invoice%s', 'event_espresso'), |
|
| 295 | + '<a href="' . $invoice_url . '">', |
|
| 296 | + '</a>' |
|
| 297 | + ); |
|
| 298 | + |
|
| 299 | + case strpos($shortcode, '[INVOICE_URL') !== false : |
|
| 300 | + // any attributes? |
|
| 301 | + $attrs = $this->_get_shortcode_attrs($shortcode); |
|
| 302 | + // downloading PDF or HTML? |
|
| 303 | + $messenger = isset($attrs['download']) ? 'pdf' : 'html'; |
|
| 304 | + $invoice_url = $transaction->invoice_url($messenger); |
|
| 305 | + return empty($invoice_url) ? 'http://dummyinvoicelinksforpreview.com' : $invoice_url; |
|
| 306 | + |
|
| 307 | + case '[INVOICE_LOGO_URL]': |
|
| 308 | + return $this->_get_invoice_logo(); |
|
| 309 | + |
|
| 310 | + case '[INVOICE_LOGO]': |
|
| 311 | + return $this->_get_invoice_logo(true); |
|
| 312 | + |
|
| 313 | + case '[INVOICE_PAYEE_NAME]': |
|
| 314 | + return $this->_get_invoice_payee_name(); |
|
| 315 | + |
|
| 316 | + case '[INVOICE_PAYEE_ADDRESS]': |
|
| 317 | + return $this->_get_invoice_payee_address(); |
|
| 318 | + |
|
| 319 | + case '[INVOICE_PAYMENT_INSTRUCTIONS]': |
|
| 320 | + return $this->_get_invoice_payment_instructions(); |
|
| 321 | + |
|
| 322 | + case '[INVOICE_PAYEE_EMAIL]': |
|
| 323 | + return $this->_get_invoice_payee_email(); |
|
| 324 | + |
|
| 325 | + case '[TOTAL_COST]': |
|
| 326 | + $total = $transaction->total(); |
|
| 327 | + return ! empty($total) ? EEH_Template::format_currency($total) : ''; |
|
| 328 | + |
|
| 329 | + // note the [payment_status] shortcode is kind of misleading because payment status might be different |
|
| 330 | + // from txn status so I'm adding this here for clarity. |
|
| 331 | + case '[PAYMENT_STATUS]': |
|
| 332 | + case '[TXN_STATUS]': |
|
| 333 | + $status = $transaction->pretty_status(); |
|
| 334 | + return ! empty($status) ? $status : esc_html__('Unknown', 'event_espresso'); |
|
| 335 | + |
|
| 336 | + case '[TXN_STATUS_ID]': |
|
| 337 | + return $transaction->status_ID(); |
|
| 338 | + |
|
| 339 | + case '[PAYMENT_GATEWAY]': |
|
| 340 | + return $this->_get_payment_gateway($transaction); |
|
| 341 | + |
|
| 342 | + case '[AMOUNT_PAID]': |
|
| 343 | + return $payment instanceof EE_Payment |
|
| 344 | + ? EEH_Template::format_currency($payment->amount()) |
|
| 345 | + : EEH_Template::format_currency(0); |
|
| 346 | + |
|
| 347 | + case '[LAST_AMOUNT_PAID]': |
|
| 348 | + $last_payment = $transaction->last_payment(); |
|
| 349 | + return $last_payment instanceof EE_Payment |
|
| 350 | + ? EEH_Template::format_currency($last_payment->amount()) |
|
| 351 | + : EEH_Template::format_currency(0); |
|
| 352 | + |
|
| 353 | + case '[TOTAL_AMOUNT_PAID]': |
|
| 354 | + return EEH_Template::format_currency($transaction->paid()); |
|
| 355 | + |
|
| 356 | + case '[TOTAL_OWING]': |
|
| 357 | + $total_owing = $transaction->remaining(); |
|
| 358 | + return EEH_Template::format_currency($total_owing); |
|
| 359 | + |
|
| 360 | + case '[TXN_SUBTOTAL]': |
|
| 361 | + return EEH_Template::format_currency($this->_get_subtotal()); |
|
| 362 | + |
|
| 363 | + case '[TXN_TAX_SUBTOTAL]': |
|
| 364 | + return EEH_Template::format_currency($this->_get_subtotal(true)); |
|
| 365 | + |
|
| 366 | + case '[TKT_QTY_PURCHASED]': |
|
| 367 | + case '[TXN_TOTAL_TICKETS]': |
|
| 368 | + return $this->_data->total_ticket_count; |
|
| 369 | + |
|
| 370 | + case '[TRANSACTION_ADMIN_URL]': |
|
| 371 | + require_once EE_CORE . 'admin/EE_Admin_Page.core.php'; |
|
| 372 | + $query_args = [ |
|
| 373 | + 'page' => 'espresso_transactions', |
|
| 374 | + 'action' => 'view_transaction', |
|
| 375 | + 'TXN_ID' => $transaction->ID(), |
|
| 376 | + ]; |
|
| 377 | + return EE_Admin_Page::add_query_args_and_nonce($query_args, admin_url('admin.php')); |
|
| 378 | + |
|
| 379 | + case strpos($shortcode, '[RECEIPT_URL') !== false : |
|
| 380 | + // get primary_registration |
|
| 381 | + $reg = $this->_data->primary_reg_obj; |
|
| 382 | + if (! $reg instanceof EE_Registration) { |
|
| 383 | + return ''; |
|
| 384 | + } |
|
| 385 | + // any attributes? |
|
| 386 | + $attrs = $this->_get_shortcode_attrs($shortcode); |
|
| 387 | + // downloading PDF or HTML? |
|
| 388 | + $messenger = isset($attrs['download']) ? 'pdf' : 'html'; |
|
| 389 | + return $reg->receipt_url($messenger); |
|
| 390 | + |
|
| 391 | + case '[INVOICE_RECEIPT_SWITCHER_URL]': |
|
| 392 | + return $this->_get_invoice_receipt_switcher(false); |
|
| 393 | + |
|
| 394 | + case '[INVOICE_RECEIPT_SWITCHER_BUTTON]': |
|
| 395 | + return $this->_get_invoice_receipt_switcher(); |
|
| 396 | + |
|
| 397 | + case '[LAST_PAYMENT_TRANSACTION_ID]': |
|
| 398 | + $id = ''; |
|
| 399 | + $payment = $payment instanceof EE_Payment && $payment->ID() !== 0 |
|
| 400 | + ? $payment |
|
| 401 | + : $transaction->last_payment(); |
|
| 402 | + if ($payment instanceof EE_Payment) { |
|
| 403 | + $id = $payment->txn_id_chq_nmbr(); |
|
| 404 | + } |
|
| 405 | + return $id; |
|
| 406 | + } |
|
| 407 | + |
|
| 408 | + |
|
| 409 | + if (strpos($shortcode, '[OWING_STATUS_MESSAGE_*') !== false) { |
|
| 410 | + return $this->_get_custom_total_owing($shortcode); |
|
| 411 | + } |
|
| 412 | + if (strpos($shortcode, '[INVOICE_PAYEE_TAX_NUMBER_*') !== false) { |
|
| 413 | + return $this->_get_invoice_payee_tax_number($shortcode); |
|
| 414 | + } |
|
| 415 | + if (strpos($shortcode, '[PAYMENT_LINK_IF_NEEDED_*') !== false) { |
|
| 416 | + return $this->_get_payment_link_if_needed($shortcode); |
|
| 417 | + } |
|
| 418 | + if (strpos($shortcode, '[PAYMENT_DUE_DATE_*') !== false) { |
|
| 419 | + return $this->_get_payment_due_date($shortcode, $transaction); |
|
| 420 | + } |
|
| 421 | + return ''; |
|
| 422 | + } |
|
| 423 | + |
|
| 424 | + |
|
| 425 | + /** |
|
| 426 | + * parser for the [OWING_STATUS_MESSAGE_*] attribute type shortcode |
|
| 427 | + * |
|
| 428 | + * @param string $shortcode the incoming shortcode |
|
| 429 | + * @return string parsed. |
|
| 430 | + * @throws EE_Error |
|
| 431 | + * @throws ReflectionException |
|
| 432 | + * @since 4.5.0 |
|
| 433 | + */ |
|
| 434 | + private function _get_custom_total_owing($shortcode) |
|
| 435 | + { |
|
| 436 | + $valid_shortcodes = ['transaction']; |
|
| 437 | + $attrs = $this->_get_shortcode_attrs($shortcode); |
|
| 438 | + // ensure default is set. |
|
| 439 | + $addressee = $this->_data instanceof EE_Messages_Addressee ? $this->_data : null; |
|
| 440 | + $total_owing = $addressee instanceof EE_Messages_Addressee && $addressee->txn instanceof EE_Transaction |
|
| 441 | + ? $addressee->txn->remaining() |
|
| 442 | + : 0; |
|
| 443 | + if ($total_owing > 0) { |
|
| 444 | + $owing_content = ! empty($attrs['still_owing']) |
|
| 445 | + ? $attrs['still_owing'] |
|
| 446 | + : sprintf( |
|
| 447 | + esc_html__('%sPlease make a payment.%s', 'event_espresso'), |
|
| 448 | + '<a href="[PAYMENT_URL]" class="noPrint">', |
|
| 449 | + '</a>' |
|
| 450 | + ); |
|
| 451 | + $owing_content = $this->_shortcode_helper->parse_message_template( |
|
| 452 | + $owing_content, |
|
| 453 | + $addressee, |
|
| 454 | + $valid_shortcodes, |
|
| 455 | + $this->_message_type, |
|
| 456 | + $this->_messenger, |
|
| 457 | + $this->_message |
|
| 458 | + ); |
|
| 459 | + } else { |
|
| 460 | + $owing_content = ! empty($attrs['none_owing']) ? $attrs['none_owing'] : ''; |
|
| 461 | + } |
|
| 462 | + return $owing_content; |
|
| 463 | + } |
|
| 464 | + |
|
| 465 | + |
|
| 466 | + /** |
|
| 467 | + * @param EE_Transaction $transaction |
|
| 468 | + * @return string |
|
| 469 | + * @throws EE_Error |
|
| 470 | + * @throws ReflectionException |
|
| 471 | + */ |
|
| 472 | + private function _get_payment_gateway($transaction) |
|
| 473 | + { |
|
| 474 | + $payment_method = $transaction instanceof EE_Transaction ? $transaction->payment_method() : null; |
|
| 475 | + return $payment_method instanceof EE_Payment_Method ? $payment_method->name() : ''; |
|
| 476 | + } |
|
| 477 | + |
|
| 478 | + |
|
| 479 | + /** |
|
| 480 | + * This retrieves a logo to be used for the invoice from whatever is set on the invoice logo settings page. If its |
|
| 481 | + * not present then the organization logo is used if its found (set on the organization settings page). |
|
| 482 | + * |
|
| 483 | + * @param bool $img_tags TRUE means to return with the img tag wrappers. False just returns the url to the image. |
|
| 484 | + * @return string url or html |
|
| 485 | + * @throws EE_Error |
|
| 486 | + * @throws InvalidArgumentException |
|
| 487 | + * @throws InvalidDataTypeException |
|
| 488 | + * @throws InvalidInterfaceException |
|
| 489 | + * @throws ReflectionException |
|
| 490 | + * @since 4.5.0 |
|
| 491 | + */ |
|
| 492 | + private function _get_invoice_logo(bool $img_tags = false): string |
|
| 493 | + { |
|
| 494 | + $invoice_logo_url = ''; |
|
| 495 | + // try to get the invoice payment method's logo for this transaction image first |
|
| 496 | + $payment_method = $this->_get_invoice_payment_method(); |
|
| 497 | + if ($payment_method instanceof EE_Payment_Method) { |
|
| 498 | + $invoice_logo_url = $payment_method->get_extra_meta('pdf_logo_image', true); |
|
| 499 | + } |
|
| 500 | + if (empty($invoice_logo_url)) { |
|
| 501 | + $invoice_logo_url = EE_Registry::instance()->CFG->organization->logo_url; |
|
| 502 | + } |
|
| 503 | + if (empty($invoice_logo_url)) { |
|
| 504 | + return ''; |
|
| 505 | + } |
|
| 506 | + if (! $img_tags) { |
|
| 507 | + return $invoice_logo_url; |
|
| 508 | + } |
|
| 509 | + $invoice_logo_url = esc_url_raw($invoice_logo_url); |
|
| 510 | + // image tags have been requested. |
|
| 511 | + $image_size = @getimagesize($invoice_logo_url); |
|
| 512 | + $image_width_attr = ''; |
|
| 513 | + // if image is wider than 300px, set the width to 300 |
|
| 514 | + if ($image_size !== false) { |
|
| 515 | + $image_width = min($image_size[0], 300); |
|
| 516 | + $image_width = esc_attr($image_width); |
|
| 517 | + $image_width_attr = " width='$image_width'"; |
|
| 518 | + } |
|
| 519 | + return '<img class="logo screen" src="' . $invoice_logo_url . '"' . $image_width_attr . ' alt="logo" />'; |
|
| 520 | + } |
|
| 521 | + |
|
| 522 | + |
|
| 523 | + /** |
|
| 524 | + * Used to retrieve the appropriate content for the invoice payee name shortcode |
|
| 525 | + * |
|
| 526 | + * @return string |
|
| 527 | + * @throws EE_Error |
|
| 528 | + * @throws InvalidArgumentException |
|
| 529 | + * @throws InvalidDataTypeException |
|
| 530 | + * @throws InvalidInterfaceException |
|
| 531 | + * @throws ReflectionException |
|
| 532 | + * @since 4.5.0 |
|
| 533 | + */ |
|
| 534 | + private function _get_invoice_payee_name() |
|
| 535 | + { |
|
| 536 | + $payment_method = $this->_get_invoice_payment_method(); |
|
| 537 | + $payee_name = $payment_method instanceof EE_Payment_Method |
|
| 538 | + ? $payment_method->get_extra_meta('pdf_payee_name', true) |
|
| 539 | + : null; |
|
| 540 | + return empty($payee_name) ? EE_Registry::instance()->CFG->organization->get_pretty('name') : $payee_name; |
|
| 541 | + } |
|
| 542 | + |
|
| 543 | + |
|
| 544 | + /** |
|
| 545 | + * gets the default invoice payment method, but has a filter so it can be overridden |
|
| 546 | + * |
|
| 547 | + * @return EE_Payment_Method|null |
|
| 548 | + * @throws EE_Error |
|
| 549 | + * @throws InvalidArgumentException |
|
| 550 | + * @throws InvalidDataTypeException |
|
| 551 | + * @throws InvalidInterfaceException |
|
| 552 | + * @throws ReflectionException |
|
| 553 | + */ |
|
| 554 | + private function _get_invoice_payment_method() |
|
| 555 | + { |
|
| 556 | + if (! $this->_invoice_pm instanceof EE_Payment_Method) { |
|
| 557 | + $transaction = $this->_data->txn instanceof EE_Transaction ? $this->_data->txn : null; |
|
| 558 | + $transaction = ! $transaction instanceof EE_Transaction |
|
| 559 | + && is_array($this->_extra_data) |
|
| 560 | + && isset($this->_extra_data['data']) |
|
| 561 | + && $this->_extra_data['data'] instanceof EE_Messages_Addressee |
|
| 562 | + ? $this->_extra_data['data']->txn |
|
| 563 | + : $transaction; |
|
| 564 | + // get the invoice payment method, and remember it for the next call too |
|
| 565 | + $this->_invoice_pm = apply_filters( |
|
| 566 | + 'FHEE__EE_Transaction_Shortcodes__get_payment_method__default', |
|
| 567 | + EEM_Payment_Method::instance()->get_one_of_type('Invoice'), |
|
| 568 | + $transaction |
|
| 569 | + ); |
|
| 570 | + } |
|
| 571 | + return $this->_invoice_pm; |
|
| 572 | + } |
|
| 573 | + |
|
| 574 | + |
|
| 575 | + /** |
|
| 576 | + * Used to retrieve the appropriate content for the invoice payee email shortcode |
|
| 577 | + * |
|
| 578 | + * @return string |
|
| 579 | + * @throws EE_Error |
|
| 580 | + * @throws InvalidArgumentException |
|
| 581 | + * @throws InvalidDataTypeException |
|
| 582 | + * @throws InvalidInterfaceException |
|
| 583 | + * @throws ReflectionException |
|
| 584 | + * @since 4.5.0 |
|
| 585 | + */ |
|
| 586 | + private function _get_invoice_payee_email() |
|
| 587 | + { |
|
| 588 | + $payment_method = $this->_get_invoice_payment_method(); |
|
| 589 | + $payee_email = $payment_method instanceof EE_Payment_Method |
|
| 590 | + ? $payment_method->get_extra_meta('pdf_payee_email', true) |
|
| 591 | + : null; |
|
| 592 | + return empty($payee_email) |
|
| 593 | + ? EE_Registry::instance()->CFG->organization->get_pretty('email') |
|
| 594 | + : $payee_email; |
|
| 595 | + } |
|
| 596 | + |
|
| 597 | + |
|
| 598 | + /** |
|
| 599 | + * Used to retrieve the appropriate content for the invoice payee tax number shortcode |
|
| 600 | + * |
|
| 601 | + * @param string $shortcode |
|
| 602 | + * @return string |
|
| 603 | + * @throws EE_Error |
|
| 604 | + * @throws InvalidArgumentException |
|
| 605 | + * @throws InvalidDataTypeException |
|
| 606 | + * @throws InvalidInterfaceException |
|
| 607 | + * @throws ReflectionException |
|
| 608 | + * @since 4.5.0 |
|
| 609 | + */ |
|
| 610 | + private function _get_invoice_payee_tax_number($shortcode) |
|
| 611 | + { |
|
| 612 | + $payee_tax_number = null; |
|
| 613 | + $payment_method = $this->_get_invoice_payment_method(); |
|
| 614 | + if ($payment_method instanceof EE_Payment_Method) { |
|
| 615 | + $payee_tax_number = $payment_method->get_extra_meta('pdf_payee_tax_number', true); |
|
| 616 | + } |
|
| 617 | + $payee_tax_number = empty($payee_tax_number) ? EE_Registry::instance()->CFG->organization->vat |
|
| 618 | + : $payee_tax_number; |
|
| 619 | + if (empty($payee_tax_number)) { |
|
| 620 | + return ''; |
|
| 621 | + } |
|
| 622 | + // any attributes? |
|
| 623 | + $attrs = $this->_get_shortcode_attrs($shortcode); |
|
| 624 | + // prefix? |
|
| 625 | + $prefix = $attrs['prefix'] ?? esc_html__('VAT/Tax Number: ', 'event_espresso'); |
|
| 626 | + return $prefix . $payee_tax_number; |
|
| 627 | + } |
|
| 628 | + |
|
| 629 | + |
|
| 630 | + /** |
|
| 631 | + * Used to retrieve the appropriate content for the invoice payee address shortcode. |
|
| 632 | + * |
|
| 633 | + * @return string |
|
| 634 | + * @throws EE_Error |
|
| 635 | + * @throws InvalidArgumentException |
|
| 636 | + * @throws ReflectionException |
|
| 637 | + * @throws InvalidDataTypeException |
|
| 638 | + * @throws InvalidInterfaceException |
|
| 639 | + * @since 4.5.0 |
|
| 640 | + */ |
|
| 641 | + private function _get_invoice_payee_address() |
|
| 642 | + { |
|
| 643 | + $payee_address = null; |
|
| 644 | + $payment_method = $this->_get_invoice_payment_method(); |
|
| 645 | + if ($payment_method instanceof EE_Payment_Method) { |
|
| 646 | + $payee_address = $payment_method->get_extra_meta('pdf_payee_address', true); |
|
| 647 | + } |
|
| 648 | + if (empty($payee_address)) { |
|
| 649 | + $organization = EE_Registry::instance()->CFG->organization; |
|
| 650 | + $payee_address = $organization->get_pretty('address_1') . '<br>'; |
|
| 651 | + $payee_address .= ! empty($organization->address_2) |
|
| 652 | + ? $organization->get_pretty('address_2') . '<br>' |
|
| 653 | + : ''; |
|
| 654 | + $payee_address .= $organization->get_pretty('city') . '<br>'; |
|
| 655 | + // state |
|
| 656 | + $state = EE_Registry::instance()->load_model('State')->get_one_by_ID($organization->STA_ID); |
|
| 657 | + $payee_address .= $state instanceof EE_State ? $state->name() : ''; |
|
| 658 | + // Country |
|
| 659 | + $payee_address .= ! empty($organization->CNT_ISO) ? ', ' . $organization->CNT_ISO . '<br>' : ''; |
|
| 660 | + $payee_address .= ! empty($organization->zip) ? $organization->zip : ''; |
|
| 661 | + } |
|
| 662 | + return $payee_address; |
|
| 663 | + } |
|
| 664 | + |
|
| 665 | + |
|
| 666 | + /** |
|
| 667 | + * Used to retrieve the appropriate content for the invoice payment instructions shortcode. |
|
| 668 | + * |
|
| 669 | + * @return string |
|
| 670 | + * @throws EE_Error |
|
| 671 | + * @throws InvalidArgumentException |
|
| 672 | + * @throws InvalidDataTypeException |
|
| 673 | + * @throws InvalidInterfaceException |
|
| 674 | + * @throws ReflectionException |
|
| 675 | + * @since 4.5.0 |
|
| 676 | + */ |
|
| 677 | + private function _get_invoice_payment_instructions() |
|
| 678 | + { |
|
| 679 | + $payment_method = $this->_get_invoice_payment_method(); |
|
| 680 | + return ($payment_method instanceof EE_Payment_Method) |
|
| 681 | + ? $payment_method->get_extra_meta('pdf_instructions', true) |
|
| 682 | + : ''; |
|
| 683 | + } |
|
| 684 | + |
|
| 685 | + |
|
| 686 | + /** |
|
| 687 | + * get invoice/receipt switch button or url. |
|
| 688 | + * |
|
| 689 | + * @param bool $button true (default) returns the html for a button, false just returns the url. |
|
| 690 | + * @return string |
|
| 691 | + */ |
|
| 692 | + protected function _get_invoice_receipt_switcher($button = true) |
|
| 693 | + { |
|
| 694 | + $reg = $this->_data->primary_reg_obj; |
|
| 695 | + $message_type = $this->_extra_data['message_type'] ?? ''; |
|
| 696 | + if (! $reg instanceof EE_Registration || empty($message_type)) { |
|
| 697 | + return ''; |
|
| 698 | + } |
|
| 699 | + $switch_to_invoice = ! $message_type instanceof EE_Invoice_message_type; |
|
| 700 | + $switch_to_label = $switch_to_invoice && ! $message_type instanceof EE_Receipt_message_type |
|
| 701 | + ? esc_html__('View Invoice', 'event_espresso') |
|
| 702 | + : esc_html__('Switch to Invoice', 'event_espresso'); |
|
| 703 | + $switch_to_label = |
|
| 704 | + ! $switch_to_invoice ? esc_html__('Switch to Receipt', 'event_espresso') : $switch_to_label; |
|
| 705 | + $switch_to_url = $switch_to_invoice ? $reg->invoice_url() : $reg->receipt_url(); |
|
| 706 | + if (! $button) { |
|
| 707 | + return $switch_to_url; |
|
| 708 | + } |
|
| 709 | + if (! empty($switch_to_url)) { |
|
| 710 | + return ' |
|
| 711 | 711 | <form method="post" action="' . $switch_to_url . '" > |
| 712 | 712 | <input class="print_button" type="submit" value="' . $switch_to_label . '" /> |
| 713 | 713 | </form> |
| 714 | 714 | '; |
| 715 | - } |
|
| 716 | - return ''; |
|
| 717 | - } |
|
| 718 | - |
|
| 719 | - |
|
| 720 | - /** |
|
| 721 | - * This returns a subtotal. |
|
| 722 | - * |
|
| 723 | - * @param bool $tax if true then return the subtotal for tax otherwise return subtotal. |
|
| 724 | - * @return int |
|
| 725 | - * @throws EE_Error |
|
| 726 | - * @throws ReflectionException |
|
| 727 | - */ |
|
| 728 | - private function _get_subtotal($tax = false) |
|
| 729 | - { |
|
| 730 | - $grand_total = $this->_data->grand_total_line_item ?? null; |
|
| 731 | - if (! $grand_total instanceof EE_Line_Item) { |
|
| 732 | - return 0; |
|
| 733 | - } |
|
| 734 | - return $tax ? $grand_total->get_total_tax() : $grand_total->get_items_total(); |
|
| 735 | - } |
|
| 736 | - |
|
| 737 | - |
|
| 738 | - /** |
|
| 739 | - * parser for the [PAYMENT_LINK_IF_NEEDED_*] attribute type shortcode |
|
| 740 | - * |
|
| 741 | - * @param string $shortcode the incoming shortcode |
|
| 742 | - * @return string parsed. |
|
| 743 | - * @throws EE_Error |
|
| 744 | - * @throws ReflectionException |
|
| 745 | - * @since 4.7.0 |
|
| 746 | - */ |
|
| 747 | - private function _get_payment_link_if_needed($shortcode) |
|
| 748 | - { |
|
| 749 | - $valid_shortcodes = ['transaction']; |
|
| 750 | - $attrs = $this->_get_shortcode_attrs($shortcode); |
|
| 751 | - // ensure default is set. |
|
| 752 | - $addressee = $this->_data instanceof EE_Messages_Addressee ? $this->_data : null; |
|
| 753 | - $total_owing = $addressee instanceof EE_Messages_Addressee && $addressee->txn instanceof EE_Transaction |
|
| 754 | - ? $addressee->txn->remaining() |
|
| 755 | - : 0; |
|
| 756 | - if ($total_owing > 0) { |
|
| 757 | - $class = $attrs['class'] ?? 'callout'; |
|
| 758 | - $custom_text = |
|
| 759 | - $attrs['custom_text'] ?? 'You can %smake a payment here »%s.'; |
|
| 760 | - $container_tag = $attrs['container_tag'] ?? 'p'; |
|
| 761 | - $opening_tag = ! empty($container_tag) ? '<' . $container_tag : ''; |
|
| 762 | - $opening_tag .= ! empty($opening_tag) && ! empty($class) ? ' class="' . $class . '"' : $opening_tag; |
|
| 763 | - $opening_tag .= ! empty($opening_tag) ? '>' : $opening_tag; |
|
| 764 | - $closing_tag = ! empty($container_tag) ? '</' . $container_tag . '>' : ''; |
|
| 765 | - $content = $opening_tag . sprintf($custom_text, '<a href="[PAYMENT_URL]">', '</a>') . $closing_tag; |
|
| 766 | - // we need to re-run this string through the parser to catch any shortcodes that are in it. |
|
| 767 | - $owing_content = $this->_shortcode_helper->parse_message_template( |
|
| 768 | - $content, |
|
| 769 | - $addressee, |
|
| 770 | - $valid_shortcodes, |
|
| 771 | - $this->_message_type, |
|
| 772 | - $this->_messenger, |
|
| 773 | - $this->_message |
|
| 774 | - ); |
|
| 775 | - } else { |
|
| 776 | - return ''; |
|
| 777 | - } |
|
| 778 | - return $owing_content; |
|
| 779 | - } |
|
| 780 | - |
|
| 781 | - |
|
| 782 | - /** |
|
| 783 | - * Parser for the [PAYMENT_DUE_DATE_*] attribute type shortcode |
|
| 784 | - * |
|
| 785 | - * @param string $shortcode The shortcode being parsed. |
|
| 786 | - * @param EE_Transaction $transaction |
|
| 787 | - * @return string |
|
| 788 | - * @throws EE_Error |
|
| 789 | - * @throws ReflectionException |
|
| 790 | - * @since 4.8.28.rc.011 |
|
| 791 | - */ |
|
| 792 | - protected function _get_payment_due_date($shortcode, EE_Transaction $transaction) |
|
| 793 | - { |
|
| 794 | - // if transaction is paid in full then we can just return an empty string |
|
| 795 | - if ($transaction->remaining() == 0) { |
|
| 796 | - return ''; |
|
| 797 | - } |
|
| 798 | - $attrs = $this->_get_shortcode_attrs($shortcode); |
|
| 799 | - $format = $attrs['format'] ?? get_option('date_format'); |
|
| 800 | - $days_until_due = isset($attrs['days_until_due']) ? (int) $attrs['days_until_due'] : 30; |
|
| 801 | - $prefix_text = $attrs['prefix_text'] ?? esc_html__('Payment in full due by: ', 'event_espresso'); |
|
| 802 | - $transaction_created = $transaction->get_DateTime_object('TXN_timestamp'); |
|
| 803 | - // setup date due: |
|
| 804 | - try { |
|
| 805 | - if ($transaction_created instanceof DateTime) { |
|
| 806 | - $date_due = $transaction_created->add( |
|
| 807 | - new DateInterval('P' . $days_until_due . 'D') |
|
| 808 | - )->format($format); |
|
| 809 | - } else { |
|
| 810 | - throw new Exception(); |
|
| 811 | - } |
|
| 812 | - } catch (Exception $e) { |
|
| 813 | - // format was likely invalid. |
|
| 814 | - $date_due = esc_html__( |
|
| 815 | - 'Unable to calculate date due, likely the format string is invalid.', |
|
| 816 | - 'event_espresso' |
|
| 817 | - ); |
|
| 818 | - } |
|
| 819 | - return $prefix_text . $date_due; |
|
| 820 | - } |
|
| 715 | + } |
|
| 716 | + return ''; |
|
| 717 | + } |
|
| 718 | + |
|
| 719 | + |
|
| 720 | + /** |
|
| 721 | + * This returns a subtotal. |
|
| 722 | + * |
|
| 723 | + * @param bool $tax if true then return the subtotal for tax otherwise return subtotal. |
|
| 724 | + * @return int |
|
| 725 | + * @throws EE_Error |
|
| 726 | + * @throws ReflectionException |
|
| 727 | + */ |
|
| 728 | + private function _get_subtotal($tax = false) |
|
| 729 | + { |
|
| 730 | + $grand_total = $this->_data->grand_total_line_item ?? null; |
|
| 731 | + if (! $grand_total instanceof EE_Line_Item) { |
|
| 732 | + return 0; |
|
| 733 | + } |
|
| 734 | + return $tax ? $grand_total->get_total_tax() : $grand_total->get_items_total(); |
|
| 735 | + } |
|
| 736 | + |
|
| 737 | + |
|
| 738 | + /** |
|
| 739 | + * parser for the [PAYMENT_LINK_IF_NEEDED_*] attribute type shortcode |
|
| 740 | + * |
|
| 741 | + * @param string $shortcode the incoming shortcode |
|
| 742 | + * @return string parsed. |
|
| 743 | + * @throws EE_Error |
|
| 744 | + * @throws ReflectionException |
|
| 745 | + * @since 4.7.0 |
|
| 746 | + */ |
|
| 747 | + private function _get_payment_link_if_needed($shortcode) |
|
| 748 | + { |
|
| 749 | + $valid_shortcodes = ['transaction']; |
|
| 750 | + $attrs = $this->_get_shortcode_attrs($shortcode); |
|
| 751 | + // ensure default is set. |
|
| 752 | + $addressee = $this->_data instanceof EE_Messages_Addressee ? $this->_data : null; |
|
| 753 | + $total_owing = $addressee instanceof EE_Messages_Addressee && $addressee->txn instanceof EE_Transaction |
|
| 754 | + ? $addressee->txn->remaining() |
|
| 755 | + : 0; |
|
| 756 | + if ($total_owing > 0) { |
|
| 757 | + $class = $attrs['class'] ?? 'callout'; |
|
| 758 | + $custom_text = |
|
| 759 | + $attrs['custom_text'] ?? 'You can %smake a payment here »%s.'; |
|
| 760 | + $container_tag = $attrs['container_tag'] ?? 'p'; |
|
| 761 | + $opening_tag = ! empty($container_tag) ? '<' . $container_tag : ''; |
|
| 762 | + $opening_tag .= ! empty($opening_tag) && ! empty($class) ? ' class="' . $class . '"' : $opening_tag; |
|
| 763 | + $opening_tag .= ! empty($opening_tag) ? '>' : $opening_tag; |
|
| 764 | + $closing_tag = ! empty($container_tag) ? '</' . $container_tag . '>' : ''; |
|
| 765 | + $content = $opening_tag . sprintf($custom_text, '<a href="[PAYMENT_URL]">', '</a>') . $closing_tag; |
|
| 766 | + // we need to re-run this string through the parser to catch any shortcodes that are in it. |
|
| 767 | + $owing_content = $this->_shortcode_helper->parse_message_template( |
|
| 768 | + $content, |
|
| 769 | + $addressee, |
|
| 770 | + $valid_shortcodes, |
|
| 771 | + $this->_message_type, |
|
| 772 | + $this->_messenger, |
|
| 773 | + $this->_message |
|
| 774 | + ); |
|
| 775 | + } else { |
|
| 776 | + return ''; |
|
| 777 | + } |
|
| 778 | + return $owing_content; |
|
| 779 | + } |
|
| 780 | + |
|
| 781 | + |
|
| 782 | + /** |
|
| 783 | + * Parser for the [PAYMENT_DUE_DATE_*] attribute type shortcode |
|
| 784 | + * |
|
| 785 | + * @param string $shortcode The shortcode being parsed. |
|
| 786 | + * @param EE_Transaction $transaction |
|
| 787 | + * @return string |
|
| 788 | + * @throws EE_Error |
|
| 789 | + * @throws ReflectionException |
|
| 790 | + * @since 4.8.28.rc.011 |
|
| 791 | + */ |
|
| 792 | + protected function _get_payment_due_date($shortcode, EE_Transaction $transaction) |
|
| 793 | + { |
|
| 794 | + // if transaction is paid in full then we can just return an empty string |
|
| 795 | + if ($transaction->remaining() == 0) { |
|
| 796 | + return ''; |
|
| 797 | + } |
|
| 798 | + $attrs = $this->_get_shortcode_attrs($shortcode); |
|
| 799 | + $format = $attrs['format'] ?? get_option('date_format'); |
|
| 800 | + $days_until_due = isset($attrs['days_until_due']) ? (int) $attrs['days_until_due'] : 30; |
|
| 801 | + $prefix_text = $attrs['prefix_text'] ?? esc_html__('Payment in full due by: ', 'event_espresso'); |
|
| 802 | + $transaction_created = $transaction->get_DateTime_object('TXN_timestamp'); |
|
| 803 | + // setup date due: |
|
| 804 | + try { |
|
| 805 | + if ($transaction_created instanceof DateTime) { |
|
| 806 | + $date_due = $transaction_created->add( |
|
| 807 | + new DateInterval('P' . $days_until_due . 'D') |
|
| 808 | + )->format($format); |
|
| 809 | + } else { |
|
| 810 | + throw new Exception(); |
|
| 811 | + } |
|
| 812 | + } catch (Exception $e) { |
|
| 813 | + // format was likely invalid. |
|
| 814 | + $date_due = esc_html__( |
|
| 815 | + 'Unable to calculate date due, likely the format string is invalid.', |
|
| 816 | + 'event_espresso' |
|
| 817 | + ); |
|
| 818 | + } |
|
| 819 | + return $prefix_text . $date_due; |
|
| 820 | + } |
|
| 821 | 821 | } |
@@ -261,7 +261,7 @@ discard block |
||
| 261 | 261 | && $this->_extra_data['data'] instanceof EE_Messages_Addressee |
| 262 | 262 | ? $this->_extra_data['data']->txn |
| 263 | 263 | : $transaction; |
| 264 | - if (! $transaction instanceof EE_Transaction) { |
|
| 264 | + if ( ! $transaction instanceof EE_Transaction) { |
|
| 265 | 265 | return ''; |
| 266 | 266 | } |
| 267 | 267 | // payment |
@@ -292,7 +292,7 @@ discard block |
||
| 292 | 292 | $invoice_url = empty($invoice_url) ? 'http://dummyinvoicelinksforpreview.com' : $invoice_url; |
| 293 | 293 | return sprintf( |
| 294 | 294 | esc_html__('%sClick here for Invoice%s', 'event_espresso'), |
| 295 | - '<a href="' . $invoice_url . '">', |
|
| 295 | + '<a href="'.$invoice_url.'">', |
|
| 296 | 296 | '</a>' |
| 297 | 297 | ); |
| 298 | 298 | |
@@ -368,7 +368,7 @@ discard block |
||
| 368 | 368 | return $this->_data->total_ticket_count; |
| 369 | 369 | |
| 370 | 370 | case '[TRANSACTION_ADMIN_URL]': |
| 371 | - require_once EE_CORE . 'admin/EE_Admin_Page.core.php'; |
|
| 371 | + require_once EE_CORE.'admin/EE_Admin_Page.core.php'; |
|
| 372 | 372 | $query_args = [ |
| 373 | 373 | 'page' => 'espresso_transactions', |
| 374 | 374 | 'action' => 'view_transaction', |
@@ -379,7 +379,7 @@ discard block |
||
| 379 | 379 | case strpos($shortcode, '[RECEIPT_URL') !== false : |
| 380 | 380 | // get primary_registration |
| 381 | 381 | $reg = $this->_data->primary_reg_obj; |
| 382 | - if (! $reg instanceof EE_Registration) { |
|
| 382 | + if ( ! $reg instanceof EE_Registration) { |
|
| 383 | 383 | return ''; |
| 384 | 384 | } |
| 385 | 385 | // any attributes? |
@@ -503,7 +503,7 @@ discard block |
||
| 503 | 503 | if (empty($invoice_logo_url)) { |
| 504 | 504 | return ''; |
| 505 | 505 | } |
| 506 | - if (! $img_tags) { |
|
| 506 | + if ( ! $img_tags) { |
|
| 507 | 507 | return $invoice_logo_url; |
| 508 | 508 | } |
| 509 | 509 | $invoice_logo_url = esc_url_raw($invoice_logo_url); |
@@ -516,7 +516,7 @@ discard block |
||
| 516 | 516 | $image_width = esc_attr($image_width); |
| 517 | 517 | $image_width_attr = " width='$image_width'"; |
| 518 | 518 | } |
| 519 | - return '<img class="logo screen" src="' . $invoice_logo_url . '"' . $image_width_attr . ' alt="logo" />'; |
|
| 519 | + return '<img class="logo screen" src="'.$invoice_logo_url.'"'.$image_width_attr.' alt="logo" />'; |
|
| 520 | 520 | } |
| 521 | 521 | |
| 522 | 522 | |
@@ -553,7 +553,7 @@ discard block |
||
| 553 | 553 | */ |
| 554 | 554 | private function _get_invoice_payment_method() |
| 555 | 555 | { |
| 556 | - if (! $this->_invoice_pm instanceof EE_Payment_Method) { |
|
| 556 | + if ( ! $this->_invoice_pm instanceof EE_Payment_Method) { |
|
| 557 | 557 | $transaction = $this->_data->txn instanceof EE_Transaction ? $this->_data->txn : null; |
| 558 | 558 | $transaction = ! $transaction instanceof EE_Transaction |
| 559 | 559 | && is_array($this->_extra_data) |
@@ -623,7 +623,7 @@ discard block |
||
| 623 | 623 | $attrs = $this->_get_shortcode_attrs($shortcode); |
| 624 | 624 | // prefix? |
| 625 | 625 | $prefix = $attrs['prefix'] ?? esc_html__('VAT/Tax Number: ', 'event_espresso'); |
| 626 | - return $prefix . $payee_tax_number; |
|
| 626 | + return $prefix.$payee_tax_number; |
|
| 627 | 627 | } |
| 628 | 628 | |
| 629 | 629 | |
@@ -647,16 +647,16 @@ discard block |
||
| 647 | 647 | } |
| 648 | 648 | if (empty($payee_address)) { |
| 649 | 649 | $organization = EE_Registry::instance()->CFG->organization; |
| 650 | - $payee_address = $organization->get_pretty('address_1') . '<br>'; |
|
| 650 | + $payee_address = $organization->get_pretty('address_1').'<br>'; |
|
| 651 | 651 | $payee_address .= ! empty($organization->address_2) |
| 652 | - ? $organization->get_pretty('address_2') . '<br>' |
|
| 652 | + ? $organization->get_pretty('address_2').'<br>' |
|
| 653 | 653 | : ''; |
| 654 | - $payee_address .= $organization->get_pretty('city') . '<br>'; |
|
| 654 | + $payee_address .= $organization->get_pretty('city').'<br>'; |
|
| 655 | 655 | // state |
| 656 | - $state = EE_Registry::instance()->load_model('State')->get_one_by_ID($organization->STA_ID); |
|
| 656 | + $state = EE_Registry::instance()->load_model('State')->get_one_by_ID($organization->STA_ID); |
|
| 657 | 657 | $payee_address .= $state instanceof EE_State ? $state->name() : ''; |
| 658 | 658 | // Country |
| 659 | - $payee_address .= ! empty($organization->CNT_ISO) ? ', ' . $organization->CNT_ISO . '<br>' : ''; |
|
| 659 | + $payee_address .= ! empty($organization->CNT_ISO) ? ', '.$organization->CNT_ISO.'<br>' : ''; |
|
| 660 | 660 | $payee_address .= ! empty($organization->zip) ? $organization->zip : ''; |
| 661 | 661 | } |
| 662 | 662 | return $payee_address; |
@@ -693,7 +693,7 @@ discard block |
||
| 693 | 693 | { |
| 694 | 694 | $reg = $this->_data->primary_reg_obj; |
| 695 | 695 | $message_type = $this->_extra_data['message_type'] ?? ''; |
| 696 | - if (! $reg instanceof EE_Registration || empty($message_type)) { |
|
| 696 | + if ( ! $reg instanceof EE_Registration || empty($message_type)) { |
|
| 697 | 697 | return ''; |
| 698 | 698 | } |
| 699 | 699 | $switch_to_invoice = ! $message_type instanceof EE_Invoice_message_type; |
@@ -703,13 +703,13 @@ discard block |
||
| 703 | 703 | $switch_to_label = |
| 704 | 704 | ! $switch_to_invoice ? esc_html__('Switch to Receipt', 'event_espresso') : $switch_to_label; |
| 705 | 705 | $switch_to_url = $switch_to_invoice ? $reg->invoice_url() : $reg->receipt_url(); |
| 706 | - if (! $button) { |
|
| 706 | + if ( ! $button) { |
|
| 707 | 707 | return $switch_to_url; |
| 708 | 708 | } |
| 709 | - if (! empty($switch_to_url)) { |
|
| 709 | + if ( ! empty($switch_to_url)) { |
|
| 710 | 710 | return ' |
| 711 | - <form method="post" action="' . $switch_to_url . '" > |
|
| 712 | - <input class="print_button" type="submit" value="' . $switch_to_label . '" /> |
|
| 711 | + <form method="post" action="' . $switch_to_url.'" > |
|
| 712 | + <input class="print_button" type="submit" value="' . $switch_to_label.'" /> |
|
| 713 | 713 | </form> |
| 714 | 714 | '; |
| 715 | 715 | } |
@@ -728,7 +728,7 @@ discard block |
||
| 728 | 728 | private function _get_subtotal($tax = false) |
| 729 | 729 | { |
| 730 | 730 | $grand_total = $this->_data->grand_total_line_item ?? null; |
| 731 | - if (! $grand_total instanceof EE_Line_Item) { |
|
| 731 | + if ( ! $grand_total instanceof EE_Line_Item) { |
|
| 732 | 732 | return 0; |
| 733 | 733 | } |
| 734 | 734 | return $tax ? $grand_total->get_total_tax() : $grand_total->get_items_total(); |
@@ -758,11 +758,11 @@ discard block |
||
| 758 | 758 | $custom_text = |
| 759 | 759 | $attrs['custom_text'] ?? 'You can %smake a payment here »%s.'; |
| 760 | 760 | $container_tag = $attrs['container_tag'] ?? 'p'; |
| 761 | - $opening_tag = ! empty($container_tag) ? '<' . $container_tag : ''; |
|
| 762 | - $opening_tag .= ! empty($opening_tag) && ! empty($class) ? ' class="' . $class . '"' : $opening_tag; |
|
| 761 | + $opening_tag = ! empty($container_tag) ? '<'.$container_tag : ''; |
|
| 762 | + $opening_tag .= ! empty($opening_tag) && ! empty($class) ? ' class="'.$class.'"' : $opening_tag; |
|
| 763 | 763 | $opening_tag .= ! empty($opening_tag) ? '>' : $opening_tag; |
| 764 | - $closing_tag = ! empty($container_tag) ? '</' . $container_tag . '>' : ''; |
|
| 765 | - $content = $opening_tag . sprintf($custom_text, '<a href="[PAYMENT_URL]">', '</a>') . $closing_tag; |
|
| 764 | + $closing_tag = ! empty($container_tag) ? '</'.$container_tag.'>' : ''; |
|
| 765 | + $content = $opening_tag.sprintf($custom_text, '<a href="[PAYMENT_URL]">', '</a>').$closing_tag; |
|
| 766 | 766 | // we need to re-run this string through the parser to catch any shortcodes that are in it. |
| 767 | 767 | $owing_content = $this->_shortcode_helper->parse_message_template( |
| 768 | 768 | $content, |
@@ -804,7 +804,7 @@ discard block |
||
| 804 | 804 | try { |
| 805 | 805 | if ($transaction_created instanceof DateTime) { |
| 806 | 806 | $date_due = $transaction_created->add( |
| 807 | - new DateInterval('P' . $days_until_due . 'D') |
|
| 807 | + new DateInterval('P'.$days_until_due.'D') |
|
| 808 | 808 | )->format($format); |
| 809 | 809 | } else { |
| 810 | 810 | throw new Exception(); |
@@ -816,6 +816,6 @@ discard block |
||
| 816 | 816 | 'event_espresso' |
| 817 | 817 | ); |
| 818 | 818 | } |
| 819 | - return $prefix_text . $date_due; |
|
| 819 | + return $prefix_text.$date_due; |
|
| 820 | 820 | } |
| 821 | 821 | } |
@@ -15,482 +15,482 @@ |
||
| 15 | 15 | */ |
| 16 | 16 | abstract class EE_Shortcodes extends EE_Base |
| 17 | 17 | { |
| 18 | - /** |
|
| 19 | - * matches a full shortcode including shortcodes with attributes or dynamic shortcodes |
|
| 20 | - * examples: |
|
| 21 | - * [RECIPIENT_LNAME] |
|
| 22 | - * [RECEIPT_URL download=true] |
|
| 23 | - * [PAYMENT_LINK_IF_NEEDED_* custom_text='pay me now man!'] |
|
| 24 | - */ |
|
| 25 | - public const REGEX_SHORTCODE_FULL = '/(\[.+?])/'; |
|
| 26 | - |
|
| 27 | - /** |
|
| 28 | - * matches the opening [ plus the shortcode name, but nothing else |
|
| 29 | - * examples: |
|
| 30 | - * [RECIPIENT_LNAME] matches as [RECIPIENT_LNAME |
|
| 31 | - * [RECEIPT_URL download=true] matches as [RECEIPT_URL |
|
| 32 | - * [PAYMENT_LINK_IF_NEEDED_* custom_text='pay me now man!'] matches as [PAYMENT_LINK_IF_NEEDED_* |
|
| 33 | - */ |
|
| 34 | - public const REGEX_SHORTCODE_NAME_ONLY = '/\[[A-Z_*]+/'; |
|
| 35 | - |
|
| 36 | - /** |
|
| 37 | - * matches the opening [ plus the dynamic shortcode name including _*, but nothing else |
|
| 38 | - * examples: |
|
| 39 | - * [RECIPIENT_LNAME] does not match |
|
| 40 | - * [RECEIPT_URL download=true] does not match |
|
| 41 | - * [PAYMENT_LINK_IF_NEEDED_* custom_text='pay me now man!'] matches as [PAYMENT_LINK_IF_NEEDED_* |
|
| 42 | - */ |
|
| 43 | - public const REGEX_SHORTCODE_DYNAMIC = '/(\[[A-Z_]+_\*)/'; |
|
| 44 | - |
|
| 45 | - |
|
| 46 | - |
|
| 47 | - /** |
|
| 48 | - * holds label for library |
|
| 49 | - * This is used for referencing the library label |
|
| 50 | - * |
|
| 51 | - * @var string |
|
| 52 | - */ |
|
| 53 | - public string $label; |
|
| 54 | - |
|
| 55 | - |
|
| 56 | - public string $name; |
|
| 57 | - |
|
| 58 | - |
|
| 59 | - /** |
|
| 60 | - * This property is used for referencing a short description of the library |
|
| 61 | - * |
|
| 62 | - * @var string |
|
| 63 | - */ |
|
| 64 | - public string $description; |
|
| 65 | - |
|
| 66 | - |
|
| 67 | - /** |
|
| 68 | - * This will hold an array of shortcodes with the key as the shortcode ([shortcode]) and the value as a |
|
| 69 | - * label/description for the shortcode. |
|
| 70 | - * |
|
| 71 | - * @var array |
|
| 72 | - */ |
|
| 73 | - protected array $_shortcodes = []; |
|
| 74 | - |
|
| 75 | - |
|
| 76 | - /** |
|
| 77 | - * This will hold the incoming data item sent to the parser method |
|
| 78 | - * |
|
| 79 | - * @var array|object |
|
| 80 | - */ |
|
| 81 | - protected $_data; |
|
| 82 | - |
|
| 83 | - |
|
| 84 | - /** |
|
| 85 | - * some shortcodes may require extra data to parse. This property is provided for that. |
|
| 86 | - * |
|
| 87 | - * @var array|EE_Messages_Addressee |
|
| 88 | - */ |
|
| 89 | - protected $_extra_data; |
|
| 90 | - |
|
| 91 | - |
|
| 92 | - /** |
|
| 93 | - * EE_messenger used to generate the template being parsed. |
|
| 94 | - * |
|
| 95 | - * @since 4.5.0 |
|
| 96 | - * @var EE_messenger |
|
| 97 | - */ |
|
| 98 | - protected EE_messenger $_messenger; |
|
| 99 | - |
|
| 100 | - |
|
| 101 | - /** |
|
| 102 | - * message type used to generate the template being parsed. |
|
| 103 | - * |
|
| 104 | - * @since 4.5.0 |
|
| 105 | - * @var EE_message_type|null |
|
| 106 | - */ |
|
| 107 | - protected ?EE_message_type $_message_type = null; |
|
| 108 | - |
|
| 109 | - |
|
| 110 | - /** |
|
| 111 | - * context used for the template being parsed |
|
| 112 | - * |
|
| 113 | - * @since 4.5.0 |
|
| 114 | - * @var string |
|
| 115 | - */ |
|
| 116 | - protected string $_context; |
|
| 117 | - |
|
| 118 | - |
|
| 119 | - /** |
|
| 120 | - * Specific Message Template Group ID |
|
| 121 | - * |
|
| 122 | - * @since 4.5.0 |
|
| 123 | - * @var int |
|
| 124 | - */ |
|
| 125 | - protected int $_GRP_ID; |
|
| 126 | - |
|
| 127 | - |
|
| 128 | - /** |
|
| 129 | - * @since 4.9.0 |
|
| 130 | - * @type EE_Message|null |
|
| 131 | - */ |
|
| 132 | - protected ?EE_Message $_message = null; |
|
| 133 | - |
|
| 134 | - |
|
| 135 | - /** |
|
| 136 | - * This will hold an instance of the EEH_Parse_Shortcodes helper that will be used when handling list type |
|
| 137 | - * shortcodes |
|
| 138 | - * |
|
| 139 | - * @var EEH_Parse_Shortcodes |
|
| 140 | - */ |
|
| 141 | - protected EEH_Parse_Shortcodes $_shortcode_helper; |
|
| 142 | - |
|
| 143 | - |
|
| 144 | - public function __construct() |
|
| 145 | - { |
|
| 146 | - $this->_set_defaults(); |
|
| 147 | - $this->_set_shortcode_helper(); |
|
| 148 | - $this->_init_props(); |
|
| 149 | - } |
|
| 150 | - |
|
| 151 | - |
|
| 152 | - /** |
|
| 153 | - * This sets the defaults for the properties. Child classes will override these properties in their _init_props |
|
| 154 | - * method |
|
| 155 | - */ |
|
| 156 | - private function _set_defaults() |
|
| 157 | - { |
|
| 158 | - $this->name = $this->description = ''; |
|
| 159 | - $this->_shortcodes = []; |
|
| 160 | - } |
|
| 161 | - |
|
| 162 | - |
|
| 163 | - /** |
|
| 164 | - * loads an instance of the EE_Shortcode_Parser helper when requested |
|
| 165 | - */ |
|
| 166 | - protected function _set_shortcode_helper() |
|
| 167 | - { |
|
| 168 | - // get shortcode_replace instance - set when _get_messages is called in child... |
|
| 169 | - $this->_shortcode_helper = new EEH_Parse_Shortcodes(); |
|
| 170 | - } |
|
| 171 | - |
|
| 172 | - |
|
| 173 | - public function get_shortcode_helper(): EEH_Parse_Shortcodes |
|
| 174 | - { |
|
| 175 | - return $this->_shortcode_helper; |
|
| 176 | - } |
|
| 177 | - |
|
| 178 | - |
|
| 179 | - /** |
|
| 180 | - * This is the public method for kicking of the parser included with each child. It can be overridden by child |
|
| 181 | - * classes if necessary (see EE_Questions_Answers for example) |
|
| 182 | - * |
|
| 183 | - * @param string $shortcode incoming shortcode to be parsed |
|
| 184 | - * @param object|array $data incoming data to be used for parsing |
|
| 185 | - * @param object|array $extra_data extra incoming data (usually EE_Messages_Addressee) |
|
| 186 | - * @return string parsed shortcode. |
|
| 187 | - */ |
|
| 188 | - public function parser(string $shortcode, $data, $extra_data = []): string |
|
| 189 | - { |
|
| 190 | - // filter setup shortcodes |
|
| 191 | - $this->_shortcodes = $this->get_shortcodes(); |
|
| 192 | - |
|
| 193 | - // we need to set up any dynamic shortcodes so that they work with the array_key_exists |
|
| 194 | - preg_match_all(EE_Shortcodes::REGEX_SHORTCODE_NAME_ONLY, $shortcode, $matches); |
|
| 195 | - $shortcode_to_verify = ! empty($matches[0]) ? $matches[0][0] . ']' : $shortcode; |
|
| 196 | - |
|
| 197 | - // first we want to make sure this is a valid shortcode |
|
| 198 | - if (! array_key_exists($shortcode_to_verify, $this->_shortcodes)) { |
|
| 199 | - // get out, this parser doesn't handle the incoming shortcode. |
|
| 200 | - return ''; |
|
| 201 | - } |
|
| 202 | - $this->_data = $data; |
|
| 203 | - $this->_extra_data = $extra_data; |
|
| 204 | - $this->_set_messages_properties(); |
|
| 205 | - $parsed = (string) apply_filters( |
|
| 206 | - 'FHEE__' . get_class($this) . '__parser_after', |
|
| 207 | - $this->_parser($shortcode), |
|
| 208 | - $shortcode, |
|
| 209 | - $data, |
|
| 210 | - $extra_data, |
|
| 211 | - $this |
|
| 212 | - ); |
|
| 213 | - |
|
| 214 | - // note the below filter applies to ALL shortcode parsers... be careful! |
|
| 215 | - return (string) apply_filters( |
|
| 216 | - 'FHEE__EE_Shortcodes__parser_after', |
|
| 217 | - $parsed, |
|
| 218 | - $shortcode, |
|
| 219 | - $data, |
|
| 220 | - $extra_data, |
|
| 221 | - $this |
|
| 222 | - ); |
|
| 223 | - } |
|
| 224 | - |
|
| 225 | - |
|
| 226 | - /** |
|
| 227 | - * This method just returns the shortcodes in the $_shortcodes array property. |
|
| 228 | - * |
|
| 229 | - * @return array array of shortcodes => description pairs |
|
| 230 | - */ |
|
| 231 | - public function get_shortcodes(): array |
|
| 232 | - { |
|
| 233 | - $this->_shortcodes = (array) apply_filters( |
|
| 234 | - 'FHEE__' . get_class($this) . '__shortcodes', |
|
| 235 | - $this->_shortcodes, |
|
| 236 | - $this |
|
| 237 | - ); |
|
| 238 | - |
|
| 239 | - // note the below filter applies to ALL shortcode parsers... be careful! |
|
| 240 | - return (array) apply_filters('FHEE__EE_Shortcodes__shortcodes', $this->_shortcodes, $this); |
|
| 241 | - } |
|
| 242 | - |
|
| 243 | - |
|
| 244 | - /** |
|
| 245 | - * Child classes use this method to set the $name, $description, and $_shortcodes properties. |
|
| 246 | - * |
|
| 247 | - * @abstract |
|
| 248 | - * @return void |
|
| 249 | - */ |
|
| 250 | - abstract protected function _init_props(); |
|
| 251 | - |
|
| 252 | - |
|
| 253 | - /** |
|
| 254 | - * This method will give parsing instructions for each shortcode defined in the _shortcodes array. Child methods |
|
| 255 | - * will have to take care of handling. |
|
| 256 | - * |
|
| 257 | - * @abstract |
|
| 258 | - * @param string $shortcode the shortcode to be parsed. |
|
| 259 | - * @return string parsed shortcode |
|
| 260 | - */ |
|
| 261 | - abstract protected function _parser($shortcode); |
|
| 262 | - |
|
| 263 | - |
|
| 264 | - /** |
|
| 265 | - * This just validates incoming data for list type shortcode parsers (and they call this method) to make sure it |
|
| 266 | - * meets their requirements |
|
| 267 | - * |
|
| 268 | - * @return void If validation fails we'll throw an exception. |
|
| 269 | - * @throws EE_Error |
|
| 270 | - */ |
|
| 271 | - protected function _validate_list_requirements() |
|
| 272 | - { |
|
| 273 | - // first test to make sure we've got an array! |
|
| 274 | - if (! is_array($this->_data)) { |
|
| 275 | - throw new EE_Error( |
|
| 276 | - sprintf( |
|
| 277 | - esc_html__( |
|
| 278 | - 'Expecting an array for the data sent to %s. Instead it was %s', |
|
| 279 | - 'event_espresso' |
|
| 280 | - ), |
|
| 281 | - get_class($this), |
|
| 282 | - gettype($this->_data) |
|
| 283 | - ) |
|
| 284 | - ); |
|
| 285 | - } |
|
| 286 | - |
|
| 287 | - // next test to make sure we've got the required template in the index! |
|
| 288 | - if (! isset($this->_data['template'])) { |
|
| 289 | - throw new EE_Error( |
|
| 290 | - esc_html__( |
|
| 291 | - 'The incoming data does not have the required template index in its array', |
|
| 292 | - 'event_espresso' |
|
| 293 | - ) |
|
| 294 | - ); |
|
| 295 | - } |
|
| 296 | - |
|
| 297 | - // next test to make sure we've got a data index in the incoming data array |
|
| 298 | - if (! isset($this->_data['data'])) { |
|
| 299 | - throw new EE_Error( |
|
| 300 | - esc_html__( |
|
| 301 | - 'The incoming data does not have the required data index in its array', |
|
| 302 | - 'event_espresso' |
|
| 303 | - ) |
|
| 304 | - ); |
|
| 305 | - } |
|
| 306 | - |
|
| 307 | - // all is well let's make sure _extra_data always has the values needed. |
|
| 308 | - // let's make sure that extra_data includes all templates (for later parsing if necessary) |
|
| 309 | - if (empty($this->_extra_data) || (empty($this->_extra_data['data']) && empty($this->_extra_data['template']))) { |
|
| 310 | - $this->_extra_data['data'] = $this->_data['data']; |
|
| 311 | - $this->_extra_data['template'] = $this->_data['template']; |
|
| 312 | - } |
|
| 313 | - } |
|
| 314 | - |
|
| 315 | - |
|
| 316 | - /** |
|
| 317 | - * This returns any attributes that may be existing on an EE_Shortcode |
|
| 318 | - * |
|
| 319 | - * @param string $shortcode incoming shortcode |
|
| 320 | - * @return array An array with the attributes |
|
| 321 | - * @since 4.5.0 |
|
| 322 | - */ |
|
| 323 | - protected function _get_shortcode_attrs(string $shortcode): array |
|
| 324 | - { |
|
| 325 | - // make sure the required wp helper function is present |
|
| 326 | - // require the shortcode file if necessary |
|
| 327 | - if (! function_exists('shortcode_parse_atts')) { |
|
| 328 | - require_once(ABSPATH . WPINC . '/shortcodes.php'); |
|
| 329 | - } |
|
| 330 | - |
|
| 331 | - // let's get any attributes that may be present and set the defaults. |
|
| 332 | - $shortcode_to_parse = str_replace(['[', ']'], '', $shortcode); |
|
| 333 | - return shortcode_parse_atts($shortcode_to_parse); |
|
| 334 | - } |
|
| 335 | - |
|
| 336 | - |
|
| 337 | - /** |
|
| 338 | - * Conditional blocks are shortcode patterns with an opening conditional tag `[IF_*]` and a corresponding |
|
| 339 | - * closing tag (eg `[/IF_*]`). The content within the tags will be displayed/hidden depending on whatever |
|
| 340 | - * conditions existed in the opening tag. This method handles parsing the actual template to show/hide this |
|
| 341 | - * conditional content. |
|
| 342 | - * |
|
| 343 | - * @param string $shortcode This should be the original shortcode as used in the template and passed to the parser. |
|
| 344 | - * @param bool $show true means the opening and closing tags are removed and the content is left showing, |
|
| 345 | - * false means the opening and closing tags and the contained content are removed. |
|
| 346 | - * @return string The template for the shortcode is returned. |
|
| 347 | - * @since 4.9.32 |
|
| 348 | - * |
|
| 349 | - */ |
|
| 350 | - protected function _mutate_conditional_block_in_template(string $shortcode, bool $show = true): string |
|
| 351 | - { |
|
| 352 | - // first let's get all the matches in the template for this particular shortcode. |
|
| 353 | - preg_match_all('~' . $this->_get_conditional_block_regex($shortcode) . '~', $this->_data['template'], $matches); |
|
| 354 | - |
|
| 355 | - if ($matches && is_array($matches[0]) && ! empty($matches[0])) { |
|
| 356 | - // we need to hide all instances of the matches |
|
| 357 | - foreach ($matches[0] as $index => $content_to_show_or_hide) { |
|
| 358 | - $content_to_show_or_hide = preg_quote($content_to_show_or_hide); |
|
| 359 | - $replacement = $show ? $matches[4][ $index ] : ''; |
|
| 360 | - $this->_data['template'] = preg_replace( |
|
| 361 | - '~' . $content_to_show_or_hide . '~', |
|
| 362 | - $replacement, |
|
| 363 | - $this->_data['template'] |
|
| 364 | - ); |
|
| 365 | - } |
|
| 366 | - } |
|
| 367 | - // return $template |
|
| 368 | - return $this->_data['template']; |
|
| 369 | - } |
|
| 370 | - |
|
| 371 | - |
|
| 372 | - /** |
|
| 373 | - * This returns the regex pattern to use for conditional shortcodes parsing. |
|
| 374 | - * |
|
| 375 | - * Note: regex comes in part from the WP `get_shortcode_regex` expression in \wp-includes\shortcodes.php |
|
| 376 | - * |
|
| 377 | - * @param string $shortcode |
|
| 378 | - * @return string |
|
| 379 | - * @since 4.9.32 |
|
| 380 | - */ |
|
| 381 | - private function _get_conditional_block_regex(string $shortcode): string |
|
| 382 | - { |
|
| 383 | - // get just the shortcode tag for the match |
|
| 384 | - preg_match('@\[([^<>&/\[\]\x00-\x20=]++)@', $shortcode, $shortcode_tag_matches); |
|
| 385 | - if (empty($shortcode_tag_matches[1])) { |
|
| 386 | - return $this->_data['template']; |
|
| 387 | - } |
|
| 388 | - |
|
| 389 | - $shortcode_tag = $shortcode_tag_matches[1]; |
|
| 390 | - // get attributes_part_of_tag |
|
| 391 | - $attributes_part = preg_quote(str_replace([$shortcode_tag, '[', ']'], '', $shortcode)); |
|
| 392 | - // escape |
|
| 393 | - $shortcode_tag = preg_quote($shortcode_tag); |
|
| 394 | - |
|
| 395 | - return |
|
| 396 | - '\[' // Opening Bracket |
|
| 397 | - . "($shortcode_tag)$attributes_part" // 1: Shortcode Name |
|
| 398 | - . '(?![\w-])' // Not followed by word character or hyphen |
|
| 399 | - . '(' // 2: Unroll the loop: Inside the opening shortcode tag |
|
| 400 | - . '[^\]\/]*' // Not a closing bracket or forward slash |
|
| 401 | - . '(?:' |
|
| 402 | - . '\/(?!\])' // A forward slash not followed by a closing bracket |
|
| 403 | - . '[^\]\/]*' // Not a closing bracket or forward slash. |
|
| 404 | - . ')*?' |
|
| 405 | - . ')' |
|
| 406 | - . '(?:' |
|
| 407 | - . '(\/)' // 3. Self closing tag ... |
|
| 408 | - . '\]' // ... and closing bracket |
|
| 409 | - . '|' |
|
| 410 | - . '\]' // Closing bracket |
|
| 411 | - . '(?:' |
|
| 412 | - . '(' // 4: Unroll the loop: Optionally, anything between the opening and closing brackets |
|
| 413 | - . '[^\[]*+' // Not an opening bracket |
|
| 414 | - . '(?:' |
|
| 415 | - . '\[(?!\/\1\])' // An opening bracket not followed by the closing shortcode tag. |
|
| 416 | - . '[^\[]*+' // Not an opening bracket |
|
| 417 | - . ')*+' |
|
| 418 | - . ')' |
|
| 419 | - . '\[\/\1\]' // Closing shortcode tag |
|
| 420 | - . ')?' |
|
| 421 | - . ')'; |
|
| 422 | - } |
|
| 423 | - |
|
| 424 | - |
|
| 425 | - /** |
|
| 426 | - * This sets the properties related to the messages system |
|
| 427 | - * |
|
| 428 | - * @return void |
|
| 429 | - * @since 4.5.0 |
|
| 430 | - */ |
|
| 431 | - protected function _set_messages_properties() |
|
| 432 | - { |
|
| 433 | - // should be in _extra_data |
|
| 434 | - if (isset($this->_extra_data['messenger'])) { |
|
| 435 | - $this->_messenger = $this->_extra_data['messenger']; |
|
| 436 | - $this->_message_type = $this->_extra_data['message_type']; |
|
| 437 | - $this->_context = $this->_extra_data['message'] instanceof EE_Message |
|
| 438 | - ? $this->_extra_data['message']->context() |
|
| 439 | - : ''; |
|
| 440 | - $this->_GRP_ID = $this->_extra_data['message'] instanceof EE_Message |
|
| 441 | - ? $this->_extra_data['message']->GRP_ID() |
|
| 442 | - : 0; |
|
| 443 | - $this->_message = $this->_extra_data['message'] instanceof EE_Message |
|
| 444 | - ? $this->_extra_data['message'] |
|
| 445 | - : null; |
|
| 446 | - } |
|
| 447 | - } |
|
| 448 | - |
|
| 449 | - |
|
| 450 | - /** |
|
| 451 | - * This returns whatever the set message type object is that was set on this shortcode parser. |
|
| 452 | - * |
|
| 453 | - * @return EE_message_type|null |
|
| 454 | - * @since 4.5.0 |
|
| 455 | - */ |
|
| 456 | - public function get_set_message_type(): ?EE_message_type |
|
| 457 | - { |
|
| 458 | - return $this->_message_type; |
|
| 459 | - } |
|
| 460 | - |
|
| 461 | - |
|
| 462 | - /** |
|
| 463 | - * This returns whatever the set messenger object is that was set on this shortcode parser |
|
| 464 | - * |
|
| 465 | - * @return EE_messenger |
|
| 466 | - * @since 4.5.0 |
|
| 467 | - */ |
|
| 468 | - public function get_set_messenger(): EE_messenger |
|
| 469 | - { |
|
| 470 | - return $this->_messenger; |
|
| 471 | - } |
|
| 472 | - |
|
| 473 | - |
|
| 474 | - /** |
|
| 475 | - * This returns whatever the set context string is on this shortcode parser. |
|
| 476 | - * |
|
| 477 | - * @return string |
|
| 478 | - * @since 4.5.0 |
|
| 479 | - */ |
|
| 480 | - public function get_set_context(): string |
|
| 481 | - { |
|
| 482 | - return $this->_context; |
|
| 483 | - } |
|
| 484 | - |
|
| 485 | - |
|
| 486 | - /** |
|
| 487 | - * This returns whatever the set EE_Message object is on this shortcode. |
|
| 488 | - * |
|
| 489 | - * @return EE_Message|null |
|
| 490 | - * @since 4.9.0 |
|
| 491 | - */ |
|
| 492 | - public function get_set_message(): ?EE_Message |
|
| 493 | - { |
|
| 494 | - return $this->_message; |
|
| 495 | - } |
|
| 18 | + /** |
|
| 19 | + * matches a full shortcode including shortcodes with attributes or dynamic shortcodes |
|
| 20 | + * examples: |
|
| 21 | + * [RECIPIENT_LNAME] |
|
| 22 | + * [RECEIPT_URL download=true] |
|
| 23 | + * [PAYMENT_LINK_IF_NEEDED_* custom_text='pay me now man!'] |
|
| 24 | + */ |
|
| 25 | + public const REGEX_SHORTCODE_FULL = '/(\[.+?])/'; |
|
| 26 | + |
|
| 27 | + /** |
|
| 28 | + * matches the opening [ plus the shortcode name, but nothing else |
|
| 29 | + * examples: |
|
| 30 | + * [RECIPIENT_LNAME] matches as [RECIPIENT_LNAME |
|
| 31 | + * [RECEIPT_URL download=true] matches as [RECEIPT_URL |
|
| 32 | + * [PAYMENT_LINK_IF_NEEDED_* custom_text='pay me now man!'] matches as [PAYMENT_LINK_IF_NEEDED_* |
|
| 33 | + */ |
|
| 34 | + public const REGEX_SHORTCODE_NAME_ONLY = '/\[[A-Z_*]+/'; |
|
| 35 | + |
|
| 36 | + /** |
|
| 37 | + * matches the opening [ plus the dynamic shortcode name including _*, but nothing else |
|
| 38 | + * examples: |
|
| 39 | + * [RECIPIENT_LNAME] does not match |
|
| 40 | + * [RECEIPT_URL download=true] does not match |
|
| 41 | + * [PAYMENT_LINK_IF_NEEDED_* custom_text='pay me now man!'] matches as [PAYMENT_LINK_IF_NEEDED_* |
|
| 42 | + */ |
|
| 43 | + public const REGEX_SHORTCODE_DYNAMIC = '/(\[[A-Z_]+_\*)/'; |
|
| 44 | + |
|
| 45 | + |
|
| 46 | + |
|
| 47 | + /** |
|
| 48 | + * holds label for library |
|
| 49 | + * This is used for referencing the library label |
|
| 50 | + * |
|
| 51 | + * @var string |
|
| 52 | + */ |
|
| 53 | + public string $label; |
|
| 54 | + |
|
| 55 | + |
|
| 56 | + public string $name; |
|
| 57 | + |
|
| 58 | + |
|
| 59 | + /** |
|
| 60 | + * This property is used for referencing a short description of the library |
|
| 61 | + * |
|
| 62 | + * @var string |
|
| 63 | + */ |
|
| 64 | + public string $description; |
|
| 65 | + |
|
| 66 | + |
|
| 67 | + /** |
|
| 68 | + * This will hold an array of shortcodes with the key as the shortcode ([shortcode]) and the value as a |
|
| 69 | + * label/description for the shortcode. |
|
| 70 | + * |
|
| 71 | + * @var array |
|
| 72 | + */ |
|
| 73 | + protected array $_shortcodes = []; |
|
| 74 | + |
|
| 75 | + |
|
| 76 | + /** |
|
| 77 | + * This will hold the incoming data item sent to the parser method |
|
| 78 | + * |
|
| 79 | + * @var array|object |
|
| 80 | + */ |
|
| 81 | + protected $_data; |
|
| 82 | + |
|
| 83 | + |
|
| 84 | + /** |
|
| 85 | + * some shortcodes may require extra data to parse. This property is provided for that. |
|
| 86 | + * |
|
| 87 | + * @var array|EE_Messages_Addressee |
|
| 88 | + */ |
|
| 89 | + protected $_extra_data; |
|
| 90 | + |
|
| 91 | + |
|
| 92 | + /** |
|
| 93 | + * EE_messenger used to generate the template being parsed. |
|
| 94 | + * |
|
| 95 | + * @since 4.5.0 |
|
| 96 | + * @var EE_messenger |
|
| 97 | + */ |
|
| 98 | + protected EE_messenger $_messenger; |
|
| 99 | + |
|
| 100 | + |
|
| 101 | + /** |
|
| 102 | + * message type used to generate the template being parsed. |
|
| 103 | + * |
|
| 104 | + * @since 4.5.0 |
|
| 105 | + * @var EE_message_type|null |
|
| 106 | + */ |
|
| 107 | + protected ?EE_message_type $_message_type = null; |
|
| 108 | + |
|
| 109 | + |
|
| 110 | + /** |
|
| 111 | + * context used for the template being parsed |
|
| 112 | + * |
|
| 113 | + * @since 4.5.0 |
|
| 114 | + * @var string |
|
| 115 | + */ |
|
| 116 | + protected string $_context; |
|
| 117 | + |
|
| 118 | + |
|
| 119 | + /** |
|
| 120 | + * Specific Message Template Group ID |
|
| 121 | + * |
|
| 122 | + * @since 4.5.0 |
|
| 123 | + * @var int |
|
| 124 | + */ |
|
| 125 | + protected int $_GRP_ID; |
|
| 126 | + |
|
| 127 | + |
|
| 128 | + /** |
|
| 129 | + * @since 4.9.0 |
|
| 130 | + * @type EE_Message|null |
|
| 131 | + */ |
|
| 132 | + protected ?EE_Message $_message = null; |
|
| 133 | + |
|
| 134 | + |
|
| 135 | + /** |
|
| 136 | + * This will hold an instance of the EEH_Parse_Shortcodes helper that will be used when handling list type |
|
| 137 | + * shortcodes |
|
| 138 | + * |
|
| 139 | + * @var EEH_Parse_Shortcodes |
|
| 140 | + */ |
|
| 141 | + protected EEH_Parse_Shortcodes $_shortcode_helper; |
|
| 142 | + |
|
| 143 | + |
|
| 144 | + public function __construct() |
|
| 145 | + { |
|
| 146 | + $this->_set_defaults(); |
|
| 147 | + $this->_set_shortcode_helper(); |
|
| 148 | + $this->_init_props(); |
|
| 149 | + } |
|
| 150 | + |
|
| 151 | + |
|
| 152 | + /** |
|
| 153 | + * This sets the defaults for the properties. Child classes will override these properties in their _init_props |
|
| 154 | + * method |
|
| 155 | + */ |
|
| 156 | + private function _set_defaults() |
|
| 157 | + { |
|
| 158 | + $this->name = $this->description = ''; |
|
| 159 | + $this->_shortcodes = []; |
|
| 160 | + } |
|
| 161 | + |
|
| 162 | + |
|
| 163 | + /** |
|
| 164 | + * loads an instance of the EE_Shortcode_Parser helper when requested |
|
| 165 | + */ |
|
| 166 | + protected function _set_shortcode_helper() |
|
| 167 | + { |
|
| 168 | + // get shortcode_replace instance - set when _get_messages is called in child... |
|
| 169 | + $this->_shortcode_helper = new EEH_Parse_Shortcodes(); |
|
| 170 | + } |
|
| 171 | + |
|
| 172 | + |
|
| 173 | + public function get_shortcode_helper(): EEH_Parse_Shortcodes |
|
| 174 | + { |
|
| 175 | + return $this->_shortcode_helper; |
|
| 176 | + } |
|
| 177 | + |
|
| 178 | + |
|
| 179 | + /** |
|
| 180 | + * This is the public method for kicking of the parser included with each child. It can be overridden by child |
|
| 181 | + * classes if necessary (see EE_Questions_Answers for example) |
|
| 182 | + * |
|
| 183 | + * @param string $shortcode incoming shortcode to be parsed |
|
| 184 | + * @param object|array $data incoming data to be used for parsing |
|
| 185 | + * @param object|array $extra_data extra incoming data (usually EE_Messages_Addressee) |
|
| 186 | + * @return string parsed shortcode. |
|
| 187 | + */ |
|
| 188 | + public function parser(string $shortcode, $data, $extra_data = []): string |
|
| 189 | + { |
|
| 190 | + // filter setup shortcodes |
|
| 191 | + $this->_shortcodes = $this->get_shortcodes(); |
|
| 192 | + |
|
| 193 | + // we need to set up any dynamic shortcodes so that they work with the array_key_exists |
|
| 194 | + preg_match_all(EE_Shortcodes::REGEX_SHORTCODE_NAME_ONLY, $shortcode, $matches); |
|
| 195 | + $shortcode_to_verify = ! empty($matches[0]) ? $matches[0][0] . ']' : $shortcode; |
|
| 196 | + |
|
| 197 | + // first we want to make sure this is a valid shortcode |
|
| 198 | + if (! array_key_exists($shortcode_to_verify, $this->_shortcodes)) { |
|
| 199 | + // get out, this parser doesn't handle the incoming shortcode. |
|
| 200 | + return ''; |
|
| 201 | + } |
|
| 202 | + $this->_data = $data; |
|
| 203 | + $this->_extra_data = $extra_data; |
|
| 204 | + $this->_set_messages_properties(); |
|
| 205 | + $parsed = (string) apply_filters( |
|
| 206 | + 'FHEE__' . get_class($this) . '__parser_after', |
|
| 207 | + $this->_parser($shortcode), |
|
| 208 | + $shortcode, |
|
| 209 | + $data, |
|
| 210 | + $extra_data, |
|
| 211 | + $this |
|
| 212 | + ); |
|
| 213 | + |
|
| 214 | + // note the below filter applies to ALL shortcode parsers... be careful! |
|
| 215 | + return (string) apply_filters( |
|
| 216 | + 'FHEE__EE_Shortcodes__parser_after', |
|
| 217 | + $parsed, |
|
| 218 | + $shortcode, |
|
| 219 | + $data, |
|
| 220 | + $extra_data, |
|
| 221 | + $this |
|
| 222 | + ); |
|
| 223 | + } |
|
| 224 | + |
|
| 225 | + |
|
| 226 | + /** |
|
| 227 | + * This method just returns the shortcodes in the $_shortcodes array property. |
|
| 228 | + * |
|
| 229 | + * @return array array of shortcodes => description pairs |
|
| 230 | + */ |
|
| 231 | + public function get_shortcodes(): array |
|
| 232 | + { |
|
| 233 | + $this->_shortcodes = (array) apply_filters( |
|
| 234 | + 'FHEE__' . get_class($this) . '__shortcodes', |
|
| 235 | + $this->_shortcodes, |
|
| 236 | + $this |
|
| 237 | + ); |
|
| 238 | + |
|
| 239 | + // note the below filter applies to ALL shortcode parsers... be careful! |
|
| 240 | + return (array) apply_filters('FHEE__EE_Shortcodes__shortcodes', $this->_shortcodes, $this); |
|
| 241 | + } |
|
| 242 | + |
|
| 243 | + |
|
| 244 | + /** |
|
| 245 | + * Child classes use this method to set the $name, $description, and $_shortcodes properties. |
|
| 246 | + * |
|
| 247 | + * @abstract |
|
| 248 | + * @return void |
|
| 249 | + */ |
|
| 250 | + abstract protected function _init_props(); |
|
| 251 | + |
|
| 252 | + |
|
| 253 | + /** |
|
| 254 | + * This method will give parsing instructions for each shortcode defined in the _shortcodes array. Child methods |
|
| 255 | + * will have to take care of handling. |
|
| 256 | + * |
|
| 257 | + * @abstract |
|
| 258 | + * @param string $shortcode the shortcode to be parsed. |
|
| 259 | + * @return string parsed shortcode |
|
| 260 | + */ |
|
| 261 | + abstract protected function _parser($shortcode); |
|
| 262 | + |
|
| 263 | + |
|
| 264 | + /** |
|
| 265 | + * This just validates incoming data for list type shortcode parsers (and they call this method) to make sure it |
|
| 266 | + * meets their requirements |
|
| 267 | + * |
|
| 268 | + * @return void If validation fails we'll throw an exception. |
|
| 269 | + * @throws EE_Error |
|
| 270 | + */ |
|
| 271 | + protected function _validate_list_requirements() |
|
| 272 | + { |
|
| 273 | + // first test to make sure we've got an array! |
|
| 274 | + if (! is_array($this->_data)) { |
|
| 275 | + throw new EE_Error( |
|
| 276 | + sprintf( |
|
| 277 | + esc_html__( |
|
| 278 | + 'Expecting an array for the data sent to %s. Instead it was %s', |
|
| 279 | + 'event_espresso' |
|
| 280 | + ), |
|
| 281 | + get_class($this), |
|
| 282 | + gettype($this->_data) |
|
| 283 | + ) |
|
| 284 | + ); |
|
| 285 | + } |
|
| 286 | + |
|
| 287 | + // next test to make sure we've got the required template in the index! |
|
| 288 | + if (! isset($this->_data['template'])) { |
|
| 289 | + throw new EE_Error( |
|
| 290 | + esc_html__( |
|
| 291 | + 'The incoming data does not have the required template index in its array', |
|
| 292 | + 'event_espresso' |
|
| 293 | + ) |
|
| 294 | + ); |
|
| 295 | + } |
|
| 296 | + |
|
| 297 | + // next test to make sure we've got a data index in the incoming data array |
|
| 298 | + if (! isset($this->_data['data'])) { |
|
| 299 | + throw new EE_Error( |
|
| 300 | + esc_html__( |
|
| 301 | + 'The incoming data does not have the required data index in its array', |
|
| 302 | + 'event_espresso' |
|
| 303 | + ) |
|
| 304 | + ); |
|
| 305 | + } |
|
| 306 | + |
|
| 307 | + // all is well let's make sure _extra_data always has the values needed. |
|
| 308 | + // let's make sure that extra_data includes all templates (for later parsing if necessary) |
|
| 309 | + if (empty($this->_extra_data) || (empty($this->_extra_data['data']) && empty($this->_extra_data['template']))) { |
|
| 310 | + $this->_extra_data['data'] = $this->_data['data']; |
|
| 311 | + $this->_extra_data['template'] = $this->_data['template']; |
|
| 312 | + } |
|
| 313 | + } |
|
| 314 | + |
|
| 315 | + |
|
| 316 | + /** |
|
| 317 | + * This returns any attributes that may be existing on an EE_Shortcode |
|
| 318 | + * |
|
| 319 | + * @param string $shortcode incoming shortcode |
|
| 320 | + * @return array An array with the attributes |
|
| 321 | + * @since 4.5.0 |
|
| 322 | + */ |
|
| 323 | + protected function _get_shortcode_attrs(string $shortcode): array |
|
| 324 | + { |
|
| 325 | + // make sure the required wp helper function is present |
|
| 326 | + // require the shortcode file if necessary |
|
| 327 | + if (! function_exists('shortcode_parse_atts')) { |
|
| 328 | + require_once(ABSPATH . WPINC . '/shortcodes.php'); |
|
| 329 | + } |
|
| 330 | + |
|
| 331 | + // let's get any attributes that may be present and set the defaults. |
|
| 332 | + $shortcode_to_parse = str_replace(['[', ']'], '', $shortcode); |
|
| 333 | + return shortcode_parse_atts($shortcode_to_parse); |
|
| 334 | + } |
|
| 335 | + |
|
| 336 | + |
|
| 337 | + /** |
|
| 338 | + * Conditional blocks are shortcode patterns with an opening conditional tag `[IF_*]` and a corresponding |
|
| 339 | + * closing tag (eg `[/IF_*]`). The content within the tags will be displayed/hidden depending on whatever |
|
| 340 | + * conditions existed in the opening tag. This method handles parsing the actual template to show/hide this |
|
| 341 | + * conditional content. |
|
| 342 | + * |
|
| 343 | + * @param string $shortcode This should be the original shortcode as used in the template and passed to the parser. |
|
| 344 | + * @param bool $show true means the opening and closing tags are removed and the content is left showing, |
|
| 345 | + * false means the opening and closing tags and the contained content are removed. |
|
| 346 | + * @return string The template for the shortcode is returned. |
|
| 347 | + * @since 4.9.32 |
|
| 348 | + * |
|
| 349 | + */ |
|
| 350 | + protected function _mutate_conditional_block_in_template(string $shortcode, bool $show = true): string |
|
| 351 | + { |
|
| 352 | + // first let's get all the matches in the template for this particular shortcode. |
|
| 353 | + preg_match_all('~' . $this->_get_conditional_block_regex($shortcode) . '~', $this->_data['template'], $matches); |
|
| 354 | + |
|
| 355 | + if ($matches && is_array($matches[0]) && ! empty($matches[0])) { |
|
| 356 | + // we need to hide all instances of the matches |
|
| 357 | + foreach ($matches[0] as $index => $content_to_show_or_hide) { |
|
| 358 | + $content_to_show_or_hide = preg_quote($content_to_show_or_hide); |
|
| 359 | + $replacement = $show ? $matches[4][ $index ] : ''; |
|
| 360 | + $this->_data['template'] = preg_replace( |
|
| 361 | + '~' . $content_to_show_or_hide . '~', |
|
| 362 | + $replacement, |
|
| 363 | + $this->_data['template'] |
|
| 364 | + ); |
|
| 365 | + } |
|
| 366 | + } |
|
| 367 | + // return $template |
|
| 368 | + return $this->_data['template']; |
|
| 369 | + } |
|
| 370 | + |
|
| 371 | + |
|
| 372 | + /** |
|
| 373 | + * This returns the regex pattern to use for conditional shortcodes parsing. |
|
| 374 | + * |
|
| 375 | + * Note: regex comes in part from the WP `get_shortcode_regex` expression in \wp-includes\shortcodes.php |
|
| 376 | + * |
|
| 377 | + * @param string $shortcode |
|
| 378 | + * @return string |
|
| 379 | + * @since 4.9.32 |
|
| 380 | + */ |
|
| 381 | + private function _get_conditional_block_regex(string $shortcode): string |
|
| 382 | + { |
|
| 383 | + // get just the shortcode tag for the match |
|
| 384 | + preg_match('@\[([^<>&/\[\]\x00-\x20=]++)@', $shortcode, $shortcode_tag_matches); |
|
| 385 | + if (empty($shortcode_tag_matches[1])) { |
|
| 386 | + return $this->_data['template']; |
|
| 387 | + } |
|
| 388 | + |
|
| 389 | + $shortcode_tag = $shortcode_tag_matches[1]; |
|
| 390 | + // get attributes_part_of_tag |
|
| 391 | + $attributes_part = preg_quote(str_replace([$shortcode_tag, '[', ']'], '', $shortcode)); |
|
| 392 | + // escape |
|
| 393 | + $shortcode_tag = preg_quote($shortcode_tag); |
|
| 394 | + |
|
| 395 | + return |
|
| 396 | + '\[' // Opening Bracket |
|
| 397 | + . "($shortcode_tag)$attributes_part" // 1: Shortcode Name |
|
| 398 | + . '(?![\w-])' // Not followed by word character or hyphen |
|
| 399 | + . '(' // 2: Unroll the loop: Inside the opening shortcode tag |
|
| 400 | + . '[^\]\/]*' // Not a closing bracket or forward slash |
|
| 401 | + . '(?:' |
|
| 402 | + . '\/(?!\])' // A forward slash not followed by a closing bracket |
|
| 403 | + . '[^\]\/]*' // Not a closing bracket or forward slash. |
|
| 404 | + . ')*?' |
|
| 405 | + . ')' |
|
| 406 | + . '(?:' |
|
| 407 | + . '(\/)' // 3. Self closing tag ... |
|
| 408 | + . '\]' // ... and closing bracket |
|
| 409 | + . '|' |
|
| 410 | + . '\]' // Closing bracket |
|
| 411 | + . '(?:' |
|
| 412 | + . '(' // 4: Unroll the loop: Optionally, anything between the opening and closing brackets |
|
| 413 | + . '[^\[]*+' // Not an opening bracket |
|
| 414 | + . '(?:' |
|
| 415 | + . '\[(?!\/\1\])' // An opening bracket not followed by the closing shortcode tag. |
|
| 416 | + . '[^\[]*+' // Not an opening bracket |
|
| 417 | + . ')*+' |
|
| 418 | + . ')' |
|
| 419 | + . '\[\/\1\]' // Closing shortcode tag |
|
| 420 | + . ')?' |
|
| 421 | + . ')'; |
|
| 422 | + } |
|
| 423 | + |
|
| 424 | + |
|
| 425 | + /** |
|
| 426 | + * This sets the properties related to the messages system |
|
| 427 | + * |
|
| 428 | + * @return void |
|
| 429 | + * @since 4.5.0 |
|
| 430 | + */ |
|
| 431 | + protected function _set_messages_properties() |
|
| 432 | + { |
|
| 433 | + // should be in _extra_data |
|
| 434 | + if (isset($this->_extra_data['messenger'])) { |
|
| 435 | + $this->_messenger = $this->_extra_data['messenger']; |
|
| 436 | + $this->_message_type = $this->_extra_data['message_type']; |
|
| 437 | + $this->_context = $this->_extra_data['message'] instanceof EE_Message |
|
| 438 | + ? $this->_extra_data['message']->context() |
|
| 439 | + : ''; |
|
| 440 | + $this->_GRP_ID = $this->_extra_data['message'] instanceof EE_Message |
|
| 441 | + ? $this->_extra_data['message']->GRP_ID() |
|
| 442 | + : 0; |
|
| 443 | + $this->_message = $this->_extra_data['message'] instanceof EE_Message |
|
| 444 | + ? $this->_extra_data['message'] |
|
| 445 | + : null; |
|
| 446 | + } |
|
| 447 | + } |
|
| 448 | + |
|
| 449 | + |
|
| 450 | + /** |
|
| 451 | + * This returns whatever the set message type object is that was set on this shortcode parser. |
|
| 452 | + * |
|
| 453 | + * @return EE_message_type|null |
|
| 454 | + * @since 4.5.0 |
|
| 455 | + */ |
|
| 456 | + public function get_set_message_type(): ?EE_message_type |
|
| 457 | + { |
|
| 458 | + return $this->_message_type; |
|
| 459 | + } |
|
| 460 | + |
|
| 461 | + |
|
| 462 | + /** |
|
| 463 | + * This returns whatever the set messenger object is that was set on this shortcode parser |
|
| 464 | + * |
|
| 465 | + * @return EE_messenger |
|
| 466 | + * @since 4.5.0 |
|
| 467 | + */ |
|
| 468 | + public function get_set_messenger(): EE_messenger |
|
| 469 | + { |
|
| 470 | + return $this->_messenger; |
|
| 471 | + } |
|
| 472 | + |
|
| 473 | + |
|
| 474 | + /** |
|
| 475 | + * This returns whatever the set context string is on this shortcode parser. |
|
| 476 | + * |
|
| 477 | + * @return string |
|
| 478 | + * @since 4.5.0 |
|
| 479 | + */ |
|
| 480 | + public function get_set_context(): string |
|
| 481 | + { |
|
| 482 | + return $this->_context; |
|
| 483 | + } |
|
| 484 | + |
|
| 485 | + |
|
| 486 | + /** |
|
| 487 | + * This returns whatever the set EE_Message object is on this shortcode. |
|
| 488 | + * |
|
| 489 | + * @return EE_Message|null |
|
| 490 | + * @since 4.9.0 |
|
| 491 | + */ |
|
| 492 | + public function get_set_message(): ?EE_Message |
|
| 493 | + { |
|
| 494 | + return $this->_message; |
|
| 495 | + } |
|
| 496 | 496 | } |
@@ -192,10 +192,10 @@ discard block |
||
| 192 | 192 | |
| 193 | 193 | // we need to set up any dynamic shortcodes so that they work with the array_key_exists |
| 194 | 194 | preg_match_all(EE_Shortcodes::REGEX_SHORTCODE_NAME_ONLY, $shortcode, $matches); |
| 195 | - $shortcode_to_verify = ! empty($matches[0]) ? $matches[0][0] . ']' : $shortcode; |
|
| 195 | + $shortcode_to_verify = ! empty($matches[0]) ? $matches[0][0].']' : $shortcode; |
|
| 196 | 196 | |
| 197 | 197 | // first we want to make sure this is a valid shortcode |
| 198 | - if (! array_key_exists($shortcode_to_verify, $this->_shortcodes)) { |
|
| 198 | + if ( ! array_key_exists($shortcode_to_verify, $this->_shortcodes)) { |
|
| 199 | 199 | // get out, this parser doesn't handle the incoming shortcode. |
| 200 | 200 | return ''; |
| 201 | 201 | } |
@@ -203,7 +203,7 @@ discard block |
||
| 203 | 203 | $this->_extra_data = $extra_data; |
| 204 | 204 | $this->_set_messages_properties(); |
| 205 | 205 | $parsed = (string) apply_filters( |
| 206 | - 'FHEE__' . get_class($this) . '__parser_after', |
|
| 206 | + 'FHEE__'.get_class($this).'__parser_after', |
|
| 207 | 207 | $this->_parser($shortcode), |
| 208 | 208 | $shortcode, |
| 209 | 209 | $data, |
@@ -231,7 +231,7 @@ discard block |
||
| 231 | 231 | public function get_shortcodes(): array |
| 232 | 232 | { |
| 233 | 233 | $this->_shortcodes = (array) apply_filters( |
| 234 | - 'FHEE__' . get_class($this) . '__shortcodes', |
|
| 234 | + 'FHEE__'.get_class($this).'__shortcodes', |
|
| 235 | 235 | $this->_shortcodes, |
| 236 | 236 | $this |
| 237 | 237 | ); |
@@ -271,7 +271,7 @@ discard block |
||
| 271 | 271 | protected function _validate_list_requirements() |
| 272 | 272 | { |
| 273 | 273 | // first test to make sure we've got an array! |
| 274 | - if (! is_array($this->_data)) { |
|
| 274 | + if ( ! is_array($this->_data)) { |
|
| 275 | 275 | throw new EE_Error( |
| 276 | 276 | sprintf( |
| 277 | 277 | esc_html__( |
@@ -285,7 +285,7 @@ discard block |
||
| 285 | 285 | } |
| 286 | 286 | |
| 287 | 287 | // next test to make sure we've got the required template in the index! |
| 288 | - if (! isset($this->_data['template'])) { |
|
| 288 | + if ( ! isset($this->_data['template'])) { |
|
| 289 | 289 | throw new EE_Error( |
| 290 | 290 | esc_html__( |
| 291 | 291 | 'The incoming data does not have the required template index in its array', |
@@ -295,7 +295,7 @@ discard block |
||
| 295 | 295 | } |
| 296 | 296 | |
| 297 | 297 | // next test to make sure we've got a data index in the incoming data array |
| 298 | - if (! isset($this->_data['data'])) { |
|
| 298 | + if ( ! isset($this->_data['data'])) { |
|
| 299 | 299 | throw new EE_Error( |
| 300 | 300 | esc_html__( |
| 301 | 301 | 'The incoming data does not have the required data index in its array', |
@@ -324,8 +324,8 @@ discard block |
||
| 324 | 324 | { |
| 325 | 325 | // make sure the required wp helper function is present |
| 326 | 326 | // require the shortcode file if necessary |
| 327 | - if (! function_exists('shortcode_parse_atts')) { |
|
| 328 | - require_once(ABSPATH . WPINC . '/shortcodes.php'); |
|
| 327 | + if ( ! function_exists('shortcode_parse_atts')) { |
|
| 328 | + require_once(ABSPATH.WPINC.'/shortcodes.php'); |
|
| 329 | 329 | } |
| 330 | 330 | |
| 331 | 331 | // let's get any attributes that may be present and set the defaults. |
@@ -350,15 +350,15 @@ discard block |
||
| 350 | 350 | protected function _mutate_conditional_block_in_template(string $shortcode, bool $show = true): string |
| 351 | 351 | { |
| 352 | 352 | // first let's get all the matches in the template for this particular shortcode. |
| 353 | - preg_match_all('~' . $this->_get_conditional_block_regex($shortcode) . '~', $this->_data['template'], $matches); |
|
| 353 | + preg_match_all('~'.$this->_get_conditional_block_regex($shortcode).'~', $this->_data['template'], $matches); |
|
| 354 | 354 | |
| 355 | 355 | if ($matches && is_array($matches[0]) && ! empty($matches[0])) { |
| 356 | 356 | // we need to hide all instances of the matches |
| 357 | 357 | foreach ($matches[0] as $index => $content_to_show_or_hide) { |
| 358 | 358 | $content_to_show_or_hide = preg_quote($content_to_show_or_hide); |
| 359 | - $replacement = $show ? $matches[4][ $index ] : ''; |
|
| 359 | + $replacement = $show ? $matches[4][$index] : ''; |
|
| 360 | 360 | $this->_data['template'] = preg_replace( |
| 361 | - '~' . $content_to_show_or_hide . '~', |
|
| 361 | + '~'.$content_to_show_or_hide.'~', |
|
| 362 | 362 | $replacement, |
| 363 | 363 | $this->_data['template'] |
| 364 | 364 | ); |
@@ -15,602 +15,602 @@ |
||
| 15 | 15 | */ |
| 16 | 16 | abstract class EE_Messages_Validator extends EE_Base |
| 17 | 17 | { |
| 18 | - /** |
|
| 19 | - * These properties just hold the name for the Messenger and Message Type (defined by child classes). |
|
| 20 | - * These are used for retrieving objects etc. |
|
| 21 | - * |
|
| 22 | - * @var string |
|
| 23 | - */ |
|
| 24 | - protected string $_m_name = ''; |
|
| 25 | - |
|
| 26 | - protected string $_mt_name = ''; |
|
| 27 | - |
|
| 28 | - |
|
| 29 | - /** |
|
| 30 | - * This will hold any error messages from the validation process. |
|
| 31 | - * The _errors property holds an associative array of error messages |
|
| 32 | - * listing the field as the key and the message as the value. |
|
| 33 | - * |
|
| 34 | - * @var array |
|
| 35 | - */ |
|
| 36 | - private array $_errors = []; |
|
| 37 | - |
|
| 38 | - |
|
| 39 | - /** |
|
| 40 | - * holds an array of fields being validated |
|
| 41 | - * |
|
| 42 | - * @var array |
|
| 43 | - */ |
|
| 44 | - protected array $_fields = []; |
|
| 45 | - |
|
| 46 | - |
|
| 47 | - /** |
|
| 48 | - * this will hold the incoming context |
|
| 49 | - * |
|
| 50 | - * @var string |
|
| 51 | - */ |
|
| 52 | - protected string $_context = ''; |
|
| 53 | - |
|
| 54 | - |
|
| 55 | - /** |
|
| 56 | - * this holds an array of fields and the relevant validation information |
|
| 57 | - * that the incoming fields data get validated against. |
|
| 58 | - * This gets setup in the _set_props() method. |
|
| 59 | - * |
|
| 60 | - * @var array |
|
| 61 | - */ |
|
| 62 | - protected array $_validators = []; |
|
| 63 | - |
|
| 64 | - protected EE_messenger $_messenger; |
|
| 65 | - |
|
| 66 | - |
|
| 67 | - protected EE_message_type $_message_type; |
|
| 68 | - |
|
| 69 | - |
|
| 70 | - /** |
|
| 71 | - * will hold any valid_shortcode modifications made by the _modify_validator() method. |
|
| 72 | - * |
|
| 73 | - * @var array |
|
| 74 | - */ |
|
| 75 | - protected array $_valid_shortcodes_modifier = []; |
|
| 76 | - |
|
| 77 | - |
|
| 78 | - /** |
|
| 79 | - * There may be times when a message type wants to include a shortcode group but exclude specific |
|
| 80 | - * shortcodes. If that's the case then it can set this property as an array of shortcodes to exclude and |
|
| 81 | - * they will not be allowed. |
|
| 82 | - * Array should be indexed by field and values are an array of specific shortcodes to exclude. |
|
| 83 | - * |
|
| 84 | - * @var array |
|
| 85 | - */ |
|
| 86 | - protected array $_specific_shortcode_excludes = []; |
|
| 87 | - |
|
| 88 | - |
|
| 89 | - /** |
|
| 90 | - * Runs the validator using the incoming fields array as the fields/values to check. |
|
| 91 | - * |
|
| 92 | - * @param array $fields The fields sent by the EEM object. |
|
| 93 | - * @param string $context |
|
| 94 | - * @throws EE_Error |
|
| 95 | - * @throws ReflectionException |
|
| 96 | - */ |
|
| 97 | - public function __construct($fields, $context) |
|
| 98 | - { |
|
| 99 | - // checks that child class has set _m_name and _mt_name, otherwise we get out. |
|
| 100 | - if (empty($this->_m_name) || empty($this->_mt_name)) { |
|
| 101 | - throw new EE_Error( |
|
| 102 | - esc_html__( |
|
| 103 | - 'EE_Messages_Validator child classes MUST set the $_m_name and $_mt_name property. Check that the child class is doing this', |
|
| 104 | - 'event_espresso' |
|
| 105 | - ) |
|
| 106 | - ); |
|
| 107 | - } |
|
| 108 | - $this->_fields = (array) $fields; |
|
| 109 | - $this->_context = (string) $context; |
|
| 110 | - |
|
| 111 | - $this->loadMessengerAndMessageType(); |
|
| 112 | - // modify any messenger/message_type specific validation instructions. This is what child classes define. |
|
| 113 | - $this->_modify_validator(); |
|
| 114 | - // let's set validators property |
|
| 115 | - $this->setValidators(); |
|
| 116 | - } |
|
| 117 | - |
|
| 118 | - |
|
| 119 | - /** |
|
| 120 | - * Child classes instantiate this and use it to modify the _validator_config array property |
|
| 121 | - * for the messenger using messengers set_validate_config() method. |
|
| 122 | - * This is so we can specify specific validation instructions for a messenger/message_type combo |
|
| 123 | - * that aren't handled by the defaults setup in the messenger. |
|
| 124 | - * |
|
| 125 | - * @abstract |
|
| 126 | - * @return void |
|
| 127 | - */ |
|
| 128 | - abstract protected function _modify_validator(); |
|
| 129 | - |
|
| 130 | - |
|
| 131 | - /** |
|
| 132 | - * loads all objects used by validator |
|
| 133 | - * |
|
| 134 | - * @throws EE_Error |
|
| 135 | - */ |
|
| 136 | - private function loadMessengerAndMessageType() |
|
| 137 | - { |
|
| 138 | - // load messenger |
|
| 139 | - $messenger = ucwords(str_replace('_', ' ', $this->_m_name)); |
|
| 140 | - $messenger = str_replace(' ', '_', $messenger); |
|
| 141 | - $messenger = 'EE_' . $messenger . '_messenger'; |
|
| 142 | - |
|
| 143 | - if (! class_exists($messenger)) { |
|
| 144 | - throw new EE_Error( |
|
| 145 | - sprintf( |
|
| 146 | - esc_html__('There is no messenger class for the given string (%s)', 'event_espresso'), |
|
| 147 | - $this->_m_name |
|
| 148 | - ) |
|
| 149 | - ); |
|
| 150 | - } |
|
| 151 | - |
|
| 152 | - $this->_messenger = new $messenger(); |
|
| 153 | - |
|
| 154 | - // load message type |
|
| 155 | - $message_type = ucwords(str_replace('_', ' ', $this->_mt_name)); |
|
| 156 | - $message_type = str_replace(' ', '_', $message_type); |
|
| 157 | - $message_type = 'EE_' . $message_type . '_message_type'; |
|
| 158 | - |
|
| 159 | - if (! class_exists($message_type)) { |
|
| 160 | - throw new EE_Error( |
|
| 161 | - sprintf( |
|
| 162 | - esc_html__('There is no message type class for the given string (%s)', 'event_espresso'), |
|
| 163 | - $this->_mt_name |
|
| 164 | - ) |
|
| 165 | - ); |
|
| 166 | - } |
|
| 167 | - |
|
| 168 | - $this->_message_type = new $message_type(); |
|
| 169 | - } |
|
| 170 | - |
|
| 171 | - |
|
| 172 | - /** |
|
| 173 | - * used to set the $_validators property |
|
| 174 | - * |
|
| 175 | - * @return void |
|
| 176 | - * @throws ReflectionException |
|
| 177 | - */ |
|
| 178 | - private function setValidators() |
|
| 179 | - { |
|
| 180 | - // let's get all valid shortcodes from mt and message type |
|
| 181 | - // (messenger will have its set in the _validator_config property for the messenger) |
|
| 182 | - $mt_codes = $this->_message_type->get_valid_shortcodes(); |
|
| 183 | - // get messenger validator_config |
|
| 184 | - $msgr_validator = $this->_messenger->get_validator_config(); |
|
| 185 | - // we only want the valid shortcodes for the given context! |
|
| 186 | - $context = $this->_context; |
|
| 187 | - $mt_codes = $mt_codes[ $context ]; |
|
| 188 | - // in this first loop we're just getting all shortcode group indexes from the msgr_validator |
|
| 189 | - // into a single array (so we can get the appropriate shortcode objects for the groups) |
|
| 190 | - $shortcode_groups = $mt_codes; |
|
| 191 | - $groups_per_field = []; |
|
| 192 | - |
|
| 193 | - foreach ($msgr_validator as $field => $config) { |
|
| 194 | - if (! isset($config['shortcodes'])) { |
|
| 195 | - continue; |
|
| 196 | - } //Nothing to see here. |
|
| 197 | - $groups_per_field[ $field ] = array_intersect($config['shortcodes'], $mt_codes); |
|
| 198 | - $shortcode_groups = array_merge($config['shortcodes'], $shortcode_groups); |
|
| 199 | - } |
|
| 200 | - $shortcode_groups = array_unique($shortcode_groups); |
|
| 201 | - |
|
| 202 | - // okay now we've got our groups. |
|
| 203 | - // Let's get the codes from the objects into an array indexed by group for easy retrieval later. |
|
| 204 | - $codes_from_objs = []; |
|
| 205 | - |
|
| 206 | - foreach ($shortcode_groups as $group) { |
|
| 207 | - $ref = ucwords(str_replace('_', ' ', $group)); |
|
| 208 | - $ref = str_replace(' ', '_', $ref); |
|
| 209 | - $classname = 'EE_' . $ref . '_Shortcodes'; |
|
| 210 | - if (class_exists($classname)) { |
|
| 211 | - $a = new ReflectionClass($classname); |
|
| 212 | - $obj = $a->newInstance(); |
|
| 213 | - $codes_from_objs[ $group ] = $obj->get_shortcodes(); |
|
| 214 | - } |
|
| 215 | - } |
|
| 216 | - |
|
| 217 | - // let's just replace the $mt shortcode group indexes with the actual shortcodes (unique) |
|
| 218 | - $final_mt_codes = []; |
|
| 219 | - foreach ($mt_codes as $group) { |
|
| 220 | - $final_mt_codes = array_merge($final_mt_codes, $codes_from_objs[ $group ]); |
|
| 221 | - } |
|
| 222 | - $mt_codes = $final_mt_codes; |
|
| 223 | - |
|
| 224 | - // k now in this next loop we're going to loop through $msgr_validator again |
|
| 225 | - // and set up the _validators property from the data we've setup so far. |
|
| 226 | - foreach ($msgr_validator as $field => $config) { |
|
| 227 | - // if required shortcode is not in our list of codes for the given field, then we skip this field. |
|
| 228 | - $required = isset($config['required']) |
|
| 229 | - ? array_intersect($config['required'], array_keys($mt_codes)) |
|
| 230 | - : true; |
|
| 231 | - if (empty($required)) { |
|
| 232 | - continue; |
|
| 233 | - } |
|
| 234 | - |
|
| 235 | - if (isset($this->_valid_shortcodes_modifier[ $context ][ $field ])) { |
|
| 236 | - // If we have an override then we use it to indicate the codes we want. |
|
| 237 | - $this->_validators[ $field ]['shortcodes'] = $this->reassembleValidShortcodesFromGroup( |
|
| 238 | - $this->_valid_shortcodes_modifier[ $context ][ $field ], |
|
| 239 | - $codes_from_objs |
|
| 240 | - ); |
|
| 241 | - } elseif (isset($groups_per_field[ $field ])) { |
|
| 242 | - // we have specific shortcodes for a field so we need to use them |
|
| 243 | - $this->_validators[ $field ]['shortcodes'] = $this->reassembleValidShortcodesFromGroup( |
|
| 244 | - $groups_per_field[ $field ], |
|
| 245 | - $codes_from_objs |
|
| 246 | - ); |
|
| 247 | - } elseif (empty($config)) { |
|
| 248 | - // no config so we're assuming we're just going to use the shortcodes from the message type context |
|
| 249 | - $this->_validators[ $field ]['shortcodes'] = $mt_codes; |
|
| 250 | - } elseif (isset($config['specific_shortcodes'])) { |
|
| 251 | - // we have specific shortcodes so we need to use them |
|
| 252 | - $this->_validators[ $field ]['shortcodes'] = $config['specific_shortcodes']; |
|
| 253 | - } else { |
|
| 254 | - // otherwise the shortcodes are what is set by the messenger for that field |
|
| 255 | - foreach ($config['shortcodes'] as $group) { |
|
| 256 | - $this->_validators[ $field ]['shortcodes'] = isset($this->_validators[ $field ]['shortcodes']) |
|
| 257 | - ? array_merge($this->_validators[ $field ]['shortcodes'], $codes_from_objs[ $group ]) |
|
| 258 | - : $codes_from_objs[ $group ]; |
|
| 259 | - } |
|
| 260 | - } |
|
| 261 | - |
|
| 262 | - // now let's just make sure that any excluded specific shortcodes are removed. |
|
| 263 | - $specific_excludes = $this->get_specific_shortcode_excludes(); |
|
| 264 | - if (isset($specific_excludes[ $field ])) { |
|
| 265 | - foreach ($specific_excludes[ $field ] as $sex) { |
|
| 266 | - if (isset($this->_validators[ $field ]['shortcodes'][ $sex ])) { |
|
| 267 | - unset($this->_validators[ $field ]['shortcodes'][ $sex ]); |
|
| 268 | - } |
|
| 269 | - } |
|
| 270 | - } |
|
| 271 | - |
|
| 272 | - // hey! don't forget to include the type if present! |
|
| 273 | - $this->_validators[ $field ]['type'] = $config['type'] ?? null; |
|
| 274 | - } |
|
| 275 | - } |
|
| 276 | - |
|
| 277 | - |
|
| 278 | - /** |
|
| 279 | - * This just returns the validators property that contains information |
|
| 280 | - * about the various shortcodes and their availability with each field |
|
| 281 | - * |
|
| 282 | - * @return array |
|
| 283 | - */ |
|
| 284 | - public function get_validators(): array |
|
| 285 | - { |
|
| 286 | - return $this->_validators; |
|
| 287 | - } |
|
| 288 | - |
|
| 289 | - |
|
| 290 | - /** |
|
| 291 | - * This simply returns the specific shortcode_excludes property that is set. |
|
| 292 | - * |
|
| 293 | - * @return array |
|
| 294 | - * @since 4.5.0 |
|
| 295 | - */ |
|
| 296 | - public function get_specific_shortcode_excludes(): array |
|
| 297 | - { |
|
| 298 | - // specific validator filter |
|
| 299 | - $shortcode_excludes = (array) apply_filters( |
|
| 300 | - 'FHEE__' . get_class($this) . '__get_specific_shortcode_excludes;', |
|
| 301 | - $this->_specific_shortcode_excludes, |
|
| 302 | - $this->_context |
|
| 303 | - ); |
|
| 304 | - // global filter |
|
| 305 | - return (array) apply_filters( |
|
| 306 | - 'FHEE__EE_Messages_Validator__get_specific_shortcode_excludes', |
|
| 307 | - $shortcode_excludes, |
|
| 308 | - $this->_context, |
|
| 309 | - $this |
|
| 310 | - ); |
|
| 311 | - } |
|
| 312 | - |
|
| 313 | - |
|
| 314 | - /** |
|
| 315 | - * This is the main method that handles validation |
|
| 316 | - * What it does is loop through the _fields (the ones that get validated) |
|
| 317 | - * and checks them against the shortcodes array for the field and the 'type' indicated by the |
|
| 318 | - * |
|
| 319 | - * @return array|bool if errors present we return the array otherwise true |
|
| 320 | - */ |
|
| 321 | - public function validate() |
|
| 322 | - { |
|
| 323 | - // some defaults |
|
| 324 | - $template_fields = $this->_messenger->get_template_fields(); |
|
| 325 | - // loop through the fields and check! |
|
| 326 | - foreach ($this->_fields as $field => $value) { |
|
| 327 | - $this->_errors[ $field ] = []; |
|
| 328 | - $err_msg = ''; |
|
| 329 | - $field_label = ''; |
|
| 330 | - // if field is not present in the _validators array then we continue |
|
| 331 | - if (! isset($this->_validators[ $field ])) { |
|
| 332 | - unset($this->_errors[ $field ]); |
|
| 333 | - continue; |
|
| 334 | - } |
|
| 335 | - |
|
| 336 | - // get the translated field label! |
|
| 337 | - // first check if it's in the main fields list |
|
| 338 | - if (isset($template_fields[ $field ])) { |
|
| 339 | - // most likely the field is found in the 'extra' array. |
|
| 340 | - $field_label = ! empty($template_fields[ $field ]) |
|
| 341 | - ? $template_fields[ $field ]['label'] |
|
| 342 | - : $field; |
|
| 343 | - } |
|
| 344 | - |
|
| 345 | - // if field label is empty OR is equal to the current field |
|
| 346 | - // then we need to loop through the 'extra' fields in the template_fields config (if present) |
|
| 347 | - if (isset($template_fields['extra']) && (empty($field_label) || $field_label === $field)) { |
|
| 348 | - foreach ($template_fields['extra'] as $main_field => $secondary_field) { |
|
| 349 | - foreach ($secondary_field as $name => $values) { |
|
| 350 | - if ($name === $field) { |
|
| 351 | - $field_label = $values['label']; |
|
| 352 | - } |
|
| 353 | - |
|
| 354 | - // if we've got a 'main' secondary field, let's see if that matches what field we're on |
|
| 355 | - // which means it contains the label for this field. |
|
| 356 | - if ($name === 'main' && $main_field === $field_label) { |
|
| 357 | - $field_label = $values['label']; |
|
| 358 | - } |
|
| 359 | - } |
|
| 360 | - } |
|
| 361 | - } |
|
| 362 | - |
|
| 363 | - // field is present. Let's validate shortcodes first (but only if shortcodes present). |
|
| 364 | - if ( |
|
| 365 | - isset($this->_validators[ $field ]['shortcodes']) |
|
| 366 | - && ! empty($this->_validators[ $field ]['shortcodes']) |
|
| 367 | - ) { |
|
| 368 | - $valid_shortcodes = array_keys((array) $this->_validators[ $field ]['shortcodes']); |
|
| 369 | - $invalid_shortcodes = $this->findInvalidShortcodes((string) $value, $valid_shortcodes); |
|
| 370 | - // if true then that means there is a returned error message |
|
| 371 | - // that we'll need to add to the _errors array for this field. |
|
| 372 | - if ($invalid_shortcodes) { |
|
| 373 | - $v_s = array_keys($this->_validators[ $field ]['shortcodes']); |
|
| 374 | - $err_msg = sprintf( |
|
| 375 | - esc_html__( |
|
| 376 | - '%3$sThe following shortcodes were found in the "%1$s" field that ARE not valid: %2$s%4$s', |
|
| 377 | - 'event_espresso' |
|
| 378 | - ), |
|
| 379 | - '<strong>' . $field_label . '</strong>', |
|
| 380 | - $invalid_shortcodes, |
|
| 381 | - '<p>', |
|
| 382 | - '</p >' |
|
| 383 | - ); |
|
| 384 | - $err_msg .= sprintf( |
|
| 385 | - esc_html__('%2$sValid shortcodes for this field are: %1$s%3$s', 'event_espresso'), |
|
| 386 | - implode(', ', $v_s), |
|
| 387 | - '<strong>', |
|
| 388 | - '</strong>' |
|
| 389 | - ); |
|
| 390 | - } |
|
| 391 | - } |
|
| 392 | - |
|
| 393 | - // if there's a "type" to be validated then let's do that too. |
|
| 394 | - if (isset($this->_validators[ $field ]['type']) && ! empty($this->_validators[ $field ]['type'])) { |
|
| 395 | - switch ($this->_validators[ $field ]['type']) { |
|
| 396 | - case 'number': |
|
| 397 | - if (! is_numeric($value)) { |
|
| 398 | - $err_msg .= sprintf( |
|
| 399 | - esc_html__( |
|
| 400 | - '%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', |
|
| 401 | - 'event_espresso' |
|
| 402 | - ), |
|
| 403 | - $field_label, |
|
| 404 | - $value, |
|
| 405 | - '<p>', |
|
| 406 | - '</p >' |
|
| 407 | - ); |
|
| 408 | - } |
|
| 409 | - break; |
|
| 410 | - case 'email': |
|
| 411 | - $valid_email = $this->_validate_email((string) $value); |
|
| 412 | - if (! $valid_email) { |
|
| 413 | - $err_msg .= htmlentities( |
|
| 414 | - sprintf( |
|
| 415 | - esc_html__( |
|
| 416 | - '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.', |
|
| 417 | - 'event_espresso' |
|
| 418 | - ), |
|
| 419 | - $field_label |
|
| 420 | - ) |
|
| 421 | - ); |
|
| 422 | - } |
|
| 423 | - break; |
|
| 424 | - default: |
|
| 425 | - break; |
|
| 426 | - } |
|
| 427 | - } |
|
| 428 | - |
|
| 429 | - // if $err_msg isn't empty, let's set up the _errors array for this field. |
|
| 430 | - if (! empty($err_msg)) { |
|
| 431 | - $this->_errors[ $field ]['msg'] = $err_msg; |
|
| 432 | - } else { |
|
| 433 | - unset($this->_errors[ $field ]); |
|
| 434 | - } |
|
| 435 | - } |
|
| 436 | - |
|
| 437 | - // if we have ANY errors, then we want to make sure we return the values |
|
| 438 | - // for ALL the fields so the user doesn't have to retype them all. |
|
| 439 | - if (! empty($this->_errors)) { |
|
| 440 | - foreach ($this->_fields as $field => $value) { |
|
| 441 | - $this->_errors[ $field ]['value'] = stripslashes($value); |
|
| 442 | - } |
|
| 443 | - } |
|
| 444 | - |
|
| 445 | - // return any errors or just TRUE if everything validates |
|
| 446 | - return empty($this->_errors) |
|
| 447 | - ? true |
|
| 448 | - : $this->_errors; |
|
| 449 | - } |
|
| 450 | - |
|
| 451 | - |
|
| 452 | - /** |
|
| 453 | - * Reassembles and returns an array of valid shortcodes |
|
| 454 | - * given the array of groups and array of shortcodes indexed by group. |
|
| 455 | - * |
|
| 456 | - * @param array $groups array of shortcode groups that we want shortcodes for |
|
| 457 | - * @param array $codes_from_objs All the codes available. |
|
| 458 | - * @return array an array of actual shortcodes (that will be used for validation). |
|
| 459 | - */ |
|
| 460 | - private function reassembleValidShortcodesFromGroup(array $groups, array $codes_from_objs): array |
|
| 461 | - { |
|
| 462 | - $shortcodes = []; |
|
| 463 | - foreach ($groups as $group) { |
|
| 464 | - $shortcodes = array_merge($shortcodes, $codes_from_objs[ $group ]); |
|
| 465 | - } |
|
| 466 | - return $shortcodes; |
|
| 467 | - } |
|
| 468 | - |
|
| 469 | - |
|
| 470 | - /** |
|
| 471 | - * Validates a string against a list of accepted shortcodes |
|
| 472 | - * This function takes in an array of shortcodes |
|
| 473 | - * and makes sure that the given string ONLY contains shortcodes in that array. |
|
| 474 | - * |
|
| 475 | - * @param string $value string to evaluate |
|
| 476 | - * @param array $valid_shortcodes array of shortcodes that are acceptable. |
|
| 477 | - * @return bool|string return either a list of invalid shortcodes OR false if the shortcodes validate. |
|
| 478 | - * @deprecated 5.0.48 |
|
| 479 | - */ |
|
| 480 | - protected function _invalid_shortcodes(string $value, array $valid_shortcodes) |
|
| 481 | - { |
|
| 482 | - return $this->findInvalidShortcodes($value, $valid_shortcodes) ?: false; |
|
| 483 | - } |
|
| 484 | - |
|
| 485 | - |
|
| 486 | - /** |
|
| 487 | - * Validates a string against a list of accepted shortcodes |
|
| 488 | - * This function takes in an array of shortcodes |
|
| 489 | - * and makes sure that the given string ONLY contains shortcodes in that array. |
|
| 490 | - * |
|
| 491 | - * @param string $incoming_text string to evaluate |
|
| 492 | - * @param array $valid_shortcodes array of shortcodes that are acceptable. |
|
| 493 | - * @return string return either a list of invalid shortcodes OR false if the shortcodes validate. |
|
| 494 | - */ |
|
| 495 | - protected function findInvalidShortcodes(string $incoming_text, array $valid_shortcodes): string |
|
| 496 | - { |
|
| 497 | - // first we need to go through the string and get ALL the shortcodes in the string |
|
| 498 | - // matches the opening [ plus the shortcode name, but nothing else |
|
| 499 | - // examples: |
|
| 500 | - // [RECIPIENT_LNAME] matches as [RECIPIENT_LNAME |
|
| 501 | - // [RECEIPT_URL download=true] matches as [RECEIPT_URL |
|
| 502 | - // [PAYMENT_LINK_IF_NEEDED_* custom_text='pay me now man!'] matches as [PAYMENT_LINK_IF_NEEDED_* |
|
| 503 | - preg_match_all(EE_Shortcodes::REGEX_SHORTCODE_NAME_ONLY, $incoming_text, $matches); |
|
| 504 | - $shortcodes_in_text = $matches[0]; |
|
| 505 | - // now all we need to do is add the closing ] to each shortcode to make them "valid" |
|
| 506 | - $shortcodes_in_text = array_map(fn($shortcode) => rtrim($shortcode) . ']', $shortcodes_in_text); |
|
| 507 | - // get a diff of the shortcodes in the string vs the valid shortcodes |
|
| 508 | - $invalid_shortcodes = array_diff($shortcodes_in_text, $valid_shortcodes); |
|
| 509 | - if (empty($invalid_shortcodes)) { |
|
| 510 | - return ''; |
|
| 511 | - } |
|
| 512 | - // made it here? then let's assemble the error message |
|
| 513 | - return '<strong>' . implode('</strong>,<strong>', $invalid_shortcodes) . '</strong>'; |
|
| 514 | - } |
|
| 515 | - |
|
| 516 | - |
|
| 517 | - /** |
|
| 518 | - * Validates an incoming string and makes sure we have valid emails in the string. |
|
| 519 | - * |
|
| 520 | - * @param string $value incoming value to validate |
|
| 521 | - * @return bool true if the string validates, false if it doesn't |
|
| 522 | - */ |
|
| 523 | - protected function _validate_email(string $value): bool |
|
| 524 | - { |
|
| 525 | - $or_val = $value; |
|
| 526 | - |
|
| 527 | - // empty strings will validate because this is how a message template |
|
| 528 | - // for a particular context can be "turned off" (if there is no email then no message) |
|
| 529 | - if (empty($value)) { |
|
| 530 | - return true; |
|
| 531 | - } |
|
| 532 | - |
|
| 533 | - // first determine if there ARE any shortcodes. |
|
| 534 | - // If there are shortcodes and then later we find that there were no other valid emails |
|
| 535 | - // but the field isn't empty... |
|
| 536 | - // that means we've got extra commas that were left after stripping out shortcodes so probably still valid. |
|
| 537 | - $has_shortcodes = preg_match(EE_Shortcodes::REGEX_SHORTCODE_FULL, $value); |
|
| 538 | - |
|
| 539 | - // first we need to strip out all the shortcodes! |
|
| 540 | - $value = preg_replace(EE_Shortcodes::REGEX_SHORTCODE_FULL, '', $value); |
|
| 541 | - |
|
| 542 | - // if original value is not empty and new value is, then we've parsed out a shortcode |
|
| 543 | - // and we now have an empty string which DOES validate. |
|
| 544 | - // We also validate complete empty field for email because |
|
| 545 | - // it's possible that this message is being "turned off" for a particular context |
|
| 546 | - |
|
| 547 | - |
|
| 548 | - if (! empty($or_val) && empty($value)) { |
|
| 549 | - return true; |
|
| 550 | - } |
|
| 551 | - |
|
| 552 | - // trim any commas from beginning and end of string ( after whitespace trimmed ); |
|
| 553 | - $value = trim(trim($value), ','); |
|
| 554 | - |
|
| 555 | - // next we need to split up the string if it's comma-delimited. |
|
| 556 | - $emails = explode(',', $value); |
|
| 557 | - $empty = false; // used to indicate that there is an empty comma. |
|
| 558 | - // now let's loop through the emails and do our checks |
|
| 559 | - foreach ($emails as $email) { |
|
| 560 | - if (empty($email)) { |
|
| 561 | - $empty = true; |
|
| 562 | - continue; |
|
| 563 | - } |
|
| 564 | - |
|
| 565 | - // trim whitespace |
|
| 566 | - $email = trim($email); |
|
| 567 | - // either its of type "[email protected]", or its of type "fname lname <[email protected]>" |
|
| 568 | - if (is_email($email)) { |
|
| 569 | - continue; |
|
| 570 | - } |
|
| 571 | - $matches = []; |
|
| 572 | - $validate = (bool) preg_match('/(.*)<(.+)>/', $email, $matches); |
|
| 573 | - if ($validate && is_email($matches[2])) { |
|
| 574 | - continue; |
|
| 575 | - } |
|
| 576 | - return false; |
|
| 577 | - } |
|
| 578 | - |
|
| 579 | - return ! ($empty && ! $has_shortcodes); |
|
| 580 | - } |
|
| 581 | - |
|
| 582 | - |
|
| 583 | - /** |
|
| 584 | - * Magic getter |
|
| 585 | - * Using this to provide back compat with add-ons referencing deprecated properties. |
|
| 586 | - * |
|
| 587 | - * @param string $property Property being requested |
|
| 588 | - * @return mixed |
|
| 589 | - * @throws Exception |
|
| 590 | - */ |
|
| 591 | - public function __get($property) |
|
| 592 | - { |
|
| 593 | - $expected_properties_map = [ |
|
| 594 | - /** |
|
| 595 | - * @deprecated 4.9.0 |
|
| 596 | - */ |
|
| 597 | - '_MSGR' => '_messenger', |
|
| 598 | - /** |
|
| 599 | - * @deprecated 4.9.0 |
|
| 600 | - */ |
|
| 601 | - '_MSGTYP' => '_message_type', |
|
| 602 | - ]; |
|
| 603 | - |
|
| 604 | - if (isset($expected_properties_map[ $property ])) { |
|
| 605 | - return $this->{$expected_properties_map[ $property ]}; |
|
| 606 | - } |
|
| 607 | - |
|
| 608 | - throw new Exception( |
|
| 609 | - sprintf( |
|
| 610 | - esc_html__('The property %1$s being requested on %2$s does not exist', 'event_espresso'), |
|
| 611 | - $property, |
|
| 612 | - get_class($this) |
|
| 613 | - ) |
|
| 614 | - ); |
|
| 615 | - } |
|
| 18 | + /** |
|
| 19 | + * These properties just hold the name for the Messenger and Message Type (defined by child classes). |
|
| 20 | + * These are used for retrieving objects etc. |
|
| 21 | + * |
|
| 22 | + * @var string |
|
| 23 | + */ |
|
| 24 | + protected string $_m_name = ''; |
|
| 25 | + |
|
| 26 | + protected string $_mt_name = ''; |
|
| 27 | + |
|
| 28 | + |
|
| 29 | + /** |
|
| 30 | + * This will hold any error messages from the validation process. |
|
| 31 | + * The _errors property holds an associative array of error messages |
|
| 32 | + * listing the field as the key and the message as the value. |
|
| 33 | + * |
|
| 34 | + * @var array |
|
| 35 | + */ |
|
| 36 | + private array $_errors = []; |
|
| 37 | + |
|
| 38 | + |
|
| 39 | + /** |
|
| 40 | + * holds an array of fields being validated |
|
| 41 | + * |
|
| 42 | + * @var array |
|
| 43 | + */ |
|
| 44 | + protected array $_fields = []; |
|
| 45 | + |
|
| 46 | + |
|
| 47 | + /** |
|
| 48 | + * this will hold the incoming context |
|
| 49 | + * |
|
| 50 | + * @var string |
|
| 51 | + */ |
|
| 52 | + protected string $_context = ''; |
|
| 53 | + |
|
| 54 | + |
|
| 55 | + /** |
|
| 56 | + * this holds an array of fields and the relevant validation information |
|
| 57 | + * that the incoming fields data get validated against. |
|
| 58 | + * This gets setup in the _set_props() method. |
|
| 59 | + * |
|
| 60 | + * @var array |
|
| 61 | + */ |
|
| 62 | + protected array $_validators = []; |
|
| 63 | + |
|
| 64 | + protected EE_messenger $_messenger; |
|
| 65 | + |
|
| 66 | + |
|
| 67 | + protected EE_message_type $_message_type; |
|
| 68 | + |
|
| 69 | + |
|
| 70 | + /** |
|
| 71 | + * will hold any valid_shortcode modifications made by the _modify_validator() method. |
|
| 72 | + * |
|
| 73 | + * @var array |
|
| 74 | + */ |
|
| 75 | + protected array $_valid_shortcodes_modifier = []; |
|
| 76 | + |
|
| 77 | + |
|
| 78 | + /** |
|
| 79 | + * There may be times when a message type wants to include a shortcode group but exclude specific |
|
| 80 | + * shortcodes. If that's the case then it can set this property as an array of shortcodes to exclude and |
|
| 81 | + * they will not be allowed. |
|
| 82 | + * Array should be indexed by field and values are an array of specific shortcodes to exclude. |
|
| 83 | + * |
|
| 84 | + * @var array |
|
| 85 | + */ |
|
| 86 | + protected array $_specific_shortcode_excludes = []; |
|
| 87 | + |
|
| 88 | + |
|
| 89 | + /** |
|
| 90 | + * Runs the validator using the incoming fields array as the fields/values to check. |
|
| 91 | + * |
|
| 92 | + * @param array $fields The fields sent by the EEM object. |
|
| 93 | + * @param string $context |
|
| 94 | + * @throws EE_Error |
|
| 95 | + * @throws ReflectionException |
|
| 96 | + */ |
|
| 97 | + public function __construct($fields, $context) |
|
| 98 | + { |
|
| 99 | + // checks that child class has set _m_name and _mt_name, otherwise we get out. |
|
| 100 | + if (empty($this->_m_name) || empty($this->_mt_name)) { |
|
| 101 | + throw new EE_Error( |
|
| 102 | + esc_html__( |
|
| 103 | + 'EE_Messages_Validator child classes MUST set the $_m_name and $_mt_name property. Check that the child class is doing this', |
|
| 104 | + 'event_espresso' |
|
| 105 | + ) |
|
| 106 | + ); |
|
| 107 | + } |
|
| 108 | + $this->_fields = (array) $fields; |
|
| 109 | + $this->_context = (string) $context; |
|
| 110 | + |
|
| 111 | + $this->loadMessengerAndMessageType(); |
|
| 112 | + // modify any messenger/message_type specific validation instructions. This is what child classes define. |
|
| 113 | + $this->_modify_validator(); |
|
| 114 | + // let's set validators property |
|
| 115 | + $this->setValidators(); |
|
| 116 | + } |
|
| 117 | + |
|
| 118 | + |
|
| 119 | + /** |
|
| 120 | + * Child classes instantiate this and use it to modify the _validator_config array property |
|
| 121 | + * for the messenger using messengers set_validate_config() method. |
|
| 122 | + * This is so we can specify specific validation instructions for a messenger/message_type combo |
|
| 123 | + * that aren't handled by the defaults setup in the messenger. |
|
| 124 | + * |
|
| 125 | + * @abstract |
|
| 126 | + * @return void |
|
| 127 | + */ |
|
| 128 | + abstract protected function _modify_validator(); |
|
| 129 | + |
|
| 130 | + |
|
| 131 | + /** |
|
| 132 | + * loads all objects used by validator |
|
| 133 | + * |
|
| 134 | + * @throws EE_Error |
|
| 135 | + */ |
|
| 136 | + private function loadMessengerAndMessageType() |
|
| 137 | + { |
|
| 138 | + // load messenger |
|
| 139 | + $messenger = ucwords(str_replace('_', ' ', $this->_m_name)); |
|
| 140 | + $messenger = str_replace(' ', '_', $messenger); |
|
| 141 | + $messenger = 'EE_' . $messenger . '_messenger'; |
|
| 142 | + |
|
| 143 | + if (! class_exists($messenger)) { |
|
| 144 | + throw new EE_Error( |
|
| 145 | + sprintf( |
|
| 146 | + esc_html__('There is no messenger class for the given string (%s)', 'event_espresso'), |
|
| 147 | + $this->_m_name |
|
| 148 | + ) |
|
| 149 | + ); |
|
| 150 | + } |
|
| 151 | + |
|
| 152 | + $this->_messenger = new $messenger(); |
|
| 153 | + |
|
| 154 | + // load message type |
|
| 155 | + $message_type = ucwords(str_replace('_', ' ', $this->_mt_name)); |
|
| 156 | + $message_type = str_replace(' ', '_', $message_type); |
|
| 157 | + $message_type = 'EE_' . $message_type . '_message_type'; |
|
| 158 | + |
|
| 159 | + if (! class_exists($message_type)) { |
|
| 160 | + throw new EE_Error( |
|
| 161 | + sprintf( |
|
| 162 | + esc_html__('There is no message type class for the given string (%s)', 'event_espresso'), |
|
| 163 | + $this->_mt_name |
|
| 164 | + ) |
|
| 165 | + ); |
|
| 166 | + } |
|
| 167 | + |
|
| 168 | + $this->_message_type = new $message_type(); |
|
| 169 | + } |
|
| 170 | + |
|
| 171 | + |
|
| 172 | + /** |
|
| 173 | + * used to set the $_validators property |
|
| 174 | + * |
|
| 175 | + * @return void |
|
| 176 | + * @throws ReflectionException |
|
| 177 | + */ |
|
| 178 | + private function setValidators() |
|
| 179 | + { |
|
| 180 | + // let's get all valid shortcodes from mt and message type |
|
| 181 | + // (messenger will have its set in the _validator_config property for the messenger) |
|
| 182 | + $mt_codes = $this->_message_type->get_valid_shortcodes(); |
|
| 183 | + // get messenger validator_config |
|
| 184 | + $msgr_validator = $this->_messenger->get_validator_config(); |
|
| 185 | + // we only want the valid shortcodes for the given context! |
|
| 186 | + $context = $this->_context; |
|
| 187 | + $mt_codes = $mt_codes[ $context ]; |
|
| 188 | + // in this first loop we're just getting all shortcode group indexes from the msgr_validator |
|
| 189 | + // into a single array (so we can get the appropriate shortcode objects for the groups) |
|
| 190 | + $shortcode_groups = $mt_codes; |
|
| 191 | + $groups_per_field = []; |
|
| 192 | + |
|
| 193 | + foreach ($msgr_validator as $field => $config) { |
|
| 194 | + if (! isset($config['shortcodes'])) { |
|
| 195 | + continue; |
|
| 196 | + } //Nothing to see here. |
|
| 197 | + $groups_per_field[ $field ] = array_intersect($config['shortcodes'], $mt_codes); |
|
| 198 | + $shortcode_groups = array_merge($config['shortcodes'], $shortcode_groups); |
|
| 199 | + } |
|
| 200 | + $shortcode_groups = array_unique($shortcode_groups); |
|
| 201 | + |
|
| 202 | + // okay now we've got our groups. |
|
| 203 | + // Let's get the codes from the objects into an array indexed by group for easy retrieval later. |
|
| 204 | + $codes_from_objs = []; |
|
| 205 | + |
|
| 206 | + foreach ($shortcode_groups as $group) { |
|
| 207 | + $ref = ucwords(str_replace('_', ' ', $group)); |
|
| 208 | + $ref = str_replace(' ', '_', $ref); |
|
| 209 | + $classname = 'EE_' . $ref . '_Shortcodes'; |
|
| 210 | + if (class_exists($classname)) { |
|
| 211 | + $a = new ReflectionClass($classname); |
|
| 212 | + $obj = $a->newInstance(); |
|
| 213 | + $codes_from_objs[ $group ] = $obj->get_shortcodes(); |
|
| 214 | + } |
|
| 215 | + } |
|
| 216 | + |
|
| 217 | + // let's just replace the $mt shortcode group indexes with the actual shortcodes (unique) |
|
| 218 | + $final_mt_codes = []; |
|
| 219 | + foreach ($mt_codes as $group) { |
|
| 220 | + $final_mt_codes = array_merge($final_mt_codes, $codes_from_objs[ $group ]); |
|
| 221 | + } |
|
| 222 | + $mt_codes = $final_mt_codes; |
|
| 223 | + |
|
| 224 | + // k now in this next loop we're going to loop through $msgr_validator again |
|
| 225 | + // and set up the _validators property from the data we've setup so far. |
|
| 226 | + foreach ($msgr_validator as $field => $config) { |
|
| 227 | + // if required shortcode is not in our list of codes for the given field, then we skip this field. |
|
| 228 | + $required = isset($config['required']) |
|
| 229 | + ? array_intersect($config['required'], array_keys($mt_codes)) |
|
| 230 | + : true; |
|
| 231 | + if (empty($required)) { |
|
| 232 | + continue; |
|
| 233 | + } |
|
| 234 | + |
|
| 235 | + if (isset($this->_valid_shortcodes_modifier[ $context ][ $field ])) { |
|
| 236 | + // If we have an override then we use it to indicate the codes we want. |
|
| 237 | + $this->_validators[ $field ]['shortcodes'] = $this->reassembleValidShortcodesFromGroup( |
|
| 238 | + $this->_valid_shortcodes_modifier[ $context ][ $field ], |
|
| 239 | + $codes_from_objs |
|
| 240 | + ); |
|
| 241 | + } elseif (isset($groups_per_field[ $field ])) { |
|
| 242 | + // we have specific shortcodes for a field so we need to use them |
|
| 243 | + $this->_validators[ $field ]['shortcodes'] = $this->reassembleValidShortcodesFromGroup( |
|
| 244 | + $groups_per_field[ $field ], |
|
| 245 | + $codes_from_objs |
|
| 246 | + ); |
|
| 247 | + } elseif (empty($config)) { |
|
| 248 | + // no config so we're assuming we're just going to use the shortcodes from the message type context |
|
| 249 | + $this->_validators[ $field ]['shortcodes'] = $mt_codes; |
|
| 250 | + } elseif (isset($config['specific_shortcodes'])) { |
|
| 251 | + // we have specific shortcodes so we need to use them |
|
| 252 | + $this->_validators[ $field ]['shortcodes'] = $config['specific_shortcodes']; |
|
| 253 | + } else { |
|
| 254 | + // otherwise the shortcodes are what is set by the messenger for that field |
|
| 255 | + foreach ($config['shortcodes'] as $group) { |
|
| 256 | + $this->_validators[ $field ]['shortcodes'] = isset($this->_validators[ $field ]['shortcodes']) |
|
| 257 | + ? array_merge($this->_validators[ $field ]['shortcodes'], $codes_from_objs[ $group ]) |
|
| 258 | + : $codes_from_objs[ $group ]; |
|
| 259 | + } |
|
| 260 | + } |
|
| 261 | + |
|
| 262 | + // now let's just make sure that any excluded specific shortcodes are removed. |
|
| 263 | + $specific_excludes = $this->get_specific_shortcode_excludes(); |
|
| 264 | + if (isset($specific_excludes[ $field ])) { |
|
| 265 | + foreach ($specific_excludes[ $field ] as $sex) { |
|
| 266 | + if (isset($this->_validators[ $field ]['shortcodes'][ $sex ])) { |
|
| 267 | + unset($this->_validators[ $field ]['shortcodes'][ $sex ]); |
|
| 268 | + } |
|
| 269 | + } |
|
| 270 | + } |
|
| 271 | + |
|
| 272 | + // hey! don't forget to include the type if present! |
|
| 273 | + $this->_validators[ $field ]['type'] = $config['type'] ?? null; |
|
| 274 | + } |
|
| 275 | + } |
|
| 276 | + |
|
| 277 | + |
|
| 278 | + /** |
|
| 279 | + * This just returns the validators property that contains information |
|
| 280 | + * about the various shortcodes and their availability with each field |
|
| 281 | + * |
|
| 282 | + * @return array |
|
| 283 | + */ |
|
| 284 | + public function get_validators(): array |
|
| 285 | + { |
|
| 286 | + return $this->_validators; |
|
| 287 | + } |
|
| 288 | + |
|
| 289 | + |
|
| 290 | + /** |
|
| 291 | + * This simply returns the specific shortcode_excludes property that is set. |
|
| 292 | + * |
|
| 293 | + * @return array |
|
| 294 | + * @since 4.5.0 |
|
| 295 | + */ |
|
| 296 | + public function get_specific_shortcode_excludes(): array |
|
| 297 | + { |
|
| 298 | + // specific validator filter |
|
| 299 | + $shortcode_excludes = (array) apply_filters( |
|
| 300 | + 'FHEE__' . get_class($this) . '__get_specific_shortcode_excludes;', |
|
| 301 | + $this->_specific_shortcode_excludes, |
|
| 302 | + $this->_context |
|
| 303 | + ); |
|
| 304 | + // global filter |
|
| 305 | + return (array) apply_filters( |
|
| 306 | + 'FHEE__EE_Messages_Validator__get_specific_shortcode_excludes', |
|
| 307 | + $shortcode_excludes, |
|
| 308 | + $this->_context, |
|
| 309 | + $this |
|
| 310 | + ); |
|
| 311 | + } |
|
| 312 | + |
|
| 313 | + |
|
| 314 | + /** |
|
| 315 | + * This is the main method that handles validation |
|
| 316 | + * What it does is loop through the _fields (the ones that get validated) |
|
| 317 | + * and checks them against the shortcodes array for the field and the 'type' indicated by the |
|
| 318 | + * |
|
| 319 | + * @return array|bool if errors present we return the array otherwise true |
|
| 320 | + */ |
|
| 321 | + public function validate() |
|
| 322 | + { |
|
| 323 | + // some defaults |
|
| 324 | + $template_fields = $this->_messenger->get_template_fields(); |
|
| 325 | + // loop through the fields and check! |
|
| 326 | + foreach ($this->_fields as $field => $value) { |
|
| 327 | + $this->_errors[ $field ] = []; |
|
| 328 | + $err_msg = ''; |
|
| 329 | + $field_label = ''; |
|
| 330 | + // if field is not present in the _validators array then we continue |
|
| 331 | + if (! isset($this->_validators[ $field ])) { |
|
| 332 | + unset($this->_errors[ $field ]); |
|
| 333 | + continue; |
|
| 334 | + } |
|
| 335 | + |
|
| 336 | + // get the translated field label! |
|
| 337 | + // first check if it's in the main fields list |
|
| 338 | + if (isset($template_fields[ $field ])) { |
|
| 339 | + // most likely the field is found in the 'extra' array. |
|
| 340 | + $field_label = ! empty($template_fields[ $field ]) |
|
| 341 | + ? $template_fields[ $field ]['label'] |
|
| 342 | + : $field; |
|
| 343 | + } |
|
| 344 | + |
|
| 345 | + // if field label is empty OR is equal to the current field |
|
| 346 | + // then we need to loop through the 'extra' fields in the template_fields config (if present) |
|
| 347 | + if (isset($template_fields['extra']) && (empty($field_label) || $field_label === $field)) { |
|
| 348 | + foreach ($template_fields['extra'] as $main_field => $secondary_field) { |
|
| 349 | + foreach ($secondary_field as $name => $values) { |
|
| 350 | + if ($name === $field) { |
|
| 351 | + $field_label = $values['label']; |
|
| 352 | + } |
|
| 353 | + |
|
| 354 | + // if we've got a 'main' secondary field, let's see if that matches what field we're on |
|
| 355 | + // which means it contains the label for this field. |
|
| 356 | + if ($name === 'main' && $main_field === $field_label) { |
|
| 357 | + $field_label = $values['label']; |
|
| 358 | + } |
|
| 359 | + } |
|
| 360 | + } |
|
| 361 | + } |
|
| 362 | + |
|
| 363 | + // field is present. Let's validate shortcodes first (but only if shortcodes present). |
|
| 364 | + if ( |
|
| 365 | + isset($this->_validators[ $field ]['shortcodes']) |
|
| 366 | + && ! empty($this->_validators[ $field ]['shortcodes']) |
|
| 367 | + ) { |
|
| 368 | + $valid_shortcodes = array_keys((array) $this->_validators[ $field ]['shortcodes']); |
|
| 369 | + $invalid_shortcodes = $this->findInvalidShortcodes((string) $value, $valid_shortcodes); |
|
| 370 | + // if true then that means there is a returned error message |
|
| 371 | + // that we'll need to add to the _errors array for this field. |
|
| 372 | + if ($invalid_shortcodes) { |
|
| 373 | + $v_s = array_keys($this->_validators[ $field ]['shortcodes']); |
|
| 374 | + $err_msg = sprintf( |
|
| 375 | + esc_html__( |
|
| 376 | + '%3$sThe following shortcodes were found in the "%1$s" field that ARE not valid: %2$s%4$s', |
|
| 377 | + 'event_espresso' |
|
| 378 | + ), |
|
| 379 | + '<strong>' . $field_label . '</strong>', |
|
| 380 | + $invalid_shortcodes, |
|
| 381 | + '<p>', |
|
| 382 | + '</p >' |
|
| 383 | + ); |
|
| 384 | + $err_msg .= sprintf( |
|
| 385 | + esc_html__('%2$sValid shortcodes for this field are: %1$s%3$s', 'event_espresso'), |
|
| 386 | + implode(', ', $v_s), |
|
| 387 | + '<strong>', |
|
| 388 | + '</strong>' |
|
| 389 | + ); |
|
| 390 | + } |
|
| 391 | + } |
|
| 392 | + |
|
| 393 | + // if there's a "type" to be validated then let's do that too. |
|
| 394 | + if (isset($this->_validators[ $field ]['type']) && ! empty($this->_validators[ $field ]['type'])) { |
|
| 395 | + switch ($this->_validators[ $field ]['type']) { |
|
| 396 | + case 'number': |
|
| 397 | + if (! is_numeric($value)) { |
|
| 398 | + $err_msg .= sprintf( |
|
| 399 | + esc_html__( |
|
| 400 | + '%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', |
|
| 401 | + 'event_espresso' |
|
| 402 | + ), |
|
| 403 | + $field_label, |
|
| 404 | + $value, |
|
| 405 | + '<p>', |
|
| 406 | + '</p >' |
|
| 407 | + ); |
|
| 408 | + } |
|
| 409 | + break; |
|
| 410 | + case 'email': |
|
| 411 | + $valid_email = $this->_validate_email((string) $value); |
|
| 412 | + if (! $valid_email) { |
|
| 413 | + $err_msg .= htmlentities( |
|
| 414 | + sprintf( |
|
| 415 | + esc_html__( |
|
| 416 | + '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.', |
|
| 417 | + 'event_espresso' |
|
| 418 | + ), |
|
| 419 | + $field_label |
|
| 420 | + ) |
|
| 421 | + ); |
|
| 422 | + } |
|
| 423 | + break; |
|
| 424 | + default: |
|
| 425 | + break; |
|
| 426 | + } |
|
| 427 | + } |
|
| 428 | + |
|
| 429 | + // if $err_msg isn't empty, let's set up the _errors array for this field. |
|
| 430 | + if (! empty($err_msg)) { |
|
| 431 | + $this->_errors[ $field ]['msg'] = $err_msg; |
|
| 432 | + } else { |
|
| 433 | + unset($this->_errors[ $field ]); |
|
| 434 | + } |
|
| 435 | + } |
|
| 436 | + |
|
| 437 | + // if we have ANY errors, then we want to make sure we return the values |
|
| 438 | + // for ALL the fields so the user doesn't have to retype them all. |
|
| 439 | + if (! empty($this->_errors)) { |
|
| 440 | + foreach ($this->_fields as $field => $value) { |
|
| 441 | + $this->_errors[ $field ]['value'] = stripslashes($value); |
|
| 442 | + } |
|
| 443 | + } |
|
| 444 | + |
|
| 445 | + // return any errors or just TRUE if everything validates |
|
| 446 | + return empty($this->_errors) |
|
| 447 | + ? true |
|
| 448 | + : $this->_errors; |
|
| 449 | + } |
|
| 450 | + |
|
| 451 | + |
|
| 452 | + /** |
|
| 453 | + * Reassembles and returns an array of valid shortcodes |
|
| 454 | + * given the array of groups and array of shortcodes indexed by group. |
|
| 455 | + * |
|
| 456 | + * @param array $groups array of shortcode groups that we want shortcodes for |
|
| 457 | + * @param array $codes_from_objs All the codes available. |
|
| 458 | + * @return array an array of actual shortcodes (that will be used for validation). |
|
| 459 | + */ |
|
| 460 | + private function reassembleValidShortcodesFromGroup(array $groups, array $codes_from_objs): array |
|
| 461 | + { |
|
| 462 | + $shortcodes = []; |
|
| 463 | + foreach ($groups as $group) { |
|
| 464 | + $shortcodes = array_merge($shortcodes, $codes_from_objs[ $group ]); |
|
| 465 | + } |
|
| 466 | + return $shortcodes; |
|
| 467 | + } |
|
| 468 | + |
|
| 469 | + |
|
| 470 | + /** |
|
| 471 | + * Validates a string against a list of accepted shortcodes |
|
| 472 | + * This function takes in an array of shortcodes |
|
| 473 | + * and makes sure that the given string ONLY contains shortcodes in that array. |
|
| 474 | + * |
|
| 475 | + * @param string $value string to evaluate |
|
| 476 | + * @param array $valid_shortcodes array of shortcodes that are acceptable. |
|
| 477 | + * @return bool|string return either a list of invalid shortcodes OR false if the shortcodes validate. |
|
| 478 | + * @deprecated 5.0.48 |
|
| 479 | + */ |
|
| 480 | + protected function _invalid_shortcodes(string $value, array $valid_shortcodes) |
|
| 481 | + { |
|
| 482 | + return $this->findInvalidShortcodes($value, $valid_shortcodes) ?: false; |
|
| 483 | + } |
|
| 484 | + |
|
| 485 | + |
|
| 486 | + /** |
|
| 487 | + * Validates a string against a list of accepted shortcodes |
|
| 488 | + * This function takes in an array of shortcodes |
|
| 489 | + * and makes sure that the given string ONLY contains shortcodes in that array. |
|
| 490 | + * |
|
| 491 | + * @param string $incoming_text string to evaluate |
|
| 492 | + * @param array $valid_shortcodes array of shortcodes that are acceptable. |
|
| 493 | + * @return string return either a list of invalid shortcodes OR false if the shortcodes validate. |
|
| 494 | + */ |
|
| 495 | + protected function findInvalidShortcodes(string $incoming_text, array $valid_shortcodes): string |
|
| 496 | + { |
|
| 497 | + // first we need to go through the string and get ALL the shortcodes in the string |
|
| 498 | + // matches the opening [ plus the shortcode name, but nothing else |
|
| 499 | + // examples: |
|
| 500 | + // [RECIPIENT_LNAME] matches as [RECIPIENT_LNAME |
|
| 501 | + // [RECEIPT_URL download=true] matches as [RECEIPT_URL |
|
| 502 | + // [PAYMENT_LINK_IF_NEEDED_* custom_text='pay me now man!'] matches as [PAYMENT_LINK_IF_NEEDED_* |
|
| 503 | + preg_match_all(EE_Shortcodes::REGEX_SHORTCODE_NAME_ONLY, $incoming_text, $matches); |
|
| 504 | + $shortcodes_in_text = $matches[0]; |
|
| 505 | + // now all we need to do is add the closing ] to each shortcode to make them "valid" |
|
| 506 | + $shortcodes_in_text = array_map(fn($shortcode) => rtrim($shortcode) . ']', $shortcodes_in_text); |
|
| 507 | + // get a diff of the shortcodes in the string vs the valid shortcodes |
|
| 508 | + $invalid_shortcodes = array_diff($shortcodes_in_text, $valid_shortcodes); |
|
| 509 | + if (empty($invalid_shortcodes)) { |
|
| 510 | + return ''; |
|
| 511 | + } |
|
| 512 | + // made it here? then let's assemble the error message |
|
| 513 | + return '<strong>' . implode('</strong>,<strong>', $invalid_shortcodes) . '</strong>'; |
|
| 514 | + } |
|
| 515 | + |
|
| 516 | + |
|
| 517 | + /** |
|
| 518 | + * Validates an incoming string and makes sure we have valid emails in the string. |
|
| 519 | + * |
|
| 520 | + * @param string $value incoming value to validate |
|
| 521 | + * @return bool true if the string validates, false if it doesn't |
|
| 522 | + */ |
|
| 523 | + protected function _validate_email(string $value): bool |
|
| 524 | + { |
|
| 525 | + $or_val = $value; |
|
| 526 | + |
|
| 527 | + // empty strings will validate because this is how a message template |
|
| 528 | + // for a particular context can be "turned off" (if there is no email then no message) |
|
| 529 | + if (empty($value)) { |
|
| 530 | + return true; |
|
| 531 | + } |
|
| 532 | + |
|
| 533 | + // first determine if there ARE any shortcodes. |
|
| 534 | + // If there are shortcodes and then later we find that there were no other valid emails |
|
| 535 | + // but the field isn't empty... |
|
| 536 | + // that means we've got extra commas that were left after stripping out shortcodes so probably still valid. |
|
| 537 | + $has_shortcodes = preg_match(EE_Shortcodes::REGEX_SHORTCODE_FULL, $value); |
|
| 538 | + |
|
| 539 | + // first we need to strip out all the shortcodes! |
|
| 540 | + $value = preg_replace(EE_Shortcodes::REGEX_SHORTCODE_FULL, '', $value); |
|
| 541 | + |
|
| 542 | + // if original value is not empty and new value is, then we've parsed out a shortcode |
|
| 543 | + // and we now have an empty string which DOES validate. |
|
| 544 | + // We also validate complete empty field for email because |
|
| 545 | + // it's possible that this message is being "turned off" for a particular context |
|
| 546 | + |
|
| 547 | + |
|
| 548 | + if (! empty($or_val) && empty($value)) { |
|
| 549 | + return true; |
|
| 550 | + } |
|
| 551 | + |
|
| 552 | + // trim any commas from beginning and end of string ( after whitespace trimmed ); |
|
| 553 | + $value = trim(trim($value), ','); |
|
| 554 | + |
|
| 555 | + // next we need to split up the string if it's comma-delimited. |
|
| 556 | + $emails = explode(',', $value); |
|
| 557 | + $empty = false; // used to indicate that there is an empty comma. |
|
| 558 | + // now let's loop through the emails and do our checks |
|
| 559 | + foreach ($emails as $email) { |
|
| 560 | + if (empty($email)) { |
|
| 561 | + $empty = true; |
|
| 562 | + continue; |
|
| 563 | + } |
|
| 564 | + |
|
| 565 | + // trim whitespace |
|
| 566 | + $email = trim($email); |
|
| 567 | + // either its of type "[email protected]", or its of type "fname lname <[email protected]>" |
|
| 568 | + if (is_email($email)) { |
|
| 569 | + continue; |
|
| 570 | + } |
|
| 571 | + $matches = []; |
|
| 572 | + $validate = (bool) preg_match('/(.*)<(.+)>/', $email, $matches); |
|
| 573 | + if ($validate && is_email($matches[2])) { |
|
| 574 | + continue; |
|
| 575 | + } |
|
| 576 | + return false; |
|
| 577 | + } |
|
| 578 | + |
|
| 579 | + return ! ($empty && ! $has_shortcodes); |
|
| 580 | + } |
|
| 581 | + |
|
| 582 | + |
|
| 583 | + /** |
|
| 584 | + * Magic getter |
|
| 585 | + * Using this to provide back compat with add-ons referencing deprecated properties. |
|
| 586 | + * |
|
| 587 | + * @param string $property Property being requested |
|
| 588 | + * @return mixed |
|
| 589 | + * @throws Exception |
|
| 590 | + */ |
|
| 591 | + public function __get($property) |
|
| 592 | + { |
|
| 593 | + $expected_properties_map = [ |
|
| 594 | + /** |
|
| 595 | + * @deprecated 4.9.0 |
|
| 596 | + */ |
|
| 597 | + '_MSGR' => '_messenger', |
|
| 598 | + /** |
|
| 599 | + * @deprecated 4.9.0 |
|
| 600 | + */ |
|
| 601 | + '_MSGTYP' => '_message_type', |
|
| 602 | + ]; |
|
| 603 | + |
|
| 604 | + if (isset($expected_properties_map[ $property ])) { |
|
| 605 | + return $this->{$expected_properties_map[ $property ]}; |
|
| 606 | + } |
|
| 607 | + |
|
| 608 | + throw new Exception( |
|
| 609 | + sprintf( |
|
| 610 | + esc_html__('The property %1$s being requested on %2$s does not exist', 'event_espresso'), |
|
| 611 | + $property, |
|
| 612 | + get_class($this) |
|
| 613 | + ) |
|
| 614 | + ); |
|
| 615 | + } |
|
| 616 | 616 | } |
@@ -138,9 +138,9 @@ discard block |
||
| 138 | 138 | // load messenger |
| 139 | 139 | $messenger = ucwords(str_replace('_', ' ', $this->_m_name)); |
| 140 | 140 | $messenger = str_replace(' ', '_', $messenger); |
| 141 | - $messenger = 'EE_' . $messenger . '_messenger'; |
|
| 141 | + $messenger = 'EE_'.$messenger.'_messenger'; |
|
| 142 | 142 | |
| 143 | - if (! class_exists($messenger)) { |
|
| 143 | + if ( ! class_exists($messenger)) { |
|
| 144 | 144 | throw new EE_Error( |
| 145 | 145 | sprintf( |
| 146 | 146 | esc_html__('There is no messenger class for the given string (%s)', 'event_espresso'), |
@@ -154,9 +154,9 @@ discard block |
||
| 154 | 154 | // load message type |
| 155 | 155 | $message_type = ucwords(str_replace('_', ' ', $this->_mt_name)); |
| 156 | 156 | $message_type = str_replace(' ', '_', $message_type); |
| 157 | - $message_type = 'EE_' . $message_type . '_message_type'; |
|
| 157 | + $message_type = 'EE_'.$message_type.'_message_type'; |
|
| 158 | 158 | |
| 159 | - if (! class_exists($message_type)) { |
|
| 159 | + if ( ! class_exists($message_type)) { |
|
| 160 | 160 | throw new EE_Error( |
| 161 | 161 | sprintf( |
| 162 | 162 | esc_html__('There is no message type class for the given string (%s)', 'event_espresso'), |
@@ -184,17 +184,17 @@ discard block |
||
| 184 | 184 | $msgr_validator = $this->_messenger->get_validator_config(); |
| 185 | 185 | // we only want the valid shortcodes for the given context! |
| 186 | 186 | $context = $this->_context; |
| 187 | - $mt_codes = $mt_codes[ $context ]; |
|
| 187 | + $mt_codes = $mt_codes[$context]; |
|
| 188 | 188 | // in this first loop we're just getting all shortcode group indexes from the msgr_validator |
| 189 | 189 | // into a single array (so we can get the appropriate shortcode objects for the groups) |
| 190 | 190 | $shortcode_groups = $mt_codes; |
| 191 | 191 | $groups_per_field = []; |
| 192 | 192 | |
| 193 | 193 | foreach ($msgr_validator as $field => $config) { |
| 194 | - if (! isset($config['shortcodes'])) { |
|
| 194 | + if ( ! isset($config['shortcodes'])) { |
|
| 195 | 195 | continue; |
| 196 | 196 | } //Nothing to see here. |
| 197 | - $groups_per_field[ $field ] = array_intersect($config['shortcodes'], $mt_codes); |
|
| 197 | + $groups_per_field[$field] = array_intersect($config['shortcodes'], $mt_codes); |
|
| 198 | 198 | $shortcode_groups = array_merge($config['shortcodes'], $shortcode_groups); |
| 199 | 199 | } |
| 200 | 200 | $shortcode_groups = array_unique($shortcode_groups); |
@@ -206,18 +206,18 @@ discard block |
||
| 206 | 206 | foreach ($shortcode_groups as $group) { |
| 207 | 207 | $ref = ucwords(str_replace('_', ' ', $group)); |
| 208 | 208 | $ref = str_replace(' ', '_', $ref); |
| 209 | - $classname = 'EE_' . $ref . '_Shortcodes'; |
|
| 209 | + $classname = 'EE_'.$ref.'_Shortcodes'; |
|
| 210 | 210 | if (class_exists($classname)) { |
| 211 | 211 | $a = new ReflectionClass($classname); |
| 212 | 212 | $obj = $a->newInstance(); |
| 213 | - $codes_from_objs[ $group ] = $obj->get_shortcodes(); |
|
| 213 | + $codes_from_objs[$group] = $obj->get_shortcodes(); |
|
| 214 | 214 | } |
| 215 | 215 | } |
| 216 | 216 | |
| 217 | 217 | // let's just replace the $mt shortcode group indexes with the actual shortcodes (unique) |
| 218 | 218 | $final_mt_codes = []; |
| 219 | 219 | foreach ($mt_codes as $group) { |
| 220 | - $final_mt_codes = array_merge($final_mt_codes, $codes_from_objs[ $group ]); |
|
| 220 | + $final_mt_codes = array_merge($final_mt_codes, $codes_from_objs[$group]); |
|
| 221 | 221 | } |
| 222 | 222 | $mt_codes = $final_mt_codes; |
| 223 | 223 | |
@@ -232,45 +232,45 @@ discard block |
||
| 232 | 232 | continue; |
| 233 | 233 | } |
| 234 | 234 | |
| 235 | - if (isset($this->_valid_shortcodes_modifier[ $context ][ $field ])) { |
|
| 235 | + if (isset($this->_valid_shortcodes_modifier[$context][$field])) { |
|
| 236 | 236 | // If we have an override then we use it to indicate the codes we want. |
| 237 | - $this->_validators[ $field ]['shortcodes'] = $this->reassembleValidShortcodesFromGroup( |
|
| 238 | - $this->_valid_shortcodes_modifier[ $context ][ $field ], |
|
| 237 | + $this->_validators[$field]['shortcodes'] = $this->reassembleValidShortcodesFromGroup( |
|
| 238 | + $this->_valid_shortcodes_modifier[$context][$field], |
|
| 239 | 239 | $codes_from_objs |
| 240 | 240 | ); |
| 241 | - } elseif (isset($groups_per_field[ $field ])) { |
|
| 241 | + } elseif (isset($groups_per_field[$field])) { |
|
| 242 | 242 | // we have specific shortcodes for a field so we need to use them |
| 243 | - $this->_validators[ $field ]['shortcodes'] = $this->reassembleValidShortcodesFromGroup( |
|
| 244 | - $groups_per_field[ $field ], |
|
| 243 | + $this->_validators[$field]['shortcodes'] = $this->reassembleValidShortcodesFromGroup( |
|
| 244 | + $groups_per_field[$field], |
|
| 245 | 245 | $codes_from_objs |
| 246 | 246 | ); |
| 247 | 247 | } elseif (empty($config)) { |
| 248 | 248 | // no config so we're assuming we're just going to use the shortcodes from the message type context |
| 249 | - $this->_validators[ $field ]['shortcodes'] = $mt_codes; |
|
| 249 | + $this->_validators[$field]['shortcodes'] = $mt_codes; |
|
| 250 | 250 | } elseif (isset($config['specific_shortcodes'])) { |
| 251 | 251 | // we have specific shortcodes so we need to use them |
| 252 | - $this->_validators[ $field ]['shortcodes'] = $config['specific_shortcodes']; |
|
| 252 | + $this->_validators[$field]['shortcodes'] = $config['specific_shortcodes']; |
|
| 253 | 253 | } else { |
| 254 | 254 | // otherwise the shortcodes are what is set by the messenger for that field |
| 255 | 255 | foreach ($config['shortcodes'] as $group) { |
| 256 | - $this->_validators[ $field ]['shortcodes'] = isset($this->_validators[ $field ]['shortcodes']) |
|
| 257 | - ? array_merge($this->_validators[ $field ]['shortcodes'], $codes_from_objs[ $group ]) |
|
| 258 | - : $codes_from_objs[ $group ]; |
|
| 256 | + $this->_validators[$field]['shortcodes'] = isset($this->_validators[$field]['shortcodes']) |
|
| 257 | + ? array_merge($this->_validators[$field]['shortcodes'], $codes_from_objs[$group]) |
|
| 258 | + : $codes_from_objs[$group]; |
|
| 259 | 259 | } |
| 260 | 260 | } |
| 261 | 261 | |
| 262 | 262 | // now let's just make sure that any excluded specific shortcodes are removed. |
| 263 | 263 | $specific_excludes = $this->get_specific_shortcode_excludes(); |
| 264 | - if (isset($specific_excludes[ $field ])) { |
|
| 265 | - foreach ($specific_excludes[ $field ] as $sex) { |
|
| 266 | - if (isset($this->_validators[ $field ]['shortcodes'][ $sex ])) { |
|
| 267 | - unset($this->_validators[ $field ]['shortcodes'][ $sex ]); |
|
| 264 | + if (isset($specific_excludes[$field])) { |
|
| 265 | + foreach ($specific_excludes[$field] as $sex) { |
|
| 266 | + if (isset($this->_validators[$field]['shortcodes'][$sex])) { |
|
| 267 | + unset($this->_validators[$field]['shortcodes'][$sex]); |
|
| 268 | 268 | } |
| 269 | 269 | } |
| 270 | 270 | } |
| 271 | 271 | |
| 272 | 272 | // hey! don't forget to include the type if present! |
| 273 | - $this->_validators[ $field ]['type'] = $config['type'] ?? null; |
|
| 273 | + $this->_validators[$field]['type'] = $config['type'] ?? null; |
|
| 274 | 274 | } |
| 275 | 275 | } |
| 276 | 276 | |
@@ -297,7 +297,7 @@ discard block |
||
| 297 | 297 | { |
| 298 | 298 | // specific validator filter |
| 299 | 299 | $shortcode_excludes = (array) apply_filters( |
| 300 | - 'FHEE__' . get_class($this) . '__get_specific_shortcode_excludes;', |
|
| 300 | + 'FHEE__'.get_class($this).'__get_specific_shortcode_excludes;', |
|
| 301 | 301 | $this->_specific_shortcode_excludes, |
| 302 | 302 | $this->_context |
| 303 | 303 | ); |
@@ -324,21 +324,21 @@ discard block |
||
| 324 | 324 | $template_fields = $this->_messenger->get_template_fields(); |
| 325 | 325 | // loop through the fields and check! |
| 326 | 326 | foreach ($this->_fields as $field => $value) { |
| 327 | - $this->_errors[ $field ] = []; |
|
| 327 | + $this->_errors[$field] = []; |
|
| 328 | 328 | $err_msg = ''; |
| 329 | 329 | $field_label = ''; |
| 330 | 330 | // if field is not present in the _validators array then we continue |
| 331 | - if (! isset($this->_validators[ $field ])) { |
|
| 332 | - unset($this->_errors[ $field ]); |
|
| 331 | + if ( ! isset($this->_validators[$field])) { |
|
| 332 | + unset($this->_errors[$field]); |
|
| 333 | 333 | continue; |
| 334 | 334 | } |
| 335 | 335 | |
| 336 | 336 | // get the translated field label! |
| 337 | 337 | // first check if it's in the main fields list |
| 338 | - if (isset($template_fields[ $field ])) { |
|
| 338 | + if (isset($template_fields[$field])) { |
|
| 339 | 339 | // most likely the field is found in the 'extra' array. |
| 340 | - $field_label = ! empty($template_fields[ $field ]) |
|
| 341 | - ? $template_fields[ $field ]['label'] |
|
| 340 | + $field_label = ! empty($template_fields[$field]) |
|
| 341 | + ? $template_fields[$field]['label'] |
|
| 342 | 342 | : $field; |
| 343 | 343 | } |
| 344 | 344 | |
@@ -362,21 +362,21 @@ discard block |
||
| 362 | 362 | |
| 363 | 363 | // field is present. Let's validate shortcodes first (but only if shortcodes present). |
| 364 | 364 | if ( |
| 365 | - isset($this->_validators[ $field ]['shortcodes']) |
|
| 366 | - && ! empty($this->_validators[ $field ]['shortcodes']) |
|
| 365 | + isset($this->_validators[$field]['shortcodes']) |
|
| 366 | + && ! empty($this->_validators[$field]['shortcodes']) |
|
| 367 | 367 | ) { |
| 368 | - $valid_shortcodes = array_keys((array) $this->_validators[ $field ]['shortcodes']); |
|
| 368 | + $valid_shortcodes = array_keys((array) $this->_validators[$field]['shortcodes']); |
|
| 369 | 369 | $invalid_shortcodes = $this->findInvalidShortcodes((string) $value, $valid_shortcodes); |
| 370 | 370 | // if true then that means there is a returned error message |
| 371 | 371 | // that we'll need to add to the _errors array for this field. |
| 372 | 372 | if ($invalid_shortcodes) { |
| 373 | - $v_s = array_keys($this->_validators[ $field ]['shortcodes']); |
|
| 373 | + $v_s = array_keys($this->_validators[$field]['shortcodes']); |
|
| 374 | 374 | $err_msg = sprintf( |
| 375 | 375 | esc_html__( |
| 376 | 376 | '%3$sThe following shortcodes were found in the "%1$s" field that ARE not valid: %2$s%4$s', |
| 377 | 377 | 'event_espresso' |
| 378 | 378 | ), |
| 379 | - '<strong>' . $field_label . '</strong>', |
|
| 379 | + '<strong>'.$field_label.'</strong>', |
|
| 380 | 380 | $invalid_shortcodes, |
| 381 | 381 | '<p>', |
| 382 | 382 | '</p >' |
@@ -391,10 +391,10 @@ discard block |
||
| 391 | 391 | } |
| 392 | 392 | |
| 393 | 393 | // if there's a "type" to be validated then let's do that too. |
| 394 | - if (isset($this->_validators[ $field ]['type']) && ! empty($this->_validators[ $field ]['type'])) { |
|
| 395 | - switch ($this->_validators[ $field ]['type']) { |
|
| 394 | + if (isset($this->_validators[$field]['type']) && ! empty($this->_validators[$field]['type'])) { |
|
| 395 | + switch ($this->_validators[$field]['type']) { |
|
| 396 | 396 | case 'number': |
| 397 | - if (! is_numeric($value)) { |
|
| 397 | + if ( ! is_numeric($value)) { |
|
| 398 | 398 | $err_msg .= sprintf( |
| 399 | 399 | esc_html__( |
| 400 | 400 | '%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', |
@@ -409,7 +409,7 @@ discard block |
||
| 409 | 409 | break; |
| 410 | 410 | case 'email': |
| 411 | 411 | $valid_email = $this->_validate_email((string) $value); |
| 412 | - if (! $valid_email) { |
|
| 412 | + if ( ! $valid_email) { |
|
| 413 | 413 | $err_msg .= htmlentities( |
| 414 | 414 | sprintf( |
| 415 | 415 | esc_html__( |
@@ -427,18 +427,18 @@ discard block |
||
| 427 | 427 | } |
| 428 | 428 | |
| 429 | 429 | // if $err_msg isn't empty, let's set up the _errors array for this field. |
| 430 | - if (! empty($err_msg)) { |
|
| 431 | - $this->_errors[ $field ]['msg'] = $err_msg; |
|
| 430 | + if ( ! empty($err_msg)) { |
|
| 431 | + $this->_errors[$field]['msg'] = $err_msg; |
|
| 432 | 432 | } else { |
| 433 | - unset($this->_errors[ $field ]); |
|
| 433 | + unset($this->_errors[$field]); |
|
| 434 | 434 | } |
| 435 | 435 | } |
| 436 | 436 | |
| 437 | 437 | // if we have ANY errors, then we want to make sure we return the values |
| 438 | 438 | // for ALL the fields so the user doesn't have to retype them all. |
| 439 | - if (! empty($this->_errors)) { |
|
| 439 | + if ( ! empty($this->_errors)) { |
|
| 440 | 440 | foreach ($this->_fields as $field => $value) { |
| 441 | - $this->_errors[ $field ]['value'] = stripslashes($value); |
|
| 441 | + $this->_errors[$field]['value'] = stripslashes($value); |
|
| 442 | 442 | } |
| 443 | 443 | } |
| 444 | 444 | |
@@ -461,7 +461,7 @@ discard block |
||
| 461 | 461 | { |
| 462 | 462 | $shortcodes = []; |
| 463 | 463 | foreach ($groups as $group) { |
| 464 | - $shortcodes = array_merge($shortcodes, $codes_from_objs[ $group ]); |
|
| 464 | + $shortcodes = array_merge($shortcodes, $codes_from_objs[$group]); |
|
| 465 | 465 | } |
| 466 | 466 | return $shortcodes; |
| 467 | 467 | } |
@@ -503,14 +503,14 @@ discard block |
||
| 503 | 503 | preg_match_all(EE_Shortcodes::REGEX_SHORTCODE_NAME_ONLY, $incoming_text, $matches); |
| 504 | 504 | $shortcodes_in_text = $matches[0]; |
| 505 | 505 | // now all we need to do is add the closing ] to each shortcode to make them "valid" |
| 506 | - $shortcodes_in_text = array_map(fn($shortcode) => rtrim($shortcode) . ']', $shortcodes_in_text); |
|
| 506 | + $shortcodes_in_text = array_map(fn($shortcode) => rtrim($shortcode).']', $shortcodes_in_text); |
|
| 507 | 507 | // get a diff of the shortcodes in the string vs the valid shortcodes |
| 508 | 508 | $invalid_shortcodes = array_diff($shortcodes_in_text, $valid_shortcodes); |
| 509 | 509 | if (empty($invalid_shortcodes)) { |
| 510 | 510 | return ''; |
| 511 | 511 | } |
| 512 | 512 | // made it here? then let's assemble the error message |
| 513 | - return '<strong>' . implode('</strong>,<strong>', $invalid_shortcodes) . '</strong>'; |
|
| 513 | + return '<strong>'.implode('</strong>,<strong>', $invalid_shortcodes).'</strong>'; |
|
| 514 | 514 | } |
| 515 | 515 | |
| 516 | 516 | |
@@ -545,7 +545,7 @@ discard block |
||
| 545 | 545 | // it's possible that this message is being "turned off" for a particular context |
| 546 | 546 | |
| 547 | 547 | |
| 548 | - if (! empty($or_val) && empty($value)) { |
|
| 548 | + if ( ! empty($or_val) && empty($value)) { |
|
| 549 | 549 | return true; |
| 550 | 550 | } |
| 551 | 551 | |
@@ -601,8 +601,8 @@ discard block |
||
| 601 | 601 | '_MSGTYP' => '_message_type', |
| 602 | 602 | ]; |
| 603 | 603 | |
| 604 | - if (isset($expected_properties_map[ $property ])) { |
|
| 605 | - return $this->{$expected_properties_map[ $property ]}; |
|
| 604 | + if (isset($expected_properties_map[$property])) { |
|
| 605 | + return $this->{$expected_properties_map[$property]}; |
|
| 606 | 606 | } |
| 607 | 607 | |
| 608 | 608 | throw new Exception( |
@@ -10,265 +10,265 @@ |
||
| 10 | 10 | */ |
| 11 | 11 | class EEH_Parse_Shortcodes |
| 12 | 12 | { |
| 13 | - /** |
|
| 14 | - * holds the template |
|
| 15 | - * |
|
| 16 | - * @access private |
|
| 17 | - * @var mixed (string|array) |
|
| 18 | - */ |
|
| 19 | - private $_template; |
|
| 20 | - |
|
| 21 | - |
|
| 22 | - /** |
|
| 23 | - * holds the incoming data object |
|
| 24 | - * |
|
| 25 | - * @access private |
|
| 26 | - * @var object |
|
| 27 | - */ |
|
| 28 | - private $_data; |
|
| 29 | - |
|
| 30 | - |
|
| 31 | - /** |
|
| 32 | - * will hold an array of EE_Shortcodes library objects. |
|
| 33 | - * |
|
| 34 | - * @access private |
|
| 35 | - * @var EE_Shortcodes[] |
|
| 36 | - */ |
|
| 37 | - private $_shortcode_objs = array(); |
|
| 38 | - |
|
| 39 | - |
|
| 40 | - /** |
|
| 41 | - * This kicks off the parsing of shortcodes in message templates |
|
| 42 | - * |
|
| 43 | - * @param string $template This is the incoming string to be parsed |
|
| 44 | - * @param EE_Messages_Addressee $data This is the incoming data object |
|
| 45 | - * @param array $valid_shortcodes An array of strings that correspond to EE_Shortcode libraries |
|
| 46 | - * @param EE_message_type $message_type The message type that called the parser |
|
| 47 | - * @param EE_messenger $messenger The active messenger for this parsing session. |
|
| 48 | - * @param EE_Message $message |
|
| 49 | - * @return string The parsed template string |
|
| 50 | - */ |
|
| 51 | - public function parse_message_template( |
|
| 52 | - $template, |
|
| 53 | - EE_Messages_Addressee $data, |
|
| 54 | - $valid_shortcodes, |
|
| 55 | - EE_message_type $message_type, |
|
| 56 | - EE_messenger $messenger, |
|
| 57 | - EE_Message $message |
|
| 58 | - ) { |
|
| 59 | - $extra_data = array( |
|
| 60 | - 'messenger' => $messenger, |
|
| 61 | - 'message_type' => $message_type, |
|
| 62 | - 'message' => $message, |
|
| 63 | - ); |
|
| 64 | - $this->_init_data($template, $data, $valid_shortcodes, $extra_data); |
|
| 65 | - $this->_template = is_array($template) ? $template['main'] : $template; |
|
| 66 | - return $this->_parse_message_template(); |
|
| 67 | - } |
|
| 68 | - |
|
| 69 | - |
|
| 70 | - public function parse_attendee_list_template( |
|
| 71 | - $template, |
|
| 72 | - EE_Registration $registration, |
|
| 73 | - $valid_shortcodes, |
|
| 74 | - $extra_data = array() |
|
| 75 | - ) { |
|
| 76 | - $this->_init_data($template, $registration, $valid_shortcodes, $extra_data); |
|
| 77 | - $this->_template = is_array($template) ? $template['attendee_list'] : $template; |
|
| 78 | - return $this->_parse_message_template(); |
|
| 79 | - } |
|
| 80 | - |
|
| 81 | - public function parse_event_list_template($template, EE_Event $event, $valid_shortcodes, $extra_data = array()) |
|
| 82 | - { |
|
| 83 | - $this->_init_data($template, $event, $valid_shortcodes, $extra_data); |
|
| 84 | - $this->_template = is_array($template) ? $template['event_list'] : $template; |
|
| 85 | - return $this->_parse_message_template(); |
|
| 86 | - } |
|
| 87 | - |
|
| 88 | - |
|
| 89 | - public function parse_ticket_list_template($template, EE_Ticket $ticket, $valid_shortcodes, $extra_data = array()) |
|
| 90 | - { |
|
| 91 | - $this->_init_data($template, $ticket, $valid_shortcodes, $extra_data); |
|
| 92 | - $this->_template = is_array($template) ? $template['ticket_list'] : $template; |
|
| 93 | - return $this->_parse_message_template(); |
|
| 94 | - } |
|
| 95 | - |
|
| 96 | - |
|
| 97 | - public function parse_line_item_list_template( |
|
| 98 | - $template, |
|
| 99 | - EE_Line_Item $line_item, |
|
| 100 | - $valid_shortcodes, |
|
| 101 | - $extra_data = array() |
|
| 102 | - ) { |
|
| 103 | - $this->_init_data($template, $line_item, $valid_shortcodes, $extra_data); |
|
| 104 | - $this->_template = is_array($template) ? $template['ticket_line_item_no_pms'] : $template; |
|
| 105 | - return $this->_parse_message_template(); |
|
| 106 | - } |
|
| 107 | - |
|
| 108 | - |
|
| 109 | - public function parse_payment_list_template( |
|
| 110 | - $template, |
|
| 111 | - EE_Payment $payment_item, |
|
| 112 | - $valid_shortcodes, |
|
| 113 | - $extra_data = array() |
|
| 114 | - ) { |
|
| 115 | - $this->_init_data($template, $payment_item, $valid_shortcodes, $extra_data); |
|
| 116 | - $this->_template = is_array($template) ? $template['payment_list'] : $template; |
|
| 117 | - return $this->_parse_message_template(); |
|
| 118 | - } |
|
| 119 | - |
|
| 120 | - |
|
| 121 | - public function parse_datetime_list_template( |
|
| 122 | - $template, |
|
| 123 | - EE_Datetime $datetime, |
|
| 124 | - $valid_shortcodes, |
|
| 125 | - $extra_data = array() |
|
| 126 | - ) { |
|
| 127 | - $this->_init_data($template, $datetime, $valid_shortcodes, $extra_data); |
|
| 128 | - $this->_template = is_array($template) ? $template['datetime_list'] : $template; |
|
| 129 | - return $this->_parse_message_template(); |
|
| 130 | - } |
|
| 131 | - |
|
| 132 | - |
|
| 133 | - public function parse_question_list_template($template, EE_Answer $answer, $valid_shortcodes, $extra_data = array()) |
|
| 134 | - { |
|
| 135 | - $this->_init_data($template, $answer, $valid_shortcodes, $extra_data); |
|
| 136 | - $this->_template = is_array($template) ? $template['question_list'] : $template; |
|
| 137 | - return $this->_parse_message_template(); |
|
| 138 | - } |
|
| 139 | - |
|
| 140 | - |
|
| 141 | - private function _init_data($template, $data, $valid_shortcodes, $extra_data = array()) |
|
| 142 | - { |
|
| 143 | - $this->_reset_props(); |
|
| 144 | - $this->_data['template'] = $template; |
|
| 145 | - $this->_data['data'] = $data; |
|
| 146 | - $this->_data['extra_data'] = $extra_data; |
|
| 147 | - $this->_set_shortcodes($valid_shortcodes); |
|
| 148 | - } |
|
| 149 | - |
|
| 150 | - |
|
| 151 | - private function _reset_props() |
|
| 152 | - { |
|
| 153 | - $this->_template = $this->_data = null; |
|
| 154 | - $this->_shortcode_objs = array(); |
|
| 155 | - } |
|
| 156 | - |
|
| 157 | - |
|
| 158 | - /** |
|
| 159 | - * takes the given template and parses it with the $_shortcodes property |
|
| 160 | - * |
|
| 161 | - * @return string |
|
| 162 | - */ |
|
| 163 | - private function _parse_message_template(): string |
|
| 164 | - { |
|
| 165 | - // now let's get a list of shortcodes that are found in the given template |
|
| 166 | - preg_match_all(EE_Shortcodes::REGEX_SHORTCODE_FULL, $this->_template, $matches); |
|
| 167 | - $shortcodes = $matches[0]; // this should be an array of shortcodes in the template string. |
|
| 168 | - |
|
| 169 | - $matched_code = array(); |
|
| 170 | - $sc_values = array(); |
|
| 171 | - |
|
| 172 | - $list_type_shortcodes = array( |
|
| 173 | - '[ATTENDEE_LIST]', |
|
| 174 | - '[EVENT_LIST]', |
|
| 175 | - '[TICKET_LIST]', |
|
| 176 | - '[DATETIME_LIST]', |
|
| 177 | - '[QUESTION_LIST]', |
|
| 178 | - '[RECIPIENT_QUESTION_LIST]', |
|
| 179 | - '[PRIMARY_REGISTRANT_QUESTION_LIST]', |
|
| 180 | - '[RECIPIENT_TICKET_LIST]', |
|
| 181 | - '[PRIMARY_REGISTRANT_TICKET_LIST]', |
|
| 182 | - '[RECIPIENT_DATETIME_LIST]', |
|
| 183 | - '[PRIMARY_REGISTRANT_DATETIME_LIST]', |
|
| 184 | - '[TICKET_LINE_ITEM_LIST]', |
|
| 185 | - '[TAX_LINE_ITEM_LIST]', |
|
| 186 | - '[ADDITIONAL_LINE_ITEM_LIST]', |
|
| 187 | - '[PRICE_MODIFIER_LINE_ITEM_LIST]', |
|
| 188 | - '[PAYMENT_LIST_*]', |
|
| 189 | - ); |
|
| 190 | - |
|
| 191 | - $list_type_shortcodes = apply_filters( |
|
| 192 | - 'FHEE__EEH_Parse_Shortcodes___parse_message_template__list_type_shortcodes', |
|
| 193 | - $list_type_shortcodes |
|
| 194 | - ); |
|
| 195 | - |
|
| 196 | - // now lets go ahead and loop through our parsers for each shortcode and set up the values |
|
| 197 | - foreach ($shortcodes as $shortcode) { |
|
| 198 | - // truncate full shortcode to shortcode name only (ie: remove attributes and dynamic portions) |
|
| 199 | - preg_match_all(EE_Shortcodes::REGEX_SHORTCODE_NAME_ONLY, $shortcode, $matches); |
|
| 200 | - // ensure shortcode ends with closing ] |
|
| 201 | - $short_code_name = rtrim(reset($matches[0]), ']') . ']'; |
|
| 202 | - |
|
| 203 | - foreach ($this->_shortcode_objs as $sc_obj) { |
|
| 204 | - if (! $sc_obj instanceof EE_Shortcodes) { |
|
| 205 | - continue; |
|
| 206 | - } |
|
| 207 | - // check if the given shortcode is in this object, if not, move on |
|
| 208 | - if (! array_key_exists($short_code_name, $sc_obj->get_shortcodes())) { |
|
| 209 | - continue; |
|
| 210 | - } |
|
| 211 | - |
|
| 212 | - // if this isn't a "list" type shortcode then we'll send along the data vanilla instead of in an array. |
|
| 213 | - if (! in_array($shortcode, $list_type_shortcodes)) { |
|
| 214 | - $data_send = ! is_object($this->_data) && isset($this->_data['data']) ? $this->_data['data'] : $this->_data; |
|
| 215 | - } else { |
|
| 216 | - $data_send = $this->_data; |
|
| 217 | - } |
|
| 218 | - |
|
| 219 | - // is this a conditional type shortcode? If it is then we actually parse the template here. |
|
| 220 | - if ($this->_is_conditional_shortcode($shortcode)) { |
|
| 221 | - // most shortcode parsers are not going to have a match for this shortcode |
|
| 222 | - // and will return an empty string so we need to make sure that we're only replacing |
|
| 223 | - // the template when there is a non-empty string. |
|
| 224 | - $parsed = $sc_obj->parser($shortcode, $data_send, $this->_data['extra_data']); |
|
| 225 | - if ($parsed) { |
|
| 226 | - $this->_template = $parsed; |
|
| 227 | - } |
|
| 228 | - } |
|
| 229 | - |
|
| 230 | - $parsed = $sc_obj->parser($shortcode, $data_send, $this->_data['extra_data']); |
|
| 231 | - |
|
| 232 | - $matched_code[] = $shortcode; |
|
| 233 | - $sc_values[] = $parsed; |
|
| 234 | - } |
|
| 235 | - } |
|
| 236 | - |
|
| 237 | - // now we've got parsed values for all the shortcodes in the template so we can go ahead and swap the shortcodes out. |
|
| 238 | - return str_replace(array_values($matched_code), array_values($sc_values), $this->_template); |
|
| 239 | - } |
|
| 240 | - |
|
| 241 | - |
|
| 242 | - /** |
|
| 243 | - * Simply returns whether the given shortcode matches the structure for a conditional shortcode. |
|
| 244 | - * |
|
| 245 | - * Does it match this format: `[IF_` |
|
| 246 | - * |
|
| 247 | - * @param $shortcode |
|
| 248 | - * @return bool |
|
| 249 | - */ |
|
| 250 | - protected function _is_conditional_shortcode($shortcode): bool |
|
| 251 | - { |
|
| 252 | - return strpos($shortcode, '[IF_') === 0; |
|
| 253 | - } |
|
| 254 | - |
|
| 255 | - |
|
| 256 | - /** |
|
| 257 | - * This sets the shortcodes property from the incoming array of valid shortcodes that corresponds to names of |
|
| 258 | - * various EE_Shortcode library objects |
|
| 259 | - * |
|
| 260 | - * @param array $valid_shortcodes an array of strings corresponding to EE_Shortcode Library objects |
|
| 261 | - * @return void |
|
| 262 | - */ |
|
| 263 | - private function _set_shortcodes(array $valid_shortcodes) |
|
| 264 | - { |
|
| 265 | - foreach ($valid_shortcodes as $shortcode_ref) { |
|
| 266 | - $ref = ucwords(str_replace('_', ' ', $shortcode_ref)); |
|
| 267 | - $ref = str_replace(' ', '_', $ref); |
|
| 268 | - $classname = 'EE_' . $ref . '_Shortcodes'; |
|
| 269 | - if (class_exists($classname) && ! isset($this->_shortcode_objs[ $classname ])) { |
|
| 270 | - $this->_shortcode_objs[ $classname ] = new $classname(); |
|
| 271 | - } |
|
| 272 | - } |
|
| 273 | - } |
|
| 13 | + /** |
|
| 14 | + * holds the template |
|
| 15 | + * |
|
| 16 | + * @access private |
|
| 17 | + * @var mixed (string|array) |
|
| 18 | + */ |
|
| 19 | + private $_template; |
|
| 20 | + |
|
| 21 | + |
|
| 22 | + /** |
|
| 23 | + * holds the incoming data object |
|
| 24 | + * |
|
| 25 | + * @access private |
|
| 26 | + * @var object |
|
| 27 | + */ |
|
| 28 | + private $_data; |
|
| 29 | + |
|
| 30 | + |
|
| 31 | + /** |
|
| 32 | + * will hold an array of EE_Shortcodes library objects. |
|
| 33 | + * |
|
| 34 | + * @access private |
|
| 35 | + * @var EE_Shortcodes[] |
|
| 36 | + */ |
|
| 37 | + private $_shortcode_objs = array(); |
|
| 38 | + |
|
| 39 | + |
|
| 40 | + /** |
|
| 41 | + * This kicks off the parsing of shortcodes in message templates |
|
| 42 | + * |
|
| 43 | + * @param string $template This is the incoming string to be parsed |
|
| 44 | + * @param EE_Messages_Addressee $data This is the incoming data object |
|
| 45 | + * @param array $valid_shortcodes An array of strings that correspond to EE_Shortcode libraries |
|
| 46 | + * @param EE_message_type $message_type The message type that called the parser |
|
| 47 | + * @param EE_messenger $messenger The active messenger for this parsing session. |
|
| 48 | + * @param EE_Message $message |
|
| 49 | + * @return string The parsed template string |
|
| 50 | + */ |
|
| 51 | + public function parse_message_template( |
|
| 52 | + $template, |
|
| 53 | + EE_Messages_Addressee $data, |
|
| 54 | + $valid_shortcodes, |
|
| 55 | + EE_message_type $message_type, |
|
| 56 | + EE_messenger $messenger, |
|
| 57 | + EE_Message $message |
|
| 58 | + ) { |
|
| 59 | + $extra_data = array( |
|
| 60 | + 'messenger' => $messenger, |
|
| 61 | + 'message_type' => $message_type, |
|
| 62 | + 'message' => $message, |
|
| 63 | + ); |
|
| 64 | + $this->_init_data($template, $data, $valid_shortcodes, $extra_data); |
|
| 65 | + $this->_template = is_array($template) ? $template['main'] : $template; |
|
| 66 | + return $this->_parse_message_template(); |
|
| 67 | + } |
|
| 68 | + |
|
| 69 | + |
|
| 70 | + public function parse_attendee_list_template( |
|
| 71 | + $template, |
|
| 72 | + EE_Registration $registration, |
|
| 73 | + $valid_shortcodes, |
|
| 74 | + $extra_data = array() |
|
| 75 | + ) { |
|
| 76 | + $this->_init_data($template, $registration, $valid_shortcodes, $extra_data); |
|
| 77 | + $this->_template = is_array($template) ? $template['attendee_list'] : $template; |
|
| 78 | + return $this->_parse_message_template(); |
|
| 79 | + } |
|
| 80 | + |
|
| 81 | + public function parse_event_list_template($template, EE_Event $event, $valid_shortcodes, $extra_data = array()) |
|
| 82 | + { |
|
| 83 | + $this->_init_data($template, $event, $valid_shortcodes, $extra_data); |
|
| 84 | + $this->_template = is_array($template) ? $template['event_list'] : $template; |
|
| 85 | + return $this->_parse_message_template(); |
|
| 86 | + } |
|
| 87 | + |
|
| 88 | + |
|
| 89 | + public function parse_ticket_list_template($template, EE_Ticket $ticket, $valid_shortcodes, $extra_data = array()) |
|
| 90 | + { |
|
| 91 | + $this->_init_data($template, $ticket, $valid_shortcodes, $extra_data); |
|
| 92 | + $this->_template = is_array($template) ? $template['ticket_list'] : $template; |
|
| 93 | + return $this->_parse_message_template(); |
|
| 94 | + } |
|
| 95 | + |
|
| 96 | + |
|
| 97 | + public function parse_line_item_list_template( |
|
| 98 | + $template, |
|
| 99 | + EE_Line_Item $line_item, |
|
| 100 | + $valid_shortcodes, |
|
| 101 | + $extra_data = array() |
|
| 102 | + ) { |
|
| 103 | + $this->_init_data($template, $line_item, $valid_shortcodes, $extra_data); |
|
| 104 | + $this->_template = is_array($template) ? $template['ticket_line_item_no_pms'] : $template; |
|
| 105 | + return $this->_parse_message_template(); |
|
| 106 | + } |
|
| 107 | + |
|
| 108 | + |
|
| 109 | + public function parse_payment_list_template( |
|
| 110 | + $template, |
|
| 111 | + EE_Payment $payment_item, |
|
| 112 | + $valid_shortcodes, |
|
| 113 | + $extra_data = array() |
|
| 114 | + ) { |
|
| 115 | + $this->_init_data($template, $payment_item, $valid_shortcodes, $extra_data); |
|
| 116 | + $this->_template = is_array($template) ? $template['payment_list'] : $template; |
|
| 117 | + return $this->_parse_message_template(); |
|
| 118 | + } |
|
| 119 | + |
|
| 120 | + |
|
| 121 | + public function parse_datetime_list_template( |
|
| 122 | + $template, |
|
| 123 | + EE_Datetime $datetime, |
|
| 124 | + $valid_shortcodes, |
|
| 125 | + $extra_data = array() |
|
| 126 | + ) { |
|
| 127 | + $this->_init_data($template, $datetime, $valid_shortcodes, $extra_data); |
|
| 128 | + $this->_template = is_array($template) ? $template['datetime_list'] : $template; |
|
| 129 | + return $this->_parse_message_template(); |
|
| 130 | + } |
|
| 131 | + |
|
| 132 | + |
|
| 133 | + public function parse_question_list_template($template, EE_Answer $answer, $valid_shortcodes, $extra_data = array()) |
|
| 134 | + { |
|
| 135 | + $this->_init_data($template, $answer, $valid_shortcodes, $extra_data); |
|
| 136 | + $this->_template = is_array($template) ? $template['question_list'] : $template; |
|
| 137 | + return $this->_parse_message_template(); |
|
| 138 | + } |
|
| 139 | + |
|
| 140 | + |
|
| 141 | + private function _init_data($template, $data, $valid_shortcodes, $extra_data = array()) |
|
| 142 | + { |
|
| 143 | + $this->_reset_props(); |
|
| 144 | + $this->_data['template'] = $template; |
|
| 145 | + $this->_data['data'] = $data; |
|
| 146 | + $this->_data['extra_data'] = $extra_data; |
|
| 147 | + $this->_set_shortcodes($valid_shortcodes); |
|
| 148 | + } |
|
| 149 | + |
|
| 150 | + |
|
| 151 | + private function _reset_props() |
|
| 152 | + { |
|
| 153 | + $this->_template = $this->_data = null; |
|
| 154 | + $this->_shortcode_objs = array(); |
|
| 155 | + } |
|
| 156 | + |
|
| 157 | + |
|
| 158 | + /** |
|
| 159 | + * takes the given template and parses it with the $_shortcodes property |
|
| 160 | + * |
|
| 161 | + * @return string |
|
| 162 | + */ |
|
| 163 | + private function _parse_message_template(): string |
|
| 164 | + { |
|
| 165 | + // now let's get a list of shortcodes that are found in the given template |
|
| 166 | + preg_match_all(EE_Shortcodes::REGEX_SHORTCODE_FULL, $this->_template, $matches); |
|
| 167 | + $shortcodes = $matches[0]; // this should be an array of shortcodes in the template string. |
|
| 168 | + |
|
| 169 | + $matched_code = array(); |
|
| 170 | + $sc_values = array(); |
|
| 171 | + |
|
| 172 | + $list_type_shortcodes = array( |
|
| 173 | + '[ATTENDEE_LIST]', |
|
| 174 | + '[EVENT_LIST]', |
|
| 175 | + '[TICKET_LIST]', |
|
| 176 | + '[DATETIME_LIST]', |
|
| 177 | + '[QUESTION_LIST]', |
|
| 178 | + '[RECIPIENT_QUESTION_LIST]', |
|
| 179 | + '[PRIMARY_REGISTRANT_QUESTION_LIST]', |
|
| 180 | + '[RECIPIENT_TICKET_LIST]', |
|
| 181 | + '[PRIMARY_REGISTRANT_TICKET_LIST]', |
|
| 182 | + '[RECIPIENT_DATETIME_LIST]', |
|
| 183 | + '[PRIMARY_REGISTRANT_DATETIME_LIST]', |
|
| 184 | + '[TICKET_LINE_ITEM_LIST]', |
|
| 185 | + '[TAX_LINE_ITEM_LIST]', |
|
| 186 | + '[ADDITIONAL_LINE_ITEM_LIST]', |
|
| 187 | + '[PRICE_MODIFIER_LINE_ITEM_LIST]', |
|
| 188 | + '[PAYMENT_LIST_*]', |
|
| 189 | + ); |
|
| 190 | + |
|
| 191 | + $list_type_shortcodes = apply_filters( |
|
| 192 | + 'FHEE__EEH_Parse_Shortcodes___parse_message_template__list_type_shortcodes', |
|
| 193 | + $list_type_shortcodes |
|
| 194 | + ); |
|
| 195 | + |
|
| 196 | + // now lets go ahead and loop through our parsers for each shortcode and set up the values |
|
| 197 | + foreach ($shortcodes as $shortcode) { |
|
| 198 | + // truncate full shortcode to shortcode name only (ie: remove attributes and dynamic portions) |
|
| 199 | + preg_match_all(EE_Shortcodes::REGEX_SHORTCODE_NAME_ONLY, $shortcode, $matches); |
|
| 200 | + // ensure shortcode ends with closing ] |
|
| 201 | + $short_code_name = rtrim(reset($matches[0]), ']') . ']'; |
|
| 202 | + |
|
| 203 | + foreach ($this->_shortcode_objs as $sc_obj) { |
|
| 204 | + if (! $sc_obj instanceof EE_Shortcodes) { |
|
| 205 | + continue; |
|
| 206 | + } |
|
| 207 | + // check if the given shortcode is in this object, if not, move on |
|
| 208 | + if (! array_key_exists($short_code_name, $sc_obj->get_shortcodes())) { |
|
| 209 | + continue; |
|
| 210 | + } |
|
| 211 | + |
|
| 212 | + // if this isn't a "list" type shortcode then we'll send along the data vanilla instead of in an array. |
|
| 213 | + if (! in_array($shortcode, $list_type_shortcodes)) { |
|
| 214 | + $data_send = ! is_object($this->_data) && isset($this->_data['data']) ? $this->_data['data'] : $this->_data; |
|
| 215 | + } else { |
|
| 216 | + $data_send = $this->_data; |
|
| 217 | + } |
|
| 218 | + |
|
| 219 | + // is this a conditional type shortcode? If it is then we actually parse the template here. |
|
| 220 | + if ($this->_is_conditional_shortcode($shortcode)) { |
|
| 221 | + // most shortcode parsers are not going to have a match for this shortcode |
|
| 222 | + // and will return an empty string so we need to make sure that we're only replacing |
|
| 223 | + // the template when there is a non-empty string. |
|
| 224 | + $parsed = $sc_obj->parser($shortcode, $data_send, $this->_data['extra_data']); |
|
| 225 | + if ($parsed) { |
|
| 226 | + $this->_template = $parsed; |
|
| 227 | + } |
|
| 228 | + } |
|
| 229 | + |
|
| 230 | + $parsed = $sc_obj->parser($shortcode, $data_send, $this->_data['extra_data']); |
|
| 231 | + |
|
| 232 | + $matched_code[] = $shortcode; |
|
| 233 | + $sc_values[] = $parsed; |
|
| 234 | + } |
|
| 235 | + } |
|
| 236 | + |
|
| 237 | + // now we've got parsed values for all the shortcodes in the template so we can go ahead and swap the shortcodes out. |
|
| 238 | + return str_replace(array_values($matched_code), array_values($sc_values), $this->_template); |
|
| 239 | + } |
|
| 240 | + |
|
| 241 | + |
|
| 242 | + /** |
|
| 243 | + * Simply returns whether the given shortcode matches the structure for a conditional shortcode. |
|
| 244 | + * |
|
| 245 | + * Does it match this format: `[IF_` |
|
| 246 | + * |
|
| 247 | + * @param $shortcode |
|
| 248 | + * @return bool |
|
| 249 | + */ |
|
| 250 | + protected function _is_conditional_shortcode($shortcode): bool |
|
| 251 | + { |
|
| 252 | + return strpos($shortcode, '[IF_') === 0; |
|
| 253 | + } |
|
| 254 | + |
|
| 255 | + |
|
| 256 | + /** |
|
| 257 | + * This sets the shortcodes property from the incoming array of valid shortcodes that corresponds to names of |
|
| 258 | + * various EE_Shortcode library objects |
|
| 259 | + * |
|
| 260 | + * @param array $valid_shortcodes an array of strings corresponding to EE_Shortcode Library objects |
|
| 261 | + * @return void |
|
| 262 | + */ |
|
| 263 | + private function _set_shortcodes(array $valid_shortcodes) |
|
| 264 | + { |
|
| 265 | + foreach ($valid_shortcodes as $shortcode_ref) { |
|
| 266 | + $ref = ucwords(str_replace('_', ' ', $shortcode_ref)); |
|
| 267 | + $ref = str_replace(' ', '_', $ref); |
|
| 268 | + $classname = 'EE_' . $ref . '_Shortcodes'; |
|
| 269 | + if (class_exists($classname) && ! isset($this->_shortcode_objs[ $classname ])) { |
|
| 270 | + $this->_shortcode_objs[ $classname ] = new $classname(); |
|
| 271 | + } |
|
| 272 | + } |
|
| 273 | + } |
|
| 274 | 274 | } |
@@ -198,19 +198,19 @@ discard block |
||
| 198 | 198 | // truncate full shortcode to shortcode name only (ie: remove attributes and dynamic portions) |
| 199 | 199 | preg_match_all(EE_Shortcodes::REGEX_SHORTCODE_NAME_ONLY, $shortcode, $matches); |
| 200 | 200 | // ensure shortcode ends with closing ] |
| 201 | - $short_code_name = rtrim(reset($matches[0]), ']') . ']'; |
|
| 201 | + $short_code_name = rtrim(reset($matches[0]), ']').']'; |
|
| 202 | 202 | |
| 203 | 203 | foreach ($this->_shortcode_objs as $sc_obj) { |
| 204 | - if (! $sc_obj instanceof EE_Shortcodes) { |
|
| 204 | + if ( ! $sc_obj instanceof EE_Shortcodes) { |
|
| 205 | 205 | continue; |
| 206 | 206 | } |
| 207 | 207 | // check if the given shortcode is in this object, if not, move on |
| 208 | - if (! array_key_exists($short_code_name, $sc_obj->get_shortcodes())) { |
|
| 208 | + if ( ! array_key_exists($short_code_name, $sc_obj->get_shortcodes())) { |
|
| 209 | 209 | continue; |
| 210 | 210 | } |
| 211 | 211 | |
| 212 | 212 | // if this isn't a "list" type shortcode then we'll send along the data vanilla instead of in an array. |
| 213 | - if (! in_array($shortcode, $list_type_shortcodes)) { |
|
| 213 | + if ( ! in_array($shortcode, $list_type_shortcodes)) { |
|
| 214 | 214 | $data_send = ! is_object($this->_data) && isset($this->_data['data']) ? $this->_data['data'] : $this->_data; |
| 215 | 215 | } else { |
| 216 | 216 | $data_send = $this->_data; |
@@ -265,9 +265,9 @@ discard block |
||
| 265 | 265 | foreach ($valid_shortcodes as $shortcode_ref) { |
| 266 | 266 | $ref = ucwords(str_replace('_', ' ', $shortcode_ref)); |
| 267 | 267 | $ref = str_replace(' ', '_', $ref); |
| 268 | - $classname = 'EE_' . $ref . '_Shortcodes'; |
|
| 269 | - if (class_exists($classname) && ! isset($this->_shortcode_objs[ $classname ])) { |
|
| 270 | - $this->_shortcode_objs[ $classname ] = new $classname(); |
|
| 268 | + $classname = 'EE_'.$ref.'_Shortcodes'; |
|
| 269 | + if (class_exists($classname) && ! isset($this->_shortcode_objs[$classname])) { |
|
| 270 | + $this->_shortcode_objs[$classname] = new $classname(); |
|
| 271 | 271 | } |
| 272 | 272 | } |
| 273 | 273 | } |