PluginProbe
Polylang / 3.8.10
Polylang v3.8.10
3.8.10 3.8.9 3.8.8 3.8.7 3.8.6 3.8.5 3.8.4 3.8.3 2.7 2.7.0.1 2.7.1 2.7.2 2.7.3 2.7.4 2.8 2.8.1 2.8.2 2.8.3 2.8.4 2.9 2.9.1 2.9.2 3.0 3.0.1 3.0.2 All 234 releases
polylang / js / build / block-editor.js

block-editor.js in Polylang 3.8.10, at js/build/block-editor.js

454 lines 15.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /******/ (() => { // webpackBootstrap
2 /******/ var __webpack_modules__ = ({
3
4 /***/ 631
5 (module) {
6
7 module.exports = (function() { return this["wp"]["apiFetch"]; }());
8
9 /***/ }
10
11 /******/ });
12 /************************************************************************/
13 /******/ // The module cache
14 /******/ const __webpack_module_cache__ = {};
15 /******/
16 /******/ // The require function
17 /******/ function __webpack_require__(moduleId) {
18 /******/ // Check if module is in cache
19 /******/ const cachedModule = __webpack_module_cache__[moduleId];
20 /******/ if (cachedModule !== undefined) {
21 /******/ return cachedModule.exports;
22 /******/ }
23 /******/ // Create a new module (and put it into the cache)
24 /******/ const module = __webpack_module_cache__[moduleId] = {
25 /******/ // no module.id needed
26 /******/ // no module.loaded needed
27 /******/ exports: {}
28 /******/ };
29 /******/
30 /******/ // Execute the module function
31 /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
32 /******/
33 /******/ // Return the exports of the module
34 /******/ return module.exports;
35 /******/ }
36 /******/
37 /************************************************************************/
38 /******/ /* webpack/runtime/compat get default export */
39 /******/ // getDefaultExport function for compatibility with non-harmony modules
40 /******/ __webpack_require__.n = (module) => {
41 /******/ const getter = module && module.__esModule ?
42 /******/ () => (module['default']) :
43 /******/ () => (module);
44 /******/ __webpack_require__.d(getter, { a: getter });
45 /******/ return getter;
46 /******/ };
47 /******/
48 /******/ /* webpack/runtime/define property getters */
49 /******/ // define getter/value functions for harmony exports
50 /******/ __webpack_require__.d = (exports, definition) => {
51 /******/ for(var key in definition) {
52 /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
53 /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
54 /******/ }
55 /******/ }
56 /******/ };
57 /******/
58 /******/ /* webpack/runtime/hasOwnProperty shorthand */
59 /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop));
60 /******/
61 /************************************************************************/
62 let __webpack_exports__ = {};
63 // This entry needs to be wrapped in an IIFE because it needs to be in strict mode.
64 (() => {
65 "use strict";
66
67 ;// ./js/src/lib/confirmation-modal.js
68 /**
69 * @package Polylang
70 */
71
72 const languagesList = jQuery('.post_lang_choice');
73
74 // Dialog box for alerting the user about a risky changing.
75 const initializeConfirmationModal = () => {
76 // We can't use underscore or lodash in this common code because it depends of the context classic or block editor.
77 // Classic editor underscore is loaded, Block editor lodash is loaded.
78 const {
79 __
80 } = wp.i18n;
81
82 // Create dialog container.
83 const dialogContainer = jQuery('<div/>', {
84 id: 'pll-dialog',
85 style: 'display:none;'
86 }).text(__('Are you sure you want to change the language of the current content?', 'polylang'));
87
88 // Put it after languages list dropdown.
89 // PHPCS ignore dialogContainer is a new safe HTML code generated above.
90 languagesList.after(dialogContainer); // phpcs:ignore WordPressVIPMinimum.JS.HTMLExecutingFunctions.after
91
92 const dialogResult = new Promise((confirm, cancel) => {
93 const confirmDialog = what => {
94 // phpcs:ignore PEAR.Functions.FunctionCallSignature.Indent
95 switch (what) {
96 // phpcs:ignore PEAR.Functions.FunctionCallSignature.Indent
97 case 'yes':
98 // Confirm the new language.
99 languagesList.data('old-value', languagesList.children(':selected').first().val());
100 confirm();
101 break;
102 case 'no':
103 // Revert to the old language.
104 languagesList.val(languagesList.data('old-value'));
105 cancel('Cancel');
106 break;
107 }
108 dialogContainer.dialog('close'); // phpcs:ignore PEAR.Functions.FunctionCallSignature.Indent
109 }; // phpcs:ignore PEAR.Functions.FunctionCallSignature.Indent
110
111 // Initialize dialog box in the case a language is selected but not added in the list.
112 const dialogOptions = {
113 autoOpen: false,
114 modal: true,
115 draggable: false,
116 resizable: false,
117 title: __('Change language', 'polylang'),
118 minWidth: 600,
119 maxWidth: '100%',
120 open: function (event, ui) {
121 // Change dialog box position for rtl language
122 if (jQuery('body').hasClass('rtl')) {
123 jQuery(this).parent().css({
124 right: jQuery(this).parent().css('left'),
125 left: 'auto'
126 });
127 }
128 },
129 close: function (event, ui) {
130 // When we're closing the dialog box we need to cancel the language change as we click on Cancel button.
131 confirmDialog('no');
132 },
133 buttons: [{
134 text: __('OK', 'polylang'),
135 click: function (event) {
136 confirmDialog('yes');
137 }
138 }, {
139 text: __('Cancel', 'polylang'),
140 click: function (event) {
141 confirmDialog('no');
142 }
143 }]
144 };
145 if (jQuery.ui.version >= '1.12.0') {
146 Object.assign(dialogOptions, {
147 classes: {
148 'ui-dialog': 'pll-confirmation-modal'
149 }
150 });
151 } else {
152 Object.assign(dialogOptions, {
153 dialogClass: 'pll-confirmation-modal'
154 }); // jQuery UI 1.11.4 - WP < 5.6
155 }
156 dialogContainer.dialog(dialogOptions);
157 });
158 return {
159 dialogContainer,
160 dialogResult
161 };
162 };
163 const initializeLanguageOldValue = () => {
164 // Keep the old language value to be able to compare to the new one and revert to it if necessary.
165 languagesList.attr('data-old-value', languagesList.children(':selected').first().val());
166 };
167 ;// ./js/src/lib/metabox-autocomplete.js
168 /**
169 * @package Polylang
170 */
171
172 // Translations autocomplete input box.
173 function initMetaboxAutoComplete() {
174 jQuery('.tr_lang').each(function () {
175 var tr_lang = jQuery(this).attr('id').substring(8);
176 var td = jQuery(this).parent().parent().siblings('.pll-edit-column');
177 jQuery(this).autocomplete({
178 minLength: 0,
179 source: ajaxurl + '?action=pll_posts_not_translated' + '&post_language=' + jQuery('.post_lang_choice').val() + '&translation_language=' + tr_lang + '&post_type=' + jQuery('#post_type').val() + '&_pll_nonce=' + jQuery('#_pll_nonce').val(),
180 select: function (event, ui) {
181 jQuery('#htr_lang_' + tr_lang).val(ui.item.id);
182 // ui.item.link is built and come from server side and is well escaped when necessary
183 td.html(ui.item.link); // phpcs:ignore WordPressVIPMinimum.JS.HTMLExecutingFunctions.html
184 }
185 });
186
187 // when the input box is emptied
188 jQuery(this).on('blur', function () {
189 if (!jQuery(this).val()) {
190 jQuery('#htr_lang_' + tr_lang).val(0);
191 // Value is retrieved from HTML already generated server side
192 td.html(td.siblings('.hidden').children().clone()); // phpcs:ignore WordPressVIPMinimum.JS.HTMLExecutingFunctions.html
193 }
194 });
195 });
196 }
197 // EXTERNAL MODULE: external {"this":["wp","apiFetch"]}
198 var external_this_wp_apiFetch_ = __webpack_require__(631);
199 var external_this_wp_apiFetch_default = /*#__PURE__*/__webpack_require__.n(external_this_wp_apiFetch_);
200 ;// ./node_modules/@wpsyntex/polylang-react-library/build/middlewares/filter-path.js
201 /**
202 * Filters requests for translatable entities.
203 * This logic is shared across all Polylang plugins.
204 *
205 * @since 3.5
206 *
207 * @param {Object} options - API fetch options object.
208 * @param {Array} filteredRoutes - Array of route paths to filter.
209 * @param {Function} filter - Function to filter matching routes.
210 * @return {Object} Modified REST request options.
211 */
212 const filterPathMiddleware = (options, filteredRoutes, filter) => {
213 const cleanPath = options.path.split('?')[0].replace(/^\/+|\/+$/g, ''); // Get path without query parameters and trim '/'.
214
215 return Object.values(filteredRoutes).find(path => cleanPath === path) ? filter(options) : options;
216 };
217 /* harmony default export */ const filter_path = (filterPathMiddleware);
218 ;// ./node_modules/@wpsyntex/polylang-react-library/build/middlewares/editors-requests-filter.js
219 /**
220 * WordPress dependencies.
221 */
222
223
224 /*
225 * Internal dependencies.
226 */
227
228
229 /**
230 * Safely filters requests for translatable entities in block editor type screens.
231 * Ensures that `pllFilteredRoutes` has been well defined on server side and
232 * that the filtered request is a REST one.
233 *
234 * @param {Function} filterCallback - Function to filter API fetch options.
235 */
236 const editorsRequestsFilter = filterCallback => {
237 external_this_wp_apiFetch_default().use((options, next) => {
238 /*
239 * If options.url is defined, this is not a REST request but a direct call to post.php for legacy metaboxes.
240 * If `filteredRoutes` is not defined, return early.
241 */
242 if ('undefined' !== typeof options.url || 'undefined' === typeof window.pllFilteredRoutes) {
243 return next(options);
244 }
245 return next(filter_path(options, window.pllFilteredRoutes, filterCallback));
246 });
247 };
248 /* harmony default export */ const editors_requests_filter = (editorsRequestsFilter);
249 ;// ./js/src/block-editor.js
250 /**
251 * @package Polylang
252 */
253
254
255
256
257
258 /**
259 * Gets the language of the currently edited post, fallback to default language if none is found.
260 *
261 * @since 2.5
262 *
263 * @return {Element.value}
264 */
265 function getCurrentLanguage() {
266 const lang = document.querySelector('[name=post_lang_choice]');
267 if (null === lang) {
268 return pllDefaultLanguage;
269 }
270 return lang.value;
271 }
272
273 /**
274 * Adds language parameter according to the current one (query string for GET, body for PUT and POST).
275 *
276 * @since 3.5
277 *
278 * @param {APIFetchOptions} options
279 * @returns {APIFetchOptions}
280 */
281 function addLanguageParameter(options) {
282 if ('undefined' === typeof options.data || null === options.data) {
283 // GET
284 options.path += (options.path.indexOf('?') >= 0 ? '&lang=' : '?lang=') + getCurrentLanguage();
285 } else {
286 // PUT, POST
287 options.data.lang = getCurrentLanguage();
288 }
289 return options;
290 }
291
292 /**
293 * Filter REST API requests to add the language in the request
294 *
295 * @since 2.5
296 */
297 editors_requests_filter(addLanguageParameter);
298
299 /**
300 * Handles internals of the metabox:
301 * Language select, autocomplete input field.
302 *
303 * @since 1.5
304 *
305 * Save post after lang choice is done and redirect to the same page for refreshing all the data.
306 *
307 * @since 2.5
308 *
309 * Link post saving after refreshing the metabox.
310 *
311 * @since 3.0
312 */
313 jQuery(function ($) {
314 // Initialize current language to be able to compare if it changes.
315 initializeLanguageOldValue();
316
317 // Ajax for changing the post's language in the languages metabox
318 $('.post_lang_choice').on('change', function (event) {
319 const {
320 select,
321 dispatch,
322 subscribe
323 } = wp.data;
324 const emptyPost = isEmptyPost();
325 const {
326 addQueryArgs
327 } = wp.url;
328
329 // Initialize the confirmation dialog box.
330 const confirmationModal = initializeConfirmationModal();
331 const {
332 dialogContainer: dialog
333 } = confirmationModal;
334 let {
335 dialogResult
336 } = confirmationModal;
337 const selectedOption = event.target; // The selected option in the dropdown list.
338
339 // Specific case for empty posts.
340 // Place at the beginning because window.location change triggers automatically page reloading.
341 if (location.pathname.match(/post-new.php/gi) && emptyPost) {
342 reloadPageForEmptyPost(selectedOption.value);
343 }
344
345 // Otherwise send an ajax request to refresh the legacy metabox and set the post language with the new language.
346 // It needs a confirmation of the user before changing the language.
347 // Need to wait the ajax response before triggering the block editor post save action.
348 if ($(this).data('old-value') !== selectedOption.value && !emptyPost) {
349 dialog.dialog('open');
350 } else {
351 // Update the old language with the new one to be able to compare it in the next change.
352 // Because the page isn't reloaded in this case.
353 initializeLanguageOldValue();
354 dialogResult = Promise.resolve();
355 }
356 dialogResult.then(() => {
357 let data = {
358 // phpcs:ignore PEAR.Functions.FunctionCallSignature.Indent
359 action: 'post_lang_choice',
360 lang: selectedOption.value,
361 post_type: $('#post_type').val(),
362 post_id: $('#post_ID').val(),
363 _pll_nonce: $('#_pll_nonce').val()
364 };
365
366 // Update post language in database as soon as possible.
367 // Because, in addition of the block editor save process, the legacy metabox uses a post.php process to update the language and is too late compared to the page reload.
368 $.post(ajaxurl, data, function () {
369 blockEditorSavePostAndReloadPage();
370 });
371 }, () => {} // Do nothing when promise is rejected by clicking the Cancel dialog button.
372 );
373 function isEmptyPost() {
374 const editor = select('core/editor');
375 return !editor.getEditedPostAttribute('title')?.trim() && !editor.getEditedPostContent() && !editor.getEditedPostAttribute('excerpt')?.trim();
376 }
377
378 /**
379 * Reload the block editor page for empty posts.
380 *
381 * @param {string} lang The target language code.
382 */
383 function reloadPageForEmptyPost(lang) {
384 // Change the new_lang parameter with the new language value for reloading the page
385 // WPCS location.search is never written in the page, just used to reload page with the right value of new_lang
386 // new_lang input is controlled server side in PHP. The value come from the dropdown list of language returned and escaped server side.
387 // Notice that window.location changing triggers automatically page reloading.
388 if (-1 != location.search.indexOf('new_lang')) {
389 // use regexp non capturing group to replace new_lang parameter no matter where it is and capture other parameters which can be behind it
390 window.location.search = window.location.search.replace(/(?:new_lang=[^&]*)(&)?(.*)/, 'new_lang=' + lang + '$1$2'); // phpcs:ignore WordPressVIPMinimum.JS.Window.location, WordPressVIPMinimum.JS.Window.VarAssignment
391 } else {
392 window.location.search = window.location.search + (-1 != window.location.search.indexOf('?') ? '&' : '?') + 'new_lang=' + lang; // phpcs:ignore WordPressVIPMinimum.JS.Window.location, WordPressVIPMinimum.JS.Window.VarAssignment
393 }
394 }
395 ;
396
397 /**
398 * Triggers block editor post save and reload the block editor page when everything is ok.
399 */
400 function blockEditorSavePostAndReloadPage() {
401 let unsubscribe = null;
402 const previousPost = select('core/editor').getCurrentPost();
403
404 // Listen if the savePost is completely done by subscribing to its events.
405 const savePostIsDone = new Promise(function (resolve, reject) {
406 unsubscribe = subscribe(function () {
407 const post = select('core/editor').getCurrentPost();
408 const {
409 id,
410 status,
411 type
412 } = post;
413 const error = select('core').getLastEntitySaveError('postType', type, id);
414 if (error) {
415 reject();
416 }
417 if (previousPost.modified !== post.modified) {
418 if (location.pathname.match(/post-new.php/gi) && status !== 'auto-draft' && id) {
419 window.history.replaceState({
420 id
421 }, 'Post ' + id, addQueryArgs('post.php', {
422 post: id,
423 action: 'edit'
424 }));
425 }
426 resolve();
427 }
428 });
429 });
430
431 // Triggers the post save.
432 dispatch('core/editor').savePost();
433
434 // Process
435 savePostIsDone.then(function () {
436 // If the post is well saved, we can reload the page
437 window.location.reload();
438 }, function () {
439 // If the post save failed
440 unsubscribe();
441 }).catch(function () {
442 // If an exception is thrown
443 unsubscribe();
444 });
445 }
446 ;
447 });
448 initMetaboxAutoComplete();
449 });
450 })();
451
452 this.polylang = __webpack_exports__;
453 /******/ })()
454 ;