loadHTML(mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8')); $scripts = $dom->getElementsByTagName('script'); $styles = $dom->getElementsByTagName('style'); $remove = array(); foreach ($scripts as $item) { $remove[] = $item; } foreach ($styles as $item) { $remove[] = $item; } foreach ($remove as $item) { $item->parentNode->removeChild($item); } $html = $dom->saveHTML(); $text = strip_tags($html); $text = trim(preg_replace('/\s\s+/', ' ', $text)); if (!$text) { return ''; } $text = mb_convert_encoding($text, 'UTF-8', 'HTML-ENTITIES'); $text = mb_substr($text, 0, $length, 'UTF-8'); return $text; } /** * Render content for Content Display block * * @param array $attributes Attributes of the block * * @return null */ function advgbRenderBlockRecentPosts($attributes) { global $post; $categories = empty($attributes['categories']) ? array() : $attributes['categories']; if (! empty($categories)) { $categories = array_column($categories, 'id'); } if (isset($attributes['category']) && !empty($attributes['category'])) { $categories = esc_html($attributes['category']); } $post_type = isset($attributes['postType']) ? esc_html($attributes['postType']) : 'post'; if (!is_post_type_viewable($post_type)) { $post_type = 'post'; } $tax_query = []; if (! empty($attributes['tags']) && ($post_type === 'post' || $post_type === 'page')) { $tax_query = array( array( 'taxonomy' => 'post_tag', 'field' => 'name', 'terms' => array_map('esc_html', $attributes['tags']), 'operator' => 'IN', ), ); } $orderBy = empty($attributes['orderBy']) ? 'date' : esc_html($attributes['orderBy']); // 'id' in https://developer.wordpress.org/rest-api/reference/posts/#list-posts // BUT // 'ID' in https://developer.wordpress.org/reference/classes/wp_query/parse_query/ if ($orderBy === 'id') { $orderBy = 'ID'; } // if multiple authors, use the first author in the list. if ($orderBy === 'author') { advgbMultipleAuthorSort(); } // if order by series order if ($orderBy === 'series_order') { advgbSeriesOrderSort(); } $args = array( 'post_type' => $post_type, 'numberposts' => empty($attributes['numberOfPosts']) ? 8 : esc_html($attributes['numberOfPosts']), 'post_status' => 'publish', 'order' => empty($attributes['order']) ? 'desc' : esc_html($attributes['order']), 'orderby' => $orderBy, 'suppress_filters' => false, ); if (isset($attributes['excludeCurrentPost']) && $attributes['excludeCurrentPost']) { $args['post__not_in'] = isset($args['post__not_in']) ? array_merge($args['post__not_in'], array( $post->ID )) : array( $post->ID ); } if (isset($attributes['offset']) && $attributes['offset']) { $args['offset'] = esc_html($attributes['offset']); } if ( defined('ADVANCED_GUTENBERG_PRO_LOADED') && isset($attributes['includePosts']) && ! empty($attributes['includePosts']) ) { // Pro $args['post__in'] = array_map('esc_html', $attributes['includePosts']); } elseif ( ( isset($attributes['excludePosts']) && ! empty($attributes['excludePosts']) ) || ( isset($attributes['exclude']) && ! empty($attributes['exclude']) ) ) { if (isset($attributes['exclude']) && ! empty($attributes['exclude'])) { // Exclude posts, backward compatibility 2.13.1 and lower $exclude = array_map('esc_html', $attributes['exclude']); $args['post__not_in'] = advgbGetPostIdsForTitles($exclude, $post_type); } else { $args['post__not_in'] = array_map('esc_html', $attributes['excludePosts']); } } else { // Nothing to do here } if (isset($attributes['taxonomies']) && ! empty($attributes['taxonomies'])) { foreach ($attributes['taxonomies'] as $slug => $terms) { if (count($terms) > 0) { $tax_query[] = array( 'taxonomy' => esc_html($slug), 'field' => 'name', 'terms' => array_map('esc_html', $terms), 'include_children' => false, 'operator' => 'IN', ); } } } // use tax for anything but pages... if (! in_array($post_type, array( 'page' ), true)) { $args = wp_parse_args($args, array( 'category__in' => is_array($categories) ? array_map('intval', $categories) : $categories, 'tax_query' => $tax_query, )); } $recent_posts = wp_get_recent_posts(apply_filters('advgb_get_recent_posts_args', $args, $attributes, $post_type), OBJECT); $saved_settings = get_option('advgb_settings'); $default_thumb = ADVANCED_GUTENBERG_PLUGIN_DIR_URL . 'assets/blocks/recent-posts/recent-post-default.png'; $rp_default_thumb = isset($saved_settings['rp_default_thumb']) ? $saved_settings['rp_default_thumb'] : array('url' => $default_thumb, 'id' => 0); $postHtml = ''; $postView = isset($attributes['postView']) && ! empty($attributes['postView']) ? esc_html($attributes['postView']) : 'grid'; if (!empty($recent_posts)) { foreach ($recent_posts as $key => $post) { $postThumbID = get_post_thumbnail_id($post->ID); $outputImage = advgbCheckElementDisplay($attributes['displayFeaturedImage'], $attributes['displayFeaturedImageFor'], $key) && ( $postThumbID || $attributes['enablePlaceholderImage'] ); $displayImageVsOrder = getDisplayImageVsOrder($attributes, $key); $postThumb = '' . esc_attr__('Post Image', 'advanced-gutenberg') . ''; $postThumbCaption = ''; $postDate = isset($attributes['displayDate']) && $attributes['displayDate'] ? 'created' : (isset($attributes['postDate']) ? esc_html($attributes['postDate']) : 'hide'); $postDateDisplay = null; if ($postThumbID) { $postThumb = wp_get_attachment_image($postThumbID, 'large'); if (get_the_post_thumbnail_caption($post->ID) && $attributes['displayFeaturedImageCaption']) { $postThumbCaption = sprintf('%1$s', wp_kses_post(get_the_post_thumbnail_caption($post->ID))); } else { $postThumbCaption = ''; } } else { if ($rp_default_thumb['id']) { $postThumb = wp_get_attachment_image($rp_default_thumb['id'], 'large'); } } // The title link below points to the same URL, so hide the redundant image link from assistive tech $postThumbLinkAttrs = $postThumbCaption === '' ? ' aria-hidden="true" tabindex="-1"' : ''; $postHtml .= '
'; if ($outputImage && $displayImageVsOrder === 'ignore-order') { $postHtml .= sprintf('
%2$s%3$s
', get_permalink($post->ID), $postThumb, $postThumbCaption, $postThumbLinkAttrs); } elseif ( ($postView === 'frontpage' && $attributes['frontpageStyle'] === 'headline') || ($postView === 'slider' && $attributes['sliderStyle'] === 'headline') && $displayImageVsOrder === 'ignore-order' ) { $postHtml .= sprintf( '
', esc_url(get_permalink($post->ID)), esc_attr(sprintf( /* translators: %s: post title. */ __('Read %s', 'advanced-gutenberg'), get_the_title($post->ID) )) ); } else { // Nothing to do here } $postHtml .= '
'; if ($outputImage && $displayImageVsOrder === 'apply-order') { $postHtml .= sprintf('
%2$s%3$s
', get_permalink($post->ID), $postThumb, $postThumbCaption, $postThumbLinkAttrs); } $postHtml .= sprintf('

%2$s

', get_permalink($post->ID), get_the_title($post->ID)); if (isset($attributes['textAfterTitle']) && !empty($attributes['textAfterTitle'])) { $postHtml .= sprintf('
%s
', wp_kses_post($attributes['textAfterTitle'])); } if( advgbCheckElementDisplay( $attributes['displayAuthor'], $attributes['displayAuthorFor'], $key ) || advgbCheckElementDisplayStr( $postDate, $attributes['postDateFor'], $key ) || ( !empty($postDateDisplay) ) || ( $post_type === 'post' && advgbCheckElementDisplay( $attributes['displayCommentCount'], $attributes['displayCommentCountFor'], $key ) ) ) { $postHtml .= ''; // end advgb-post-info } if ( advgbCheckElementDisplayStr($attributes['showCategories'], $attributes['showCategoriesFor'], $key) || advgbCheckElementDisplayStr($attributes['showTags'], $attributes['showTagsFor'], $key) || ( !in_array($post_type, array( 'post', 'page' ), true) && advgbCheckElementDisplayArr($attributes['showCustomTaxList'], $attributes['showCustomTaxListFor'], $key) ) ) { $postHtml .= '
'; if (advgbCheckElementDisplayStr($attributes['showCategories'], $attributes['showCategoriesFor'], $key)) { $categories = get_the_category($post->ID); if (! empty($categories)) { $postHtml .= ''; } } if (advgbCheckElementDisplayStr($attributes['showTags'], $attributes['showTagsFor'], $key)) { $tags = get_the_tags($post->ID); if (! empty($tags)) { $postHtml .= ''; } } if (! in_array($post_type, array( 'post', 'page' ), true) && advgbCheckElementDisplayArr($attributes['showCustomTaxList'], $attributes['showCustomTaxListFor'], $key)) { $info = advgbGetTaxonomyTerms($post_type, $post->ID, true, false); if (! empty($info)) { foreach ($attributes['showCustomTaxList'] as $name) { if (! isset($info[ $name ])) { // maybe the name changed? continue; } $props = $info[ $name ]; $slug = $props['slug']; $postHtml .= "
"; if (isset($attributes['linkCustomTax']) && $attributes['linkCustomTax']) { $postHtml .= implode('', $props['linked']); } else { $postHtml .= implode('', $props['unlinked']); } $postHtml .= '
'; } } } $postHtml .= '
'; // end advgb-post-tax-info } $postHtml .= '
'; if (advgbCheckElementDisplay($attributes['displayExcerpt'], $attributes['displayExcerptFor'], $key)) { if (post_password_required($post)) { // Same text as core's Latest Posts block $introText = esc_html__('This content is password protected.'); // phpcs:ignore WordPress.WP.I18n.MissingArgDomain -- Use core's translation. } else { $introText = wp_kses_post($post->post_excerpt); if (isset($attributes['displayExcerpt']) && $attributes['postTextAsExcerpt']) { if (!is_admin()) { $postContent = get_post_field('post_content', $post->ID); // Leave out blocks that Block Controls hides from the current visitor if (class_exists('\\PublishPress\\Blocks\\Controls')) { $postContent = \PublishPress\Blocks\Controls::removeHiddenBlocks($postContent); } $postContent = strip_shortcodes($postContent); $postContent = preg_replace('/)/is', '', $postContent); $introText = esc_html(advgbExtractHtml($postContent, $attributes['postTextExcerptLength'])); } } } $postHtml .= sprintf('
%1$s
', $introText); } if (isset($attributes['textBeforeReadmore']) && !empty($attributes['textBeforeReadmore'])) { $postHtml .= sprintf('
%s
', wp_kses_post($attributes['textBeforeReadmore'])); } if (advgbCheckElementDisplay($attributes['displayReadMore'], $attributes['displayReadMoreFor'], $key)) { $readMoreText = esc_html__('Read More', 'advanced-gutenberg'); if (isset($attributes['readMoreLbl']) && $attributes['readMoreLbl']) { $readMoreText = esc_html($attributes['readMoreLbl']); } $postHtml .= sprintf('
%2$s
', get_permalink($post->ID), $readMoreText); } $postHtml .= '
'; // end advgb-post-content $postHtml .= '
'; // end advgb-post-wrapper $postHtml .= '
'; } } $blockClass = ''; if ($postView === 'grid') { $blockClass = 'grid-view columns-' . esc_html($attributes['columns']); } elseif ($postView === 'list') { $blockClass = 'list-view'; if ($attributes['imagePosition'] !== 'left') { $blockClass .= ' image-' . esc_html($attributes['imagePosition']); } } elseif ($postView === 'slider') { $blockClass = 'slider-view'; $blockClass .= ' style-' . esc_html($attributes['sliderStyle']); if (isset($attributes['sliderAutoplay']) && $attributes['sliderAutoplay']) { $blockClass .= ' slider-autoplay'; } } elseif ($postView === 'frontpage') { $blockClass = 'frontpage-view'; $blockClass .= ' layout-' . esc_html($attributes['frontpageLayout']); $blockClass .= ' gap-' . esc_html($attributes['gap']); $blockClass .= ' style-' . esc_html($attributes['frontpageStyle']); (isset($attributes['frontpageLayoutT']) && $attributes['frontpageLayoutT']) ? $blockClass .= ' tbl-layout-' . esc_html($attributes['frontpageLayoutT']) : ''; (isset($attributes['frontpageLayoutM']) && $attributes['frontpageLayoutM']) ? $blockClass .= ' mbl-layout-' . esc_html($attributes['frontpageLayoutM']) : ''; } elseif ($postView === 'newspaper') { $blockClass = 'newspaper-view'; $blockClass .= ' layout-' . esc_html($attributes['newspaperLayout']); } elseif ($postView === 'masonry') { $blockClass = 'masonry-view columns-' . esc_html($attributes['columns']) . ' tbl-columns-' . esc_html($attributes['columnsT']) . ' mbl-columns-' . esc_html($attributes['columnsM']) . ' gap-' . esc_html($attributes['gap']); } if (defined('ADVANCED_GUTENBERG_PRO_LOADED') && isset($attributes['orderSections'])) { $blockClass .= ' sections-' . esc_html($attributes['orderSections']); } if (isset($attributes['className'])) { $blockClass .= ' ' . esc_html($attributes['className']); } if (isset($attributes['id'])) { $blockClass .= ' ' . esc_html($attributes['id']); } if (isset($attributes['removeDateTimeSeparator']) && $attributes['removeDateTimeSeparator']) { $blockClass .= ' advgb-no-datetime-separator'; } $blockHtml = sprintf('
%1$s
', $postHtml, esc_attr($blockClass)); return $blockHtml; } /** * Register block Content Display * * @return void */ function advgbRegisterBlockRecentPosts() { if (!function_exists('register_block_type')) { return; } register_block_type('advgb/recent-posts', array( 'attributes' => array( 'id' => array( 'type' => 'string', ), 'postView' => array( 'type' => 'string', 'default' => 'grid', ), 'order' => array( 'type' => 'string', 'default' => 'desc', ), 'orderBy' => array( 'type' => 'string', 'default' => 'date', ), 'categories' => array( 'type' => 'array', 'items' => array( 'type' => 'object' ) ), 'tags' => array( 'type' => 'array', 'items' => array( 'type' => 'string' ) ), 'numberOfPosts' => array( 'type' => 'number', 'default' => 8, ), 'columns' => array( 'type' => 'number', 'default' => 2, ), 'columnsT' => array( 'type' => 'number', 'default' => 2, ), 'columnsM' => array( 'type' => 'number', 'default' => 1, ), 'displayFeaturedImage' => array( 'type' => 'boolean', 'default' => true, ), 'displayFeaturedImageFor' => array( 'type' => 'string', 'default' => 'all', ), 'displayFeaturedImageCaption' => array( 'type' => 'boolean', 'default' => false, ), 'enablePlaceholderImage' => array( 'type' => 'boolean', 'default' => true, ), 'imageOverlayColor' => array( 'type' => 'string', 'default' => '#000', ), 'imageOpacity' => array( 'type' => 'number', 'default' => 1, ), 'customDateFormat' => array( 'type' => 'string', 'default' => '', ), 'infoSectionOrder' => array( 'type' => 'array', 'default' => array('author', 'date', 'comments'), ), 'infoSectionSeparator' => array( 'type' => 'string', 'default' => ' ', ), 'hideInfoSeparators' => array( 'type' => 'boolean', 'default' => false, ), 'removeDateTimeSeparator' => array( 'type' => 'boolean', 'default' => false, ), 'absoluteDateCreatedPrefix' => array( 'type' => 'string', 'default' => esc_html__('Posted on', 'advanced-gutenberg'), ), 'absoluteDateUpdatedPrefix' => array( 'type' => 'string', 'default' => esc_html__('Updated on', 'advanced-gutenberg'), ), 'relativeDateCreatedPrefix' => array( 'type' => 'string', 'default' => esc_html__('Posted', 'advanced-gutenberg'), ), 'relativeDateUpdatedPrefix' => array( 'type' => 'string', 'default' => esc_html__('Updated', 'advanced-gutenberg'), ), 'showDatePrefix' => array( 'type' => 'boolean', 'default' => true, ), 'displayAuthor' => array( 'type' => 'boolean', 'default' => false, ), 'displayAuthorFor' => array( 'type' => 'string', 'default' => 'all', ), 'authorLinkNewTab' => array( 'type' => 'boolean', 'default' => true, ), 'postDate' => array( 'type' => 'string', 'default' => 'hide', ), 'postDateFor' => array( 'type' => 'string', 'default' => 'all', ), 'postDateFormat' => array( 'type' => 'string', 'default' => 'absolute', ), 'displayTime' => array( 'type' => 'boolean', 'default' => false, ), 'displayExcerpt' => array( 'type' => 'boolean', 'default' => true, ), 'displayExcerptFor' => array( 'type' => 'string', 'default' => 'all', ), 'postTextAsExcerpt' => array( 'type' => 'boolean', 'default' => false, ), 'postTextExcerptLength' => array( 'type' => 'number', 'default' => 150, ), 'displayReadMore' => array( 'type' => 'boolean', 'default' => true, ), 'displayReadMoreFor' => array( 'type' => 'string', 'default' => 'all', ), 'myToken' => array( 'type' => 'number', ), 'readMoreLbl' => array( 'type' => 'string', ), 'frontpageLayout' => array( 'type' => 'string', 'default' => '1-3', ), 'frontpageLayoutT' => array( 'type' => 'string', ), 'frontpageLayoutM' => array( 'type' => 'string', ), 'gap' => array( 'type' => 'number', 'default' => 10, ), 'frontpageStyle' => array( 'type' => 'string', 'default' => 'default', ), 'sliderStyle' => array( 'type' => 'string', 'default' => 'default', ), 'sliderAutoplay' => array( 'type' => 'boolean', 'default' => false, ), 'sliderAutoplaySpeed' => array( 'type' => 'number', 'default' => 3000, ), 'newspaperLayout' => array( 'type' => 'string', 'default' => 'np-1-3', ), 'changed' => array( 'type' => 'boolean', 'default' => false, ), 'excludeCurrentPost' => array( 'type' => 'boolean', 'default' => false, ), 'postType' => array( 'type' => 'string', ), 'showCategories' => array( 'type' => 'string', 'default' => 'hide', ), 'showCategoriesFor' => array( 'type' => 'string', 'default' => 'all', ), 'showTags' => array( 'type' => 'string', 'default' => 'hide', ), 'showTagsFor' => array( 'type' => 'string', 'default' => 'all', ), 'displayCommentCount' => array( 'type' => 'boolean', 'default' => false, ), 'displayCommentCountFor' => array( 'type' => 'string', 'default' => 'all', ), 'textAfterTitle' => array( 'type' => 'string', ), 'textBeforeReadmore' => array( 'type' => 'string', ), 'excludePosts' => array( 'type' => 'array', 'items' => array( 'type' => 'number' ) ), 'includePosts' => array( 'type' => 'array', 'items' => array( 'type' => 'number' ) ), 'offset' => array( 'type' => 'number', 'default' => 0, ), 'author' => array( 'type' => 'string', ), 'taxonomies' => array( 'type' => 'object', ), 'showCustomTaxList' => array( 'type' => 'array', 'items' => array( 'type' => 'string' ) ), 'showCustomTaxListFor' => array( 'type' => 'string', 'default' => 'all', ), 'linkCustomTax' => array( 'type' => 'boolean', 'default' => false, ), 'imagePosition' => array( 'type' => 'string', 'default' => 'left', ), 'onlyFromCurrentUser' => array( 'type' => 'boolean', 'default' => false, ), 'orderSections' => array( 'type' => 'string', 'default' => 'image-title-info-text', ), // deprecrated attributes... 'exclude' => array( 'type' => 'array', 'items' => array( 'type' => 'string' ) ), 'displayDate' => array( 'type' => 'boolean', 'default' => false, ), 'category' => array( 'type' => 'string', ), ), 'render_callback' => 'advgbRenderBlockRecentPosts', )); } add_action('init', 'advgbRegisterBlockRecentPosts'); /** * Register additional fields returned in REST. * * @return void */ function advgbRegisterCustomFields() { // POST fields register_rest_field( 'post', 'coauthors', array( 'get_callback' => 'advgbGetCoauthors', 'update_callback' => null, 'schema' => null, ) ); register_rest_field( 'post', 'tax_additional', array( 'get_callback' => 'advgbGetAdditionalTaxInfo', 'update_callback' => null, 'schema' => null, ) ); register_rest_field( 'post', 'comment_count', array( 'get_callback' => 'advgbGetComments', 'update_callback' => null, 'schema' => null, ) ); register_rest_field( 'post', 'relative_dates', array( 'get_callback' => 'advgbGetRelativeDates', 'update_callback' => null, 'schema' => null, ) ); register_rest_field( 'post', 'absolute_dates', array( 'get_callback' => 'advgbGetAbsoluteDates', 'update_callback' => null, 'schema' => null, ) ); register_rest_field( 'post', 'absolute_dates_time', array( 'get_callback' => 'advgbGetAbsoluteDatesTime', 'update_callback' => null, 'schema' => null, ) ); register_rest_field( 'post', 'featured_img_caption', array( 'get_callback' => 'advgbGetImageCaption', 'update_callback' => null, 'schema' => null, ) ); register_rest_field( 'post', 'series_order', array( 'get_callback' => 'advgbGetSeriesOrder', 'update_callback' => null, 'schema' => null, ) ); // PAGE fields register_rest_field( 'page', 'coauthors', array( 'get_callback' => 'advgbGetCoauthors', 'update_callback' => null, 'schema' => null, ) ); register_rest_field( 'page', 'author_meta', array( 'get_callback' => 'advgbGetAuthorMeta', 'update_callback' => null, 'schema' => null, ) ); register_rest_field( 'page', 'relative_dates', array( 'get_callback' => 'advgbGetRelativeDates', 'update_callback' => null, 'schema' => null, ) ); register_rest_field( 'page', 'absolute_dates', array( 'get_callback' => 'advgbGetAbsoluteDates', 'update_callback' => null, 'schema' => null, ) ); register_rest_field( 'page', 'absolute_dates_time', array( 'get_callback' => 'advgbGetAbsoluteDatesTime', 'update_callback' => null, 'schema' => null, ) ); register_rest_field( 'page', 'featured_img_caption', array( 'get_callback' => 'advgbGetImageCaption', 'update_callback' => null, 'schema' => null, ) ); register_rest_field( 'page', 'featured_img', array( 'get_callback' => 'advgbGetFeaturedImage', 'update_callback' => null, 'schema' => null, ) ); register_rest_field( 'page', 'series_order', array( 'get_callback' => 'advgbGetSeriesOrder', 'update_callback' => null, 'schema' => null, ) ); // CPT fields foreach (advgbGetCPTs() as $cpt) { register_rest_field($cpt, 'author'); register_rest_field( $cpt, 'featured_img', array( 'get_callback' => 'advgbGetFeaturedImage', 'update_callback' => null, 'schema' => null, ) ); register_rest_field( $cpt, 'coauthors', array( 'get_callback' => 'advgbGetCoauthors', 'update_callback' => null, 'schema' => null, ) ); register_rest_field( $cpt, 'author_meta', array( 'get_callback' => 'advgbGetAuthorMeta', 'update_callback' => null, 'schema' => null, ) ); register_rest_field( $cpt, 'relative_dates', array( 'get_callback' => 'advgbGetRelativeDates', 'update_callback' => null, 'schema' => null, ) ); register_rest_field( $cpt, 'absolute_dates', array( 'get_callback' => 'advgbGetAbsoluteDates', 'update_callback' => null, 'schema' => null, ) ); register_rest_field( $cpt, 'absolute_dates_time', array( 'get_callback' => 'advgbGetAbsoluteDatesTime', 'update_callback' => null, 'schema' => null, ) ); register_rest_field( $cpt, 'featured_img_caption', array( 'get_callback' => 'advgbGetImageCaption', 'update_callback' => null, 'schema' => null, ) ); register_rest_field( $cpt, 'tax_additional', array( 'get_callback' => 'advgbGetAdditionalTaxInfo', 'update_callback' => null, 'schema' => null, ) ); register_rest_field( $cpt, 'series_order', array( 'get_callback' => 'advgbGetSeriesOrder', 'update_callback' => null, 'schema' => null, ) ); } // custom routes register_rest_route('advgb/v1', '/authors/', array( 'methods' => 'GET', 'callback' => 'advgbGetAllAuthors', 'permission_callback' => function () { return current_user_can('edit_others_posts'); }, )); register_rest_route('advgb/v1', '/exclude_post_types/', array( 'methods' => 'GET', 'callback' => 'advgbExcludePostTypes', 'permission_callback' => function () { return current_user_can('edit_others_posts'); }, )); } add_action('rest_api_init', 'advgbRegisterCustomFields'); /** * Returns the custom post types. * * @return array */ function advgbGetCPTs() { return get_post_types(array( '_builtin' => false, 'public' => true )); } /** * Allow more orderBy values for posts. * * @return array */ function advgbAllowPostQueryVars($query_params) { $query_params['orderby']['enum'][] = 'rand'; $query_params['orderby']['enum'][] = 'comment_count'; $query_params['orderby']['enum'][] = 'series_order'; return $query_params; } add_filter('rest_post_collection_params', 'advgbAllowPostQueryVars'); /** * Allow more orderBy values for pages. * * @return array */ function advgbAllowPageQueryVars($query_params) { $query_params['orderby']['enum'][] = 'author'; $query_params['orderby']['enum'][] = 'rand'; $query_params['orderby']['enum'][] = 'series_order'; return $query_params; } add_filter('rest_page_collection_params', 'advgbAllowPageQueryVars'); /** * Allow more orderBy values for custom post types. * * @return array */ function advgbAllowCPTQueryVars($query_params) { $query_params['orderby']['enum'][] = 'author'; $query_params['orderby']['enum'][] = 'series_order'; return $query_params; } /** * Returns the relative dates of the post. * * @return array */ function advgbGetRelativeDates($post) { return array( 'created' => __('Posted', 'advanced-gutenberg') . ' ' . human_time_diff((int) get_the_date('U', $post['id'])) . ' ' . __('ago', 'advanced-gutenberg'), 'modified' => __('Updated', 'advanced-gutenberg') . ' ' . human_time_diff((int) get_the_modified_date('U', $post['id'])) . ' ' . __('ago', 'advanced-gutenberg') ); } /** * Returns the absolute dates of the post. * * @return array */ function advgbGetAbsoluteDates($post) { $format = get_option('date_format'); return array( 'created' => esc_html__('Posted on', 'advanced-gutenberg') . ' ' . get_the_date($format, $post['id']), 'modified' => esc_html__('Updated on', 'advanced-gutenberg') . ' ' . get_the_modified_date($format, $post['id']) ); } /** * Returns the absolute dates with time of the post. * * @return array */ function advgbGetAbsoluteDatesTime($post) { $format = get_option('date_format') . ' ' . get_option('time_format'); return array( 'created' => esc_html__('Posted on', 'advanced-gutenberg') . ' ' . get_the_date($format, $post['id']), 'modified' => esc_html__('Updated on', 'advanced-gutenberg') . ' ' . get_the_modified_date($format, $post['id']) ); } /** * Returns the featured image caption * * @return string */ function advgbGetImageCaption($post) { return get_the_post_thumbnail_caption($post['id']); } /** * Returns the Series order for each post * * @return int */ function advgbGetSeriesOrder($post) { // Series 2.11.4+ meta_key now uses _series_part_${id} if ( function_exists('publishpress_multi_series_supported') && publishpress_multi_series_supported() ) { // Get the terms array from a post so later we can get the term id $terms = wp_get_post_terms($post['id'], advgbGetSeriesTaxonomy()); if (is_array($terms) && count($terms) && $terms[0]->term_id) { return (int) get_post_meta($post['id'], '_series_part_' . $terms[0]->term_id, true); } } else { // Series Pro 2.11.3- and Series Free 2.11.2- return get_post_meta($post['id'], '_series_part', true); } return null; } /** * Returns the number of comments against the post; * * @return int */ function advgbGetComments($post) { return get_comments_number($post['id']); } /** * Populates the HTML corresponding to the categories and tags in case they need to be shown in the post. * * @return array */ function advgbGetAdditionalTaxInfo($post) { $info = array(); $post_type = get_post_type($post['id']); if ('post' === $post_type) { $categories = get_the_category($post['id']); if (! empty($categories)) { $cats = array( 'linked' => array(), 'unlinked' => array() ); foreach ($categories as $category) { $cats['linked'][] = sprintf('%s', esc_url(get_category_link($category)), esc_html($category->name)); $cats['unlinked'][] = sprintf('%s', esc_html($category->name)); } $info['categories'] = $cats; } $tags = get_the_tags($post['id']); if (! empty($tags)) { $cats = array( 'linked' => array(), 'unlinked' => array() ); foreach ($tags as $tag) { $cats['linked'][] = sprintf('%s', esc_url(get_tag_link($category)), esc_html($tag->name)); $cats['unlinked'][] = sprintf('%s', esc_html($tag->name)); } $info['tags'] = $cats; } } else { $info = advgbGetTaxonomyTerms($post_type, $post['id'], false); } return $info; } /** * Gets the taxonomy terms for a specific custom post. * * @return array */ function advgbGetTaxonomyTerms($post_type, $post_id, $front_end = false, $use_tax_slug = true) { $info = array(); $taxonomies = get_object_taxonomies($post_type, 'objects'); foreach ($taxonomies as $slug => $tax) { $terms = get_the_terms($post_id, $slug); $linked = $unlinked = array(); if ($terms) { foreach ($terms as $term) { if ($front_end) { $linked[] = sprintf('
%s
', esc_url(get_term_link($term->slug, $slug)), esc_html($term->name)); $unlinked[] = sprintf('
%s
', esc_html($term->name)); } else { $linked[] = sprintf('%s', esc_url(get_term_link($term->slug, $slug)), esc_html($term->name)); $unlinked[] = sprintf('%s', esc_html($term->name)); } } } $info[ $use_tax_slug ? $slug : html_entity_decode($tax->label, ENT_QUOTES) ] = array( 'linked' => $linked, 'unlinked' => $unlinked, 'slug' => $slug, 'name' => esc_html($tax->label) ); } return $info; } /** * Get the coauthors from the PublishPress Authors plugin if it is activated. * * @return array */ function advgbGetCoauthors($post) { $coauthors = array(); if (function_exists('get_multiple_authors')) { $authors = get_multiple_authors($post[ 'id' ]); foreach ($authors as $user) { $author = advgbGetAuthorByID($user->ID); if ($author) { $coauthors[] = array( 'link' => $author->__get('link'), 'display_name' => $author->__get('name')); } } } return $coauthors; } /** * Populate the author_meta for pages/custom post types. * * @return array */ function advgbGetAuthorMeta($page) { if (isset($page['author'])) { return array( 'author_link' => get_author_posts_url($page['author']), 'display_name' => get_the_author_meta('display_name', $page['author']) ); } return array( 'author_link' => '', 'display_name' => '' ); } /** * Populate the correct arguments for filtering by author. * * The results depends on whether PublishPress Authors plugin is activated. * * @return array */ function advgbGetAuthorFilter($args, $attributes, $post_type) { // Get current logged in user if (isset($attributes['onlyFromCurrentUser']) && $attributes['onlyFromCurrentUser']) { if (! function_exists('get_multiple_authors')) { $args['author'] = advgbGetCurrentUserId(); } elseif (advgbGetCurrentUserId() === 999999) { $args['author'] = advgbGetCurrentUserId(); } else { advgbSetPPAuthorArgs(advgbGetCurrentUserId(), $args); } } else { // Get author attribute if (isset($attributes['author']) && ! empty($attributes['author'])) { // WooCommerce Products don't support multiple authors... if ($post_type === 'product' || ! function_exists('get_multiple_authors')) { $args['author'] = esc_html($attributes['author']); } else { advgbSetPPAuthorArgs(esc_html($attributes['author']), $args); } } } return $args; } add_filter('advgb_get_recent_posts_args', 'advgbGetAuthorFilter', 10, 3); /** * Populate the correct arguments in REST for filtering by author. * * The results depends on whether PublishPress Authors plugin is activated. * * @return array */ function advgbGetAuthorFilterREST($args, $request) { if (isset($request['author']) && ! empty($request['author'])) { // WooCommerce Products don't support multiple authors... if ($args['post_type'] !== 'product' && function_exists('get_multiple_authors')) { $author = $request['author']; $user_id = is_array($author) ? reset($author) : $author; advgbSetPPAuthorArgs($user_id, $args); } else { unset($args['author']); $args['author__in'] = $request['author']; } } return $args; } add_filter('rest_post_query', 'advgbGetAuthorFilterREST', 10, 2); add_filter('rest_page_query', 'advgbGetAuthorFilterREST', 10, 2); /** * Populate the correct arguments in REST for filtering by series order. * * @return array */ function advgbSetSeriesOrderREST($args, $request) { $orderby = esc_html($request['orderby']); $taxonomy = advgbGetSeriesTaxonomy(); $taxonomy_object = get_taxonomy($taxonomy); $rest_base = ($taxonomy_object && ! empty($taxonomy_object->rest_base)) ? $taxonomy_object->rest_base : $taxonomy; $series_param = isset($request[$rest_base]) ? $request[$rest_base] : (isset($request['series']) ? $request['series'] : null); if (isset($orderby) && $orderby === 'series_order' && isset($series_param)) { $args['orderby'] = 'meta_value_num'; // Series 2.11.4+ meta_key now uses _series_part_${id} $ids = array_map('intval', (array) $series_param); if (advgbSeriesUsesPerSeriesMetaKey($ids)) { foreach ($ids as $id) { $args['meta_key'][] = '_series_part_' . $id; } } else { // Series Pro 2.11.3- and Series Free 2.11.2- $args['meta_key'] = '_series_part'; } } return $args; } add_filter('rest_post_query', 'advgbSetSeriesOrderREST', 10, 2); add_filter('rest_page_query', 'advgbSetSeriesOrderREST', 10, 2); /** * Sets the author args for the meta_query. */ function advgbSetPPAuthorArgs($user_id, &$args) { $author = advgbGetAuthorByID($user_id); if ($author) { $args['meta_query'][] = array( 'key' => 'ppma_authors_name', 'value' => $author->__get('display_name'), 'compare' => 'LIKE', ); unset($args['author']); unset($args['author__in']); } } /** * Populate the correct arguments in REST for sorting by author. * * The results depends on whether PublishPress Authors plugin is activated. * * @return array */ function advgbMultipleAuthorSortREST($args, $request) { if (isset($request['orderby']) && 'author' === $request['orderby'] && function_exists('get_multiple_authors')) { $args['meta_key'] = 'ppma_authors_name'; $args['orderby'] = 'meta_value'; } return $args; } add_filter('rest_post_query', 'advgbMultipleAuthorSortREST', 10, 2); /** * Populate the correct arguments for filtering by author. * * If multiple authors are defined using PublishPress Authors plugin, use the first author in the list. */ function advgbMultipleAuthorSort() { if (function_exists('get_multiple_authors')) { add_action('pre_get_posts', function ($query) { if (is_admin() || $query->query_vars['orderby'] !== 'author') { return $query; } $query->set('orderby', 'meta_value'); $query->set('meta_key', 'ppma_authors_name'); return $query; }); } } /** * Populate the correct arguments for filtering by series order. * */ function advgbSeriesOrderSort() { if (class_exists('orgSeries')) { add_action('pre_get_posts', function ($query) { if (is_admin() || ! isset($query->query_vars['orderby']) || $query->query_vars['orderby'] !== 'series_order') { return $query; } $query->set('orderby', 'meta_value_num'); // The series taxonomy slug can be renamed in Series settings, e.g. "issue" $taxonomy = advgbGetSeriesTaxonomy(); $term_ids = []; $tax_query = isset($query->query_vars['tax_query']) ? (array) $query->query_vars['tax_query'] : []; foreach ($tax_query as $clause) { if (! is_array($clause) || ! isset($clause['taxonomy']) || $clause['taxonomy'] !== $taxonomy || empty($clause['terms'])) { continue; } // The terms are the ones stored in the block's taxonomies attribute (names by default) // @TODO - Store and use term ids instead as attributes $field = isset($clause['field']) ? $clause['field'] : 'term_id'; foreach ((array) $clause['terms'] as $term) { // Get the term object and then use the id to get the meta_key $term_obj = get_term_by($field, $term, $taxonomy); if ($term_obj) { $term_ids[] = (int) $term_obj->term_id; } } } if (empty($term_ids)) { // No series selected: nothing to sort on, as before if (! (function_exists('publishpress_multi_series_supported') && publishpress_multi_series_supported())) { // Series Pro 2.11.3- and Series Free 2.11.2- $query->set('meta_key', '_series_part'); } } elseif (advgbSeriesUsesPerSeriesMetaKey($term_ids)) { // Series 2.11.4+ meta_key now uses _series_part_${id} $metakeys = []; foreach ($term_ids as $term_id) { $metakeys[] = '_series_part_' . $term_id; } $query->set('meta_key', $metakeys); } else { // Series Pro 2.11.3- and Series Free 2.11.2- $query->set('meta_key', '_series_part'); } return $query; }); } } /** * Get the slug of the series taxonomy. It can be renamed in Series settings. * * @return string */ function advgbGetSeriesTaxonomy() { if (function_exists('ppseries_get_series_slug')) { $slug = ppseries_get_series_slug(); if (! empty($slug)) { return $slug; } } return 'series'; } /** * Check whether Series stores the order of the given series in _series_part_${id} meta keys. * * The publishpress_multi_series_supported option is only set by a Series upgrade * notice, so it can be empty although the posts already use the new meta keys. * * @param int[] $term_ids Series term ids * * @return boolean */ function advgbSeriesUsesPerSeriesMetaKey($term_ids) { $term_ids = array_filter(array_map('intval', (array) $term_ids)); if (empty($term_ids)) { return false; } if ( function_exists('publishpress_multi_series_supported') && publishpress_multi_series_supported() ) { return true; } global $wpdb; $meta_keys = array_map(function ($id) { return '_series_part_' . $id; }, $term_ids); $placeholders = implode(', ', array_fill(0, count($meta_keys), '%s')); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare -- The IN fragment contains only generated placeholders. $found = $wpdb->get_var($wpdb->prepare("SELECT meta_id FROM {$wpdb->postmeta} WHERE meta_key IN ($placeholders) LIMIT 1", $meta_keys)); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- Query prepared above. return ! empty($found); } /** * Check if an element is enabled for each post when $display is a boolean * * @param string $element Element to display * @param boolean $display Display or not the element? * @param int $key Index of the element * * @return boolean */ function advgbCheckElementDisplay($element, $display, $key) { if ( isset($element) && $element && ( $display === 'all' || $key < $display ) ) { return true; } else { return false; } } /** * Check if an element is enabled for each post when $display is a string * * @param string $element Element to display * @param boolean $display Display or not the element? * @param int $key Index of the element * * @return boolean */ function advgbCheckElementDisplayStr($element, $display, $key) { if ( isset($element) && $element !== 'hide' && ( $display === 'all' || $key < $display ) ) { return true; } else { return false; } } /** * Check if an element is enabled for each post when $element is an array * * @param array $element Element(s) to display * @param boolean $display Display or not the element? * @param int $key Index of the element * * @return boolean */ function advgbCheckElementDisplayArr($element, $display, $key) { if ( isset($element) && ! empty($element) && ( $display === 'all' || $key < $display ) ) { return true; } else { return false; } } /** * Check if Featured image is enable for each post * * Deprecated since 2.13.3 * * @return boolean */ function advgbCheckImageStatus($attributes, $key) { if ( isset($attributes['displayFeaturedImage']) && $attributes['displayFeaturedImage'] && ($attributes['displayFeaturedImageFor'] === 'all' || $key < $attributes['displayFeaturedImageFor']) ) { return true; } else { return false; } } /** * Skip images floating on left or right, and with headline style for each post * * @return boolean */ function getDisplayImageVsOrder($attributes, $key) { $postView = isset($attributes['postView']) && ! empty($attributes['postView']) ? esc_html($attributes['postView']) : 'grid'; if ( ( ( isset($attributes['orderSections']) && $attributes['orderSections'] && ( in_array(esc_html($attributes['orderSections']), array( 'default', 'image-title-info-text' )) ) ) || ( ( $postView === 'frontpage' && esc_html($attributes['frontpageStyle']) === 'headline' ) || ( $postView === 'slider' && esc_html($attributes['sliderStyle']) === 'headline' ) || ( $postView === 'list' ) || ( ( $postView === 'newspaper' ) && ( in_array(esc_html($attributes['newspaperLayout']), array( 'np-2','np-3-1','np-3-2','np-3-3' )) || $key > 0 ) ) ) ) || !defined('ADVANCED_GUTENBERG_PRO_LOADED') ) { return 'ignore-order'; } else { return 'apply-order'; } } /** * Get id of current user * * @return integer */ function advgbGetCurrentUserId() { return is_user_logged_in() ? get_current_user_id() : 999999; // 999999 means user is a guest :) } /** * Returns post ids corresponding to post titles. * * Only for backward compatibility 2.13.1 and lower * * @return array */ function advgbGetPostIdsForTitles($titles, $post_type) { global $wpdb; if (! empty($titles)) { // don't use post_name__in here because the title may be different from the slug $placeholders = implode(',', array_fill(0, count($titles), '%s')); $params = $titles; $params[] = $post_type; $query = $wpdb->prepare("SELECT DISTINCT ID FROM {$wpdb->posts} WHERE post_title IN ($placeholders) AND post_type = '%s'", $params); return $wpdb->get_col($query); } return array(); } /** * Returns all valid authors. * * If PublishPress Authors plugin is active, only those authors are returned. * * @return array */ function advgbGetAllAuthors(WP_REST_Request $request) { $authors = array(); if (function_exists('multiple_authors_get_all_authors')) { $coauthors = multiple_authors_get_all_authors(); foreach ($coauthors as $coauthor) { $name = $coauthor->__get('display_name'); $authors[ $name ] = (object) array( 'name' => $name, 'id' => $coauthor->__get('ID') ); } } else { $users = get_users(array( 'per_page' => -1, 'who' => 'authors', 'fields' => 'all' )); foreach ($users as $user) { $author = $user->data; $author->id = $author->ID; $author->name = $author->display_name; $authors[ $author->name ] = $author; } } return array_values($authors); } /** * Wrapper method to fetch an author on the basis of it's ID. * * This ID can either be the WP_User ID (positive integer) or guest author ID (negative integer). * * @return Author|false */ function advgbGetAuthorByID($id) { $author = false; if (method_exists('MultipleAuthors\Classes\Objects\Author', 'get_by_id')) { $author = MultipleAuthors\Classes\Objects\Author::get_by_id($id); } else { if (intval($id) > -1) { $author = MultipleAuthors\Classes\Objects\Author::get_by_user_id($id); } else { $author = MultipleAuthors\Classes\Objects\Author::get_by_term_id($id); } } return $author; } /** * Returns the featured image URL. * * @return string */ function advgbGetFeaturedImage($post) { return get_the_post_thumbnail_url($post[ 'id' ]); } /** * Returns all the post types that need to be excluded. * * @return array */ function advgbExcludePostTypes(WP_REST_Request $request) { // allow users to add more return apply_filters('advgb_exclude_post_types', array( 'attachment', 'web-story' )); } /** * Fires all the relevant hooks for CPTs. */ function advgbInitializeHooksForCPTs() { foreach (advgbGetCPTs() as $cpt) { add_filter("rest_{$cpt}_query", 'advgbGetAuthorFilterREST', 10, 2); add_filter("rest_{$cpt}_query", 'advgbMultipleAuthorSortREST', 10, 2); add_filter("rest_{$cpt}_collection_params", 'advgbAllowCPTQueryVars'); add_filter("rest_{$cpt}_query", 'advgbSetSeriesOrderREST', 10, 2); } } add_action('init', 'advgbInitializeHooksForCPTs');