Add bulk term generation functionality and enhance logging
- Introduced a new JavaScript file for handling bulk term generation in the admin interface. - Implemented AJAX requests for generating terms and handling responses with appropriate logging. - Enhanced the Groq_AI_Ajax_Controller to support new options for term generation, including origin and force parameters. - Improved error handling and logging for term generation events. - Updated the user interface to reflect the status of term generation and provide feedback to the user.
This commit is contained in:
@@ -41,6 +41,14 @@
|
|||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.groq-ai-bulk-actions {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 8px;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
#groq-ai-bulk-status {
|
#groq-ai-bulk-status {
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
}
|
}
|
||||||
@@ -89,3 +97,12 @@
|
|||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.groq-ai-term-actions {
|
||||||
|
width: 180px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.groq-ai-regenerate-term.is-busy {
|
||||||
|
opacity: 0.6;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,212 +0,0 @@
|
|||||||
(function () {
|
|
||||||
const data = window.GroqAICategoryBulk || {};
|
|
||||||
const startButton = document.getElementById('groq-ai-bulk-generate');
|
|
||||||
const stopButton = document.getElementById('groq-ai-bulk-cancel');
|
|
||||||
const statusField = document.getElementById('groq-ai-bulk-status');
|
|
||||||
const logList = document.getElementById('groq-ai-bulk-log');
|
|
||||||
|
|
||||||
if (!startButton || !data.ajaxUrl) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let queue = [];
|
|
||||||
let totalCount = 0;
|
|
||||||
let processed = 0;
|
|
||||||
let successes = 0;
|
|
||||||
let isRunning = false;
|
|
||||||
let abortRequested = false;
|
|
||||||
|
|
||||||
function formatString(template, values) {
|
|
||||||
if (!template) {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
let autoIndex = 0;
|
|
||||||
return template.replace(/%(\d+\$)?[sd]/g, (match, position) => {
|
|
||||||
let valueIndex;
|
|
||||||
if (position) {
|
|
||||||
valueIndex = parseInt(position, 10) - 1;
|
|
||||||
} else {
|
|
||||||
valueIndex = autoIndex;
|
|
||||||
autoIndex += 1;
|
|
||||||
}
|
|
||||||
const replacement = values[valueIndex];
|
|
||||||
return typeof replacement === 'undefined' ? '' : String(replacement);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function setStatus(message, type) {
|
|
||||||
if (!statusField) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
statusField.textContent = message || '';
|
|
||||||
statusField.dataset.status = type || '';
|
|
||||||
}
|
|
||||||
|
|
||||||
function appendLog(message, type) {
|
|
||||||
if (!logList || !message) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const item = document.createElement('li');
|
|
||||||
item.textContent = message;
|
|
||||||
item.dataset.status = type || '';
|
|
||||||
logList.appendChild(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
function resetLog() {
|
|
||||||
if (!logList) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
logList.innerHTML = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
function toggleButtons(running) {
|
|
||||||
isRunning = running;
|
|
||||||
startButton.disabled = running;
|
|
||||||
if (stopButton) {
|
|
||||||
stopButton.hidden = !running;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getPendingTerms() {
|
|
||||||
if (!Array.isArray(data.terms)) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
return data.terms.filter((term) => !term.processed);
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateRow(termId, words) {
|
|
||||||
const row = document.querySelector('[data-groq-ai-term-id="' + termId + '"]');
|
|
||||||
if (!row) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
row.classList.remove('groq-ai-term-missing');
|
|
||||||
row.classList.add('groq-ai-term-updated');
|
|
||||||
const wordCell = row.querySelector('.groq-ai-word-count');
|
|
||||||
if (wordCell) {
|
|
||||||
wordCell.textContent = String(typeof words === 'number' ? words : wordCell.textContent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function finish(state) {
|
|
||||||
const summaryTemplate =
|
|
||||||
state === 'done'
|
|
||||||
? data.strings && data.strings.statusDone
|
|
||||||
: state === 'stopped'
|
|
||||||
? data.strings && data.strings.statusStopped
|
|
||||||
: '';
|
|
||||||
|
|
||||||
const summary = summaryTemplate
|
|
||||||
? formatString(summaryTemplate, [successes])
|
|
||||||
: '';
|
|
||||||
|
|
||||||
const statusType = state === 'done' ? 'success' : state === 'stopped' ? 'info' : '';
|
|
||||||
setStatus(summary, statusType);
|
|
||||||
toggleButtons(false);
|
|
||||||
queue = [];
|
|
||||||
totalCount = 0;
|
|
||||||
abortRequested = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
function processNext() {
|
|
||||||
if (abortRequested) {
|
|
||||||
finish('stopped');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!queue.length) {
|
|
||||||
finish('done');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const term = queue.shift();
|
|
||||||
const position = processed + 1;
|
|
||||||
const progressTemplate = data.strings && data.strings.statusProgress;
|
|
||||||
if (progressTemplate) {
|
|
||||||
setStatus(formatString(progressTemplate, [position, totalCount, term.name || '']), 'loading');
|
|
||||||
}
|
|
||||||
|
|
||||||
const payload = new URLSearchParams();
|
|
||||||
payload.append('action', 'groq_ai_bulk_generate_terms');
|
|
||||||
payload.append('nonce', data.nonce || '');
|
|
||||||
payload.append('taxonomy', data.taxonomy || 'product_cat');
|
|
||||||
payload.append('term_id', term.id);
|
|
||||||
|
|
||||||
fetch(data.ajaxUrl, {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
|
|
||||||
},
|
|
||||||
body: payload.toString(),
|
|
||||||
})
|
|
||||||
.then((response) => response.json())
|
|
||||||
.then((json) => {
|
|
||||||
if (!json.success) {
|
|
||||||
const errorMessage = (json.data && json.data.message) || 'Onbekende fout';
|
|
||||||
appendLog(formatString((data.strings && data.strings.logError) || '%1$s: %2$s', [term.name || term.id, errorMessage]), 'error');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
term.processed = true;
|
|
||||||
successes += 1;
|
|
||||||
const words = json.data && typeof json.data.words !== 'undefined' ? json.data.words : 0;
|
|
||||||
updateRow(term.id, words);
|
|
||||||
appendLog(formatString((data.strings && data.strings.logSuccess) || '%1$s gevuld.', [term.name || term.id, words]), 'success');
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
appendLog(
|
|
||||||
formatString((data.strings && data.strings.logError) || '%1$s: %2$s', [term.name || term.id, error && error.message ? error.message : 'Onbekende fout']),
|
|
||||||
'error'
|
|
||||||
);
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
processed += 1;
|
|
||||||
if (abortRequested) {
|
|
||||||
finish('stopped');
|
|
||||||
} else {
|
|
||||||
processNext();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function startBulk() {
|
|
||||||
if (isRunning) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const pending = getPendingTerms();
|
|
||||||
if (!pending.length) {
|
|
||||||
setStatus((data.strings && data.strings.statusEmpty) || '', 'info');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
queue = pending.slice();
|
|
||||||
totalCount = queue.length;
|
|
||||||
processed = 0;
|
|
||||||
successes = 0;
|
|
||||||
abortRequested = false;
|
|
||||||
resetLog();
|
|
||||||
toggleButtons(true);
|
|
||||||
setStatus((data.strings && data.strings.statusIdle) || '', 'info');
|
|
||||||
processNext();
|
|
||||||
}
|
|
||||||
|
|
||||||
startButton.addEventListener('click', startBulk);
|
|
||||||
|
|
||||||
if (stopButton) {
|
|
||||||
stopButton.addEventListener('click', () => {
|
|
||||||
if (!isRunning) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const confirmation = ! (data.strings && data.strings.confirmStop)
|
|
||||||
? window.confirm('Stoppen?')
|
|
||||||
: window.confirm(data.strings.confirmStop);
|
|
||||||
if (confirmation) {
|
|
||||||
abortRequested = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Array.isArray(data.terms) || !data.terms.length) {
|
|
||||||
setStatus((data.strings && data.strings.statusEmpty) || '', 'info');
|
|
||||||
}
|
|
||||||
})();
|
|
||||||
288
assets/js/term-bulk.js
Normal file
288
assets/js/term-bulk.js
Normal file
@@ -0,0 +1,288 @@
|
|||||||
|
(function () {
|
||||||
|
const data = window.GroqAITermBulk || {};
|
||||||
|
const startButton = document.getElementById('groq-ai-bulk-generate');
|
||||||
|
const stopButton = document.getElementById('groq-ai-bulk-cancel');
|
||||||
|
const statusField = document.getElementById('groq-ai-bulk-status');
|
||||||
|
const logList = document.getElementById('groq-ai-bulk-log');
|
||||||
|
|
||||||
|
if (!data.ajaxUrl || !startButton || !statusField || !logList) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const strings = data.strings || {};
|
||||||
|
const allowRegenerate = !!data.allowRegenerate;
|
||||||
|
const terms = (Array.isArray(data.terms) ? data.terms : [])
|
||||||
|
.map((term) => {
|
||||||
|
const id = parseInt(term.id, 10);
|
||||||
|
if (!Number.isFinite(id)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const words = typeof term.words === 'number' ? term.words : parseInt(term.words, 10) || 0;
|
||||||
|
const hasDescription = !!term.hasDescription;
|
||||||
|
return {
|
||||||
|
id,
|
||||||
|
name: term.name || '',
|
||||||
|
slug: term.slug || '',
|
||||||
|
count: typeof term.count === 'number' ? term.count : parseInt(term.count, 10) || 0,
|
||||||
|
words,
|
||||||
|
hasDescription,
|
||||||
|
needsGeneration: !hasDescription,
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.filter(Boolean);
|
||||||
|
|
||||||
|
const termMap = new Map();
|
||||||
|
terms.forEach((term) => termMap.set(term.id, term));
|
||||||
|
|
||||||
|
let queue = [];
|
||||||
|
let totalCount = 0;
|
||||||
|
let processed = 0;
|
||||||
|
let successes = 0;
|
||||||
|
let isRunning = false;
|
||||||
|
let abortRequested = false;
|
||||||
|
|
||||||
|
function formatString(template, values) {
|
||||||
|
if (!template) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
let autoIndex = 0;
|
||||||
|
return template.replace(/%(\d+\$)?[sd]/g, (match, position) => {
|
||||||
|
let valueIndex;
|
||||||
|
if (position) {
|
||||||
|
valueIndex = parseInt(position, 10) - 1;
|
||||||
|
} else {
|
||||||
|
valueIndex = autoIndex;
|
||||||
|
autoIndex += 1;
|
||||||
|
}
|
||||||
|
const replacement = values[valueIndex];
|
||||||
|
return typeof replacement === 'undefined' ? '' : String(replacement);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function setStatus(message, type) {
|
||||||
|
statusField.textContent = message || '';
|
||||||
|
statusField.dataset.status = type || '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function appendLog(message, type) {
|
||||||
|
if (!message) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const item = document.createElement('li');
|
||||||
|
item.textContent = message;
|
||||||
|
item.dataset.status = type || '';
|
||||||
|
logList.appendChild(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetLog() {
|
||||||
|
logList.innerHTML = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggleButtons(running) {
|
||||||
|
isRunning = running;
|
||||||
|
startButton.disabled = running;
|
||||||
|
if (stopButton) {
|
||||||
|
stopButton.hidden = !running;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPendingTerms() {
|
||||||
|
return terms.filter((term) => term.needsGeneration);
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateRow(term) {
|
||||||
|
const row = document.querySelector('[data-groq-ai-term-id="' + term.id + '"]');
|
||||||
|
if (!row) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
row.classList.remove('groq-ai-term-missing');
|
||||||
|
row.classList.add('groq-ai-term-updated');
|
||||||
|
const wordCell = row.querySelector('.groq-ai-word-count');
|
||||||
|
if (wordCell) {
|
||||||
|
wordCell.textContent = String(term.words);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function markTermCompleted(term, words) {
|
||||||
|
term.hasDescription = true;
|
||||||
|
term.needsGeneration = false;
|
||||||
|
if (Number.isFinite(words)) {
|
||||||
|
term.words = words;
|
||||||
|
}
|
||||||
|
updateRow(term);
|
||||||
|
}
|
||||||
|
|
||||||
|
function finish(state) {
|
||||||
|
const summaryTemplate = state === 'done' ? strings.statusDone : state === 'stopped' ? strings.statusStopped : '';
|
||||||
|
const summary = summaryTemplate ? formatString(summaryTemplate, [successes]) : '';
|
||||||
|
const statusType = state === 'done' ? 'success' : state === 'stopped' ? 'info' : '';
|
||||||
|
setStatus(summary, statusType);
|
||||||
|
toggleButtons(false);
|
||||||
|
queue = [];
|
||||||
|
totalCount = 0;
|
||||||
|
processed = 0;
|
||||||
|
successes = 0;
|
||||||
|
abortRequested = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function sendRequest(term, options = {}) {
|
||||||
|
const payload = new URLSearchParams();
|
||||||
|
payload.append('action', 'groq_ai_bulk_generate_terms');
|
||||||
|
payload.append('nonce', data.nonce || '');
|
||||||
|
payload.append('taxonomy', data.taxonomy || '');
|
||||||
|
payload.append('term_id', term.id);
|
||||||
|
if (options.force) {
|
||||||
|
payload.append('force', '1');
|
||||||
|
}
|
||||||
|
|
||||||
|
return fetch(data.ajaxUrl, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
|
||||||
|
},
|
||||||
|
body: payload.toString(),
|
||||||
|
}).then((response) => response.json());
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleResponse(term, json, context) {
|
||||||
|
if (!json || !json.success) {
|
||||||
|
const errorMessage = (json && json.data && json.data.message) || 'Onbekende fout';
|
||||||
|
appendLog(formatString(strings.logError || '%1$s: %2$s', [term.name || term.id, errorMessage]), 'error');
|
||||||
|
if (context === 'single') {
|
||||||
|
setStatus(formatString(strings.regenerateError || '%1$s mislukt: %2$s', [term.name || term.id, errorMessage]), 'error');
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const words = json.data && typeof json.data.words !== 'undefined' ? parseInt(json.data.words, 10) : term.words;
|
||||||
|
markTermCompleted(term, Number.isFinite(words) ? words : term.words);
|
||||||
|
appendLog(formatString(strings.logSuccess || '%1$s gevuld.', [term.name || term.id, term.words]), 'success');
|
||||||
|
if (context === 'single') {
|
||||||
|
setStatus(formatString(strings.regenerateDone || '%s is bijgewerkt.', [term.name || term.id]), 'success');
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function processNext() {
|
||||||
|
if (abortRequested) {
|
||||||
|
finish('stopped');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!queue.length) {
|
||||||
|
finish('done');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const term = queue.shift();
|
||||||
|
const progressTemplate = strings.statusProgress;
|
||||||
|
if (progressTemplate) {
|
||||||
|
setStatus(formatString(progressTemplate, [processed + 1, totalCount, term.name || '']), 'loading');
|
||||||
|
}
|
||||||
|
|
||||||
|
sendRequest(term)
|
||||||
|
.then((json) => {
|
||||||
|
if (handleResponse(term, json, 'bulk')) {
|
||||||
|
successes += 1;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
appendLog(
|
||||||
|
formatString(strings.logError || '%1$s: %2$s', [term.name || term.id, error && error.message ? error.message : 'Onbekende fout']),
|
||||||
|
'error'
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
processed += 1;
|
||||||
|
if (abortRequested) {
|
||||||
|
finish('stopped');
|
||||||
|
} else {
|
||||||
|
processNext();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function startBulk() {
|
||||||
|
if (isRunning) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const pending = getPendingTerms();
|
||||||
|
if (!pending.length) {
|
||||||
|
setStatus(strings.statusEmpty || '', 'info');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
queue = pending.slice();
|
||||||
|
totalCount = queue.length;
|
||||||
|
processed = 0;
|
||||||
|
successes = 0;
|
||||||
|
abortRequested = false;
|
||||||
|
resetLog();
|
||||||
|
toggleButtons(true);
|
||||||
|
if (strings.statusIdle) {
|
||||||
|
setStatus(strings.statusIdle, 'info');
|
||||||
|
}
|
||||||
|
processNext();
|
||||||
|
}
|
||||||
|
|
||||||
|
startButton.addEventListener('click', startBulk);
|
||||||
|
|
||||||
|
if (stopButton) {
|
||||||
|
stopButton.addEventListener('click', () => {
|
||||||
|
if (!isRunning) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const confirmation = strings.confirmStop ? window.confirm(strings.confirmStop) : window.confirm('Stoppen?');
|
||||||
|
if (confirmation) {
|
||||||
|
abortRequested = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (allowRegenerate) {
|
||||||
|
const buttons = document.querySelectorAll('.groq-ai-regenerate-term');
|
||||||
|
buttons.forEach((button) => {
|
||||||
|
button.addEventListener('click', () => {
|
||||||
|
if (isRunning) {
|
||||||
|
setStatus(strings.regenerateBlocked || '', 'error');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const termId = parseInt(button.getAttribute('data-term-id'), 10);
|
||||||
|
const term = termMap.get(termId);
|
||||||
|
if (!term) {
|
||||||
|
setStatus('Onbekende term.', 'error');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (strings.confirmRegenerate) {
|
||||||
|
const confirmed = window.confirm(formatString(strings.confirmRegenerate, [term.name || term.id]));
|
||||||
|
if (!confirmed) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
button.classList.add('is-busy');
|
||||||
|
button.disabled = true;
|
||||||
|
if (strings.regenerateProgress) {
|
||||||
|
setStatus(formatString(strings.regenerateProgress, [term.name || term.id]), 'loading');
|
||||||
|
}
|
||||||
|
sendRequest(term, { force: true })
|
||||||
|
.then((json) => {
|
||||||
|
handleResponse(term, json, 'single');
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
const message = error && error.message ? error.message : 'Onbekende fout';
|
||||||
|
appendLog(formatString(strings.logError || '%1$s: %2$s', [term.name || term.id, message]), 'error');
|
||||||
|
setStatus(formatString(strings.regenerateError || '%1$s mislukt: %2$s', [term.name || term.id, message]), 'error');
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
button.disabled = false;
|
||||||
|
button.classList.remove('is-busy');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getPendingTerms().length === 0) {
|
||||||
|
setStatus(strings.statusEmpty || '', 'info');
|
||||||
|
}
|
||||||
|
})();
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
/**
|
/**
|
||||||
* Plugin Name: SitiAI Product Teksten
|
* Plugin Name: SitiAI Product Teksten
|
||||||
* Description: Genereer productteksten met diverse AI-aanbieders rechtstreeks vanuit WooCommerce.
|
* Description: Genereer productteksten met diverse AI-aanbieders rechtstreeks vanuit WooCommerce.
|
||||||
* Version: 1.6.0
|
* Version: 1.6.1
|
||||||
* Author: SitiAI
|
* Author: SitiAI
|
||||||
* Text Domain: siti-ai-product-content-generator
|
* Text Domain: siti-ai-product-content-generator
|
||||||
* Domain Path: /languages
|
* Domain Path: /languages
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -42,6 +42,7 @@ class Groq_AI_Ajax_Controller {
|
|||||||
[
|
[
|
||||||
'include_top_products' => $include_top_products,
|
'include_top_products' => $include_top_products,
|
||||||
'top_products_limit' => $top_products_limit,
|
'top_products_limit' => $top_products_limit,
|
||||||
|
'origin' => 'term_manual',
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -92,6 +93,9 @@ class Groq_AI_Ajax_Controller {
|
|||||||
$term
|
$term
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$options['origin'] = $force ? 'term_force_regenerate' : 'term_bulk_auto';
|
||||||
|
$options['force'] = $force;
|
||||||
|
|
||||||
$result = $this->run_term_generation( $term, $this->get_term_prompt_text( $term ), $options );
|
$result = $this->run_term_generation( $term, $this->get_term_prompt_text( $term ), $options );
|
||||||
if ( is_wp_error( $result ) ) {
|
if ( is_wp_error( $result ) ) {
|
||||||
wp_send_json_error( [ 'message' => $result->get_error_message() ], 500 );
|
wp_send_json_error( [ 'message' => $result->get_error_message() ], 500 );
|
||||||
@@ -119,18 +123,26 @@ class Groq_AI_Ajax_Controller {
|
|||||||
return new WP_Error( 'groq_ai_invalid_term', __( 'Term niet gevonden.', GROQ_AI_PRODUCT_TEXT_DOMAIN ) );
|
return new WP_Error( 'groq_ai_invalid_term', __( 'Term niet gevonden.', GROQ_AI_PRODUCT_TEXT_DOMAIN ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$taxonomy = isset( $term->taxonomy ) ? sanitize_key( (string) $term->taxonomy ) : '';
|
||||||
|
$term_id = isset( $term->term_id ) ? absint( $term->term_id ) : 0;
|
||||||
|
|
||||||
$options = wp_parse_args(
|
$options = wp_parse_args(
|
||||||
$options,
|
$options,
|
||||||
[
|
[
|
||||||
'include_top_products' => true,
|
'include_top_products' => true,
|
||||||
'top_products_limit' => 10,
|
'top_products_limit' => 10,
|
||||||
|
'origin' => 'term_manual',
|
||||||
|
'force' => false,
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$origin = isset( $options['origin'] ) ? sanitize_key( (string) $options['origin'] ) : 'term_manual';
|
||||||
|
$force_run = ! empty( $options['force'] );
|
||||||
$include_top_products = ! empty( $options['include_top_products'] );
|
$include_top_products = ! empty( $options['include_top_products'] );
|
||||||
$top_products_limit = isset( $options['top_products_limit'] ) ? absint( $options['top_products_limit'] ) : 10;
|
$top_products_limit = isset( $options['top_products_limit'] ) ? absint( $options['top_products_limit'] ) : 10;
|
||||||
$top_products_limit = max( 1, min( 25, $top_products_limit ) );
|
$top_products_limit = max( 1, min( 25, $top_products_limit ) );
|
||||||
|
|
||||||
|
$logger = $this->plugin->get_generation_logger();
|
||||||
$settings = $this->plugin->get_settings();
|
$settings = $this->plugin->get_settings();
|
||||||
$provider_manager = $this->plugin->get_provider_manager();
|
$provider_manager = $this->plugin->get_provider_manager();
|
||||||
$provider_key = $settings['provider'];
|
$provider_key = $settings['provider'];
|
||||||
@@ -162,6 +174,19 @@ class Groq_AI_Ajax_Controller {
|
|||||||
? $prompt_builder->prepend_term_context_to_prompt( $prompt, $context_block )
|
? $prompt_builder->prepend_term_context_to_prompt( $prompt, $context_block )
|
||||||
: $prompt_builder->prepend_context_to_prompt( $prompt, $context_block );
|
: $prompt_builder->prepend_context_to_prompt( $prompt, $context_block );
|
||||||
|
|
||||||
|
$usage_meta = [
|
||||||
|
'term_context' => [
|
||||||
|
'taxonomy' => $taxonomy,
|
||||||
|
'term_id' => $term_id,
|
||||||
|
'origin' => $origin,
|
||||||
|
],
|
||||||
|
'term_options' => [
|
||||||
|
'include_top_products' => $include_top_products,
|
||||||
|
'top_products_limit' => $top_products_limit,
|
||||||
|
'force' => $force_run,
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
$response_format = null;
|
$response_format = null;
|
||||||
$use_response_format = $this->plugin->should_use_response_format( $provider, $settings );
|
$use_response_format = $this->plugin->should_use_response_format( $provider, $settings );
|
||||||
if ( $use_response_format && method_exists( $prompt_builder, 'get_term_response_format_definition' ) ) {
|
if ( $use_response_format && method_exists( $prompt_builder, 'get_term_response_format_definition' ) ) {
|
||||||
@@ -187,20 +212,71 @@ class Groq_AI_Ajax_Controller {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if ( is_wp_error( $result ) ) {
|
if ( is_wp_error( $result ) ) {
|
||||||
|
if ( $logger ) {
|
||||||
|
$logger->log_generation_event(
|
||||||
|
[
|
||||||
|
'provider' => $provider_key,
|
||||||
|
'model' => $model,
|
||||||
|
'prompt' => $final_prompt,
|
||||||
|
'response' => '',
|
||||||
|
'usage' => $usage_meta,
|
||||||
|
'status' => 'error',
|
||||||
|
'error_message' => $result->get_error_message(),
|
||||||
|
'post_id' => 0,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
$response_text = $this->extract_content_text( $result );
|
$response_text = $this->extract_content_text( $result );
|
||||||
|
$response_usage = is_array( $result ) && isset( $result['usage'] ) ? $result['usage'] : [];
|
||||||
|
if ( ! is_array( $response_usage ) ) {
|
||||||
|
$response_usage = [];
|
||||||
|
}
|
||||||
|
$response_usage['term_context'] = $usage_meta['term_context'];
|
||||||
|
$response_usage['term_options'] = $usage_meta['term_options'];
|
||||||
$parsed = null;
|
$parsed = null;
|
||||||
if ( method_exists( $prompt_builder, 'parse_term_structured_response' ) ) {
|
if ( method_exists( $prompt_builder, 'parse_term_structured_response' ) ) {
|
||||||
$parsed = $prompt_builder->parse_term_structured_response( $response_text, $settings );
|
$parsed = $prompt_builder->parse_term_structured_response( $response_text, $settings );
|
||||||
}
|
}
|
||||||
|
if ( is_wp_error( $parsed ) ) {
|
||||||
|
if ( $logger ) {
|
||||||
|
$logger->log_generation_event(
|
||||||
|
[
|
||||||
|
'provider' => $provider_key,
|
||||||
|
'model' => $model,
|
||||||
|
'prompt' => $final_prompt,
|
||||||
|
'response' => $response_text,
|
||||||
|
'usage' => $response_usage,
|
||||||
|
'status' => 'error',
|
||||||
|
'error_message' => $parsed->get_error_message(),
|
||||||
|
'post_id' => 0,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return $parsed;
|
||||||
|
}
|
||||||
if ( ! is_array( $parsed ) ) {
|
if ( ! is_array( $parsed ) ) {
|
||||||
$parsed = [
|
$parsed = [
|
||||||
'description' => trim( (string) $response_text ),
|
'description' => trim( (string) $response_text ),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( $logger ) {
|
||||||
|
$logger->log_generation_event(
|
||||||
|
[
|
||||||
|
'provider' => $provider_key,
|
||||||
|
'model' => $model,
|
||||||
|
'prompt' => $final_prompt,
|
||||||
|
'response' => $response_text,
|
||||||
|
'usage' => $response_usage,
|
||||||
|
'status' => 'success',
|
||||||
|
'post_id' => 0,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'top_description' => isset( $parsed['top_description'] ) ? $parsed['top_description'] : ( isset( $parsed['description'] ) ? $parsed['description'] : '' ),
|
'top_description' => isset( $parsed['top_description'] ) ? $parsed['top_description'] : ( isset( $parsed['description'] ) ? $parsed['description'] : '' ),
|
||||||
'bottom_description' => isset( $parsed['bottom_description'] ) ? $parsed['bottom_description'] : '',
|
'bottom_description' => isset( $parsed['bottom_description'] ) ? $parsed['bottom_description'] : '',
|
||||||
|
|||||||
Reference in New Issue
Block a user