PluginProbe
Elementor Website Builder – more than just a page builder / 3.11.5
Elementor Website Builder – more than just a page builder v3.11.5
4.3.0-beta2 4.3.0-beta1 4.2.4 4.2.3 4.2.2 4.2.1 4.2.0 4.1.5 4.2.0-beta2 4.2.0-dev2 4.2.0-beta1 4.1.4 4.1.3 4.1.2 4.1.1 4.1.0 4.1.0-beta3 4.1.0-dev3 4.0.9 4.1.0-beta2 4.1.0-dev2 4.0.8 4.1.0-beta1 4.1.0-dev1 4.0.7 All 451 releases
elementor / core / editor / editor-loader.php

editor-loader.php in Elementor Website Builder – more than just a page builder 3.11.5, at core/editor/editor-loader.php

240 lines 6.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace Elementor\Core\Editor;
3
4 use Elementor\Core\Editor\Config_Providers\Config_Provider_Interface;
5 use Elementor\Core\Utils\Collection;
6 use Elementor\Utils;
7
8 if ( ! defined( 'ABSPATH' ) ) {
9 exit; // Exit if accessed directly.
10 }
11
12 class Editor_Loader {
13 /**
14 * @var Config_Provider_Interface
15 */
16 private $config_provider;
17
18 /**
19 * @param Config_Provider_Interface $config_provider
20 */
21 public function __construct( Config_Provider_Interface $config_provider ) {
22 $this->config_provider = $config_provider;
23 }
24
25 /**
26 * @return void
27 */
28 public function register_hooks() {
29 $script_configs = $this->get_script_configs();
30
31 // Pointing WordPress to use translations for external files ('assets/js/editor.strings.js') and not
32 // for the original file (assets/js/editor.js).
33 add_filter( 'load_script_textdomain_relative_path', function ( $relative_path, $src ) use ( $script_configs ) {
34 return $this->replace_requested_translation_file( $relative_path, $src, $script_configs );
35 }, 10, 2 );
36 }
37
38 /**
39 * @return void
40 */
41 public function register_scripts() {
42 $script_configs = $this->get_script_configs();
43
44 foreach ( $script_configs as $script_config ) {
45 wp_register_script(
46 $script_config['handle'],
47 $script_config['src'],
48 $script_config['deps'],
49 $script_config['version'],
50 $script_config['in_footer']
51 );
52 }
53 }
54
55 /**
56 * @return void
57 */
58 public function enqueue_scripts() {
59 foreach ( $this->config_provider->get_script_handles_to_enqueue() as $script_handle ) {
60 wp_enqueue_script( $script_handle );
61 }
62 }
63
64 /**
65 * @return void
66 */
67 public function load_scripts_translations() {
68 $script_configs = $this->get_script_configs();
69
70 foreach ( $script_configs as $script_config ) {
71 if ( $script_config['i18n']['domain'] ) {
72 wp_set_script_translations(
73 $script_config['handle'],
74 $script_config['i18n']['domain']
75 );
76 }
77 }
78 }
79
80 /**
81 * @return void
82 */
83 public function register_styles() {
84 $styles_config = $this->get_style_configs();
85
86 foreach ( $styles_config as $style_config ) {
87 wp_register_style(
88 $style_config['handle'],
89 $style_config['src'],
90 $style_config['deps'],
91 $style_config['version'],
92 $style_config['media']
93 );
94 }
95 }
96
97 /**
98 * @return void
99 */
100 public function enqueue_styles() {
101 foreach ( $this->config_provider->get_style_handles_to_enqueue() as $style_handle ) {
102 wp_enqueue_style( $style_handle );
103 }
104 }
105
106 /**
107 * @return void
108 */
109 public function print_root_template() {
110 // Exposing the path for the view part to render the body of the editor template.
111 $body_file_path = $this->config_provider->get_template_body_file_path();
112
113 include ELEMENTOR_PATH . 'includes/editor-templates/editor-wrapper.php';
114 }
115
116 /**
117 * @return Collection
118 */
119 private function get_script_configs() {
120 return $this->normalize_asset_configs(
121 $this->config_provider->get_script_configs(),
122 'script'
123 );
124 }
125
126 /**
127 * @return Collection
128 */
129 private function get_style_configs() {
130 return $this->normalize_asset_configs(
131 $this->config_provider->get_style_configs(),
132 'style'
133 );
134 }
135
136 /**
137 * Normalize script/style configs to enqueue and register methods.
138 *
139 * @param array $script_configs
140 * @param string $type can be ['script', 'style']
141 *
142 * @return Collection
143 */
144 private function normalize_asset_configs( array $script_configs, $type ) {
145 $additional_defaults = 'style' === $type ?
146 [ 'media' => 'all' ] :
147 [
148 'in_footer' => true,
149 'i18n' => [
150 'domain' => null,
151 'replace_requested_file' => false,
152 'replace_requested_file_callback' => function ( $relative_path ) {
153 // By default, we suffix the file with `.strings` e.g 'assets/js/editor.js' => 'assets/js/editor.strings.js'.
154
155 // Translations are always based on the non-minified filename.
156 $relative_path_without_ext = preg_replace( '/(\.min)?\.js$/i', '', $relative_path );
157
158 return implode( '.', [
159 $relative_path_without_ext,
160 'strings',
161 'js',
162 ] );
163 },
164 ],
165 ];
166
167 $default = array_replace_recursive( [
168 'handle' => '',
169 'src' => '',
170 'deps' => [],
171 'version' => ELEMENTOR_VERSION,
172 'in_footer' => true,
173 ], $additional_defaults );
174
175 $replacements = [
176 '{{ELEMENTOR_ASSETS_URL}}' => ELEMENTOR_ASSETS_URL,
177 '{{MIN_SUFFIX}}' => ( Utils::is_script_debug() || Utils::is_elementor_tests() ) ? '' : '.min',
178 '{{DIRECTION_SUFFIX}}' => is_rtl() ? '-rtl' : '',
179 ];
180
181 return Collection::make( $script_configs )
182 ->filter( function ( $config ) {
183 return ! empty( $config['handle'] ) && ! empty( $config['src'] );
184 } )
185 ->map( function ( $config ) use ( $default, $replacements ) {
186 // Assign default values.
187 $config = array_replace_recursive( $default, $config );
188
189 // Replace placeholders with actual values.
190 foreach ( $replacements as $replacement_key => $replacement_value ) {
191 $config['src'] = str_replace(
192 $replacement_key,
193 $replacement_value,
194 $config['src']
195 );
196 }
197
198 return $config;
199 } );
200 }
201
202 /**
203 * The purpose of this function is to replace the requested translation file
204 * with a file that contains all the translations for specific scripts.
205 *
206 * When writing a script and using Webpack's dynamic load feature,
207 * the script will be split into multiple chunks,
208 * therefore the translations that generated by WordPress will also split into multiple files,
209 * for that reason we replace the requested translation file with another file (generated in the build process)
210 * that contains all the translations for the specific script (including dynamically loaded chunks).
211 *
212 * Want to go deeper? Read the following article:
213 * @see https://developer.wordpress.com/2022/01/06/wordpress-plugin-i18n-webpack-and-composer/
214 *
215 * @param string $relative_path
216 * @param string $src
217 * @param Collection $script_configs Collection of all the script configs
218 *
219 * @return string
220 */
221 private function replace_requested_translation_file( $relative_path, $src, $script_configs ) {
222 $script_config = $script_configs->find( function ( $script_config ) use ( $src ) {
223 return $script_config['src'] === $src;
224 } );
225
226 $should_suffix_path = $script_config &&
227 $script_config['i18n']['domain'] &&
228 $script_config['i18n']['replace_requested_file'];
229
230 if ( ! $should_suffix_path ) {
231 return $relative_path;
232 }
233
234 return $script_config['i18n']['replace_requested_file_callback'](
235 $relative_path,
236 $script_config
237 );
238 }
239 }
240