// 1. Admin page to manage manual shortcodes
function bam_register_shortcode_settings_page() {
add_options_page(
'Shortcode Manager',
'Shortcodes',
'manage_options',
'bam-shortcodes',
'bam_render_shortcode_settings_page'
);
}
add_action('admin_menu', 'bam_register_shortcode_settings_page');
function bam_render_shortcode_settings_page() {
$shortcode_list = get_option('bam_shortcode_list', []);
usort($shortcode_list, function($a, $b) {
return [$a['category'], $a['label']] <=> [$b['category'], $b['label']];
});
?>
<div class="wrap">
<h1>Shortcode Manager</h1>
<form method="post">
<?php wp_nonce_field('bam_save_shortcode_list'); ?>
<p><input type="text" id="bam-shortcode-search" placeholder="Search shortcodes..." style="width: 300px;" /></p>
<table class="form-table" id="shortcode-table">
<thead><tr><th>Category</th><th>Label</th><th>Shortcode</th><th></th></tr></thead>
<tbody>
<?php foreach ($shortcode_list as $index => $row): ?>
<tr>
<td><input type="text" name="bam_shortcode_list[<?= $index ?>][category]" value="<?= esc_attr($row['category']) ?>" style="font-weight: bold;" /></td>
<td><input type="text" name="bam_shortcode_list[<?= $index ?>][label]" value="<?= esc_attr($row['label']) ?>" /></td>
<td><input type="text" name="bam_shortcode_list[<?= $index ?>][shortcode]" value="<?= esc_attr($row['shortcode']) ?>" /></td>
<td><button type="button" class="button bam-remove-row">Remove</button></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<p><button type="button" class="button" id="bam-add-row">Add Row</button></p>
<p><input type="submit" class="button-primary" value="Save Changes" /></p>
</form>
</div>
<script>
document.getElementById('bam-add-row').addEventListener('click', function() {
const table = document.querySelector('#shortcode-table tbody');
const rowCount = table.rows.length;
const row = table.insertRow();
row.innerHTML =
'<td><input type="text" name="bam_shortcode_list[' + rowCount + '][category]" style="font-weight: bold;" /></td>' +
'<td><input type="text" name="bam_shortcode_list[' + rowCount + '][label]" /></td>' +
'<td><input type="text" name="bam_shortcode_list[' + rowCount + '][shortcode]" /></td>' +
'<td><button type="button" class="button bam-remove-row">Remove</button></td>';
});
document.addEventListener('click', function(e) {
if (e.target && e.target.classList.contains('bam-remove-row')) {
e.target.closest('tr').remove();
}
});
document.getElementById('bam-shortcode-search').addEventListener('input', function() {
const query = this.value.toLowerCase();
const rows = document.querySelectorAll('#shortcode-table tbody tr');
rows.forEach(row => {
row.style.display = row.innerText.toLowerCase().includes(query) ? '' : 'none';
});
});
</script>
<?php
}
// 2. Save and clean manually entered shortcodes
function bam_save_shortcode_settings() {
if (!current_user_can('manage_options') || !isset($_POST['bam_shortcode_list'])) return;
if (!wp_verify_nonce($_POST['_wpnonce'], 'bam_save_shortcode_list')) return;
$raw_list = $_POST['bam_shortcode_list'];
$cleaned = [];
foreach ($raw_list as $row) {
$category = isset($row['category']) ? wp_unslash(trim($row['category'])) : '';
$label = isset($row['label']) ? wp_unslash(trim($row['label'])) : '';
$shortcode = isset($row['shortcode']) ? wp_unslash(trim($row['shortcode'])) : '';
if ($category && $label && $shortcode) {
$cleaned[] = [
'category' => $category,
'label' => $label,
'shortcode' => $shortcode
];
}
}
update_option('bam_shortcode_list', $cleaned);
}
add_action('admin_init', 'bam_save_shortcode_settings');
// 3. Register TinyMCE button and pass shortcode data to JS
function bam_load_editor_button($hook) {
if ($hook !== 'post.php' && $hook !== 'post-new.php') return;
add_filter("mce_buttons", function($buttons) {
$buttons[] = "my_shortcode_button";
return $buttons;
});
add_filter("mce_external_plugins", function($plugins) {
$plugins["my_shortcode_button"] = get_stylesheet_directory_uri() . "/js/custom-mce-button.js";
return $plugins;
});
// Build shortcode data
$shortcode_data = [];
// Manual entries
$rows = get_option('bam_shortcode_list', []);
foreach ($rows as $row) {
if ($row['category'] && $row['label'] && $row['shortcode']) {
$shortcode_data[$row['category']][] = [
'name' => $row['label'],
'shortcode' => $row['shortcode']
];
}
}
// Elementor templates
$templates = get_posts([
'post_type' => 'elementor_library',
'posts_per_page' => -1,
'post_status' => 'publish',
'orderby' => 'title',
'order' => 'ASC'
]);
foreach ($templates as $template) {
$types = wp_get_post_terms($template->ID, 'elementor_library_type', ['fields' => 'slugs']);
$type = isset($types[0]) ? $types[0] : 'other';
if ($type === 'page') {
$group = 'Elementor Page Templates';
} elseif ($type === 'section') {
$group = 'Elementor Section Templates';
} else {
$group = 'Other Elementor Templates';
}
$shortcode_data[$group][] = [
'name' => $template->post_title,
'shortcode' => '[awam-template id="' . $template->ID . '"]'
];
}
// ACF fields organized by group
if (function_exists('acf_get_field_groups')) {
$field_groups = acf_get_field_groups();
foreach ($field_groups as $group) {
$group_label = $group['title'];
$fields = acf_get_fields($group['key']);
if (!$fields) continue;
$submenu = [];
foreach ($fields as $field) {
$is_image = ($field['type'] === 'image');
$submenu[] = [
'name' => $field['label'] . ' (' . $field['name'] . ')',
'shortcode' => $is_image
? '[acf_image field="' . $field['name'] . '"]'
: ' . '"]'
];
}
if (!empty($submenu)) {
$shortcode_data['ACF Fields'][] = [
'name' => 'Group: ' . $group_label,
'submenu' => $submenu
];
}
}
}
// Pass to JS
wp_enqueue_script("custom_mce_button", get_stylesheet_directory_uri() . "/js/custom-mce-button.js", array("jquery"), null, true);
wp_localize_script("custom_mce_button", "MyShortcodesData", $shortcode_data);
}
add_action("admin_enqueue_scripts", "bam_load_editor_button");