Files
profile/utils/acf-category.php
2026-01-29 01:31:22 +03:00

504 lines
21 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/*
Plugin Name: ACF Fields Viewer by Post Type
Description: Показывает все ACF поля для типов постов и таксономий
Version: 2.0
Author: Your Name
*/
// Добавляем пункт в главное меню админки
add_action('admin_menu', 'acf_viewer_add_menu');
function acf_viewer_add_menu() {
add_menu_page(
'ACF Fields Viewer',
'ACF Viewer',
'manage_options',
'acf-fields-viewer',
'acf_viewer_main_page',
'dashicons-list-view',
30
);
}
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 Fields Viewer</h1>
<!-- Вкладки навигации -->
<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>
<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();
}
?>
</div>
<style>
.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);
}
.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>';
}
}