Add PSR HTTP Message Interfaces and Dependencies

- Implemented StreamInterface, UploadedFileInterface, and UriInterface as per PSR standards.
- Added getallheaders function to retrieve HTTP headers in a compatible manner.
- Included LICENSE files for ralouphie/getallheaders and symfony/deprecation-contracts.
- Introduced function for triggering deprecation notices in Symfony.
This commit is contained in:
2025-12-28 12:44:00 +01:00
parent cf600ae727
commit cd264483f8
410 changed files with 60841 additions and 16 deletions

View File

@@ -0,0 +1,312 @@
'use strict';
(() => {
const { createBlock } = wp.blocks;
const { dispatch, select } = wp.data;
class atfpCreateNewBlock {
constructor() {
this.updateBlockStore = {};
this.loaderRemove = null;
this.loader = null;
this.replaceAttributes = null;
this.updateBlockId = new Array();
}
copyTranslateText = () => {
// Get the current selection object
const selection = window.getSelection();
// Create a new range object
const range = document.createRange();
// Select the contents of the copy text element
range.selectNodeContents(document.getElementById('atfp-copy-text'));
// Remove any existing selections
selection.removeAllRanges();
// Add the new range to the selection
selection.addRange(range);
// Execute the copy command
document.execCommand('copy');
// Clear the selection
selection.removeAllRanges();
}
noticeInitialize = () => {
dispatch("core/notices").createNotice('info', 'To enable translation, please include the Make This Content Available for Translation text in your block content. For help, watch the video and click <b>"Copy Text"</b> to use. Then, paste it into the section of your block you want automatically translated',
{
isDismissible : false,
id: 'atfp-notice-id',
actions: [
{
label: 'Watch Video.',
url: `${atfpAddBlockVars.atfp_demo_page_url}#custom-block-translate`,
},
],
__unstableHTML: true
}).then(()=>{
const targetAnchor=document.querySelector(`a[href^="${atfpAddBlockVars.atfp_demo_page_url}#custom-block-translate"]`);
if(targetAnchor){
targetAnchor.addEventListener('click', (e)=>{
e.preventDefault();
window.open(targetAnchor.href, '_blank');
})
}
});
}
copyBtnInitialize = () => { // Initialize the copy button
const copyBtn = document.createElement('div'); // Create a new div element for the copy button
copyBtn.id = 'atfp-copy-btn'; // Set the ID of the copy button
copyBtn.innerHTML = 'Copy Text'; // Set the inner HTML of the copy button
copyBtn.addEventListener('click', this.copyTranslateText); // Add click event listener to copy text
copyBtn.ariaLabel = 'Copy Text'; // Set the aria-label for accessibility
copyBtn.title = 'Click to copy the text "Make This Content Available for Translation"'; // Tooltip message
const copyText = document.createElement('div'); // Create a new div element for the copy text
copyText.id = 'atfp-copy-text'; // Set the ID of the copy text div
copyText.innerHTML = 'Make This Content Available for Translation'; // Set the inner HTML of the copy text div
document.body.appendChild(copyBtn); // Append the copy button to the document body
document.body.appendChild(copyText); // Append the copy text to the document body
}
addBlockInitialize = (newBlock) => {
this.newBlock = newBlock;
this.creteNewBlock();
this.skeletonLoader();
}
removeLoader = () => {
clearTimeout(this.loaderRemove);
this.loaderRemove = setTimeout(() => {
if (this.loader) {
this.loader.remove();
}
}, 2000);
}
creteNewBlock = () => {
const newBlock = createBlock(this.newBlock);
this.updateBlockData(newBlock);
}
updateBlockData = async (Block) => {
await dispatch('core/block-editor').insertBlocks([Block]);
setTimeout(() => {
const blockWrp = document.getElementById(`block-${Block.clientId}`);
if (blockWrp) {
blockWrp.appendChild(this.loader);
}
}, 100);
setTimeout(() => {
this.updateBlockContent(Block);
}, 400);
}
updateBlockContent = (Block) => {
const newBlock = document.getElementById(`block-${Block.clientId}`);
if (newBlock) {
this.updateContent(newBlock);
}
return;
}
updateContent = async (ele) => {
const element = ele;
let i = 1;
this.removeLoader();
if (element) {
if (element.contentEditable == 'true' && element.children.length < 2) {
element.innerHTML = 'Make This Content Available for Translation';
} else {
const innerElements = element.getElementsByTagName('*');
for (let innerElement of innerElements) {
if (i === innerElements.length) {
this.removeLoader();
setTimeout(() => {
this.updateBlockFromStore();
}, 500);
}
i++;
if (["SCRIPT", "STYLE", "META", "LINK", "TITLE", "NOSCRIPT", "STYLE", "SCRIPT", "NOSCRIPT", "STYLE", "SCRIPT", "NOSCRIPT", "STYLE", "SCRIPT", "NOSCRIPT"].includes(innerElement.tagName)) {
continue;
}
if (innerElement.childNodes.length > 0) {
innerElement.childNodes.forEach((child) => {
if (child.nodeType === Node.TEXT_NODE) {
this.updateBlockAttr(innerElement, child);
}
});
}
}
}
}
}
updateBlockAttr = (innerElement, child) => {
let blockId = false;
if (innerElement.classList.contains('wp-block')) {
blockId = innerElement.dataset.block;
} else {
const parentBlock = innerElement.closest('.wp-block');
if (parentBlock) {
blockId = parentBlock.dataset.block;
}
}
const blockAttributes = select('core/block-editor').getBlockAttributes(blockId);
let index = 0;
if (!this.updateBlockStore[blockId]) {
let attributes = JSON.parse(JSON.stringify(blockAttributes));
this.updateBlockStore[blockId] = { attributes: attributes };
this.updateBlockStore[blockId].updateBlockData = {};
}
const updateNestedAttributes = async (attributes, child) => {
const updateAttributes = async (key) => {
index++;
if (typeof attributes[key] === 'string' && attributes[key].trim() !== '' && (attributes[key].trim() === child.textContent.trim() || attributes[key] === child.textContent.trim())) {
const originalValue = attributes[key];
const newValue = 'Make This Content Available for Translation ' + index;
this.updateBlockStore[blockId].updateBlockData[newValue.replace(/\s+/g, '-')] = originalValue;
attributes[key] = newValue;
}
};
if (typeof attributes === 'object' && attributes !== null) {
for (const key of Object.keys(attributes)) {
await updateAttributes(key);
if (typeof attributes[key] === 'object' && attributes[key] !== null) {
await updateNestedAttributes(attributes[key], child); // Recursively update nested objects
}
}
}
};
const blockStoreAttributes = this.updateBlockStore[blockId].attributes;
updateNestedAttributes(blockStoreAttributes, child);
}
updateBlockFromStore = () => {
const blockStoreAttributes = this.updateBlockStore;
Object.keys(blockStoreAttributes).forEach((blockId) => {
const blockAttributes = blockStoreAttributes[blockId].attributes;
this.removeLoader();
dispatch('core/block-editor').updateBlockAttributes(blockId, blockAttributes).then(() => {
clearTimeout(this.replaceAttributes);
this.replaceAttributes = setTimeout(() => {
this.removeLoader();
const blockIds = Object.keys(this.updateBlockStore);
this.replaceBlockContent(blockIds[0]);
}, 500);
});
});
}
replaceBlockContent = (blockId) => {
const blockStoreAttributes = this.updateBlockStore;
const checkValidAttributes = (value = false, blockId) => {
const blockElement = document.querySelector(`#block-${blockId}`);
const regex = new RegExp(value, 'g'); // Create regex from the value parameter with global flag
const matchFound = regex.test(blockElement.innerText); // Check if the regex matches
return matchFound; // Return the result of the regex test directly
};
const blockAttributes = blockStoreAttributes[blockId].attributes;
const upateNestedAttributes = async (attributes) => {
const updateAttributes = async (key) => {
if (typeof attributes[key] === 'string' && attributes[key].includes('Make This Content Available for Translation')) {
try {
const keyWithDashes = attributes[key].replace(/\s+/g, '-');
const originalValue = this.updateBlockStore[blockId].updateBlockData[keyWithDashes];
const status = checkValidAttributes(attributes[key], blockId);
if (!status) {
attributes[key] = originalValue;
} else {
attributes[key] = 'Make This Content Available for Translation';
}
} catch (e) {
console.log(`${attributes[key]} is not valid JSON.`);
}
}
};
if (typeof attributes === 'object' && attributes !== null) {
for (const key of Object.keys(attributes)) {
await updateAttributes(key);
if (typeof attributes[key] === 'object' && attributes[key] !== null) {
await upateNestedAttributes(attributes[key]); // Recursively update nested objects
}
}
}
}
upateNestedAttributes(blockAttributes);
setTimeout(() => {
dispatch('core/block-editor').updateBlockAttributes(blockId, blockAttributes).then(() => {
const blockIds = Object.keys(this.updateBlockStore);
if (blockIds.length > 0) {
this.updateBlockId.push(blockId);
dispatch('core/block-editor').selectBlock(null);
this.removeLoader();
const firstBlockId = blockIds.find(id => !this.updateBlockId.includes(id));
if (firstBlockId) {
this.replaceBlockContent(firstBlockId);
}
}
});
}, 500);
}
skeletonLoader = () => {
const loader = document.createElement('div');
const loaderContainer = () => {
const container = '<style>.atfp-loader-wrapper{position:absolute;width:100%;height:100%;top:0;left:0;z-index:99999;}.atfp-loader-container{width:100%;height:100%;}.atfp-loader-skeleton{--skbg:hsl(227deg, 13%, 50%, 0.2);display:grid;gap:20px;width:100%;height:100%;background:#ffffff;padding:15px;border-radius:8px;box-shadow:0 4px 12px rgba(0, 0, 0, 0.1);transition:transform 0.3s ease;transform:scale(1.02);}.atfp-loader-shimmer{display:flex;aspect-ratio:2/1;width:100%;height:100%;background:var(--skbg);border-radius:4px;overflow:hidden;position:relative;}.atfp-loader-shimmer::before{content:"";position:absolute;width:100%;height:100%;background-image:linear-gradient(-90deg,transparent 8%,rgba(255,255,255,0.28) 18%,transparent 33%);background-size:200%;animation:shimerAnimate 1.5s ease-in-out infinite;}@keyframes shimerAnimate{0%{background-position:100% 0;}100%{background-position:-100% 0;}}</style>'
return '<div class="atfp-loader-container">' + container + '<div class="atfp-loader-skeleton"><span class="atfp-loader-shimmer"></span></div></div>';
}
loader.className = 'atfp-loader-wrapper'; // Add the atfp class to the loader
loader.innerHTML = loaderContainer();
this.loader = loader;
}
}
window.addEventListener('load', () => {
const atfpCreateBlockObj = new atfpCreateNewBlock();
atfpCreateBlockObj.copyBtnInitialize();
atfpCreateBlockObj.noticeInitialize();
const urlParams = new URLSearchParams(window.location.search);
let newBlock = '';
if (urlParams.has('atfp_new_block') && '' !== urlParams.get('atfp_new_block').trim()) {
newBlock = urlParams.get('atfp_new_block');
atfpCreateBlockObj.addBlockInitialize(newBlock);
}
});
})();

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,34 @@
jQuery(document).ready(function(){
const atfpSubsubsubList = jQuery('.atfp_subsubsub');
const atfpBulkTranslateBtn = jQuery('.atfpp-bulk-translate-btn');
if(atfpSubsubsubList.length){
const $defaultSubsubsub = jQuery('ul.subsubsub:not(.atfp_subsubsub_list)');
if($defaultSubsubsub.length){
$defaultSubsubsub.after(atfpSubsubsubList);
atfpSubsubsubList.show();
}
}
if(atfpBulkTranslateBtn.length){
const $defaultFilter = jQuery('.actions:not(.bulkactions)');
const $bulkAction=jQuery('.actions.bulkactions');
if($defaultFilter.length){
$defaultFilter.each(function(){
const clone=atfpBulkTranslateBtn.clone(true);
jQuery(this).append(clone);
clone.show();
});
atfpBulkTranslateBtn.remove();
}else if($bulkAction.length){
$bulkAction.each(function(){
const clone=atfpBulkTranslateBtn.clone(true);
jQuery(this).after(clone);
clone.show();
});
}
}
});

