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