File: /var/www/quadcodewordpressapi/public/wp-content/plugins/transtations/translations.php
<?php
/*
Plugin Name: API Post translations
Description: A plugin for storing translations data
Version: 1.0.10
*/
function create_translations_table()
{
global $table_prefix, $wpdb;
$charset_collate = $wpdb->get_charset_collate();
$table_name = $table_prefix . 'translations';
$sql = "CREATE TABLE IF NOT EXISTS " . $table_name . " (
id INT(11) NOT NULL AUTO_INCREMENT,
post_id BIGINT(20) UNSIGNED NOT NULL,
lang VARCHAR(10) NOT NULL,
post_title TEXT NOT NULL,
post_content LONGTEXT NULL,
post_attributes LONGTEXT NULL,
date_created DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
date_modified DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (post_id) REFERENCES {$table_prefix}posts(ID) ON DELETE CASCADE ON UPDATE CASCADE,
UNIQUE KEY lang_post (lang, post_id),
PRIMARY KEY (id));";
$wpdb->query($sql);
}
function create_users_translations_table()
{
global $table_prefix, $wpdb;
$table_name = $table_prefix . 'user_translations';
$sql = "CREATE TABLE IF NOT EXISTS " . $table_name . " (
id INT(11) NOT NULL AUTO_INCREMENT,
user_id BIGINT(20) UNSIGNED NOT NULL,
lang VARCHAR(10) NOT NULL,
description TEXT NOT NULL,
position TEXT NOT NULL,
education TEXT NOT NULL,
experience TEXT NOT NULL,
date_created DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
date_modified DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES {$table_prefix}users(ID) ON DELETE CASCADE ON UPDATE CASCADE,
UNIQUE KEY lang_post (lang, user_id),
PRIMARY KEY (id));";
$wpdb->query($sql);
$table_name = $table_prefix . 'expertise_translations';
$sql = "CREATE TABLE IF NOT EXISTS " . $table_name . " (
id INT(11) NOT NULL AUTO_INCREMENT,
expertise_id BIGINT(20) UNSIGNED NOT NULL,
lang VARCHAR(10) NOT NULL,
name TEXT NOT NULL,
date_created DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
date_modified DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY lang_post (lang, expertise_id),
PRIMARY KEY (id));";
$wpdb->query($sql);
$table_name = $table_prefix . 'users';
$sql = "ALTER TABLE $table_name
ADD COLUMN date_modified DATETIME NULL ON UPDATE CURRENT_TIMESTAMP AFTER user_registered
";
$wpdb->query($sql);
}
function create_tags_translations_table()
{
global $table_prefix, $wpdb;
$table_name = $table_prefix . 'tag_translations';
$sql = "CREATE TABLE IF NOT EXISTS " . $table_name . " (
id INT(11) NOT NULL AUTO_INCREMENT,
tag_id BIGINT(20) UNSIGNED NOT NULL,
lang VARCHAR(10) NOT NULL,
name TEXT NOT NULL,
date_created DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
date_modified DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY lang_post (lang, tag_id),
PRIMARY KEY (id));";
$wpdb->query($sql);
}
function plugin_updates()
{
global $wpdb, $table_prefix;
$pluginVersion = get_site_option('translationsPluginVersion');
$table_name = $table_prefix . 'translations';
switch ($pluginVersion) {
case '':
$wpdb->query(
"ALTER TABLE $table_name
ADD COLUMN post_excerpt TEXT NOT NULL AFTER post_title
"
);
update_option('translationsPluginVersion', '1.0.1');
break;
case '1.0.1':
$wpdb->query(
"ALTER TABLE $table_name
ADD COLUMN yoast_title TEXT NULL
"
);
$wpdb->query(
"ALTER TABLE $table_name
ADD COLUMN yoast_description MEDIUMTEXT NULL
"
);
update_option('translationsPluginVersion', '1.0.2');
break;
case '1.0.2':
$wpdb->query(
"ALTER TABLE $table_name
ADD COLUMN is_active TINYINT DEFAULT 1 NOT NULL AFTER yoast_description
"
);
update_option('translationsPluginVersion', '1.0.3');
break;
case '1.0.3':
$wpdb->query(
"ALTER TABLE $table_name
ADD COLUMN ai_summary TEXT NULL AFTER post_content
"
);
update_option('translationsPluginVersion', '1.0.4');
break;
case '1.0.4':
$table_name = $table_prefix . 'translations';
$sql = "UPDATE $table_name
SET post_content = REPLACE(REPLACE(post_content, '<a href', ' <a href'), '</a>', '</a> ')
WHERE post_content like '%</a>%'";
$wpdb->query($sql);
update_option('translationsPluginVersion', '1.0.5');
break;
case '1.0.5':
$table_name = $table_prefix . 'translations';
$sql = "ALTER TABLE $table_name DROP COLUMN ai_summary";
$wpdb->query($sql);
$sql = "DELETE FROM wp_postmeta
WHERE meta_key = 'ai_summary' OR meta_key = '_ai_summary'";
$wpdb->query($sql);
update_option('translationsPluginVersion', '1.0.6');
break;
case '1.0.6':
create_users_translations_table();
update_option('translationsPluginVersion', '1.0.7');
break;
case '1.0.7':
create_tags_translations_table();
update_option('translationsPluginVersion', '1.0.8');
break;
case '1.0.8':
$table_name = $table_prefix . 'translations';
$sql = "UPDATE $table_name
SET post_attributes = '', is_active = 0
WHERE post_id IN (SELECT DISTINCT post_id FROM {$table_prefix}postmeta WHERE meta_key like '%youtube_video%title' AND meta_value != '');";
$wpdb->query($sql);
update_option('translationsPluginVersion', '1.0.9');
break;
case '1.0.9':
$table_name = $table_prefix . 'user_translations';
$sql = "DELETE FROM $table_name;";
$wpdb->query($sql);
update_option('translationsPluginVersion', '1.0.10');
break;
default:
break;
}
}
add_action('plugins_loaded', 'plugin_updates');
register_activation_hook(__FILE__, 'create_translations_table');
add_action('profile_update', 'userUpdated');
add_action('edit_user_profile_update', 'userUpdated');
function userUpdated($userId, $old_user_data = [])
{
global $wpdb, $table_prefix;
$updateTime = date('Y-m-d H:i:s');
$sql = "UPDATE $table_prefix" . "users SET date_modified = '$updateTime' WHERE ID = $userId";
$wpdb->query($sql);
}
function getPostTranslation($postId, $lang, $isActive = 1, $isCron = false)
{
global $table_prefix,
$wpdb;
if (!is_array($postId)) {
// For single post, if we are swithcihng from existed translated post to non-existed, we should find English post id first
$translatedPostIds = pll_get_post_translations($postId);
foreach ($translatedPostIds as $translatedPostLang => $translatedPostId) {
if ($translatedPostLang === DEFAULT_LANG) {
$postId = $translatedPostId;
}
}
$postId = [$postId];
}
$table_name = $table_prefix . 'translations';
$sql = "SELECT * FROM $table_name WHERE post_id IN (" . implode(',', $postId) . ") AND lang = '$lang' AND is_active = " . $isActive;
$result = $wpdb->get_results($sql);
// Return data for English post if no translation found and call is not from cron job
if (empty($result[0]) && !$isCron) {
$englishPostId = $postId[0];
$englishPost = get_post($englishPostId);
$result = [
json_decode(json_encode([
'post_title' => $englishPost->post_title,
'post_content' => $englishPost->post_content,
'post_excerpt' => $englishPost->post_excerpt,
'post_attributes' => serialize(get_fields($englishPostId)),
'yoast_title' => get_post_meta($englishPostId, '_yoast_wpseo_title', true),
'yoast_description' => get_post_meta($englishPostId, '_yoast_wpseo_metadesc', true),
])),
];
} else {
if (!empty($result[0])) {
// Clean tags generated by GPT
$result[0]->post_title = cleanHtmlTags($result[0]->post_title);
}
}
return $result;
}
function cleanHtmlTags($text)
{
// if text is like <html> <head> <title>Prueba</title> </head> <body> <h1>Prueba</h1> </body> </html> need to split by html tags and get only unique text parts
$textParts = preg_split('/<[^>]+>/', $text);
$cleanParts = [];
foreach ($textParts as $part) {
$part = trim($part);
if (!empty($part) && !in_array($part, $cleanParts)) {
$cleanParts[] = $part;
}
}
return implode(' ', $cleanParts);
}
function add_translation($postData, $lang)
{
$postTranslation = getPostTranslation($postData['id'], $lang);
if (!empty($postTranslation[0])) {
$translation = $postTranslation[0];
if (!empty($postData['yoast_head_json'])) {
if ($postData['yoast_head_json']['title'] == $postData['title']['rendered']) {
$postData['yoast_head_json']['title'] = do_shortcode($translation->post_title);
} else {
$postData['yoast_head_json']['title'] = do_shortcode($translation->yoast_title);
}
$postData['yoast_head_json']['description'] = do_shortcode($translation->yoast_description);
$postData['yoast_head_json']['og_title'] = $postData['yoast_head_json']['title'];
$postData['yoast_head_json']['og_description'] = $postData['yoast_head_json']['description'];
}
if (!empty($postData['title']) && !empty($postData['title']['rendered'])) {
$postData['title']['rendered'] = do_shortcode($translation->post_title);
} elseif (!empty($postData['title'])) {
$postData['title'] = do_shortcode($translation->post_title);
}
if (!empty($postData['excerpt']) && !empty($postData['excerpt']['rendered'])) {
$postData['excerpt']['rendered'] = do_shortcode($translation->post_excerpt);
} elseif (!empty($postData['excerpt'])) {
$postData['excerpt'] = do_shortcode($translation->post_excerpt);
}
// Images url fix
$translation->post_content = str_replace('http:/wp-content/', 'https://wp.quadcode.com/wp-content/', $translation->post_content);
if (!empty($postData['content']) && !empty($postData['content']['rendered'])) {
$postData['content']['initial'] = $postData['content']['rendered'];
$postData['content']['rendered'] = do_shortcode($translation->post_content);
} elseif (!empty($postData['content'])) {
$postData['content'] = do_shortcode($translation->post_content);
}
if ($translation->post_attributes && !empty($postData['acf']) && !empty($postData['acf']['faq'])) {
if (is_base64($translation->post_attributes)) {
$translation->post_attributes = base64_decode($translation->post_attributes);
}
$attributes = unserialize($translation->post_attributes);
if (!empty($attributes) && !empty($attributes['faq'])) {
$postData['acf']['faq'] = $attributes['faq'];
}
}
if (!empty($postData['tag']) && !empty($postData['tagId'])) {
$tagsTranslations = getTagTranslations($lang);
if (!empty($tagsTranslations[$postData['tagId']])) {
$postData['tag'] = $tagsTranslations[$postData['tagId']];
}
}
}
return $postData;
}
function is_base64($data) {
return base64_encode(base64_decode($data, true)) === $data;
}
add_filter(
'wp_post_revision_meta_keys',
function ($keys, $post_type) {
if (in_array($post_type, [POST_TYPE, EVENT_TYPE, GLOSSARY_TYPE])) {
$keys[] = '_yoast_wpseo_title';
$keys[] = '_yoast_wpseo_metadesc';
}
return $keys;
},
10, 2
);
//detect when a revision is being saved, then copy relevant meta from the parent:
add_action(
'_wp_put_post_revision',
function ($revision_id, $parent_id) {
// Copy desired meta keys from parent → revision
$keys = ['_yoast_wpseo_title', '_yoast_wpseo_metadesc'];
foreach ($keys as $meta_key) {
delete_metadata('post', $revision_id, $meta_key);
$values = get_post_meta($parent_id, $meta_key, false);
foreach ($values as $val) {
add_metadata('post', $revision_id, $meta_key, $val);
}
}
},
10, 2
);
//to restore meta into the parent when restoring:
add_action('wp_restore_post_revision', function ($post_id, $revision_id) {
$keys = ['_yoast_wpseo_title', '_yoast_wpseo_metadesc'];
foreach ($keys as $meta_key) {
$meta = get_metadata('post', $revision_id, $meta_key, true);
if (false !== $meta) {
update_post_meta($post_id, $meta_key, $meta);
} else {
delete_post_meta($post_id, $meta_key);
}
}
}, 10, 2);
//To display meta data on the revision comparison screen:
add_filter('_wp_post_revision_fields', function ($fields) {
$fields['_yoast_wpseo_title'] = 'Meta Title';
$fields['_yoast_wpseo_metadesc'] = 'Meta Description';
return $fields;
});
add_filter('_wp_post_revision_field_yoast_wpseo_title', function ($value, $revision) {
return get_metadata('post', $revision->ID, '_yoast_wpseo_title', true);
}, 10, 2);
add_filter('_wp_post_revision_field_yoast_wpseo_metadesc', function ($value, $revision) {
return get_metadata('post', $revision->ID, '_yoast_wpseo_metadesc', true);
}, 10, 2);
add_action('save_post', 'resetTranslationsAfterPostUpdated', 10, 3);
function resetTranslationsAfterPostUpdated($post_id, WP_Post $post, $update)
{
global $wpdb;
if (wp_is_post_revision($post_id)) {
return;
}
// Optional: restrict to a specific post type
if (!in_array($post->post_type, [POST_TYPE, EVENT_TYPE, GLOSSARY_TYPE])) {
return;
}
$revisions = wp_get_post_revisions($post_id);
$prevRevision = null;
$postLang = pll_get_post_language($post_id);
if ($revisions && count($revisions) > 1) {
$prevRevision = array_values($revisions)[1];
$fieldsChanged = [];
if (isset($prevRevision)) {
$post_has_changed = false;
$meta = get_post_meta($post->ID);
if (!empty($meta)) {
if (!empty($meta['_yoast_wpseo_title'])) {
$metaTitle = $meta['_yoast_wpseo_title'][0];
}
if (!empty($meta['_yoast_wpseo_metadesc'])) {
$metaDescription = $meta['_yoast_wpseo_metadesc'][0];
}
}
$revisionMeta = get_post_meta($prevRevision->ID);
if (!empty($revisionMeta)) {
if (!empty($revisionMeta['_yoast_wpseo_title'])) {
$revisionMetaTitle = $revisionMeta['_yoast_wpseo_title'][0];
}
if (!empty($revisionMeta['_yoast_wpseo_metadesc'])) {
$revisionMetaDescription = $revisionMeta['_yoast_wpseo_metadesc'][0];
}
}
$checkFields = [
'post_title',
'post_content',
'post_excerpt',
];
foreach ($checkFields as $field) {
if (normalize_whitespace($post->$field) !== normalize_whitespace($prevRevision->$field)) {
$post_has_changed = true;
$fieldsChanged[] = $field;
}
}
$attributes = get_fields($post->ID);
$revisionAttributes = get_fields($prevRevision->ID);
foreach (array_keys($attributes) as $attributeKey => $field) {
if (!empty($attributes[$attributeKey]) && is_string($attributes[$attributeKey]) && !is_numeric($attributes[$attributeKey])) {
if (normalize_whitespace($attributes[$attributeKey]) !== normalize_whitespace($revisionAttributes[$attributeKey])) {
$post_has_changed = true;
$fieldsChanged[] = $field;
}
}
}
if (!empty($attributes['faq'])) {
if ($attributes['faq'] !== $revisionAttributes['faq']) {
$post_has_changed = true;
$fieldsChanged[] = 'faq';
}
}
if (!empty($attributes['youtube_video'])) {
if ($attributes['youtube_video'] !== $revisionAttributes['youtube_video']) {
$post_has_changed = true;
$fieldsChanged[] = 'youtube_video';
}
}
if ($metaTitle !== $revisionMetaTitle) {
$post_has_changed = true;
$fieldsChanged[] = 'yoast_title';
}
if ($metaDescription !== $revisionMetaDescription) {
$post_has_changed = true;
$fieldsChanged[] = 'yoast_description';
}
/**
* Filters whether a post has changed.
*
* By default a revision is saved only if one of the revisioned fields has changed.
* This filter allows for additional checks to determine if there were changes.
*/
$post_has_changed = (bool) apply_filters('wp_save_post_revision_post_has_changed', $post_has_changed, $prevRevision, $post);
if ($post_has_changed && !empty($fieldsChanged)) {
// Clean updated fields in translations table, to translate them again
$table_name = $wpdb->prefix . 'translations';
$sql = "UPDATE $table_name SET is_active = 0 WHERE post_id = $post_id";
$wpdb->query($sql);
$sql = "UPDATE $table_name SET ";
if (in_array('faq', $fieldsChanged)) {
unset($fieldsChanged[array_search('faq', $fieldsChanged)]);
$sql .= "post_attributes = '', ";
}
if (in_array('youtube_video', $fieldsChanged)) {
unset($fieldsChanged[array_search('youtube_video', $fieldsChanged)]);
$sql .= "post_attributes = '', ";
}
foreach ($fieldsChanged as $field) {
$sql .= "$field = '', ";
}
$sql = rtrim($sql, ', ');
$sql .= " WHERE post_id = $post_id";
$wpdb->query($sql);
}
}
}
}
add_action('admin_menu', 'custom_translations_menu');
function custom_translations_menu()
{
add_menu_page('Custom Posts Translations', 'Custom Posts Translations', 'manage_options', 'custom-translations', 'custom_translations_page');
}
function custom_translations_page()
{
?>
<div class="wrap">
<h1>Custom Posts Translations</h1>
<?php
// Display data
global $wpdb;
$table_name = $wpdb->prefix . 'translations';
$results = $wpdb->get_results("SELECT * FROM $table_name");
if ($results) {
echo '<table class="widefat"><thead><tr><th>Post ID</th><th>Lang</th><th>Updated At</th><th>Title</th><th>Is Active</th></tr></thead><tbody>';
foreach ($results as $row) {
echo "<tr><td><a href='/wp-admin/post.php?post={$row->post_id}&action=edit'>{$row->post_id}</a></td><td>{$row->lang}</td><td>{$row->date_modified}</td><td>{$row->post_title}</td><th>{$row->is_active}</th></tr>";
}
echo '</tbody></table>';
} else {
echo '<p>No data found.</p>';
}
?>
</div>
<?php
}
add_action('admin_menu', 'translations_add_admin_menu');
add_action('admin_init', 'translations_settings_init');
function translations_add_admin_menu()
{
add_options_page(
'Translations Settings',
'Translations',
'manage_options',
'translations-settings-form',
'translation_settings_page'
);
}
function translation_settings_page()
{
?>
<form action="options.php" method="post">
<h2>Translation Settings</h2>
<?php
settings_fields('translations_settings');
do_settings_sections('translations-settings-form');
submit_button();
?>
</form>
<?php
}
function translations_settings_init()
{
register_setting('translations_settings', 'translation_settings');
add_settings_section(
'translations_section_main',
'',
null,
'translations-settings-form'
);
add_settings_field(
'translations_token',
'GPT Token',
'translations_token_render',
'translations-settings-form',
'translations_section_main'
);
add_settings_field(
'translations_prompt',
'GPT Prompt for generating Summary',
'translations_prompt_render',
'translations-settings-form',
'translations_section_main'
);
add_settings_field(
'translations_prompt_fulltext',
'GPT Prompt for generating Summary after Translation',
'translations_prompt_fulltext_render',
'translations-settings-form',
'translations_section_main'
);
}
function translations_prompt_render()
{
$options = get_option('translation_settings');
?>
<textarea name="translation_settings[gpt_prompt]" rows="5" cols="50"><?php echo esc_attr($options['gpt_prompt'] ?? ''); ?></textarea>
<p class="description">
GPT prompt used for generating summary. Placeholders available: {url} - for page url, {lang} for page lang.
<br> Ex. Generate a concise summary for the following article in {lang} language. Article URL: {url} <br/> The summary should be no more than 400 characters and should accurately reflect the content of the
article. Return only summary text.
</p>
<?php
}
function translations_prompt_fulltext_render()
{
$options = get_option('translation_settings');
?>
<textarea name="translation_settings[gpt_prompt_fulltext]" rows="5" cols="50"><?php echo esc_attr($options['gpt_prompt_fulltext'] ?? ''); ?></textarea>
<p class="description">
GPT prompt used for generating summary after new translation. Placeholders available: {lang} for page lang.
<br> Ex. Generate a concise summary for the following article in {lang} language. <br/> The summary should be no more than 400 characters and should accurately reflect the content of the article. Return only
summary text.
</p>
<?php
}
function translations_token_render()
{
$options = get_option('translation_settings');
?>
<input type="text" name="translation_settings[gpt_token]" value="<?php echo esc_attr($options['gpt_token'] ?? ''); ?>" size="50">
<p class="description">OpenAI API Token</p>
<?php
}
add_filter('plugin_action_links_' . plugin_basename(__FILE__), 'translation_settings_link');
function translation_settings_link($links)
{
$settings_link = '<a href="options-general.php?page=translations-settings-form">' . __('Settings') . '</a>';
array_unshift($links, $settings_link);
return $links;
}
function sendOpenAiRequest($prompt, $token)
{
$headers = [
'Authorization: Bearer ' . $token,
];
$messages = [
['role' => 'user', 'content' => $prompt],
];
$url = 'https://api.openai.com/v1/chat/completions';
$data = [
'model' => 'gpt-4o-mini-2024-07-18',
'messages' => $messages,
'temperature' => 0.7,
];
return sendCurl($url, $data, $headers);
}
function sendCurl($url, $body = [], $headers = [])
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
if (empty($body)) {
curl_setopt($ch, CURLOPT_POST, false);
} else {
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($body));
$headers[] = "Content-Type: application/json";
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
}
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$errors = curl_error($ch);
if (!empty($errors)) {
print_r($errors);
saveLog(json_encode($errors));
}
return $response;
}
function addAuthorTranslations($user, $data, $lang)
{
$pluginVersion = get_site_option('translationsPluginVersion');
if (version_compare($pluginVersion, '1.0.7', '<')) {
return $data;
}
$expertise = $user->expertise;
$expertiseArray = [];
$translatedExpertiseList = getTranslatedExpertiseList($lang);
$translatedAuthorData = getTranslatedAuthorData($user->ID, $lang);
if (!empty($expertise)) {
foreach ($expertise as $exp) {
$term = get_term_by('id', $exp, 'expertise');
if (!empty($translatedExpertiseList[$term->term_id])) {
$expertiseArray[] = $translatedExpertiseList[$term->term_id];
} else {
$expertiseArray[] = $term->name;
}
}
$data['expertise'] = $expertiseArray;
}
if (!empty($translatedAuthorData)) {
if (is_array($data['description']) &&
(empty($data['description'][$lang]) || (!empty($data['description']['en']) && $data['description']['en'] == $data['description'][$lang]))
) {
$data['description']['en'] = $translatedAuthorData->description;
$data['description'][$lang] = $translatedAuthorData->description;
} elseif (empty($data['description']) || (!empty($data['descriptionEn']) && $data['descriptionEn'] == $data['description'])) {
$data['description'] = $translatedAuthorData->description;
} elseif (is_array($data['description']) && !empty($data['description'][$lang])) {
$data['description']['en'] = $data['description'][$lang];
}
$data['position'] = $translatedAuthorData->position;
if (property_exists($translatedAuthorData, 'experience') && !empty($data['experience'])) {
$translatedExpertise = json_decode($translatedAuthorData->experience);
foreach ($data['experience'] as $key => $experience) {
if (!empty($data['experience'][$key])) {
$data['experience'][$key]['years'] = $translatedExpertise[$key]->years;
$data['experience'][$key]['position'] = $translatedExpertise[$key]->position;
$data['experience'][$key]['description'] = $translatedExpertise[$key]->description;
}
}
}
if (property_exists($translatedAuthorData, 'education') && !empty($data['education'])) {
$translatedEducation = json_decode($translatedAuthorData->education);
foreach ($data['education'] as $key => $education) {
if (!empty($data['education'][$key])) {
$data['education'][$key]['title'] = $translatedEducation[$key]->title;
$data['education'][$key]['subtitle'] = $translatedEducation[$key]->subtitle;
}
}
}
}
return $data;
}
function getTranslatedExpertiseList($lang)
{
global $wpdb, $table_prefix;
$pluginVersion = get_site_option('translationsPluginVersion');
if (version_compare($pluginVersion, '1.0.7', '<')) {
return [];
}
$rows = $wpdb->get_results(
$wpdb->prepare(
"SELECT expertise_id, name from {$table_prefix}expertise_translations WHERE lang = %s",
$lang
)
);
return array_column($rows, 'name', 'expertise_id');
}
function getTranslatedAuthorData($userId, $lang)
{
global $wpdb, $table_prefix;
$pluginVersion = get_site_option('translationsPluginVersion');
if (version_compare($pluginVersion, '1.0.7', '<')) {
return [];
}
$data = $wpdb->get_row(
$wpdb->prepare(
"SELECT * from {$table_prefix}user_translations WHERE user_id = %d AND lang = %s",
$userId,
$lang
)
);
return $data;
}
function getTagTranslations($lang)
{
global $wpdb, $table_prefix;
$pluginVersion = get_site_option('translationsPluginVersion');
if (version_compare($pluginVersion, '1.0.7', '<')) {
return [];
}
$rows = $wpdb->get_results(
$wpdb->prepare(
"SELECT tag_id, name from {$table_prefix}tag_translations WHERE lang = %s",
$lang
)
);
return array_column($rows, 'name', 'tag_id');
}
function saveLog($text = '')
{
$text .= PHP_EOL;
echo $text;
// WP Log save but not only error
$file = wp_upload_dir()['basedir'] . '/translations-log.txt';
$file = fopen($file, 'a');
fwrite($file, date('Y-m-d H:i:s') . ' - ' . $text . PHP_EOL);
fclose($file);
}
function sendAlert($text = '') {
$telegramToken = '8201724315:AAHJaMFNER4i14pdMniuml9bu0oU7d90K0g';
$userIds = [203456552, 517650898];
$iniUrl = "https://api.telegram.org/bot{$telegramToken}";
$finalUrl = $iniUrl . '/sendMessage';
foreach ($userIds as $userId) {
$body = [
"chat_id" => $userId,
"text" => $text,
];
sendCurl($finalUrl, $body);
}
}