File: /var/www/quadcodewordpressapi/public/wp-content/themes/intentionally-blank/lib/api.php
<?php
const GLOSSARY_TYPE = 'glossary';
const POST_TYPE = 'post';
const EVENT_TYPE = 'event';
const DEFAULT_LANG = 'en';
const DEFAULT_POSTS_PER_PAGE = 100;
function getMediaSrcSizes(int $mediaId): array
{
return [
'thumbnail' => wp_get_attachment_image_src($mediaId)[0] ?? null,
'medium' => wp_get_attachment_image_src($mediaId, 'medium')[0] ?? null,
'mediumLarge' => wp_get_attachment_image_src($mediaId, 'medium_large')[0] ?? null,
'large' => wp_get_attachment_image_src($mediaId, 'large')[0] ?? null,
];
}
function getMediaSrc(?int $mediaId, string $size = 'thumbnail'): ?string
{
return empty($mediaId) ? null : (is_array(wp_get_attachment_image_src($mediaId, $size)) ? wp_get_attachment_image_src($mediaId, $size)[0] : null);
}
function getAuthorData($post, $attributeName, $request): array
{
if (is_array($post)) {
$authorId = $post['author'];
} else {
$authorId = $post->post_author;
}
$author = get_user_by('ID', $authorId);
$meta = get_user_meta($authorId);
$firstName = $meta['first_name'][0];
$lastName = $meta['last_name'][0];
$avatarId = (int) $meta['avatar'][0];
$linkedin = !empty($meta['linkedin']) ? $meta['linkedin'][0] : '';
$description = $meta['description'][0];
$lang = getLangFromRequest($request);
if ($lang !== DEFAULT_LANG && !empty($meta['description_' . $lang])) {
$description = $meta['description_' . $lang][0];
}
$data = [
'name' => join(' ', array_filter([$firstName, $lastName])),
'description' => $description,
'descriptionEn' => $meta['description'][0],
'position' => $meta['position'][0],
'avatar' => getMediaSrcSizes($avatarId),
'linkedin' => $linkedin,
'slug' => $author->user_nicename,
'totalPosts' => countUserPosts($authorId),
];
$lang = getLangFromRequest($request);
if ($lang !== DEFAULT_LANG) {
$data = addAuthorTranslations($author, $data, $lang);
}
return $data;
}
register_rest_field('post', 'authorData', ['get_callback' => 'getAuthorData']);
register_rest_field('glossary', 'authorData', ['get_callback' => 'getAuthorData']);
function getImageData($post): array
{
return getMediaSrcSizes($post['featured_media']);
}
register_rest_field('post', 'imageData', ['get_callback' => 'getImageData']);
register_rest_field('event', 'imageData', ['get_callback' => 'getImageData']);
register_rest_field('glossary', 'imageData', ['get_callback' => 'getImageData']);
function getReadAlso($post): array
{
$result = [];
$readAlso = get_field('read_also', $post['id']);
if (empty($readAlso)) {
return $result;
}
foreach ($readAlso as $subPostId) {
$subPost = get_post($subPostId);
$tags = get_the_tags($subPost);
$tag = $tags[0] ?? null;
if (!empty($tag)) {
$color = get_field('color', $tag->taxonomy . '_' . $tag->term_id);
}
$lang = !empty($_GET['lang']) ? sanitize_text_field($_GET['lang']) : DEFAULT_LANG;
$postTranslation = getPostTranslation($subPostId, $lang);
if (!empty($postTranslation[0])) {
$translation = $postTranslation[0];
$subPost->post_title = $translation->post_title;
}
$result[] = [
'title' => $subPost->post_title,
'slug' => $subPost->post_name,
'color' => $color ?? null,
'type' => $subPost->post_type,
];
}
return $result;
}
register_rest_field('post', 'readAlso', ['get_callback' => 'getReadAlso']);
register_rest_field('glossary', 'readAlso', ['get_callback' => 'getReadAlso']);
function getTags($post): array
{
$result = [];
$tags = get_the_tags($post['id']);
if (empty($tags)) {
return $result;
}
$tagTranslations = [];
if (!empty($_GET['lang'])) {
$lang = sanitize_text_field($_GET['lang']);
$tagTranslations = getTagTranslations($lang);
}
foreach ($tags as $tag) {
if (!empty($_GET['lang'])) {
$translations = pll_get_term_translations($tag->term_id);
if (!empty($translations[$lang])) {
$tag = get_term($translations[$lang]);
$result[] = $tag->name;
continue;
}
}
if (!empty($tagTranslations[$tag->term_id])) {
$result[] = $tagTranslations[$tag->term_id];
} else {
$result[] = $tag->name;
}
}
return $result;
}
register_rest_field('post', 'tagsData', ['get_callback' => 'getTags']);
register_rest_field('glossary', 'tagsData', ['get_callback' => 'getTags']);
function getViews($post): int
{
return (int) get_field('views', $post['id']);
}
register_rest_field('post', 'views', ['get_callback' => 'getViews']);
register_rest_field('glossary', 'views', ['get_callback' => 'getViews']);
function getWordsNumberCallback($post): int
{
return getWordsNumber($post['content']['rendered']);
}
function getEstReadingTimeCallback($post): int
{
$lang = getLangFromRequest() ?? DEFAULT_LANG;
return getEstReadingTime($post['content']['initial'] ?? $post['content']['rendered'], $lang);
}
register_rest_field('post', 'wordsNumber', ['get_callback' => 'getWordsNumberCallback']);
register_rest_field('glossary', 'wordsNumber', ['get_callback' => 'getWordsNumberCallback']);
register_rest_field('post', 'estReadingTime', ['get_callback' => 'getEstReadingTimeCallback']);
register_rest_field('glossary', 'estReadingTime', ['get_callback' => 'getEstReadingTimeCallback']);
add_action('rest_api_init', static function () {
function filterPostData($post): array
{
$clearData = [
'id' => $post['id'],
'date' => $post['date'],
'modified' => $post['modified'],
'slug' => $post['slug'],
'status' => $post['status'],
'title' => $post['title'],
'content' => $post['content'],
'excerpt' => $post['excerpt'],
'authorData' => $post['authorData'],
'imageData' => $post['imageData'],
'readAlso' => $post['readAlso'],
'views' => $post['views'],
'wordsNumber' => $post['wordsNumber'],
'estReadingTime' => $post['estReadingTime'],
'expertData' => $post['expertData'],
'tagsData' => $post['tagsData'],
];
if (!empty($post['yoast_head_json'])) {
unset($post['yoast_head_json']['schema']);
$clearData['yoast_head_json'] = $post['yoast_head_json'];
}
if (!empty($post['acf']['faq'])) {
$clearData['acf']['faq'] = $post['acf']['faq'];
}
return $clearData;
}
function getLangFromRequest(WP_REST_Request $request = null): string
{
if (!empty($_GET['lang'])) {
return $_GET['lang'];
}
$params = [];
if ($request) {
$params = $request->get_params();
if (empty($params['lang'])) {
$params = $request->get_json_params();
}
}
return !empty($params['lang']) ? $params['lang'] : DEFAULT_LANG;
}
register_rest_route('api/v1', 'posts', [
'methods' => 'GET, POST',
'permission_callback' => fn(WP_REST_Request $Request) => true, // Required
'callback' => function (WP_REST_Request $request) {
$body = $request->get_params();
if (empty($body)) {
$body = $request->get_json_params();
}
$categorySlug = $body['categorySlug'] ?? null;
$authorId = $body['authorId'] ?? null;
$excludeSlugs = $body['excludeSlugs'] ?? null;
$excludeIds = $body['excludeIds'] ?? null;
$orderBy = $body['orderBy'] ?? null;
$order = $body['order'] ?? null;
$perPage = $body['per_page'] ?? DEFAULT_POSTS_PER_PAGE;
$lang = getLangFromRequest($request);
if (empty($body['page'])) {
$body['page'] = 1;
}
$args = [
'post_type' => POST_TYPE,
'post_status' => 'publish',
'posts_per_page' => $perPage ?? -1,
'offset' => $body['page'] ? $perPage * ($body['page'] - 1) : 0,
'lang' => DEFAULT_LANG,
];
if (!empty($categorySlug)) {
$args['category_name'] = $categorySlug;
}
if (!empty($authorId)) {
$args['author'] = $authorId;
}
if (!empty($perPage)) {
$args['per_page'] = $perPage;
}
if (!empty($excludeSlugs)) {
foreach ($excludeSlugs as $excludeSlug) {
$excludeIds[] = url_to_postid($excludeSlug);
}
}
if (!empty($excludeIds)) {
$args['post__not_in'] = $excludeIds;
}
if (!empty($orderBy)) {
$args['orderby'] = $orderBy;
if ('views' === $orderBy) {
$args['meta_key'] = $orderBy;
$args['orderby'] = 'meta_value_num';
}
}
if (!empty($order)) {
$args['order'] = $order;
}
$args['fields'] = 'ids';
$posts = get_posts($args);
$wpQuery = new WP_Query($args);
$totalCount = $wpQuery->found_posts;
$translatedPostIds = [];
$postsIds = array_map(function ($postId) use ($lang, &$translatedPostIds) {
$translations = pll_get_post_translations($postId);
foreach ($translations as $l => $translatedPostId) {
$translatedPostStatus = get_post_status($translatedPostId);
if ($l === $lang && $translatedPostStatus == 'publish') {
$postId = $translatedPostId;
$translatedPostIds[] = $translatedPostId;
}
}
return $postId;
}, $posts);
$posts = [];
if (!empty($postsIds)) {
foreach ($postsIds as $postId) {
$internal_request = new WP_REST_Request('GET', '/wp/v2/posts/' . $postId);
$response = rest_do_request($internal_request);
if ($response->is_error()) {
return new WP_Error('internal_error', 'An error occurred while fetching data.', ['status' => 500]);
}
$postData = filterPostData($response->get_data());
if ($lang !== DEFAULT_LANG) {
if (!in_array($postData['id'], $translatedPostIds)) {
$postData = add_translation($postData, $lang);
}
}
$posts[] = $postData;
}
}
$max_pages = $perPage > 0 ? (int) ceil($totalCount / $perPage) : 0;
header('X-WP-Total: ' . (int) $totalCount);
header('X-WP-TotalPages: ' . $max_pages);
return compact('posts', 'totalCount');
},
]);
register_rest_route('api/v1', 'post/(?P<slug>.+)', [
'methods' => 'GET, POST',
'permission_callback' => fn(WP_REST_Request $Request) => true, // Required
'callback' => function (WP_REST_Request $request) {
$slug = $request['slug'] ?? null;
if (empty($slug)) {
return new WP_Error(400, 'Post slug is required', ['status' => 400]);
}
$lang = getLangFromRequest($request);
$args = [
'name' => $slug,
'post_type' => POST_TYPE,
'post_status' => 'publish',
];
$posts = get_posts($args);
$post = null;
foreach ($posts as $innerPost) {
$post = $innerPost;
}
if (empty($post)) {
return new WP_Error(404, 'Post not found', ['status' => 404]);
}
$translatedPost = null;
$translatedPostIds = pll_get_post_translations($post->ID);
foreach ($translatedPostIds as $translatedPostLang => $translatedPostId) {
if ($translatedPostLang === $lang) {
$translatedPost = get_post($translatedPostId);
if ($translatedPost->post_status == 'publish') {
$post = $translatedPost;
}
}
}
// Get response in old format
$internal_request = new WP_REST_Request('GET', '/wp/v2/posts/' . $post->ID);
$response = rest_do_request($internal_request);
if ($response->is_error()) {
return new WP_Error('internal_error', 'An error occurred while fetching data.', ['status' => 500]);
}
$post = filterPostData($response->get_data());
if ($lang !== DEFAULT_LANG) {
if(!$translatedPost || $translatedPost->post_status != 'publish') {
$post = add_translation($post, $lang);
}
}
if (!empty($post['content']) && !empty($post['content']['rendered'])) {
$post['content']['rendered'] = replaceLinks($post['content']['rendered']);
} elseif (!empty($post['content'])) {
$post['content'] = replaceLinks($post['content']);
}
$result = [$post];
return $result;
},
]);
register_rest_route('api/v1', 'view', [
'methods' => WP_REST_Server::EDITABLE,
'permission_callback' => fn(WP_REST_Request $Request) => true, // Required
'callback' => function (WP_REST_Request $request) {
$postId = $request->get_param('post_id');
if (empty($postId)) {
return new WP_Error(400, 'Post ID is required', ['status' => 400]);
}
$post = get_post($postId);
if (empty($post) || !in_array($post->post_type, [POST_TYPE, GLOSSARY_TYPE])) {
return new WP_Error(404, 'Post not found', ['status' => 404]);
}
$count = (int) get_field('views', $postId);
$count++;
update_field('views', $count, $postId);
return ['new_count' => $count];
},
'args' => [
'post_id' => [
'description' => 'Post ID',
'type' => 'integer',
],
],
]);
register_rest_route('api/v1', 'events', [
'methods' => 'GET, POST',
'permission_callback' => fn(WP_REST_Request $Request) => true, // Required
'callback' => function (WP_REST_Request $request) {
$body = $request->get_json_params();
if (empty($body) && $request->get_params()) {
$body = $request->get_params();
}
if (empty($body) && $request->get_body()) {
$body = json_decode($request->get_body(), true);
}
$lang = getLangFromRequest($request);
$isPast = $body['isPast'] ?? null;
$args = [
'post_type' => EVENT_TYPE,
'post_status' => 'publish',
'posts_per_page' => $body['limit'] ?? 3,
'offset' => $body['offset'] ?? 0,
'orderby' => 'period_start_date',
'order' => 'DESC',
'lang' => DEFAULT_LANG,
];
$today = date('Ymd');
if ($isPast) {
$args['meta_query'] = [
['key' => 'period_end_date', 'compare' => '<=', 'value' => $today],
];
} else {
$args['meta_query'] = [
['key' => 'period_end_date', 'compare' => '>=', 'value' => $today],
];
}
$events = get_posts($args);
$wpQuery = new WP_Query($args);
$totalCount = $wpQuery->found_posts;
$max_pages = !empty($body['limit']) && $body['limit'] > 0 ? (int) ceil($totalCount / $body['limit']) : 0;
header('X-WP-Total: ' . (int) $totalCount);
header('X-WP-TotalPages: ' . $max_pages);
$events = array_map(function ($event) use ($lang) {
return convertEvent($event, $lang);
}, $events);
return compact('totalCount', 'events');
},
]);
register_rest_route('api/v2', 'initial-events', [
'methods' => 'GET, POST',
'permission_callback' => fn(WP_REST_Request $request) => true, // Required
'callback' => function (WP_REST_Request $request) {
$body = $request->get_json_params();
if (empty($body) && $request->get_params()) {
$body = $request->get_params();
}
if (empty($body) && $request->get_body()) {
$body = json_decode($request->get_body(), true);
}
$lang = getLangFromRequest($request);
$args = [
'post_type' => 'event',
'post_status' => 'publish',
'posts_per_page' => $body['limit'] ?? 3,
'offset' => 0,
'orderby' => 'period_start_date',
'order' => 'DESC',
'lang' => DEFAULT_LANG,
];
$today = date('Ymd');
$pastEventsArgs = array_merge($args, ['meta_query' => [
['key' => 'period_end_date', 'compare' => '<=', 'value' => $today],
]]);
$upcomingEventsArgs = array_merge($args, ['meta_query' => [
['key' => 'period_end_date', 'compare' => '>=', 'value' => $today],
]]);
$pastEvents = new WP_Query($pastEventsArgs);
$totalCountPast = $pastEvents->found_posts;
$pastEvents = $pastEvents->posts;
$upcomingEvents = new WP_Query($upcomingEventsArgs);
$totalCountUpcoming = $upcomingEvents->found_posts;
$upcomingEvents = $upcomingEvents->posts;
$response = [
"past" => [
"totalCount" => $totalCountPast,
"events" => [],
],
"upcoming" => [
"totalCount" => $totalCountUpcoming,
"events" => [],
],
];
$pastEvents = array_map(function ($event) use ($lang) {
return convertEvent($event, $lang);
}, $pastEvents);
$upcomingEvents = array_map(function ($event) use ($lang) {
return convertEvent($event, $lang);
}, $upcomingEvents);
$response['past']['events'] = $pastEvents;
$response['upcoming']['events'] = $upcomingEvents;
return $response;
},
]);
function convertEvent ($event, $lang) {
if (!$event) {
return;
}
$translations = pll_get_post_translations($event->ID);
$eventTranlatedInAdmin = false;
foreach ($translations as $l => $translatedPostId) {
$translatedPostStatus = get_post_status($translatedPostId);
if ($l === $lang && $translatedPostStatus == 'publish') {
$event = get_post($translatedPostId); // Event translated in admin
if ($event) {
$eventTranlatedInAdmin = true;
}
}
}
$period = get_field('period', $event->ID);
$address = get_field('address', $event->ID);
$link = get_field('external_link', $event->ID);
$tag = get_field('tag', $event->ID);
$mediaId = get_post_thumbnail_id($event->ID);
$linkData = null;
if (!empty($link['button_text']) && !empty($link['link'])) {
$linkData = [
'buttonText' => $link['button_text'],
'link' => $link['link'],
];
}
$translatedData = [];
$translatedAttributes = [];
if (!$eventTranlatedInAdmin) {
$translatedData = getPostTranslation($event->ID, $lang);
if (!empty($translatedData[0])) {
$translatedData = $translatedData[0];
if ($translatedData->post_attributes) {
if (is_base64($translatedData->post_attributes)) {
$translatedData->post_attributes = base64_decode($translatedData->post_attributes);
}
// Bad serialized strings will be rebuild on translation cron run
$translatedAttributes = @unserialize($translatedData->post_attributes);
}
}
}
return [
'title' => $translatedData->post_title ?? $event->post_title,
'description' => !empty($translatedData->post_content) ? trim(strip_tags($translatedData->post_content)) : trim(strip_tags($event->post_content)),
'startDate' => $period['start_date'],
'endDate' => $period['end_date'],
'city' => $address['city'] ?? null,
'location' => $address['location'] ?? null,
'linkData' => $linkData,
'tag' => $translatedAttributes['tag'] ?? ($tag ?? null),
'image' => getMediaSrcSizes($mediaId),
];
}
register_rest_route('api/v1', 'webinars', [
'methods' => 'POST',
'permission_callback' => fn(WP_REST_Request $Request) => true, // Required
'callback' => function (WP_REST_Request $request) {
$body = $request->get_json_params();
$excludeIds = $body['excludeIds'] ?? null;
$orderBy = $body['orderBy'] ?? null;
$order = $body['order'] ?? null;
$isFeatured = $body['isFeatured'] ?? null;
$args = [
'post_type' => 'webinar',
'post_status' => 'publish',
'posts_per_page' => $body['limit'] ?? 3,
'offset' => $body['offset'] ?? 0,
];
if (!empty($excludeIds)) {
$args['post__not_in'] = $excludeIds;
}
if (!empty($orderBy)) {
$args['orderby'] = $orderBy;
if ('date' === $orderBy) {
$args['meta_key'] = $orderBy;
$args['orderby'] = 'meta_value';
}
}
if (!empty($order)) {
$args['order'] = $order;
}
if (!is_null($isFeatured)) {
$args['meta_query'] = [
['key' => 'is_featured', 'compare' => '=', 'value' => (int) $isFeatured],
];
}
$webinars = get_posts($args);
$wpQuery = new WP_Query($args);
$totalCount = $wpQuery->found_posts;
$max_pages = !empty($body['limit']) && $body['limit'] > 0 ? (int) ceil($totalCount / $body['limit']) : 0;
header('X-WP-Total: ' . (int) $totalCount);
header('X-WP-TotalPages: ' . $max_pages);
$usersCache = [];
$webinars = array_map(function ($webinar) use (&$usersCache) {
$agenda = get_field('agenda', $webinar->ID);
$date = get_field('date', $webinar->ID);
$presentersIds = get_field('presenters', $webinar->ID);
$registrationLink = get_field('registration_link', $webinar->ID);
$youTubeLink = get_field('youtube_link', $webinar->ID);
$isFeatured = get_field('is_featured', $webinar->ID);
$mediaId = get_post_thumbnail_id($webinar->ID);
$presenters = [];
foreach ($presentersIds as $presenterId) {
if (empty($usersCache[$presenterId])) {
$meta = get_user_meta($presenterId);
$firstName = $meta['first_name'][0];
$lastName = $meta['last_name'][0];
$avatarId = (int) $meta['avatar'][0];
$usersCache[$presenterId] = [
'name' => join(' ', array_filter([$firstName, $lastName])),
'description' => $meta['description'][0],
'position' => $meta['position'][0],
'avatar' => getMediaSrc($avatarId),
'linkedin' => get_user_meta($presenterId, 'linkedin', true) ?? '',
];
}
$presenters[] = $usersCache[$presenterId];
}
return [
'title' => $webinar->post_title,
'agenda' => trim($agenda),
'date' => $date,
'presenters' => $presenters,
'registrationLink' => $registrationLink,
'youTubeLink' => $youTubeLink,
'image' => getMediaSrcSizes($mediaId),
'isFeatured' => (bool) $isFeatured,
];
}, $webinars);
return compact('totalCount', 'webinars');
},
]);
register_rest_route('api/v1', GLOSSARY_TYPE, [
'methods' => 'GET',
'permission_callback' => fn(WP_REST_Request $Request) => true, // Required
'callback' => function (WP_REST_Request $request) {
$lang = getLangFromRequest($request);
$args = [
'post_type' => GLOSSARY_TYPE,
'post_status' => 'publish',
'posts_per_page' => -1,
'lang' => DEFAULT_LANG,
];
$glossariesCollection = get_posts($args);
$noLangArgs = $args;
unset($noLangArgs['lang']);
$noLangArgs = array_merge($noLangArgs, [
'meta_query' => [
[
'key' => '_pll_language',
'compare' => 'NOT EXISTS',
],
],
]);
$noLangGlossaries = get_posts($noLangArgs);
$glossariesCollection = array_merge($glossariesCollection, $noLangGlossaries);
$glossariesCollection = array_map(function ($glossary) use ($lang) {
$translations = pll_get_post_translations($glossary->ID);
foreach ($translations as $l => $translated_post_id) {
if ($l === $lang) {
$glossary = get_post($translated_post_id);
}
}
return [
'word' => get_field('word', $glossary->ID),
'title' => $glossary->post_title,
'slug' => $glossary->post_name,
];
}, $glossariesCollection);
$glossary = [];
foreach ($glossariesCollection as $word) {
$key = mb_strtolower(mb_substr($word['word'], 0, 1));
$glossary[$key][mb_strtolower($word['word'])] = $word;
}
ksort($glossary);
return $glossary;
},
]);
register_rest_route('api/v1', 'glossary/(?P<slug>.+)', [
'methods' => 'GET',
'permission_callback' => fn(WP_REST_Request $Request) => true, // Required
'callback' => function (WP_REST_Request $request) {
$slug = $request['slug'] ?? null;
if (empty($slug)) {
return new WP_Error(400, 'Glossary slug is required', ['status' => 400]);
}
$lang = getLangFromRequest($request);
$args = [
'name' => $slug,
'post_type' => GLOSSARY_TYPE,
'post_status' => 'publish',
];
$glossariesCollection = get_posts($args);
$glossaryObject = null;
foreach ($glossariesCollection as $glossary) {
$glossaryObject = $glossary;
}
if (empty($glossaryObject)) {
return new WP_Error(404, 'Glossary not found', ['status' => 404]);
}
$translatedGlossaryIds = [];
$translatedGlossaryPosts = pll_get_post_translations($glossaryObject->ID);
foreach ($translatedGlossaryPosts as $translatedGlossaryLang => $translatedGlossaryId) {
$translatedGlossaryStatus = get_post_status($translatedGlossaryId);
if ($translatedGlossaryLang === $lang && $translatedGlossaryStatus === 'publish') {
$translatedGlossary = get_post($translatedGlossaryId);
$glossaryObject = $translatedGlossary; // Replace post with translated post in database
$translatedGlossaryIds[] = $translatedGlossaryId;
}
}
// Get response in old format
$internal_request = new WP_REST_Request('GET', '/wp/v2/glossaries/' . $glossaryObject->ID);
$response = rest_do_request($internal_request);
if ($response->is_error()) {
return new WP_Error('internal_error', 'An error occurred while fetching data.', ['status' => 500]);
}
$glossary = filterPostData($response->get_data());
if ($lang !== DEFAULT_LANG) {
if(!in_array($glossary['id'], $translatedGlossaryIds)) {
$glossary = add_translation($glossary, $lang);
}
}
if (!empty($glossary['content'])) {
$glossary['content']['rendered'] = replaceLinks($glossary['content']['rendered']);
}
$result = [$glossary];
return $result;
},
]);
function calculateReadingTime(string $text, int $wordsPerMinute = 120): float
{
$words = str_word_count(strip_tags($text));
return ceil($words / $wordsPerMinute);
}
function authorFormatting(int $authorId): array
{
$user = get_user_by('ID', $authorId);
$meta = get_user_meta($authorId);
$firstName = $meta['first_name'][0] ?? '';
$lastName = $meta['last_name'][0] ?? '';
$langs = get_available_languages();
$langsArray = [];
foreach ($langs as $lang) {
$langParts = explode('_', $lang);
$langsArray[] = $langParts[0];
}
$description = [
'en' => $meta['description'][0] ?? '',
];
foreach ($langsArray as $lang) {
$description[$lang] = $meta['description_' . $lang][0] ?? '';
}
$avatarId = (int) $meta['avatar'][0];
$fields = get_fields('user_' . $user->ID);
$position = $fields['position'];
return [
'id' => $user->ID,
'slug' => $user->user_nicename,
'name' => join(' ', array_filter([$firstName, $lastName])),
'position' => $position,
'description' => $description,
'avatar' => getMediaSrc($avatarId, 'medium'),
'instagram' => get_user_meta($user->ID, 'instagram', true) ?? '',
'linkedin' => get_user_meta($user->ID, 'linkedin', true) ?? '',
'views' => (int)(get_user_meta($user->ID, 'total_views', true) ?? 0),
];
}
// Get author page data
register_rest_route('api/v1', '/author/(?P<slug>.+)', [
'methods' => 'GET',
'permission_callback' => fn(WP_REST_Request $Request) => true, // Required
'callback' => function (WP_REST_Request $request) {
$slug = $request['slug'] ?? null;
if (empty($slug)) {
return new WP_Error(400, 'Author slug is required', ['status' => 400]);
}
$user = get_user_by('slug', $slug);
if (empty($user)) {
return new WP_Error(404, 'Author not found', ['status' => 404]);
}
$authorData = authorFormatting($user->ID);
$authorData['totalPosts'] = countUserPosts($user->ID);
$expertise = $user->expertise;
$expertiseArray = [];
if (!empty($expertise)) {
foreach ($expertise as $exp) {
$term = get_term_by('id', $exp, 'expertise');
$expertiseArray[] = $term->name;
}
}
$authorData['expertise'] = $expertiseArray;
$fields = get_fields('user_' . $user->ID);
if (!empty($fields['education'])) {
$authorData['education'] = $fields['education'];
}
if (!empty($fields['experience'])) {
$authorData['experience'] = $fields['experience'];
}
$lang = getLangFromRequest($request);
if ($lang !== DEFAULT_LANG) {
$authorData = addAuthorTranslations($user, $authorData, $lang);
}
return $authorData;
},
]);
register_rest_route('api/v2', 'popup/(?P<title>.+)', [
'methods' => 'GET',
'permission_callback' => fn(WP_REST_Request $Request) => true, // Required
'callback' => function (WP_REST_Request $request) {
$title = $request['title'] ?? null;
if (empty($title)) {
return new WP_Error(400, 'Popup title is required', ['status' => 400]);
}
$lang = getLangFromRequest($request);
$args = [
'title' => $title,
'post_type' => 'popup',
];
$posts = get_posts($args);
$post = null;
foreach ($posts as $innerPost) {
$post = $innerPost;
}
if (empty($post)) {
return new WP_Error(404, 'Popup not found', ['status' => 404]);
}
$translatedPostIds = pll_get_post_translations($post->ID);
foreach ($translatedPostIds as $translatedPostLang => $translatedPostId) {
if ($translatedPostLang === $lang) {
$translatedPost = get_post($translatedPostId);
$post = $translatedPost;
}
}
$fields = get_fields($post->ID);
if (!empty($fields['date']) && date($fields['date']) < date('Y-m-d')) {
return new WP_Error(404, 'Popup not found', ['status' => 404]);
}
return [
'title' => $fields['title'],
'subtitle' => $fields['subtitle'],
'text' => $fields['text'],
'bullets' => $fields['bullets'],
'date' => $fields['date'],
'buttonText' => $fields['button_text'],
'buttonLink' => $fields['button_link'],
];
},
]);
register_rest_route('api/v1', 'sitemap', [
'methods' => 'GET',
'permission_callback' => fn(WP_REST_Request $Request) => true, // Required
'callback' => function (WP_REST_Request $request) {
$args = [
'post_type' => POST_TYPE,
'post_status' => 'publish',
'posts_per_page' => -1,
'orderby' => 'meta_value_num',
'order' => 'ASC',
'lang' => DEFAULT_LANG,
];
$posts = get_posts($args);
$args = [
'post_type' => GLOSSARY_TYPE,
'post_status' => 'publish',
'posts_per_page' => -1,
'orderby' => 'meta_value_num',
'order' => 'ASC',
'lang' => DEFAULT_LANG,
];
$glossaries = get_posts($args);
$processedPosts = [];
$postsData = [];
foreach ($posts as $post) {
$postId = $post->ID;
$postData = [
'url' => '/blog/' . $post->post_name,
'alternatives' => [],
];
$processedPosts[] = $postId;
$translations = pll_get_post_translations($postId);
foreach ($translations as $lang => $translated_post_id) {
if (!in_array($translated_post_id, $processedPosts)) {
$translated_post = get_post($translated_post_id);
$postData['alternatives'][$lang] = '/blog/' . $translated_post->post_name;
$processedPosts[] = $translated_post_id;
}
}
$langs = get_available_languages();
foreach ($langs as $lang) {
$langParts = explode('_', $lang);
$lang = $langParts[0];
if (empty($postData['alternatives'][$lang])) {
$additionalTranslation = getPostTranslation($postId, $lang);
if (!empty($additionalTranslation[0])) {
$postData['alternatives'][$lang] = '/blog/' . $post->post_name;
}
}
}
if (empty($postData['alternatives'])) {
$postData['alternatives'] = null;
}
$postsData[] = $postData;
}
foreach ($glossaries as $post) {
$postId = $post->ID;
$postData = [
'url' => '/glossary/' . $post->post_name,
'alternatives' => [],
];
$processedPosts[] = $postId;
$translations = pll_get_post_translations($postId);
foreach ($translations as $lang => $translated_post_id) {
if (!in_array($translated_post_id, $processedPosts)) {
$translated_post = get_post($translated_post_id);
$postData['alternatives'][$lang] = '/glossary/' . $translated_post->post_name;
$processedPosts[] = $translated_post_id;
}
}
$langs = get_available_languages();
foreach ($langs as $lang) {
$langParts = explode('_', $lang);
$lang = $langParts[0];
if (empty($postData['alternatives'][$lang])) {
$additionalTranslation = getPostTranslation($postId, $lang);
if (!empty($additionalTranslation[0])) {
$postData['alternatives'][$lang] = '/blog/' . $post->post_name;
}
}
}
if (empty($postData['alternatives'])) {
$postData['alternatives'] = null;
}
$postsData[] = $postData;
}
return $postsData;
},
]);
register_rest_route('api/v2', 'webinar-banner', [
'methods' => 'GET',
'permission_callback' => static fn(WP_REST_Request $Request) => true,
'callback' => static function (WP_REST_Request $request) {
$fields = get_fields( 'option');
return [
'enabled' => $fields['enabled'],
'title' => $fields['title'],
'webinarTime' => $fields['webinar_time_utc'],
'buttonText' => $fields['button_text'],
'buttonLink' => $fields['button_link'],
];
},
]);
function getExpertData($post, $attributeName, $request)
{
$expert = get_field('expert', $post['id']);
if (empty($expert)) {
return null;
}
if (is_object($expert)) {
$expertId = $expert->ID;
} else {
$expertId = $expert;
$expert = get_user_by('id', $expertId);
}
$meta = get_user_meta($expertId);
$firstName = $meta['first_name'][0];
$lastName = $meta['last_name'][0];
$avatarId = (int) $meta['avatar'][0];
$linkedin = !empty($meta['linkedin']) ? $meta['linkedin'][0] : '';
$description = $meta['description'][0];
$lang = getLangFromRequest($request);
if ($lang !== DEFAULT_LANG && !empty($meta['description_' . $lang])) {
$description = $meta['description_' . $lang][0];
}
$data = [
'name' => join(' ', array_filter([$firstName, $lastName])),
'description' => $description,
'descriptionEn' => $meta['description'][0],
'company' => $expert->company,
'position' => $meta['position'][0],
'avatar' => getMediaSrcSizes($avatarId),
'linkedin' => $linkedin,
'slug' => $expert->user_nicename,
'totalPosts' => countUserPosts($expertId),
];
if ($lang !== DEFAULT_LANG) {
$data = addAuthorTranslations($expert, $data, $lang);
}
return $data;
}
register_rest_field('post', 'expertData', ['get_callback' => 'getExpertData']);
register_rest_field('glossary', 'expertData', ['get_callback' => 'getExpertData']);
});
function countUserPosts(int $userId): int
{
$args = [
'author' => $userId,
'post_type' => POST_TYPE,
'post_status' => 'publish',
'posts_per_page' => -1,
];
$posts = get_posts($args);
$combinations = [];
foreach ($posts as $key => $post) {
$translatedPostIds = pll_get_post_translations($post->ID);
if (!empty($translatedPostIds)) {
asort($translatedPostIds);
$combinations[] = implode(',', $translatedPostIds);
}
}
return count(array_unique($combinations));
}
function replaceLinks($content)
{
$domain = 'quadcode';
$content = str_replace('http:\/\/' . $domain, 'https:\/\/' . $domain, $content);
$content = str_replace('http://' . $domain, 'https://' . $domain, $content);
return $content;
}