| @@ -68,11 +68,18 @@ | ||
| 68 | 68 | return $plugin_work['yaymail']; |
| 69 | 69 | } |
| 70 | 70 | } |
| 71 | 71 | |
| 72 | -if ( ! function_exists( 'yaymail_is_wp_mail_installed' ) ) { | |
| 73 | - function yaymail_is_wp_mail_installed() { | |
| 74 | - return defined( 'YAYMAIL_WP_VERSION' ); | |
| 72 | +if ( ! function_exists( 'yaymail_sanitize_template_variant' ) ) { | |
| 73 | + /** | |
| 74 | + * Variant slugs are stored as post meta and used as lookup keys, so only [a-z0-9_-] survives. | |
| 75 | + * Anything else (including null) means the default design. | |
| 76 | + */ | |
| 77 | + function yaymail_sanitize_template_variant( $variant ) { | |
| 78 | + if ( ! is_string( $variant ) ) { | |
| 79 | + return ''; | |
| 80 | + } | |
| 81 | + return preg_match( '/^[a-z0-9_-]{1,40}$/', $variant ) ? $variant : ''; | |
| 75 | 82 | } |
| 76 | 83 | } |
| 77 | 84 | |
| 78 | 85 | if ( ! function_exists( 'yaymail_version' ) ) { |
| @@ -118,8 +125,9 @@ | ||
| 118 | 125 | } |
| 119 | 126 | |
| 120 | 127 | // TODO: do later |
| 121 | 128 | ob_start(); |
| 129 | + // nosemgrep: audit.php.lang.security.file.inclusion-arg | |
| 122 | 130 | include $path; |
| 123 | 131 | // nosemgrep |
| 124 | 132 | $html = ob_get_contents(); |
| 125 | 133 | ob_end_clean(); |
| @@ -207,28 +215,8 @@ | ||
| 207 | 215 | return ElementsLoader::get_instance()->get_all(); |
| 208 | 216 | } |
| 209 | 217 | } |
| 210 | 218 | |
| 211 | -if ( ! function_exists( 'yaymail_get_email_available_elements' ) ) { | |
| 212 | - | |
| 213 | - /** | |
| 214 | - * Get all available elements of given email | |
| 215 | - * | |
| 216 | - * @param string $email_id | |
| 217 | - * | |
| 218 | - * @return BaseElement[] | |
| 219 | - */ | |
| 220 | - function yaymail_get_email_available_elements( $email_id ) { | |
| 221 | - $find_email = yaymail_get_email( $email_id ); | |
| 222 | - | |
| 223 | - if ( ! $find_email ) { | |
| 224 | - return []; | |
| 225 | - } | |
| 226 | - | |
| 227 | - return $find_email->get_elements(); | |
| 228 | - } | |
| 229 | -} | |
| 230 | - | |
| 231 | 219 | if ( ! function_exists( 'yaymail_get_email_elements_data' ) ) { |
| 232 | 220 | |
| 233 | 221 | /** |
| 234 | 222 | * Get all elements data of given email |
| @@ -243,8 +231,14 @@ | ||
| 243 | 231 | if ( ! $find_email ) { |
| 244 | 232 | return []; |
| 245 | 233 | } |
| 246 | 234 | |
| 235 | + // Not passed as a get_data() argument: ColumnLayout::get_data( $amount, $attributes ) | |
| 236 | + // uses that same first/second position for its own params, so any element's | |
| 237 | + // default color must read this out-of-band instead. Scoped to this one request. | |
| 238 | + global $yaymail_current_email_id; | |
| 239 | + $yaymail_current_email_id = $email_id; | |
| 240 | + | |
| 247 | 241 | $all_elements = yaymail_get_all_elements(); |
| 248 | 242 | $result = []; |
| 249 | 243 | |
| 250 | 244 | foreach ( $all_elements as $element ) { |
| @@ -295,8 +289,60 @@ | ||
| 295 | 289 | return $element; |
| 296 | 290 | } |
| 297 | 291 | }//end if |
| 298 | 292 | |
| 293 | +if ( ! function_exists( 'yaymail_get_default_brand_color' ) ) { | |
| 294 | + | |
| 295 | + /** | |
| 296 | + * Default accent color for newly dragged elements (Heading background, Button | |
| 297 | + * background, etc.), matching the frontend's brand color per platform | |
| 298 | + * (constants/theme.ts WP_COLORS vs YAYMAIL_TOKENS.color.wcPurple). | |
| 299 | + * | |
| 300 | + * Element get_data() methods share BaseElement's abstract contract, but | |
| 301 | + * ColumnLayout::get_data( $amount, $attributes ) repurposes that same | |
| 302 | + * position for a non-attributes param -- so the email/template id can't be | |
| 303 | + * threaded through as a get_data() argument without breaking it. Falls back | |
| 304 | + * to the id yaymail_get_email_elements_data() stashed for the current request. | |
| 305 | + * | |
| 306 | + * @param string|null $email_id Email/template id to check; defaults to the | |
| 307 | + * current request's when omitted. | |
| 308 | + * @return string Hex color. | |
| 309 | + */ | |
| 310 | + function yaymail_get_default_brand_color( $email_id = null ) { | |
| 311 | + if ( null === $email_id ) { | |
| 312 | + global $yaymail_current_email_id; | |
| 313 | + $email_id = $yaymail_current_email_id; | |
| 314 | + } | |
| 315 | + $email_id = (string) $email_id; | |
| 316 | + | |
| 317 | + $is_wp_template = 0 === strpos( $email_id, 'wp-core-' ) || 'wp_global_header_footer' === $email_id; | |
| 318 | + | |
| 319 | + return $is_wp_template ? YAYMAIL_COLOR_WP_DEFAULT : YAYMAIL_COLOR_WC_DEFAULT; | |
| 320 | + } | |
| 321 | +} | |
| 322 | + | |
| 323 | +if ( ! function_exists( 'yaymail_get_ghf_disallowed_element_types' ) ) { | |
| 324 | + | |
| 325 | + /** | |
| 326 | + * Element types that cannot be used in global header/footer. | |
| 327 | + * Derived from the same availability rules as the GHF customizer sidebar. | |
| 328 | + * | |
| 329 | + * @return string[] | |
| 330 | + */ | |
| 331 | + function yaymail_get_ghf_disallowed_element_types() { | |
| 332 | + $elements = yaymail_get_email_elements_data( 'yaymail_global_header_footer' ); | |
| 333 | + | |
| 334 | + $disallowed = []; | |
| 335 | + foreach ( $elements as $element ) { | |
| 336 | + if ( empty( $element['available'] ) && ! empty( $element['type'] ) ) { | |
| 337 | + $disallowed[] = $element['type']; | |
| 338 | + } | |
| 339 | + } | |
| 340 | + | |
| 341 | + return array_values( array_unique( $disallowed ) ); | |
| 342 | + } | |
| 343 | +}//end if | |
| 344 | + | |
| 299 | 345 | if ( ! function_exists( 'yaymail_get_element' ) ) { |
| 300 | 346 | |
| 301 | 347 | /** |
| 302 | 348 | * Get element by given type |
| @@ -351,8 +397,31 @@ | ||
| 351 | 397 | $logger = new Logger(); |
| 352 | 398 | $logger->log_exception_message( new \Exception( $message ), $log_type, $additional_data ); |
| 353 | 399 | } |
| 354 | 400 | } |
| 401 | + | |
| 402 | +if ( ! function_exists( 'yaymail_get_attachment_image_url' ) ) { | |
| 403 | + | |
| 404 | + /** | |
| 405 | + * Safely resolve an attachment image URL. | |
| 406 | + * | |
| 407 | + * Returns '' for an empty id or a dangling/deleted attachment (where | |
| 408 | + * wp_get_attachment_image_src() returns false). Never throws, so a missing | |
| 409 | + * image degrades gracefully instead of breaking the request that triggered | |
| 410 | + * rendering (e.g. WooCommerce checkout). | |
| 411 | + * | |
| 412 | + * @param int|string $image_id Attachment ID. | |
| 413 | + * @param string $size Registered image size. | |
| 414 | + * @return string Image URL or '' when unavailable. | |
| 415 | + */ | |
| 416 | + function yaymail_get_attachment_image_url( $image_id, $size = 'full' ) { | |
| 417 | + if ( empty( $image_id ) ) { | |
| 418 | + return ''; | |
| 419 | + } | |
| 420 | + $image = wp_get_attachment_image_src( $image_id, $size ); | |
| 421 | + return ( is_array( $image ) && ! empty( $image[0] ) ) ? $image[0] : ''; | |
| 422 | + } | |
| 423 | +}//end if | |
| 355 | 424 | |
| 356 | 425 | if ( ! function_exists( 'yaymail_get_wc_email_settings' ) ) { |
| 357 | 426 | /** |
| 358 | 427 | * Get WooCommerce email settings |