diff --git a/api/coauthor.php b/api/coauthor.php index b0234ab..ec3ff6f 100644 --- a/api/coauthor.php +++ b/api/coauthor.php @@ -11,18 +11,48 @@ add_action('rest_api_init', function() { global $coauthors_plus; - // Метод 1: Через объект плагина (работает всегда) if (isset($coauthors_plus) && method_exists($coauthors_plus, 'get_coauthor_by')) { $coauthor = $coauthors_plus->get_coauthor_by('user_nicename', $slug); if ($coauthor) { + // Получаем ID записи гостевого автора + $author_post_id = $coauthor->ID; + + // ПОЛУЧАЕМ ФОТО ИЗ МИНИАТЮРЫ ЗАПИСИ (post thumbnail) + $photo = null; + $photo_sizes = []; + + if (has_post_thumbnail($author_post_id)) { + $photo_id = get_post_thumbnail_id($author_post_id); + + // Основные размеры + $photo_sizes = [ + 'thumbnail' => wp_get_attachment_image_url($photo_id, 'thumbnail'), + 'medium' => wp_get_attachment_image_url($photo_id, 'medium'), + 'large' => wp_get_attachment_image_url($photo_id, 'large'), + 'full' => wp_get_attachment_image_url($photo_id, 'full'), + ]; + + $photo = $photo_sizes['medium']; + } + return [ 'id' => $coauthor->user_nicename, 'name' => $coauthor->display_name, 'firstName' => $coauthor->first_name ?? '', 'lastName' => $coauthor->last_name ?? '', 'description' => $coauthor->description ?? '', - 'avatar' => get_avatar_url($coauthor->user_email, ['size' => 192]), + + // Фото из миниатюры поста (это то, что вам нужно) + 'photo' => $photo, + 'photo_sizes' => $photo_sizes, + + // Оставляем gravatar как запасной вариант, если фото нет + 'gravatar' => get_avatar_url($coauthor->user_email, ['size' => 192]), + + // Для обратной совместимости + 'avatar' => $photo ?: get_avatar_url($coauthor->user_email, ['size' => 192]), + 'url' => get_author_posts_url($coauthor->ID, $coauthor->user_nicename), 'type' => $coauthor->type ?? 'guest-author' ]; @@ -33,4 +63,248 @@ add_action('rest_api_init', function() { }, 'permission_callback' => '__return_true' ]); +}); + + + +add_action('rest_api_init', function() { + register_rest_route('my/v1', '/author/(?P[a-zA-Z0-9-]+)/posts', [ + 'methods' => 'GET', + 'callback' => function($request) { + $slug = $request['slug']; + $per_page = $request->get_param('per_page') ?: 10; + $cursor = $request->get_param('cursor'); + $before = $request->get_param('before'); + $after = $request->get_param('after'); + + // Устанавливаем нужные типы постов + $post_type = ['profile_article', 'anew', 'yellow']; + + if (!function_exists('get_coauthors')) { + return new WP_Error('no_plugin', 'Co-Authors Plus not active', ['status' => 404]); + } + + global $coauthors_plus; + + // Получаем автора по slug + $coauthor = null; + if (isset($coauthors_plus) && method_exists($coauthors_plus, 'get_coauthor_by')) { + $coauthor = $coauthors_plus->get_coauthor_by('user_nicename', $slug); + } + + if (!$coauthor) { + return new WP_Error('not_found', 'Author not found', ['status' => 404]); + } + + // Определяем тип автора и получаем термин таксономии author + $author_term = null; + if ($coauthor->type === 'guest-author') { + $author_term = get_term_by('slug', 'cap-' . $coauthor->user_nicename, 'author'); + } else { + $author_term = get_term_by('slug', $coauthor->user_nicename, 'author'); + } + + if (!$author_term) { + return new WP_Error('not_found', 'Author term not found', ['status' => 404]); + } + + // Базовые аргументы запроса + $args = [ + 'post_type' => $post_type, + 'posts_per_page' => $per_page, + 'post_status' => 'publish', + 'tax_query' => [ + [ + 'taxonomy' => 'author', + 'field' => 'term_id', + 'terms' => $author_term->term_id, + ] + ], + 'orderby' => 'date', + 'order' => 'DESC', + ]; + + // Применяем курсорную пагинацию + if ($after) { + $args['date_query'] = [ + [ + 'column' => 'post_date', + 'before' => $after, + 'inclusive' => false, + ] + ]; + } elseif ($before) { + $args['date_query'] = [ + [ + 'column' => 'post_date', + 'after' => $before, + 'inclusive' => false, + ] + ]; + $args['order'] = 'ASC'; + } elseif ($cursor) { + $cursor_post = get_post($cursor); + if ($cursor_post) { + $args['date_query'] = [ + [ + 'column' => 'post_date', + 'before' => $cursor_post->post_date, + 'inclusive' => false, + ] + ]; + } + } + + $query = new WP_Query($args); + $posts = $query->posts; + + if ($before) { + $posts = array_reverse($posts); + } + + // Форматируем посты - ТОЛЬКО нужные поля + $formatted_posts = []; + foreach ($posts as $post) { + setup_postdata($post); + + // Получаем соавторов + $coauthors = []; + if (function_exists('get_coauthors')) { + $post_coauthors = get_coauthors($post->ID); + foreach ($post_coauthors as $post_coauthor) { + $coauthors[] = [ + 'id' => $post_coauthor->user_nicename, + 'name' => $post_coauthor->display_name, + ]; + } + } + + // Получаем рубрики/категории + $categories = []; + $taxonomies = ['category', 'rubric']; + + foreach ($taxonomies as $taxonomy) { + $terms = get_the_terms($post->ID, $taxonomy); + if ($terms && !is_wp_error($terms)) { + foreach ($terms as $term) { + $categories[] = [ + 'id' => $term->term_id, + 'name' => $term->name, + 'slug' => $term->slug, + 'taxonomy' => $taxonomy, + ]; + } + } + } + + $formatted_posts[] = [ + 'id' => $post->ID, + 'title' => $post->post_title, + 'slug' => $post->post_name, + 'type' => $post->post_type, + 'date' => $post->post_date, + 'link' => get_permalink($post->ID), + + // Только картинка (разные размеры) + 'featured_image' => [ + 'full' => get_the_post_thumbnail_url($post->ID, 'full'), + 'large' => get_the_post_thumbnail_url($post->ID, 'large'), + 'medium' => get_the_post_thumbnail_url($post->ID, 'medium'), + 'thumbnail' => get_the_post_thumbnail_url($post->ID, 'thumbnail'), + ], + + // Рубрики + 'categories' => $categories, + + // Соавторы + 'coauthors' => $coauthors, + + // Курсор для пагинации + 'cursor' => $post->post_date, + ]; + } + wp_reset_postdata(); + + // ИСПРАВЛЕННАЯ ПАГИНАЦИЯ + $has_next = false; + $next_cursor = null; + $has_previous = false; + $previous_cursor = null; + $first_cursor = null; + $last_cursor = null; + + if (!empty($posts)) { + $first_post = reset($posts); + $last_post = end($posts); + + $first_cursor = $first_post->post_date; + $last_cursor = $last_post->post_date; + + // Простая проверка: если количество найденных постов больше, чем количество на странице + // ИЛИ если есть больше страниц + $has_next = $query->max_num_pages > 1; + + // Если есть следующая страница, курсор - дата последнего поста + if ($has_next) { + $next_cursor = $last_post->post_date; + } + + // Проверяем предыдущие посты (если это не первая страница) + if ($cursor || $after || $before) { + // Если есть курсор, значит это не первая страница + $has_previous = true; + $previous_cursor = $first_post->post_date; + } + } + + // Добавим отладку (можно убрать после тестирования) + error_log('=== AUTHOR POSTS DEBUG ==='); + error_log('Slug: ' . $slug); + error_log('Posts found: ' . count($posts)); + error_log('Total posts: ' . $query->found_posts); + error_log('Max num pages: ' . $query->max_num_pages); + error_log('Has next: ' . ($has_next ? 'true' : 'false')); + error_log('Next cursor: ' . ($next_cursor ?? 'null')); + error_log('========================'); + + return [ + 'data' => $formatted_posts, + 'pagination' => [ + 'total' => $query->found_posts, + 'per_page' => (int)$per_page, + 'has_next' => $has_next, + 'has_previous' => $has_previous, + 'next_cursor' => $next_cursor, + 'previous_cursor' => $previous_cursor, + 'first_cursor' => $first_cursor, + 'last_cursor' => $last_cursor, + ], + 'author' => [ + 'id' => $coauthor->user_nicename, + 'name' => $coauthor->display_name, + ] + ]; + }, + 'args' => [ + 'per_page' => [ + 'type' => 'integer', + 'default' => 10, + 'minimum' => 1, + 'maximum' => 100, + ], + 'cursor' => [ + 'type' => 'string', + 'description' => 'Cursor for pagination', + ], + 'after' => [ + 'type' => 'string', + 'description' => 'Get posts after this date', + ], + 'before' => [ + 'type' => 'string', + 'description' => 'Get posts before this date', + ], + ], + 'permission_callback' => '__return_true' + ]); }); \ No newline at end of file