View File

@@ -0,0 +1,221 @@
class BlockFilterSorter {
constructor() {
this.tableBody = document.querySelector('.atfp-custom-data-table-table tbody');
this.filters = document.querySelectorAll('.atfp-custom-data-table-filters .atfp-filter-tab');
this.atfpDataTableObj = null;
this.saveButtonEnabled = false;
this.saveButtonText = false;
this.saveButtonClass = false;
this.saveButtonAction = false;
this.saveButtonNonce = false;
this.displayAjaxNotice=false;
this.ajaxUrl = false;
if (window.atfpCustomTableDataObject) {
if (atfpCustomTableDataObject.save_button_enabled && '' !== atfpCustomTableDataObject.save_button_enabled) {
this.saveButtonEnabled = atfpCustomTableDataObject.save_button_enabled;
}
if (atfpCustomTableDataObject.save_button_text && '' !== atfpCustomTableDataObject.save_button_text) {
this.saveButtonText = atfpCustomTableDataObject.save_button_text;
}
if (atfpCustomTableDataObject.save_button_class && '' !== atfpCustomTableDataObject.save_button_class) {
this.saveButtonClass = atfpCustomTableDataObject.save_button_class;
}
if (atfpCustomTableDataObject.save_button_handler && '' !== atfpCustomTableDataObject.save_button_handler) {
this.saveButtonAction = atfpCustomTableDataObject.save_button_handler;
}
if (atfpCustomTableDataObject.save_button_nonce && '' !== atfpCustomTableDataObject.save_button_nonce) {
this.saveButtonNonce = atfpCustomTableDataObject.save_button_nonce;
}
if (atfpCustomTableDataObject.admin_url && '' !== atfpCustomTableDataObject.admin_url) {
this.ajaxUrl = atfpCustomTableDataObject.admin_url;
}
const inputFields = document.querySelectorAll('#atfp-custom-datatable tbody input[name="atfp_fields_status"]');
inputFields.forEach(input => {
input.addEventListener('change', this.updateStatusHandler.bind(this));
});
}
if (this.tableBody) {
this.atfpDataTable();
this.filters.forEach(filter => {
filter.addEventListener('input', this.datatableFilterHandler.bind(this));
});
}
}
atfpDataTable() {
if (this.tableBody) {
this.atfpDataTableObj = new DataTable('#atfp-custom-datatable', {
pageLength: 25,
infoCallback: function (settings, start, end, total, max) {
return `Showing ${start} to ${end} of ${max} records`;
}
});
this.atfpDataTableObj.on('draw.dt', function (e) {
const rows = jQuery(this).find('tbody tr');
if (rows.length.length === 0) {
this.atfpDataTableObj.empty();
}
const length = e.dt.page.info().length;
const page = e.dt.page.info().page;
rows.each(function (index, row) {
const emptyCell = row.querySelector('td.dt-empty');
if (!emptyCell) {
row.children[0].textContent = (page * length) + index + 1;
}
});
});
const tableWrp = document.getElementById('atfp-custom-datatable_wrapper');
const selectWrapper = document.querySelector('.atfp-custom-data-table-filters');
selectWrapper.remove();
tableWrp.prepend(selectWrapper);
if (this.saveButtonEnabled && '' !== this.saveButtonText && 'false' !== this.saveButtonText) {
const saveButton = this.appendSaveButton();
const lastRow = tableWrp.querySelector('.dt-layout-row:last-child');
lastRow.before(saveButton);
jQuery(`.${this.saveButtonClass}`).on('click', this.saveButtonHandler.bind(this));
}
}
}
datatableFilterHandler(e) {
if (this.atfpDataTableObj) {
let value = e.target.value;
let wrapper = e.target.closest('.atfp-filter-tab');
let column = parseInt(wrapper.dataset.column);
let defaultValue = wrapper.dataset.default;
value = value === defaultValue ? false : value;
this.atfpDataTableObj.column(column).search(value ? new RegExp('^' + value, 'i') : '', false, false, false).draw();
}
}
updateStatusHandler(e) {
const table = jQuery('#atfp-custom-datatable').DataTable();
if (!table) return; // DataTable not initialized
const $tr = jQuery(e.target).closest('tr');
if (!$tr.length) return; // no row found
const dtRow = table.row($tr);
if (!dtRow.node()) return; // row doesnt exist in DataTable
const checked = e.target.checked;
const status = checked ? 'Supported' : 'Unsupported';
// Make sure cell exists
const cell = dtRow.cell(dtRow.index(), 3);
if (!cell) return;
// Update via DataTables API
cell.data(status);
}
saveButtonHandler(e) {
e.preventDefault();
const saveBtns = jQuery(`.${this.saveButtonClass}`);
if (saveBtns.hasClass('saving')) {
return;
}
if (!this.saveButtonAction || '' === this.saveButtonAction || !this.saveButtonNonce || '' === this.saveButtonNonce || !this.ajaxUrl || '' === this.ajaxUrl) {
return;
}
const selectedCheckbox = [];
const tdNodes = this.atfpDataTableObj.column(4).nodes();
if (tdNodes.length > 0) {
Array.from(tdNodes).forEach(tdNode => {
const checkbox = tdNode.querySelector('input[type="checkbox"]');
if (checkbox && checkbox.checked) {
selectedCheckbox.push(checkbox.value);
}
});
}
if (selectedCheckbox.length === 0) {
return;
}
const apiSendData = {
action: this.saveButtonAction,
atfp_nonce: this.saveButtonNonce,
save_custom_fields_data: JSON.stringify(selectedCheckbox)
};
saveBtns.addClass('saving').html('<span class="saving-text">Saving<span class="dot" style="--i:0"></span><span class="dot" style="--i:1"></span><span class="dot" style="--i:2"></span></span>', true);
fetch(this.ajaxUrl, {
method: 'POST',
headers: {
'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
'Accept': 'application/json',
},
body: new URLSearchParams(apiSendData)
})
.then(response => response.json())
.then(data => {
saveBtns.removeClass('saving').html(this.saveButtonText, true);
if (data.success) {
if (data.data.message) {
this.appendMessageNotice(data.data.message, 'success');
}
}
})
.catch(error => {
console.log(error);
if (error.data.message) {
this.appendMessageNotice(data.data.message, 'error');
}
saveBtns.removeClass('saving').html(this.saveButtonText, true);
console.error(error);
});
}
appendMessageNotice(message, type) {
if(this.displayAjaxNotice){
jQuery('#atfp-custom-fields-message-notice').remove();
clearTimeout(this.displayAjaxNotice);
}
this.displayAjaxNotice=setTimeout(() => {
this.displayAjaxNotice=false;
jQuery('#atfp-custom-fields-message-notice').remove();
}, 10000);
let messageNotice = jQuery('<div id="atfp-custom-fields-message-notice"><p>' + message + '</p></div>');
messageNotice.addClass('is-dismissible notice notice-' + type);
jQuery('.atfpp-dashboard-wrapper').before(messageNotice);
}
appendSaveButton() {
if (!this.saveButtonText || '' === this.saveButtonText || 'false' === this.saveButtonText || !this.saveButtonEnabled) {
return;
}
const saveButton = document.createElement('button');
saveButton.className = 'button button-primary ' + this.saveButtonClass;
saveButton.textContent = this.saveButtonText;
return saveButton;
}
}
// Call the class after window load
window.addEventListener('load', () => {
new BlockFilterSorter();
});

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,126 @@
const { __, sprintf } = wp.i18n;
const atfpElementorConfirmBox = {
init: function() {
this.pageTitleEvent=false;
if(window.atfpElementorConfirmBoxData){
this.createConfirmBox();
}
},
createConfirmBox: function() {
const sourceLangName=window.atfpElementorConfirmBoxData.sourceLangName;
const targetLangName=window.atfpElementorConfirmBoxData.targetLangName;
const confirmBox = jQuery(`<div class="atfp-elementor-translate-confirm-box modal-container" style="display:flex">
<div class="modal-content">
<p>
${sprintf(
__("The original page in %s was built with Elementor. Its content has already been copied into this new %s version. You can now translate it with Elementor to keep the same design, or edit it with the Gutenberg editor.", "autopoly-ai-translation-for-polylang-pro"),
sourceLangName,
targetLangName
)}
</p>
<div>
<button data-value="yes">
${__("Translate with Elementor", "autopoly-ai-translation-for-polylang-pro")}
</button>
<button data-value="no">
${__("Edit with Gutenberg", "autopoly-ai-translation-for-polylang-pro")}
</button>
</div>
</div>
</div>
`);
confirmBox.appendTo(jQuery('body'));
confirmBox.find('button[data-value="yes"]').on('click', (e)=>{this.confirmTranslation(e)});
confirmBox.find('button[data-value="no"]').on('click', (e)=>{e.preventDefault();this.closeConfirmBox();});
},
closeConfirmBox: function() {
this.setPageTitle();
const confirmBox = jQuery('.atfp-elementor-translate-confirm-box.modal-container');
confirmBox.remove();
},
confirmTranslation: function(e) {
this.setPageTitle();
e.preventDefault();
const postId=window.atfpElementorConfirmBoxData.postId;
const targetLangSlug=window.atfpElementorConfirmBoxData.targetLangSlug;
if(postId && targetLangSlug) {
let oldData=localStorage.getItem('atfpElementorConfirmBox');
let data={[postId+'_'+targetLangSlug]: true};
if(oldData && 'string' === typeof oldData && '' !== oldData) {
oldData=JSON.parse(oldData);
data={...oldData, ...data};
}
localStorage.setItem('atfpElementorConfirmBox', JSON.stringify(data));
const elementorButton=document.getElementById('elementor-editor-button');
const elementorEditModeButton=document.getElementById('elementor-edit-mode-button');
if(elementorEditModeButton) {
elementorEditModeButton.click();
}else if(elementorButton) {
elementorButton.click();
}
this.closeConfirmBox();
}
},
setPageTitle: function() {
if(window.atfpElementorConfirmBoxData.editorType !== 'classic') {
return;
}
if(this.pageTitleEvent) {
return;
}
this.pageTitleEvent=true;
const elementorButtons=document.querySelectorAll('#elementor-editor-button, #elementor-edit-mode-button');
elementorButtons.forEach(button=>{
button.addEventListener('click', (e)=>{
e.preventDefault();
if(window.wp && window.elementorAdmin && window.elementorAdmin.getDefaultElements){
const defaultElements=window.elementorAdmin.getDefaultElements();
if(defaultElements) {
$goToEditLink=defaultElements.$goToEditLink;
if($goToEditLink) {
var $wpTitle = jQuery('#title');
if (!$wpTitle.val()) {
$wpTitle.val('Elementor #' + jQuery('#post_ID').val());
}
if (wp.autosave) {
wp.autosave.server.triggerSave();
}
jQuery(document).on('heartbeat-tick.autosave', function () {
window.elementorCommon.elements.$window.off('beforeunload.edit-post');
location.href = $goToEditLink.attr('href');
});
}
}
}
});
});
}
};
jQuery(document).ready(function($) {
atfpElementorConfirmBox.init();
});

