add support mainitem and colonitem in GraphQL

This commit is contained in:
Profile Profile
2026-01-29 01:31:22 +03:00
parent d99f75aed7
commit b771da4504

View File

@@ -1,105 +1,503 @@
<?php
// Добавляем отдельный пункт в главное меню админки
add_action('admin_menu', 'show_category_acf_fields_menu_separate');
/*
Plugin Name: ACF Fields Viewer by Post Type
Description: Показывает все ACF поля для типов постов и таксономий
Version: 2.0
Author: Your Name
*/
function show_category_acf_fields_menu_separate() {
// Добавляем пункт в главное меню админки
add_action('admin_menu', 'acf_viewer_add_menu');
function acf_viewer_add_menu() {
add_menu_page(
'ACF поля категорий', // Заголовок страницы
'ACF категорий', // Название в меню
'manage_options', // Права доступа
'show-category-acf-fields', // Слаг страницы
'show_category_acf_fields_page', // Функция отображения
'dashicons-category', // Иконка
30 // Позиция в меню
'ACF Fields Viewer',
'ACF Viewer',
'manage_options',
'acf-fields-viewer',
'acf_viewer_main_page',
'dashicons-list-view',
30
);
}
function show_category_acf_fields_page() {
// Проверяем права
function acf_viewer_main_page() {
if (!current_user_can('manage_options')) {
wp_die('Недостаточно прав для доступа к этой странице.');
}
// Получаем текущую вкладку
$current_tab = isset($_GET['tab']) ? sanitize_text_field($_GET['tab']) : 'post_types';
?>
<div class="wrap">
<h1>ACF поля всех категорий</h1>
<h1>ACF Fields Viewer</h1>
<?php
// Получаем все категории
$categories = get_terms(array(
'taxonomy' => 'category',
'hide_empty' => false,
'orderby' => 'name',
'order' => 'ASC'
));
<!-- Вкладки навигации -->
<h2 class="nav-tab-wrapper">
<a href="?page=acf-fields-viewer&tab=post_types" class="nav-tab <?php echo $current_tab === 'post_types' ? 'nav-tab-active' : ''; ?>">
Типы постов
</a>
<a href="?page=acf-fields-viewer&tab=taxonomies" class="nav-tab <?php echo $current_tab === 'taxonomies' ? 'nav-tab-active' : ''; ?>">
Таксономии
</a>
<a href="?page=acf-fields-viewer&tab=options" class="nav-tab <?php echo $current_tab === 'options' ? 'nav-tab-active' : ''; ?>">
Options Pages
</a>
</h2>
if (is_wp_error($categories)) {
echo '<p>Ошибка при получении категорий: ' . $categories->get_error_message() . '</p>';
return;
}
// Проверяем, есть ли категории
if (empty($categories)) {
echo '<p>Категории не найдены.</p>';
return;
}
foreach ($categories as $category) {
echo '<div style="background: #fff; padding: 20px; margin: 20px 0; border: 1px solid #ccd0d4; border-radius: 4px;">';
echo '<h2>' . esc_html($category->name) . ' (ID: ' . $category->term_id . ')</h2>';
echo '<p><strong>Slug:</strong> ' . esc_html($category->slug) . '</p>';
echo '<p><strong>Описание:</strong> ' . esc_html($category->description) . '</p>';
// Получаем все ACF поля для категории
// Важно: указываем правильный параметр для таксономии
$fields = get_field_objects('category_' . $category->term_id);
if ($fields) {
echo '<table class="wp-list-table widefat fixed striped">';
echo '<thead><tr><th width="20%">Название поля</th><th width="15%">Ключ (Key)</th><th width="10%">Тип</th><th width="55%">Значение</th></tr></thead>';
echo '<tbody>';
foreach ($fields as $field_name => $field) {
echo '<tr>';
echo '<td>' . esc_html($field['label']) . '</td>';
echo '<td><code>' . esc_html($field['name']) . '</code></td>';
echo '<td>' . esc_html($field['type']) . '</td>';
// Форматируем вывод значения
echo '<td>';
if ($field['value'] === null || $field['value'] === false || $field['value'] === '') {
echo '<em style="color: #999;">(пусто)</em>';
} elseif (is_array($field['value'])) {
echo '<pre style="max-height: 200px; overflow: auto; background: #f6f7f7; padding: 10px; margin: 0;">' . esc_html(print_r($field['value'], true)) . '</pre>';
} elseif (is_object($field['value'])) {
echo '<pre style="max-height: 200px; overflow: auto; background: #f6f7f7; padding: 10px; margin: 0;">' . esc_html(print_r($field['value'], true)) . '</pre>';
} else {
echo esc_html($field['value']);
}
echo '</td>';
echo '</tr>';
}
echo '</tbody></table>';
} else {
echo '<div class="notice notice-info inline"><p>ACF поля не найдены для этой категории.</p></div>';
<div class="tab-content">
<?php
if ($current_tab === 'post_types') {
acf_viewer_show_post_types();
} elseif ($current_tab === 'taxonomies') {
acf_viewer_show_taxonomies();
} elseif ($current_tab === 'options') {
acf_viewer_show_options_pages();
}
echo '</div>';
}
?>
?>
</div>
<style>
.wrap h2 {
color: #1d2327;
margin-bottom: 10px;
.acf-viewer-container {
background: #fff;
padding: 20px;
margin: 20px 0;
border: 1px solid #ccd0d4;
border-radius: 4px;
box-shadow: 0 1px 1px rgba(0,0,0,.04);
}
pre {
.acf-viewer-container h2 {
color: #1d2327;
margin: 0 0 15px 0;
padding-bottom: 10px;
border-bottom: 2px solid #2271b1;
}
.acf-viewer-info {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 10px;
margin-bottom: 20px;
padding: 15px;
background: #f6f7f7;
border-radius: 4px;
}
.acf-viewer-info-item {
padding: 5px 0;
}
.acf-viewer-info-item strong {
color: #2271b1;
}
.acf-viewer-table {
margin-top: 15px;
}
.acf-viewer-table pre {
max-height: 200px;
overflow: auto;
background: #f6f7f7;
padding: 10px;
margin: 0;
font-size: 12px;
line-height: 1.4;
border-radius: 3px;
}
.acf-empty {
color: #999;
font-style: italic;
}
.post-type-section {
margin-bottom: 30px;
padding: 20px;
background: #fff;
border: 1px solid #ccd0d4;
border-radius: 4px;
}
.post-type-section > h2 {
margin-top: 0;
color: #2271b1;
font-size: 24px;
}
.tab-content {
margin-top: 20px;
}
code.field-key {
background: #f0f0f1;
padding: 2px 6px;
border-radius: 3px;
font-size: 11px;
}
.field-group-box {
background: #f9f9f9;
border-left: 4px solid #2271b1;
padding: 15px;
margin: 15px 0;
}
.field-group-box h3 {
margin-top: 0;
color: #2271b1;
}
.field-item {
padding: 10px;
background: #fff;
margin: 5px 0;
border: 1px solid #ddd;
border-radius: 3px;
}
.field-item:hover {
background: #f0f0f1;
}
.badge {
display: inline-block;
padding: 3px 8px;
background: #2271b1;
color: #fff;
border-radius: 3px;
font-size: 11px;
margin-left: 5px;
}
.badge.required {
background: #d63638;
}
.location-rules {
background: #fff3cd;
border: 1px solid #ffc107;
padding: 10px;
margin: 10px 0;
border-radius: 3px;
}
</style>
</div>
<?php
}
// Функция для отображения типов постов
function acf_viewer_show_post_types() {
// Получаем все зарегистрированные типы постов
$all_post_types = get_post_types(array(), 'objects');
if (empty($all_post_types)) {
echo '<div class="notice notice-warning"><p>Типы постов не найдены.</p></div>';
return;
}
foreach ($all_post_types as $post_type_slug => $post_type) {
// Пропускаем служебные типы
if (in_array($post_type_slug, array('revision', 'nav_menu_item', 'custom_css', 'customize_changeset', 'oembed_cache', 'user_request', 'wp_block', 'wp_template', 'wp_template_part', 'wp_global_styles', 'wp_navigation', 'acf-field-group', 'acf-field'))) {
continue;
}
echo '<div class="post-type-section">';
echo '<h2>' . esc_html($post_type->labels->name) . ' <span style="font-weight: normal; font-size: 18px; color: #666;">(' . esc_html($post_type_slug) . ')</span></h2>';
// Информация о типе поста
echo '<div class="acf-viewer-info">';
echo '<div class="acf-viewer-info-item"><strong>Slug:</strong> ' . esc_html($post_type_slug) . '</div>';
echo '<div class="acf-viewer-info-item"><strong>Публичный:</strong> ' . ($post_type->public ? 'Да' : 'Нет') . '</div>';
echo '<div class="acf-viewer-info-item"><strong>Иерархический:</strong> ' . ($post_type->hierarchical ? 'Да' : 'Нет') . '</div>';
// Подсчет постов
$count = wp_count_posts($post_type_slug);
$total = 0;
foreach ($count as $status => $number) {
$total += $number;
}
echo '<div class="acf-viewer-info-item"><strong>Всего постов:</strong> ' . $total . '</div>';
echo '</div>';
// Получаем группы полей для этого типа постов
$field_groups = acf_get_field_groups(array(
'post_type' => $post_type_slug
));
if (empty($field_groups)) {
echo '<div class="notice notice-info inline"><p>ACF группы полей не найдены для этого типа постов.</p></div>';
} else {
echo '<p><strong>Найдено групп полей:</strong> ' . count($field_groups) . '</p>';
foreach ($field_groups as $field_group) {
echo '<div class="field-group-box">';
echo '<h3>' . esc_html($field_group['title']) . '</h3>';
// Информация о группе
echo '<div style="margin-bottom: 15px;">';
echo '<div><strong>Key:</strong> <code>' . esc_html($field_group['key']) . '</code></div>';
// Показываем правила размещения
if (!empty($field_group['location'])) {
echo '<div class="location-rules">';
echo '<strong>Правила размещения:</strong><br>';
foreach ($field_group['location'] as $group_index => $rules) {
if ($group_index > 0) echo '<em style="color: #666;">или</em><br>';
foreach ($rules as $rule_index => $rule) {
if ($rule_index > 0) echo '<em style="color: #666;">и</em> ';
$operator_text = ($rule['operator'] == '==') ? 'равно' : 'не равно';
echo esc_html($rule['param']) . ' ' . $operator_text . ' <strong>' . esc_html($rule['value']) . '</strong><br>';
}
}
echo '</div>';
}
if (!empty($field_group['description'])) {
echo '<div><strong>Описание:</strong> ' . esc_html($field_group['description']) . '</div>';
}
echo '</div>';
// Получаем поля группы
$fields = acf_get_fields($field_group['key']);
if ($fields) {
echo '<table class="wp-list-table widefat fixed striped acf-viewer-table">';
echo '<thead><tr>';
echo '<th width="25%">Название поля</th>';
echo '<th width="20%">Ключ (Name)</th>';
echo '<th width="15%">Тип</th>';
echo '<th width="40%">Настройки</th>';
echo '</tr></thead>';
echo '<tbody>';
acf_viewer_display_fields($fields, 0);
echo '</tbody></table>';
} else {
echo '<p><em>Поля не найдены в этой группе.</em></p>';
}
echo '</div>';
}
}
echo '</div>';
}
}
// Рекурсивная функция для отображения полей (включая вложенные)
function acf_viewer_display_fields($fields, $level = 0) {
foreach ($fields as $field) {
$indent = str_repeat('—', $level);
echo '<tr>';
echo '<td>';
echo $indent . ' <strong>' . esc_html($field['label']) . '</strong>';
if (!empty($field['required'])) {
echo '<span class="badge required">обязательное</span>';
}
echo '</td>';
echo '<td><code class="field-key">' . esc_html($field['name']) . '</code></td>';
echo '<td>' . esc_html($field['type']) . '</td>';
echo '<td>';
// Показываем ключевые настройки в зависимости от типа
$settings = array();
if (!empty($field['instructions'])) {
$settings[] = '<strong>Инструкции:</strong> ' . esc_html($field['instructions']);
}
if (!empty($field['default_value'])) {
$settings[] = '<strong>По умолчанию:</strong> ' . esc_html($field['default_value']);
}
// Специфичные настройки для разных типов
switch ($field['type']) {
case 'text':
case 'textarea':
if (!empty($field['placeholder'])) {
$settings[] = '<strong>Placeholder:</strong> ' . esc_html($field['placeholder']);
}
if (!empty($field['maxlength'])) {
$settings[] = '<strong>Макс. длина:</strong> ' . esc_html($field['maxlength']);
}
break;
case 'select':
case 'checkbox':
case 'radio':
if (!empty($field['choices'])) {
$choices = is_array($field['choices']) ? implode(', ', array_keys($field['choices'])) : $field['choices'];
$settings[] = '<strong>Варианты:</strong> ' . esc_html($choices);
}
break;
case 'image':
case 'file':
if (!empty($field['return_format'])) {
$settings[] = '<strong>Формат возврата:</strong> ' . esc_html($field['return_format']);
}
if (!empty($field['mime_types'])) {
$settings[] = '<strong>Типы файлов:</strong> ' . esc_html($field['mime_types']);
}
break;
case 'post_object':
case 'relationship':
if (!empty($field['post_type'])) {
$pt = is_array($field['post_type']) ? implode(', ', $field['post_type']) : $field['post_type'];
$settings[] = '<strong>Типы постов:</strong> ' . esc_html($pt);
}
break;
case 'taxonomy':
if (!empty($field['taxonomy'])) {
$settings[] = '<strong>Таксономия:</strong> ' . esc_html($field['taxonomy']);
}
break;
}
if (!empty($settings)) {
echo implode('<br>', $settings);
} else {
echo '<em class="acf-empty">—</em>';
}
echo '</td>';
echo '</tr>';
// Рекурсивно обрабатываем вложенные поля (для repeater, group, flexible content)
if (in_array($field['type'], array('repeater', 'group', 'flexible_content')) && !empty($field['sub_fields'])) {
acf_viewer_display_fields($field['sub_fields'], $level + 1);
}
}
}
// Функция для отображения таксономий
function acf_viewer_show_taxonomies() {
// Получаем все таксономии
$taxonomies = get_taxonomies(array(), 'objects');
if (empty($taxonomies)) {
echo '<div class="notice notice-warning"><p>Таксономии не найдены.</p></div>';
return;
}
foreach ($taxonomies as $taxonomy_slug => $taxonomy) {
// Пропускаем служебные таксономии
if (in_array($taxonomy_slug, array('nav_menu', 'link_category', 'post_format', 'wp_theme', 'wp_template_part_area'))) {
continue;
}
echo '<div class="post-type-section">';
echo '<h2>' . esc_html($taxonomy->labels->name) . ' <span style="font-weight: normal; font-size: 18px; color: #666;">(' . esc_html($taxonomy_slug) . ')</span></h2>';
// Информация о таксономии
echo '<div class="acf-viewer-info">';
echo '<div class="acf-viewer-info-item"><strong>Slug:</strong> ' . esc_html($taxonomy_slug) . '</div>';
echo '<div class="acf-viewer-info-item"><strong>Публичная:</strong> ' . ($taxonomy->public ? 'Да' : 'Нет') . '</div>';
echo '<div class="acf-viewer-info-item"><strong>Иерархическая:</strong> ' . ($taxonomy->hierarchical ? 'Да' : 'Нет') . '</div>';
echo '<div class="acf-viewer-info-item"><strong>Типы постов:</strong> ' . implode(', ', $taxonomy->object_type) . '</div>';
// Подсчет терминов
$terms_count = wp_count_terms(array('taxonomy' => $taxonomy_slug, 'hide_empty' => false));
echo '<div class="acf-viewer-info-item"><strong>Всего терминов:</strong> ' . (is_wp_error($terms_count) ? 0 : $terms_count) . '</div>';
echo '</div>';
// Получаем группы полей для этой таксономии
$field_groups = acf_get_field_groups(array(
'taxonomy' => $taxonomy_slug
));
if (empty($field_groups)) {
echo '<div class="notice notice-info inline"><p>ACF группы полей не найдены для этой таксономии.</p></div>';
} else {
echo '<p><strong>Найдено групп полей:</strong> ' . count($field_groups) . '</p>';
foreach ($field_groups as $field_group) {
echo '<div class="field-group-box">';
echo '<h3>' . esc_html($field_group['title']) . '</h3>';
echo '<div style="margin-bottom: 15px;">';
echo '<div><strong>Key:</strong> <code>' . esc_html($field_group['key']) . '</code></div>';
if (!empty($field_group['description'])) {
echo '<div><strong>Описание:</strong> ' . esc_html($field_group['description']) . '</div>';
}
echo '</div>';
// Получаем поля группы
$fields = acf_get_fields($field_group['key']);
if ($fields) {
echo '<table class="wp-list-table widefat fixed striped acf-viewer-table">';
echo '<thead><tr>';
echo '<th width="25%">Название поля</th>';
echo '<th width="20%">Ключ (Name)</th>';
echo '<th width="15%">Тип</th>';
echo '<th width="40%">Настройки</th>';
echo '</tr></thead>';
echo '<tbody>';
acf_viewer_display_fields($fields, 0);
echo '</tbody></table>';
} else {
echo '<p><em>Поля не найдены в этой группе.</em></p>';
}
echo '</div>';
}
}
echo '</div>';
}
}
// Функция для отображения Options Pages
function acf_viewer_show_options_pages() {
// Проверяем, есть ли функция acf_get_options_pages
if (!function_exists('acf_get_options_pages')) {
echo '<div class="notice notice-info"><p>ACF Options Pages не зарегистрированы или недоступны.</p></div>';
return;
}
$options_pages = acf_get_options_pages();
if (empty($options_pages)) {
echo '<div class="notice notice-info"><p>ACF Options Pages не найдены.</p></div>';
return;
}
foreach ($options_pages as $options_page) {
echo '<div class="post-type-section">';
echo '<h2>' . esc_html($options_page['page_title']) . '</h2>';
echo '<div class="acf-viewer-info">';
echo '<div class="acf-viewer-info-item"><strong>Menu Slug:</strong> ' . esc_html($options_page['menu_slug']) . '</div>';
echo '<div class="acf-viewer-info-item"><strong>Post ID:</strong> ' . esc_html($options_page['post_id']) . '</div>';
echo '</div>';
// Получаем группы полей для этой options page
$field_groups = acf_get_field_groups(array(
'options_page' => $options_page['menu_slug']
));
if (empty($field_groups)) {
echo '<div class="notice notice-info inline"><p>ACF группы полей не найдены для этой страницы опций.</p></div>';
} else {
echo '<p><strong>Найдено групп полей:</strong> ' . count($field_groups) . '</p>';
foreach ($field_groups as $field_group) {
echo '<div class="field-group-box">';
echo '<h3>' . esc_html($field_group['title']) . '</h3>';
$fields = acf_get_fields($field_group['key']);
if ($fields) {
echo '<table class="wp-list-table widefat fixed striped acf-viewer-table">';
echo '<thead><tr>';
echo '<th width="25%">Название поля</th>';
echo '<th width="20%">Ключ (Name)</th>';
echo '<th width="15%">Тип</th>';
echo '<th width="40%">Настройки</th>';
echo '</tr></thead>';
echo '<tbody>';
acf_viewer_display_fields($fields, 0);
echo '</tbody></table>';
}
echo '</div>';
}
}
echo '</div>';
}
}