PluginProbe ʕ •ᴥ•ʔ
WooCommerce / 10.9.4
WooCommerce v10.9.4
10.9.4 10.9.3 10.9.2 10.9.1 10.9.0 10.9.0-rc.1 10.9.0-beta.2 10.9.0-beta.1 10.8.1 10.8.0 10.8.0-rc.1 10.8.0-beta.2 10.8.0-beta.1 7.8.0-beta.1 7.8.0-beta.2 7.8.0-rc.1 7.8.0-rc.2 7.8.1 7.8.2 7.8.3 7.8.4 7.9.0 7.9.0-beta.1 7.9.0-beta.2 7.9.0-rc.2 7.9.0-rc.3 7.9.1 7.9.2 8.0.0 8.0.0-beta.1 8.0.0-beta.2 8.0.0-rc.1 8.0.0-rc.2 8.0.1 8.0.2 8.0.3 8.0.4 8.0.5 8.1.0 8.1.0-beta.1 8.1.0-rc.1 8.1.0-rc.2 8.1.1 8.1.2 8.1.3 8.1.4 8.2.0 8.2.0-beta.1 8.2.0-rc.1 8.2.0-rc.2 8.2.1 8.2.2 8.2.3 8.2.4 8.2.5 8.3.0 8.3.0-beta.1 8.3.0-rc.1 8.3.0-rc.2 8.3.1 8.3.2 8.3.3 8.3.4 8.4.0 8.4.0-beta.1 8.4.0-rc.1 8.4.1 8.4.2 8.4.3 8.5.0 8.5.0-beta.1 8.5.0-rc.1 8.5.1 8.5.2 8.5.3 8.5.4 8.5.5 8.6.0 8.6.0-beta.1 8.6.0-rc.1 8.6.1 8.6.2 8.6.3 8.6.4 8.7.0 8.7.0-beta.1 8.7.0-beta.2 8.7.0-rc.1 8.7.1 8.7.2 8.7.3 8.8.0 8.8.0-beta.1 8.8.0-rc.1 8.8.1 8.8.2 8.8.3 8.8.4 8.8.5 8.8.6 8.8.7 8.9.0 8.9.0-beta.1 8.9.0-rc.1 8.9.1 8.9.2 8.9.3 8.9.4 8.9.5 9.0.0 9.0.0-beta.1 9.0.0-beta.2 9.0.0-rc.1 9.0.1 9.0.2 9.0.3 9.0.4 9.1.0 9.1.0-beta.1 9.1.0-rc.1 9.1.1 9.1.2 9.1.3 9.1.4 9.1.5 9.1.6 9.2.0 9.2.0-beta.1 9.2.0-rc.1 9.2.1 9.2.2 9.2.3 9.2.4 9.2.5 9.3.0 9.3.0-beta.1 9.3.0-rc.1 9.3.1 9.3.2 9.3.3 9.3.4 9.3.5 9.3.6 9.4.0 9.4.0-beta.1 9.4.0-beta.2 9.4.0-rc.1 9.4.0-rc.2 9.4.0-rc.3 9.4.0-rc.4 9.4.1 9.4.2 9.4.3 9.4.4 9.4.5 9.5.0 9.5.0-beta.1 9.5.0-beta.2 9.5.0-rc.1 9.5.1 9.5.2 9.5.3 9.5.4 9.6.0 9.6.0-beta.1 9.6.0-beta.2 9.6.0-rc.1 9.6.1 9.6.2 9.6.3 9.6.4 9.7.0 9.7.0-beta.1 9.7.0-rc.1 9.7.1 9.7.2 9.7.3 9.8.0 9.8.0-beta.1 9.8.0-rc.1 9.8.1 9.8.2 9.8.3 9.8.4 9.8.5 9.8.6 9.8.7 9.9.0 9.9.0-beta.1 9.9.0-rc.1 9.9.1 9.9.2 9.9.3 9.9.4 9.9.5 9.9.6 9.9.7 3.7.3 7.1.2 3.8.0 7.2.0 3.8.0-beta.1 7.2.0-beta.1 3.8.0-rc.1 7.2.0-beta.2 3.8.0-rc.2 7.2.0-rc.1 3.8.1 7.2.0-rc.2 3.8.2 7.2.1 3.8.3 7.2.2 3.9.0 7.2.3 3.9.0-beta.1 7.2.4 3.9.0-beta.2 7.3.0 3.9.0-rc.1 7.3.0-beta.1 3.9.0-rc.2 7.3.0-beta.2 3.9.0-rc.3 7.3.0-rc.1 3.9.0-rc.4 7.3.0-rc.2 3.9.1 7.3.1 3.9.2 7.4.0 3.9.3 7.4.0-beta.1 3.9.4 7.4.0-beta.2 3.9.5 7.4.0-rc.1 4.0.0 7.4.0-rc.2 4.0.0-beta.1 7.4.1 4.0.0-rc.1 7.4.2 4.0.0-rc.2 7.5.0 4.0.1 7.5.0-beta.1 4.0.2 7.5.0-beta.2 4.0.3 7.5.0-rc.1 4.0.4 7.5.1 4.1.0 7.5.2 4.1.0-beta.1 7.6.0 4.1.0-beta.2 7.6.0-beta.1 4.1.0-rc.1 7.6.0-beta.2 4.1.0-rc.2 7.6.0-rc.1 4.1.1 7.6.0-rc.2 4.1.2 7.6.0-rc.3 4.1.3 7.6.1 4.1.4 7.6.2 4.2.0 7.7.0 4.2.0-RC.1 7.7.0-beta.1 4.2.0-RC.2 7.7.0-beta.2 4.2.0-beta.1 7.7.0-rc.1 4.2.1 7.7.1 4.2.2 7.7.2 4.2.3 7.7.3 4.2.4 7.8.0 4.2.5 4.3.0 4.3.0-beta.1 4.3.0-rc.1 4.3.0-rc.2 4.3.0-rc.3 4.3.1 4.3.2 4.3.3 4.3.4 4.3.5 4.3.6 4.4.0 4.4.0-beta.1 4.4.0-rc.1 4.4.1 4.4.2 4.4.3 4.4.4 4.5.0 4.5.0-beta.1 4.5.0-rc.1 4.5.0-rc.3 4.5.1 4.5.2 4.5.3 4.5.4 4.5.5 4.6.0 4.6.0-beta.1 4.6.0-rc.1 4.6.1 4.6.2 4.6.3 4.6.4 4.6.5 4.7.0 4.7.0-beta.1 4.7.0-beta.2 4.7.0-rc.1 4.7.1 4.7.1-beta.1 4.7.2 4.7.3 4.7.4 4.8.0 4.8.0-beta.1 4.8.0-rc.1 4.8.0-rc.2 4.8.1 4.8.2 4.8.3 4.9.0 4.9.0-beta.1 4.9.0-rc.1 4.9.0-rc.2 4.9.1 4.9.2 4.9.3 4.9.4 4.9.5 5.0.0 5.0.0-beta.1 5.0.0-beta.2 5.0.0-rc.1 5.0.0-rc.2 5.0.0-rc.3 5.0.1 5.0.2 5.0.3 5.1.0 5.1.0-beta.1 5.1.0-rc.1 trunk 5.1.1 10.0.0 5.1.2 10.0.0-rc.1 5.1.3 10.0.0-rc.2 5.2.0 10.0.1 5.2.0-beta.1 10.0.2 5.2.0-rc.1 10.0.3 5.2.0-rc.2 10.0.4 5.2.1 10.0.5 5.2.2 10.0.6 5.2.3 10.1.0 5.2.4 10.1.0-rc.1 5.2.5 10.1.0-rc.2 5.3.0 10.1.0-rc.3 5.3.0-beta.1 10.1.0-rc.4 5.3.0-rc.1 10.1.1 5.3.0-rc.2 10.1.2 5.3.1 10.1.3 5.3.2 10.1.4 5.3.3 10.2.0 5.4.0 10.2.0-beta.1 5.4.0-beta.1 10.2.0-beta.2 5.4.0-rc.1 10.2.0-rc.1 5.4.1 10.2.1 5.4.2 10.2.2 5.4.3 10.2.3 5.4.4 10.2.4 5.4.5 10.3.0 5.5.0 10.3.0-beta.1 5.5.0-beta.1 10.3.0-beta.2 5.5.0-rc.1 10.3.0-rc.1 5.5.0-rc.2 10.3.0-rc.2 5.5.1 10.3.1 5.5.2 10.3.2 5.5.3 10.3.3 5.5.4 10.3.4 5.5.5 10.3.5 5.6.0 10.3.6 5.6.0-beta.1 10.3.7 5.6.0-rc.1 10.3.8 5.6.0-rc.2 10.4.0 5.6.1 10.4.0-beta.1 5.6.2 10.4.0-beta.2 5.6.3 10.4.0-rc.1 5.7.0 10.4.1 5.7.0-beta.1 10.4.2 5.7.0-rc.1 10.4.3 5.7.1 10.4.4 5.7.2 10.5.0 5.7.3 10.5.0-beta.1 5.8.0 10.5.0-beta.2 5.8.0-beta.1 10.5.0-rc.1 5.8.0-beta.2 10.5.0-rc.2 5.8.0-rc.1 10.5.0-rc.3 5.8.1 10.5.1 5.8.2 10.5.2 5.9.0 10.5.3 5.9.0-beta.1 10.6.0 5.9.0-rc.1 10.6.0-beta.1 5.9.0-rc.2 10.6.0-beta.2 5.9.1 10.6.0-rc.1 5.9.2 10.6.1 6.0.0 10.6.2 6.0.0-beta.1 10.7.0 6.0.0-rc.1 10.7.0-beta.1 6.0.1 10.7.0-beta.2 6.0.2 10.7.0-rc.1 6.1.0 3.0.0 6.1.0-beta.1 3.0.1 6.1.0-rc.1 3.0.2 6.1.0-rc.2 3.0.3 6.1.1 3.0.4 6.1.2 3.0.5 6.1.3 3.0.6 6.2.0 3.0.7 6.2.0-beta.1 3.0.8 6.2.0-rc.1 3.0.9 6.2.0-rc.2 3.1.0 6.2.1 3.1.1 6.2.2 3.1.2 6.2.3 3.2.0 6.3.0 3.2.1 6.3.0-beta.1 3.2.2 6.3.0-rc.1 3.2.3 6.3.0-rc.2 3.2.4 6.3.1 3.2.5 6.3.2 3.2.6 6.4.0 3.3.0 6.4.0-beta.1 3.3.1 6.4.0-rc.1 3.3.2 6.4.1 3.3.2-rc.1 6.4.2 3.3.3 6.5.0 3.3.4 6.5.0-beta.1 3.3.5 6.5.0-rc.1 3.3.6 6.5.0-rc.2 3.4.0 6.5.1 3.4.0-beta.1 6.5.2 3.4.0-rc.2 6.6.0 3.4.1 6.6.0-beta.1 3.4.2 6.6.0-rc.1 3.4.3 6.6.0-rc.2 3.4.4 6.6.1 3.4.5 6.6.2 3.4.6 6.7.0 3.4.7 6.7.0-beta.1 3.4.8 6.7.0-beta.2 3.5.0 6.7.0-rc.1 3.5.0-beta.1 6.7.1 3.5.0-rc.1 6.8.0 3.5.0-rc.2 6.8.0-beta.1 3.5.1 6.8.0-beta.2 3.5.10 6.8.0-rc.1 3.5.2 6.8.1 3.5.3 6.8.2 3.5.4 6.8.3 3.5.5 6.9.0 3.5.6 6.9.0-beta.1 3.5.7 6.9.0-beta.2 3.5.8 6.9.0-rc.1 3.5.9 6.9.1 3.6.0 6.9.2 3.6.0-beta.1 6.9.3 3.6.0-rc.1 6.9.4 3.6.0-rc.2 6.9.5 3.6.0-rc.3 7.0.0 3.6.1 7.0.0-beta.1 3.6.2 7.0.0-beta.2 3.6.3 7.0.0-beta.3 3.6.4 7.0.0-rc.1 3.6.5 7.0.0-rc.2 3.6.6 7.0.1 3.6.7 7.0.2 3.7.0 7.1.0 3.7.0-beta.1 7.1.0-beta.1 3.7.0-rc.1 7.1.0-beta.2 3.7.0-rc.2 7.1.0-rc.1 3.7.1 7.1.0-rc.2 3.7.2 7.1.1
woocommerce / packages / email-editor / src / Engine / Renderer / ContentRenderer / class-rendering-context.php
woocommerce / packages / email-editor / src / Engine / Renderer / ContentRenderer Last commit date
Layout 1 month ago Postprocessors 9 months ago Preprocessors 1 month ago class-block-renderer.php 11 months ago class-blocks-parser.php 1 year ago class-content-renderer.php 1 month ago class-preset-variable-resolver.php 2 months ago class-process-manager.php 1 month ago class-rendering-context.php 1 month ago content.css 1 year ago
class-rendering-context.php
303 lines
1 <?php
2 /**
3 * This file is part of the WooCommerce Email Editor package.
4 *
5 * @package Automattic\WooCommerce\EmailEditor
6 */
7
8 declare(strict_types = 1);
9 namespace Automattic\WooCommerce\EmailEditor\Engine\Renderer\ContentRenderer;
10
11 use Automattic\WooCommerce\EmailEditor\Integrations\Utils\Styles_Helper;
12 use WP_Theme_JSON;
13
14 /**
15 * Class Rendering_Context
16 */
17 class Rendering_Context {
18 /**
19 * Instance of the WP Theme.
20 *
21 * @var WP_Theme_JSON
22 */
23 private WP_Theme_JSON $theme_json;
24
25 /**
26 * Email-specific context data.
27 *
28 * This array contains email-specific information that can be used during rendering,
29 * such as:
30 * - 'user_id': The ID of the user receiving the email
31 * - 'recipient_email': The recipient's email address
32 * - Additional context can be added by extensions using the generic get() method
33 *
34 * @var array<string, mixed>
35 */
36 private array $email_context;
37
38 /**
39 * Email language used for deterministic direction fallback.
40 *
41 * @var string|null
42 */
43 private ?string $language;
44
45 /**
46 * Rendering_Context constructor.
47 *
48 * @param WP_Theme_JSON $theme_json Theme Json used in the email.
49 * @param array<string, mixed> $email_context Email-specific context data.
50 * @param string|null $language Email language.
51 */
52 public function __construct( WP_Theme_JSON $theme_json, array $email_context = array(), ?string $language = null ) {
53 $this->theme_json = $theme_json;
54 $this->email_context = $email_context;
55 $this->language = $language;
56 }
57
58 /**
59 * Returns WP_Theme_JSON instance that should be used during the email rendering.
60 *
61 * @return WP_Theme_JSON
62 */
63 public function get_theme_json(): WP_Theme_JSON {
64 return $this->theme_json;
65 }
66
67 /**
68 * Get the email theme styles.
69 *
70 * @return array{
71 * spacing: array{
72 * blockGap: string,
73 * padding: array{bottom: string, left: string, right: string, top: string}
74 * },
75 * color: array{
76 * background: string,
77 * text: string
78 * },
79 * typography: array{
80 * fontFamily: string
81 * }
82 * }
83 */
84 public function get_theme_styles(): array {
85 $theme = $this->get_theme_json();
86 return $theme->get_data()['styles'] ?? array();
87 }
88
89 /**
90 * Get settings from the theme.
91 *
92 * @return array
93 */
94 public function get_theme_settings() {
95 return $this->get_theme_json()->get_settings();
96 }
97
98 /**
99 * Returns the width of the layout without padding.
100 *
101 * @return string
102 */
103 public function get_layout_width_without_padding(): string {
104 $styles = $this->get_theme_styles();
105 $layout_settings = $this->get_theme_settings()['layout'] ?? array();
106 $width = Styles_Helper::parse_value( $layout_settings['contentSize'] ?? '0px' );
107 $padding = $styles['spacing']['padding'] ?? array();
108 $width -= Styles_Helper::parse_value( $padding['left'] ?? '0px' );
109 $width -= Styles_Helper::parse_value( $padding['right'] ?? '0px' );
110 return "{$width}px";
111 }
112
113 /**
114 * Translate color slug to color.
115 *
116 * @param string $color_slug Color slug.
117 * @return string
118 */
119 public function translate_slug_to_color( string $color_slug ): string {
120 $settings = $this->get_theme_settings();
121
122 $color_definitions = array_merge(
123 $settings['color']['palette']['theme'] ?? array(),
124 $settings['color']['palette']['default'] ?? array()
125 );
126 foreach ( $color_definitions as $color_definition ) {
127 if ( $color_definition['slug'] === $color_slug ) {
128 return strtolower( $color_definition['color'] );
129 }
130 }
131 return $color_slug;
132 }
133
134 /**
135 * Get the email-specific context data.
136 *
137 * @return array<string, mixed>
138 */
139 public function get_email_context(): array {
140 return $this->email_context;
141 }
142
143 /**
144 * Get the email language.
145 *
146 * @return string|null
147 */
148 public function get_language(): ?string {
149 return $this->language;
150 }
151
152 /**
153 * Get the user ID from the email context.
154 *
155 * @return int|null The user ID if available, null otherwise.
156 */
157 public function get_user_id(): ?int {
158 return isset( $this->email_context['user_id'] ) && is_numeric( $this->email_context['user_id'] ) ? (int) $this->email_context['user_id'] : null;
159 }
160
161 /**
162 * Get the recipient email address from the email context.
163 *
164 * @return string|null The email address if available, null otherwise.
165 */
166 public function get_recipient_email(): ?string {
167 return isset( $this->email_context['recipient_email'] ) && is_string( $this->email_context['recipient_email'] ) ? $this->email_context['recipient_email'] : null;
168 }
169
170 /**
171 * Get a specific value from the email context.
172 *
173 * This method allows extensions to access custom context data that may be
174 * specific to their implementation (e.g., order IDs, email types, etc.).
175 *
176 * @param string $key The context key.
177 * @param mixed $default_value Default value if key is not found.
178 * @return mixed The context value or default.
179 */
180 public function get( string $key, $default_value = null ) {
181 return $this->email_context[ $key ] ?? $default_value;
182 }
183
184 /**
185 * Whether this render should use right-to-left direction.
186 *
187 * @return bool
188 */
189 public function is_rtl(): bool {
190 if ( isset( $this->email_context['is_rtl'] ) && is_bool( $this->email_context['is_rtl'] ) ) {
191 return $this->email_context['is_rtl'];
192 }
193
194 $primary_language = $this->get_primary_language_subtag( $this->language );
195 if ( null === $primary_language ) {
196 return false;
197 }
198
199 return in_array(
200 $primary_language,
201 array(
202 'ar',
203 'arc',
204 'azb',
205 'ckb',
206 'dv',
207 'fa',
208 'he',
209 'ku',
210 'nqo',
211 'ps',
212 'sd',
213 'ug',
214 'ur',
215 'yi',
216 ),
217 true
218 );
219 }
220
221 /**
222 * Get the HTML/CSS text direction.
223 *
224 * @return string
225 */
226 public function get_text_direction(): string {
227 return $this->is_rtl() ? 'rtl' : 'ltr';
228 }
229
230 /**
231 * Get the default physical text alignment for this render.
232 *
233 * @return string
234 */
235 public function get_default_text_align(): string {
236 return $this->is_rtl() ? 'right' : 'left';
237 }
238
239 /**
240 * Get the physical start side.
241 *
242 * @return string
243 */
244 public function get_start_side(): string {
245 return $this->is_rtl() ? 'right' : 'left';
246 }
247
248 /**
249 * Get the physical end side.
250 *
251 * @return string
252 */
253 public function get_end_side(): string {
254 return $this->is_rtl() ? 'left' : 'right';
255 }
256
257 /**
258 * Sanitize a text alignment value.
259 *
260 * @param mixed $alignment Alignment candidate.
261 * @return string|null
262 */
263 public function sanitize_text_align( $alignment ): ?string {
264 if ( ! is_string( $alignment ) ) {
265 return null;
266 }
267 return in_array( $alignment, array( 'left', 'center', 'right' ), true ) ? $alignment : null;
268 }
269
270 /**
271 * Resolve a text alignment value with direction-aware default.
272 *
273 * @param mixed $alignment Alignment candidate.
274 * @return string
275 */
276 public function resolve_text_align( $alignment ): string {
277 return $this->sanitize_text_align( $alignment ) ?? $this->get_default_text_align();
278 }
279
280 /**
281 * Get the primary language subtag from a locale/language value.
282 *
283 * @param string|null $language Language or locale.
284 * @return string|null
285 */
286 private function get_primary_language_subtag( ?string $language ): ?string {
287 if ( null === $language || '' === trim( $language ) ) {
288 return null;
289 }
290
291 $language = strtolower( str_replace( '_', '-', trim( $language ) ) );
292 $parts = explode( '-', $language );
293 $primary = $parts[0] ?? '';
294 $length = strlen( $primary );
295
296 if ( $length < 2 || $length > 3 ) {
297 return null;
298 }
299
300 return strspn( $primary, 'abcdefghijklmnopqrstuvwxyz' ) === $length ? $primary : null;
301 }
302 }
303