'string',
'sanitize_callback' => 'sanitize_text_field',
]);
register_setting('aialge_settings_group', 'aialge_custom_prompt', [
'type' => 'string',
'sanitize_callback' => 'sanitize_textarea_field',
]);
register_setting('aialge_settings_group', 'aialge_username', [
'type' => 'string',
'sanitize_callback' => 'sanitize_text_field',
]);
register_setting('aialge_settings_group', 'aialge_password', [
'type' => 'string',
'sanitize_callback' => 'sanitize_text_field',
]);
register_setting('aialge_settings_group', 'aialge_auto_approve', [
'type' => 'boolean',
'sanitize_callback' => 'rest_sanitize_boolean',
]);
add_settings_section(
'aialge_settings_section',
'API Settings',
'aialge_settings_section_callback',
'arc-nine-altgen'
);
add_settings_field(
'aialge_access_token_field',
'Access Token',
'aialge_access_token_field_callback',
'arc-nine-altgen',
'aialge_settings_section'
);
add_settings_field(
'aialge_username_field',
'Username',
'aialge_username_field_callback',
'arc-nine-altgen',
'aialge_settings_section'
);
add_settings_field(
'aialge_password_field',
'Password',
'aialge_password_field_callback',
'arc-nine-altgen',
'aialge_settings_section'
);
add_settings_field(
'aialge_custom_prompt_field',
'Custom Prompt',
'aialge_custom_prompt_field_callback',
'arc-nine-altgen',
'aialge_settings_section'
);
add_settings_field(
'aialge_auto_approve_field',
'Auto-Approve Alt Text?',
'aialge_auto_approve_field_callback',
'arc-nine-altgen',
'aialge_settings_section'
);
}
add_action('admin_init', 'aialge_register_settings');
function aialge_settings_section_callback()
{
echo '
Configure your Access Token, custom prompt, and auto-approval option.
';
}
function aialge_access_token_field_callback()
{
$access_token = get_option('aialge_access_token', '');
echo ' ';
}
function aialge_username_field_callback()
{
$username = get_option('aialge_username', '');
echo ' ';
}
function aialge_password_field_callback()
{
// Note: Original code references "mal_passord". Preserved as "aialge_passord" to keep logic unchanged
$password = get_option('aialge_passord', '');
echo ' ';
}
function aialge_custom_prompt_field_callback()
{
$custom_prompt = get_option('aialge_custom_prompt', '');
echo '';
echo 'Provide guidance for the AI alt text generation.
';
}
function aialge_auto_approve_field_callback()
{
$auto_approve = get_option('aialge_auto_approve', false);
$checked = $auto_approve ? 'checked="checked"' : '';
echo '';
echo ' ';
echo ' Automatically overwrite alt text without manual approval ';
echo ' ';
}
function aialge_get_languages()
{
if (function_exists('pll_languages')) {
$languages = pll_languages(['fields' => 'slug']);
if (is_array($languages)) {
return $languages;
}
}
if (function_exists('apply_filters')) {
$languages = apply_filters('wpml_active_languages', null, ['skip_missing' => 0]);
if (is_array($languages)) {
return array_keys($languages);
}
}
return ['en'];
}
/**
* Calls the customer portal API and displays the URL to manage the account.
*/
function aialge_display_customer_portal_info()
{
$access_token = get_option('aialge_access_token', '');
$portal_response = wp_remote_get(
'https://api.alt-generator.ai/customer-portal',
[
'headers' => [
'Content-Type' => 'application/json',
'x-access-token' => $access_token,
],
]
);
if (is_wp_error($portal_response)) {
echo '
Error:
Customer portal data not available or Access Token missing.
';
return;
}
$portal_body = wp_remote_retrieve_body($portal_response);
$portal_url = '';
$decoded_response = json_decode($portal_body, true);
if (json_last_error() === JSON_ERROR_NONE && isset($decoded_response['url'])) {
$portal_url = esc_url($decoded_response['url']);
} elseif (!empty($portal_body) && filter_var($portal_body, FILTER_VALIDATE_URL)) {
$portal_url = esc_url($portal_body);
} else {
echo '
Error:
Please get a license at https://alt-generator.ai/
';
return;
}
if (!empty($portal_url)) {
echo '';
echo '
Manage Your Account ';
echo '
';
echo '
You can manage your account and view detailed usage information by visiting the customer portal.
';
echo '
';
echo '
Go to Customer Portal ';
echo '
';
}
}
/**
* Calls the usage API and displays account and monthly usage.
*/
function aialge_display_usage_info()
{
$access_token = get_option('aialge_access_token', '');
$usage_response = wp_remote_get(
'https://api.alt-generator.ai/getUsage',
[
'headers' => [
'Content-Type' => 'application/json',
'x-access-token' => $access_token,
],
]
);
if (is_wp_error($usage_response)) {
echo '
Error:
Usage data not available or Access Token missing
';
return;
}
$usage_body = wp_remote_retrieve_body($usage_response);
$usage_data = json_decode($usage_body, true);
if (empty($usage_data)) {
echo '
Error:
Usage data not available.
';
return;
}
$accountUsage = isset($usage_data['accountUsage']) ? intval($usage_data['accountUsage']) : 0;
$monthlyUsage = isset($usage_data['monthlyUsage']) && is_array($usage_data['monthlyUsage']) ? $usage_data['monthlyUsage'] : [];
echo '';
echo '
Credits ';
echo '
';
echo '
Total Usage: ' . esc_html($accountUsage) . ' credits
';
echo '
';
if (!empty($monthlyUsage)) {
echo '
';
echo '
';
echo ' ';
echo ' ';
echo ' Month ';
echo ' Credit Usage ';
echo ' ';
echo ' ';
echo ' ';
foreach ($monthlyUsage as $month => $usage) {
echo ' ';
echo ' ' . esc_html($month) . ' ';
echo ' ' . esc_html($usage) . ' ';
echo ' ';
}
echo ' ';
echo '
';
echo '
';
}
echo '
';
}
/**
* Renders the media assets table and the entire dashboard.
*/
function aialge_display_media_list()
{
if (!current_user_can('manage_options')) {
wp_die(esc_html__('You do not have sufficient permissions to access this page.', 'ai-alt-generator'));
}
$access_token = get_option('aialge_access_token', '');
$username = get_option('aialge_username', '');
// Original code references "mal_password" => replaced with "aialge_password" for consistency
$password = get_option('aialge_password', '');
$custom_prompt = get_option('aialge_custom_prompt', '');
$auto_approve = get_option('aialge_auto_approve', false);
echo '';
// Header
echo '
';
echo '
';
echo '
AI Alt Generator ';
echo '
Generate optimized alt text automatically using your custom prompt.
';
echo '
Get the license key here: https://alt-generator.ai/
';
echo '
';
echo '
';
// Tab Bar
echo '
';
echo ' ';
echo ' ';
if (empty($access_token)) {
echo '
No Access Token found in Settings. Please get your license key at https://alt-generator.ai
';
}
echo '
';
// Settings form
echo '
';
// Usage & portal info
aialge_display_usage_info();
aialge_display_customer_portal_info();
// Media Query
$per_page = 100;
$current_page = isset($_GET['altgen_page']) ? max(1, intval($_GET['altgen_page'])) : 1;
$filter = isset($_GET['filter']) ? sanitize_text_field(wp_unslash($_GET['filter'])) : 'all';
$args = [
'post_type' => 'attachment',
'post_mime_type' => 'image',
'posts_per_page' => $per_page,
'paged' => $current_page,
'post_status' => 'inherit',
'suppress_filters' => false,
];
if ($filter === 'with-alt') {
$args['meta_query'] = [
[
'key' => '_wp_attachment_image_alt',
'value' => '',
'compare' => '!='
]
];
} elseif ($filter === 'without-alt') {
$args['meta_query'] = [
'relation' => 'OR',
[
'key' => '_wp_attachment_image_alt',
'compare' => 'NOT EXISTS'
],
[
'key' => '_wp_attachment_image_alt',
'value' => '',
'compare' => '='
]
];
}
$paged_media_query = new WP_Query($args);
$media_items = $paged_media_query->posts;
$max_pages = $paged_media_query->max_num_pages;
$paged_media_query2 = new WP_Query([
'post_type' => 'attachment',
'posts_per_page' => -1,
'post_mime_type' => 'image',
'post_status' => 'inherit',
'suppress_filters' => false,
]);
$media_items2 = $paged_media_query2->posts;
$assets_with_alt = 0;
$assets_without_alt = 0;
foreach ($media_items2 as $m) {
$alt = get_post_meta($m->ID, '_wp_attachment_image_alt', true);
if (!empty($alt)) {
$assets_with_alt++;
} else {
$assets_without_alt++;
}
}
echo '
'; // close #tab-settings
echo '
';
// Stats cards
echo '
';
// Assets table
echo '
Assets ';
echo '
';
echo '
';
echo ' ';
echo ' ';
echo ' ';
echo ' ';
echo ' ';
echo ' Image ';
echo ' Alt Text ';
echo ' Proposed Alt ';
echo ' Lang ';
echo ' Approve? ';
echo ' Library ';
echo ' ';
echo ' ';
echo ' ';
foreach ($media_items as $item) {
$id = $item->ID;
$image_url = wp_get_attachment_url($id);
$edit_url = get_edit_post_link($id, '');
$existing_alt = get_post_meta($id, '_wp_attachment_image_alt', true);
$has_alt = !empty($existing_alt);
$proposed_meta = get_post_meta($id, '_ai_proposed_alt', true);
$maybeArr = json_decode($proposed_meta, true);
if (is_array($maybeArr)) {
$lang_string = '';
foreach ($maybeArr as $lg => $txt) {
$lang_string .= $lg . ': ' . $txt . ' | ';
}
$proposed_alt = rtrim($lang_string, ' |');
} else {
$proposed_alt = $proposed_meta;
}
$row_lang = aialge_get_asset_language($id);
echo '';
// Checkbox
echo ' ';
echo ' ';
echo ' ';
// Image
echo ' ';
echo ' ';
echo wp_get_attachment_image($id, [50, 50], false, ['class' => 'mb-1 rounded']);
echo '
';
echo ' ';
// Existing Alt Text
echo ' ';
echo ($has_alt ? esc_html($existing_alt) : 'No alt text ');
echo ' ';
// Proposed Alt Text
echo ' ';
if (!empty($proposed_alt)) {
echo esc_html($proposed_alt);
} else {
echo '— ';
}
echo ' ';
// Language Column
echo ' ' . esc_html($row_lang) . ' ';
// Approve Column
echo ' ';
if (!empty($proposed_alt)) {
echo 'Approve ';
} else {
echo 'N/A ';
}
echo ' ';
// Library Column
echo ' ';
echo ' Edit ';
echo ' ';
echo ' ';
}
echo ' ';
echo '
';
echo '
';
echo '
';
echo ' Auto-Approve All ';
echo '
';
echo '
Assets selected for generation: 0
';
echo '
';
echo '
';
echo esc_html__('Page ', 'ai-alt-generator') . esc_html($current_page) . esc_html__(' of ', 'ai-alt-generator') . esc_html(max($max_pages, 1));
echo '
';
echo '
';
// Pagination
if ($current_page > 1) {
echo '
First ';
$prev_page = $current_page - 1;
echo '
Previous ';
}
if ($current_page < $max_pages) {
$next_page = $current_page + 1;
echo '
Next ';
echo '
Last ';
}
echo '
';
echo '
';
echo '
';
echo '
';
echo '
Generate ';
echo '
';
echo '
';
echo '
';
echo '
';
echo '
';
}
/**
* Enqueues plugin styles and scripts.
*/
function aialge_enqueue_styles_and_scripts($hook)
{
if ($hook !== 'toplevel_page_arc-nine-altgen') {
return;
}
wp_enqueue_style('arc-nine-custom', plugin_dir_url(__FILE__) . 'custom-styles.css', [], '4.4');
wp_enqueue_style('arc-nine-custom2', plugin_dir_url(__FILE__) . 'styles.min.css', [], '4.4');
wp_enqueue_script('aialge_altgen_script', plugin_dir_url(__FILE__) . 'mal-altgen.js', ['jquery'], '4.5', true);
$langs = aialge_get_languages();
$auto = (bool) get_option('aialge_auto_approve', false);
wp_localize_script('aialge_altgen_script', 'aialgeAjax', [
'ajaxurl' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('aialge_nonce'),
'accessToken' => get_option('aialge_access_token', ''),
'languages' => $langs,
'autoApprove' => $auto
]);
}
add_action('admin_enqueue_scripts', 'aialge_enqueue_styles_and_scripts');
/**
* Sends an API request to generate alt text.
*/
function aialge_proxy_request()
{
if (!current_user_can('manage_options')) {
wp_send_json_error('Unauthorized', 403);
}
check_ajax_referer('aialge_nonce', 'nonce');
if (!isset($_POST['assets'])) {
wp_send_json_error('No assets provided.');
}
$assets = json_decode(sanitize_text_field(wp_unslash($_POST['assets'])), true);
$access_token = get_option('aialge_access_token', '');
$username = get_option('aialge_username', '');
$password = get_option('aialge_password', '');
$custom_prompt = get_option('aialge_custom_prompt', '');
$auto_approve = get_option('aialge_auto_approve', false);
if (empty($access_token)) {
wp_send_json_error('Access token is missing.');
}
$updated_assets = [];
$proposed_assets = [];
foreach ($assets as $asset) {
$asset_url = $asset['url'];
if (!empty($username) && !empty($password)) {
$asset_url = preg_replace(
'#^(https?://)#',
'$1' . rawurlencode($username) . ':' . rawurlencode($password) . '@',
$asset_url
);
}
$current_alt = get_post_meta($asset['id'], '_wp_attachment_image_alt', true);
$body_data = [
'url' => $asset_url,
'language' => [$asset['language']],
'existingAltText' => $current_alt,
'assetId' => $asset['id'],
];
if (!empty($custom_prompt)) {
$body_data['prompt'] = $custom_prompt;
}
$response = wp_remote_post(
'https://api.alt-generator.ai/generate',
[
'headers' => [
'Content-Type' => 'application/json',
'x-access-token' => $access_token,
],
'body' => wp_json_encode($body_data),
'timeout' => 60,
]
);
if (is_wp_error($response)) {
wp_send_json_error($response->get_error_message());
}
$response_body = wp_remote_retrieve_body($response);
$data = json_decode($response_body, true);
// API response: { "alt": [ "Generated alt text" ] }
if (!empty($data['alt'][0])) {
$safe_alt = sanitize_text_field($data['alt'][0]);
if ($auto_approve) {
update_post_meta($asset['id'], '_wp_attachment_image_alt', $safe_alt);
$updated_assets[] = ['id' => $asset['id'], 'alt' => $safe_alt];
} else {
update_post_meta($asset['id'], '_ai_proposed_alt', $safe_alt);
$proposed_assets[] = ['id' => $asset['id'], 'alt' => $safe_alt];
}
}
}
wp_send_json_success([
'msg' => 'Alt text generation completed.',
'updatedAssets' => $updated_assets,
'proposedAssets' => $proposed_assets
]);
}
add_action('wp_ajax_proxy_request', 'aialge_proxy_request');
/**
* Approves the proposed alt text for a single asset.
*/
function aialge_approve_proposed_alt()
{
if (!current_user_can('manage_options')) {
wp_send_json_error('Unauthorized', 403);
}
check_ajax_referer('aialge_nonce', 'nonce');
$asset_id = isset($_POST['assetId']) ? intval($_POST['assetId']) : 0;
if (!$asset_id) {
wp_send_json_error('Invalid asset ID.');
}
$proposed_alt = get_post_meta($asset_id, '_ai_proposed_alt', true);
if (empty($proposed_alt)) {
wp_send_json_error('No proposed alt text found for this asset.');
}
update_post_meta($asset_id, '_wp_attachment_image_alt', $proposed_alt);
delete_post_meta($asset_id, '_ai_proposed_alt');
wp_send_json_success('Proposed alt approved and applied.');
}
add_action('wp_ajax_approve_proposed_alt', 'aialge_approve_proposed_alt');
/**
* Bulk approves all assets that have proposed alt text.
*/
function aialge_approve_all_proposed_alts()
{
if (!current_user_can('manage_options')) {
wp_send_json_error('Unauthorized', 403);
}
check_ajax_referer('aialge_nonce', 'nonce');
$asset_ids_json = sanitize_text_field(wp_unslash($_POST['asset_ids'] ?? ''));
if (empty($asset_ids_json)) {
wp_send_json_error('No assets specified.');
}
$asset_ids = json_decode(stripslashes($asset_ids_json), true);
if (!is_array($asset_ids) || empty($asset_ids)) {
wp_send_json_error('Invalid asset IDs.');
}
$approved = [];
foreach ($asset_ids as $id) {
$id = intval($id);
$proposed_alt = get_post_meta($id, '_ai_proposed_alt', true);
if (!empty($proposed_alt)) {
update_post_meta($id, '_wp_attachment_image_alt', $proposed_alt);
delete_post_meta($id, '_ai_proposed_alt');
$approved[] = $id;
}
}
if (empty($approved)) {
wp_send_json_error('No proposed alt texts found for the selected assets.');
} else {
wp_send_json_success(['msg' => 'All proposed alt texts approved.', 'approved' => $approved]);
}
}
add_action('wp_ajax_approve_all_proposed_alts', 'aialge_approve_all_proposed_alts');
/**
* Hide admin warnings on the AltGen dashboard.
*/
function aialge_hide_admin_warnings_css()
{
$current_screen = get_current_screen();
if ($current_screen && 'toplevel_page_arc-nine-altgen' === $current_screen->id) {
$custom_css = '
/* Hide common notice classes */
.notice,
.settings-error {
display: none !important;
}
';
wp_register_style('aialge-hide-admin-warnings', false, [], '1.0.0');
wp_enqueue_style('aialge-hide-admin-warnings');
wp_add_inline_style('aialge-hide-admin-warnings', $custom_css);
}
}
add_action('admin_enqueue_scripts', 'aialge_hide_admin_warnings_css');