function openBulkConvertPopup() {
document.getElementById('bulkconvertlog').innerHTML = '';
document.getElementById('bulkconvertcontent').innerHTML = '
Receiving list of files to convert...
';
tb_show('Bulk Convert', '#TB_inline?inlineId=bulkconvertpopup');
var data = {
'action': 'list_unconverted_files',
'nonce' : window.webpExpress['ajax-nonces']['list-unconverted-files'],
};
jQuery.ajax({
type: "POST",
url: ajaxurl,
data: data,
dataType: 'text',
timeout: 30000,
error: function (jqXHR, status, errorThrown) {
html = '
Error: ' + status + '
';
html += errorThrown;
document.getElementById('bulkconvertcontent').innerHTML = html;
},
success: function(response) {
if ((typeof response == 'object') && (response['success'] == false)) {
html = '
Error
';
if (response['data'] && ((typeof response['data']) == 'string')) {
html += webpexpress_escapeHTML(response['data']);
}
document.getElementById('bulkconvertcontent').innerHTML = html;
return;
}
if (response == '') {
html = '
Error
';
html += '
Could not fetch list of files to convert. The server returned nothing (which is unexpected - ' +
'it is not simply because there are no files to convert.)
';
document.getElementById('bulkconvertcontent').innerHTML = html;
return;
}
var responseObj;
try {
responseObj = JSON.parse(response);
} catch (e) {
html = '
Error
';
html += '
The ajax call did not return valid JSON, as expected.
';
html += '
Check the javascript console to see what was returned.
';
console.log('The ajax call did not return valid JSON, as expected');
console.log('Here is what was received:');
console.log(response);
document.getElementById('bulkconvertcontent').innerHTML = html;
return;
}
var bulkInfo = {
'groups': responseObj,
'groupPointer': 0,
'filePointer': 0,
'paused': false,
'webpTotalFilesize': 0,
'orgTotalFilesize': 0,
};
window.webpexpress_bulkconvert = bulkInfo;
// count files
var numFiles = 0;
for (var i=0; iThere are no unconverted files';
} else {
html += '
'
html += '
There are ' + numFiles + ' unconverted files.
';
html += '
Note that in a typical setup, you will have redirect rules which trigger conversion when needed, ' +
'and thus you have no need for bulk conversion. In fact, in that case, you should probably not bulk convert ' +
'because bulk conversion will also convert images and thumbnails which are not in use, and thus take up ' +
'more disk space than necessary. The bulk conversion feature was only added in order to make the plugin usable even when ' +
'there are problems with redirects (ie on Nginx in case you do not have access to the config or on Microsoft IIS). ' +
'
';
html += '';
html += '
';
}
document.getElementById('bulkconvertcontent').innerHTML = html;
}
});
}
function pauseBulkConversion() {
var bulkInfo = window.webpexpress_bulkconvert;
bulkInfo.paused = true;
}
function pauseOrResumeBulkConversion() {
var bulkInfo = window.webpexpress_bulkconvert;
bulkInfo.paused = !bulkInfo.paused;
document.getElementById('bulkPauseResumeBtn').innerText = (bulkInfo.paused ? 'Resume' : 'Pause');
if (!bulkInfo.paused) {
convertNextInBulkQueue();
}
}
function startBulkConversion() {
var html = ' ';
html += '';
html += '';
//html += '
Total reduction: ' + getReductionHtml(bulkInfo['orgTotalFilesize'], bulkInfo['webpTotalFilesize'], 'Total size of converted originals', 'Total size of converted webp files') + '
'
document.getElementById('bulkPauseResumeBtn').style.display = 'none';
}
function getPrintableSizeInfo(orgSize, webpSize) {
if (orgSize < 10000) {
return {
'org': orgSize + ' bytes',
'webp': webpSize + ' bytes'
};
} else {
return {
'org': Math.round(orgSize / 1024) + ' kb',
'webp': Math.round(webpSize / 1024) + ' kb'
};
}
}
function getReductionHtml(orgSize, webpSize, sizeOfOriginalText, sizeOfWebpText) {
var reduction = Math.round((orgSize - webpSize)/orgSize * 100);
var sizeInfo = getPrintableSizeInfo(orgSize, webpSize);
var hoverText = sizeOfOriginalText + ': ' + sizeInfo['org'] + '. ' + sizeOfWebpText + ': ' + sizeInfo['webp'];
// ps: this is all safe to print
return '' + reduction + '%' +
'' + hoverText + '' +
' ';
}
function logLn() {
var html = '';
for (i = 0; i < arguments.length; i++) {
html += arguments[i];
}
var spanEl = document.createElement('span');
spanEl.innerHTML = html;
document.getElementById('bulkconvertlog').appendChild(spanEl);
//document.getElementById('bulkconvertlog').innerHTML += html;
}
function webpexpress_viewLog(groupPointer, filePointer) {
/*
disabled until I am certain that security is in place.
var bulkInfo = window.webpexpress_bulkconvert;
var group = bulkInfo.groups[groupPointer];
var filename = group.files[filePointer];
var source = group.root + '/' + filename;
var w = Math.min(1200, Math.max(200, document.documentElement.clientWidth - 100));
var h = Math.max(250, document.documentElement.clientHeight - 80);
document.getElementById('conversionlog_content').innerHTML = 'loading log...'; // + source;
jQuery.ajax({
method: 'POST',
url: ajaxurl,
data: {
'action': 'webpexpress_view_log',
'nonce' : window.webpExpress['ajax-nonces']['view-log'],
'source': source
},
success: (response) => {
//alert(response);
if ((typeof response == 'object') && (response['success'] == false)) {
html = '
Error
';
if (response['data'] && ((typeof response['data']) == 'string')) {
html += webpexpress_escapeHTML(response['data']);
}
document.getElementById('conversionlog_content').innerHTML = html;
return;
}
var result = JSON.parse(response);
// the "log" result is a simply form of markdown, using just italic, bold and newlines.
// It ought not to return anything evil, but for good practice, let us encode.
result = webpexpress_escapeHTML(result);
var html = '
//tb_show('Conversion log', '#TB_inline?inlineId=conversionlog');
openDasPopup('conversionlog', w, h);
*/
}
function convertNextInBulkQueue() {
var html;
var bulkInfo = window.webpexpress_bulkconvert;
//console.log('convertNextInBulkQueue', bulkInfo);
// Current group might contain 0, - skip if that is the case
while ((bulkInfo.groupPointer < bulkInfo.groups.length) && (bulkInfo.filePointer >= bulkInfo.groups[bulkInfo.groupPointer].files.length)) {
logLn(
'
'
);
bulkInfo.groupPointer++;
bulkInfo.filePointer = 0;
}
if (bulkInfo.groupPointer >= bulkInfo.groups.length) {
convertDone();
return;
}
var group = bulkInfo.groups[bulkInfo.groupPointer];
var filename = group.files[bulkInfo.filePointer];
if (bulkInfo.filePointer == 0) {
logLn('
' + group.groupName + '
');
}
logLn('Converting ' + filename + '');
var data = {
'action': 'convert_file',
'nonce' : window.webpExpress['ajax-nonces']['convert'],
'filename': group.root + '/' + filename
//'whatever': ajax_object.we_value // We pass php values differently!
};
function responseCallback(response){
try {
if ((typeof response == 'object') && (response['success'] == false)) {
html = '
Error
';
if (response['data'] && ((typeof response['data']) == 'string')) {
// disabled. Need to check if it is secure
//html += webpexpress_escapeHTML(response['data']);
}
logLn(html);
return
}
var result;
// Handle different types of responses safely
if (typeof response.requestError === 'boolean' && response.requestError) {
result = {
success: false,
msg: 'Request failed',
log: '',
};
} else if (typeof response === 'string') {
try {
result = JSON.parse(response);
} catch (e) {
result = {
success: false,
msg: 'Invalid response received from server',
log: '',
};
}
} else if (typeof response === 'object' && response !== null) {
// If it's already an object, check if it has the expected structure
if (typeof response.success !== 'undefined') {
result = response;
} else {
result = {
success: false,
msg: 'Invalid object response received from server',
log: '',
};
}
} else {
result = {
success: false,
msg: 'Unexpected response type: ' + typeof response,
log: '',
};
}
var bulkInfo = window.webpexpress_bulkconvert;
if (!bulkInfo || !bulkInfo.groups || bulkInfo.groupPointer >= bulkInfo.groups.length) {
logLn('Bulk conversion state is invalid ');
convertDone();
return;
}
var group = bulkInfo.groups[bulkInfo.groupPointer];
if (!group || !group.files || bulkInfo.filePointer >= group.files.length) {
logLn('Group or file index is invalid ');
convertDone();
return;
}
var filename = group.files[bulkInfo.filePointer];
//console.log(result);
var html = '';
var htmlViewLog = '';
// uncommented until I'm certain that security is in place
//var htmlViewLog = ' view log';
if (result['success']) {
//console.log('nonce tick:' + result['nonce-tick']);
if (result['new-convert-nonce']) {
//console.log('new convert nonce:' + result['new-convert-nonce']);
window.webpExpress['ajax-nonces']['convert'] = result['new-convert-nonce'];
}
var orgSize = result['filesize-original'];
var webpSize = result['filesize-webp'];
var orgSizePrint, webpSizePrint;
bulkInfo['orgTotalFilesize'] += orgSize;
bulkInfo['webpTotalFilesize'] += webpSize;
//'- Saved at: ' + result['destination-path'] +
/*
html += ' ok' +
htmlViewLog +
getReductionHtml(orgSize, webpSize, 'Size of original', 'Size of webp')*/
html += ' ok' +
'' +
'Destination: ' + result['destination-path'] + '
' +
'Url: ' + result['destination-url'] + ' ' +
'' +
'' +
getReductionHtml(orgSize, webpSize, 'Size of original', 'Size of webp')
} else {
html += ' failed' + htmlViewLog;
if (result['msg']) {
// Show the error message but continue processing
html += ' ' + webpexpress_escapeHTML(result['msg']) + '';
}
// Only stop for critical errors (security nonce issues), not file-specific errors
if (result['stop'] && result['msg'] && result['msg'].indexOf('security nonce') !== -1) {
logLn(html);
logLn(' Bulk conversion stopped due to security error. Please reload the page (F5) and try again.');
return;
}
html += ' ';
}
logLn(html);
// Get next
bulkInfo.filePointer++;
if (bulkInfo.filePointer == group.files.length) {
bulkInfo.filePointer = 0;
bulkInfo.groupPointer++;
}
if (bulkInfo.groupPointer == bulkInfo.groups.length) {
convertDone();
} else {
if (bulkInfo.paused) {
document.getElementById('bulkconvertlog').innerHTML += '
on pause ' +
'Reduction this far: ' + getReductionHtml(bulkInfo['orgTotalFilesize'], bulkInfo['webpTotalFilesize'], 'Total size of originals this far', 'Total size of webp files this far') + '
'
bulkInfo['orgTotalFilesize'] += orgSize;
bulkInfo['webpTotalFilesize'] += webpSize;
} else {
convertNextInBulkQueue();
}
}
} catch (error) {
// Catch any unexpected errors in responseCallback
logLn(' JavaScript error in response processing: ' + error.message + ' ');
// Try to continue with next file
var bulkInfo = window.webpexpress_bulkconvert;
if (bulkInfo && bulkInfo.groups && bulkInfo.groupPointer < bulkInfo.groups.length) {
bulkInfo.filePointer++;
if (bulkInfo.filePointer >= bulkInfo.groups[bulkInfo.groupPointer].files.length) {
bulkInfo.filePointer = 0;
bulkInfo.groupPointer++;
}
if (bulkInfo.groupPointer >= bulkInfo.groups.length) {
convertDone();
} else if (!bulkInfo.paused) {
convertNextInBulkQueue();
}
} else {
convertDone();
}
}
}
// jQuery.post(ajaxurl, data, responseCallback);
jQuery.ajax({
method: 'POST',
url: ajaxurl,
data: data,
timeout: 30000, // 30 second timeout per file
success: (response) => {
responseCallback(response);
},
error: (jqXHR, textStatus, errorThrown) => {
var errorMsg = 'unknown error';
if (textStatus === 'timeout') {
errorMsg = 'timeout (30s)';
} else if (textStatus === 'error') {
if (jqXHR.status === 500) {
errorMsg = 'server error (500)';
} else if (jqXHR.status === 0) {
errorMsg = 'connection failed';
} else {
errorMsg = 'error (' + jqXHR.status + ')';
}
} else {
errorMsg = 'error (' + textStatus + ')';
}
// Get current file info for logging
var bulkInfo = window.webpexpress_bulkconvert;
var filename = 'unknown file';
if (bulkInfo && bulkInfo.groups && bulkInfo.groupPointer < bulkInfo.groups.length) {
var group = bulkInfo.groups[bulkInfo.groupPointer];
if (group && group.files && bulkInfo.filePointer < group.files.length) {
filename = group.files[bulkInfo.filePointer];
}
}
logLn('Converting ' + filename + '' + errorMsg + ' ');
// Continue with next file instead of stopping
if (bulkInfo && bulkInfo.groups && bulkInfo.groupPointer < bulkInfo.groups.length) {
var group = bulkInfo.groups[bulkInfo.groupPointer];
// Get next
bulkInfo.filePointer++;
if (bulkInfo.filePointer >= group.files.length) {
bulkInfo.filePointer = 0;
bulkInfo.groupPointer++;
}
if (bulkInfo.groupPointer >= bulkInfo.groups.length) {
convertDone();
} else {
if (!bulkInfo.paused) {
convertNextInBulkQueue();
}
}
} else {
convertDone();
}
},
});
}