View File

@@ -0,0 +1,333 @@
const { parse } = wp.blocks;
const { select, subscribe } = wp.data;
class blockDataReterive {
constructor() {
this.blockLists = [];
this.customBlockTranslateData = {};
this.customBlocksData = [];
this.loaderContainer = null;
this.init();
}
init = () => {
this.fetchCustomBlocks();
// Create full-page overlay and append to <body>
this.loaderContainer = document.createElement('div');
this.loaderContainer.className = 'atfp-overlay';
this.loaderContainer.setAttribute('role', 'status');
this.loaderContainer.setAttribute('aria-live', 'polite');
this.loaderContainer.innerHTML = this.getOverlayTemplate(); // see section 2
document.body.appendChild(this.loaderContainer);
document.body.classList.add('atfp-overlay-open');
}
getBlocks = (blocks) => {
const innerBlocks = (block) => {
const innerBlock = block.innerBlocks;
if (innerBlock.length > 0) {
innerBlock.forEach(innerBlock => {
this.customBlocksData.push(innerBlock);
innerBlocks(innerBlock);
});
}
}
const blockLists = blocks;
blockLists.forEach(block => {
innerBlocks(block);
});
this.customBlocksData = [...this.customBlocksData, ...blockLists];
this.getBlockData();
}
fetchCustomBlocks = () => {
/**
* Prepare data to send in API request.
*/
const apiSendData = {
atfp_nonce: atfp_block_update_object.ajax_nonce,
action: atfp_block_update_object.action_get_content
};
const apiUrl = atfp_block_update_object.ajax_url;
fetch(apiUrl, {
method: 'POST',
headers: {
'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
},
body: new URLSearchParams(apiSendData)
})
.then(response => response.json())
.then(data => {
if (data.message === 'No custom blocks found.') {
this.loaderContainer && this.loaderContainer.remove();
return;
}
const customBlocks = parse(data.data.block_data);
this.getBlocks(customBlocks);
// Save new block translate data
this.saveBlockData();
})
.catch(error => {
this.loaderContainer && this.loaderContainer.remove();
console.error('Error fetching block rules:', error);
});
}
saveBlockData = () => {
if (Object.keys(this.customBlockTranslateData).length < 1) {
this.loaderContainer && this.loaderContainer.remove();
return;
}
/**
* Prepare data to send in API request & update latest translate block data.
*/
const apiSendData = {
atfp_nonce: atfp_block_update_object.ajax_nonce,
action: atfp_block_update_object.action_update_content,
save_block_data: JSON.stringify(this.customBlockTranslateData)
};
const apiUrl = atfp_block_update_object.ajax_url;
fetch(apiUrl, {
method: 'POST',
headers: {
'content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
},
body: new URLSearchParams(apiSendData)
})
.then(response => response.json())
.then(data => {
this.setOverlayState('success');
this.teardownOverlay();
if (data.success && data.data.message) {
console.log(data.data.message);
}
})
.catch(error => {
this.setOverlayState('error');
this.teardownOverlay();
console.error('Error fetching block rules:', error);
});
}
nestedAttrValue = (idsArr) => {
const convertToArrays = (obj) => {
// Check if obj is an object
if (typeof obj !== 'object' || obj === null) {
return obj;
}
// Process each key-value pair in the object
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
// If the current value is an object and has the key 'atfp_array_key_replace'
if (typeof obj[key] === 'object' && obj[key] !== null && obj[key].hasOwnProperty('atfp_array_key_replace')) {
// Replace the value with 'true' directly in the array
obj[key] = Object.values(obj[key]);
obj[key] = convertToArrays(obj[key]);
} else {
// Recursively call convertToArrays for nested objects or arrays
obj[key] = convertToArrays(obj[key]);
}
}
}
return obj;
}
const deepMerge = (target, source) => {
for (const key in source) {
if (source[key] instanceof Object && key in target) {
Object.assign(source[key], deepMerge(target[key], source[key]));
}
}
Object.assign(target || {}, source);
return target;
};
let currentElement = {};
let tempObj = currentElement;
let lastKey = idsArr[idsArr.length - 1];
idsArr.slice(0, -1).forEach((key) => {
tempObj[key] = tempObj[key] || {};
tempObj = tempObj[key];
});
tempObj[lastKey] = true;
const obj = convertToArrays(currentElement);
deepMerge(this.customBlockTranslateData, obj);
}
filterAttr = (idsArray, value) => {
if (null === value || undefined === value) {
return;
}
if (Object.getPrototypeOf(value) === Array.prototype) {
this.filterBlockArrayAttr(idsArray, value);
} else if (Object.getPrototypeOf(value) === Object.prototype) {
this.filterBlockObjectAttr(idsArray, value);
} else if (typeof value === 'string' && /Make This Content Available for Translation/i.test(value)) {
this.nestedAttrValue(idsArray, value);
} else if (value instanceof wp.richText.RichTextData && /Make This Content Available for Translation/i.test(value.originalHTML)) {
this.nestedAttrValue(idsArray, value.originalHTML);
}
}
filterBlockArrayAttr = (idsArr, blockData) => {
const newIdArr = new Array(...idsArr);
newIdArr.push('atfp_array_key_replace');
blockData.forEach((value, key) => {
if ((typeof value === 'string' && /Make This Content Available for Translation/i.test(value)) || (![null, undefined].includes(value) && [Array.prototype, Object.prototype].includes(Object.getPrototypeOf(value)))) {
this.filterAttr(newIdArr, value)
};
});
}
filterBlockObjectAttr = (idsArr, blockData) => {
Object.keys(blockData).forEach(key => {
const newIdArr = new Array(...idsArr);
const value = blockData[key];
if (value !== null && value !== undefined) {
if ((typeof value === 'string' && /Make This Content Available for Translation/i.test(value)) || [Array.prototype, Object.prototype].includes(Object.getPrototypeOf(value))) {
newIdArr.push(key);
this.filterAttr(newIdArr, blockData[key]);
};
}
})
}
filterBlockAttribute = (blockData) => {
Object.keys(blockData).map(clientId => {
const blockName = Object.keys(blockData[clientId])[0];
const attributes = blockData[clientId][blockName];
Object.keys(attributes).forEach(keytwo => {
const value = attributes[keytwo];
const idsArray = new Array(blockName, "attributes", keytwo);
this.filterAttr(idsArray, value);
});
})
}
getBlockData = () => {
if (typeof this.customBlocksData !== 'object' || Object.keys(this.customBlocksData).length === 0) {
return;
}
const blockData = this.customBlocksData;
const blockAttributes = {};
Object.values(blockData).forEach(block => {
if (Object.values(block.attributes).length > 0) {
blockAttributes[block.clientId] = {};
blockAttributes[block.clientId][block.name] = block.attributes;
}
});
if (Object.values(blockAttributes).length > 0) {
this.filterBlockAttribute(blockAttributes);
}
}
setOverlayState = (state /* 'loading' | 'success' | 'error' */) => {
if (!this.loaderContainer) return;
const panel = this.loaderContainer.querySelector('.atfp-overlay .atfp-box');
if (panel) panel.setAttribute('data-state', state);
};
teardownOverlay = (delayMs = 3000) => {
if (!this.loaderContainer) return;
setTimeout(() => {
this.loaderContainer.classList.add('atfp-overlay--closing');
setTimeout(() => {
this.loaderContainer.remove();
this.loaderContainer = null;
document.body.classList.remove('atfp-overlay-open');
}, 300);
}, delayMs);
};
getOverlayTemplate = () => {
return `
<div class="atfp-overlay" role="status" aria-live="polite">
<div class="atfp-backdrop"></div>
<div class="atfp-box" data-state="loading">
<div class="atfp-row">
<span class="atfp-spinner" aria-hidden="true"></span>
<span class="atfp-icon atfp-icon--ok" aria-hidden="true">✓</span>
<span class="atfp-icon atfp-icon--err" aria-hidden="true">!</span>
<div class="atfp-text">
<div class="atfp-title" data-label="loading">Saving block content</div>
<div class="atfp-title" data-label="success">Supported block content has been updated</div>
<div class="atfp-title" data-label="error">Update failed</div>
<div class="atfp-desc" data-label="loading">
Please dont close or refresh this window until the update is complete.
</div>
<div class="atfp-desc" data-label="success">
Supported block content has been updated. You may continue.
</div>
<div class="atfp-desc" data-label="error">
Something went wrong. You can retry without closing this window.
</div>
</div>
</div>
<div class="atfp-bar"><span></span></div>
</div>
</div>
`;
}
}
const debounce = (func, delay) => {
let timeoutId;
return function (...args) {
clearTimeout(timeoutId);
timeoutId = setTimeout(() => func.apply(this, args), delay);
};
};
let isBlockContentUpdating = false;
const saveBlockContent = debounce(() => {
new blockDataReterive();
isBlockContentUpdating = false;
}, 300);
if (select && select('core/editor') && subscribe) {
subscribe(() => {
const {
isCurrentPostPublished,
isSavingPost,
isPublishingPost,
isAutosavingPost,
} = select('core/editor');
const isAutoSaving = isAutosavingPost();
const isPublishing = isPublishingPost();
const isSaving = isSavingPost();
const postPublished = isCurrentPostPublished();
if ((isPublishing || (postPublished && isSaving)) && !isAutoSaving && !isBlockContentUpdating) {
isBlockContentUpdating = true;
saveBlockContent();
}
})
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long