From 102ca98b2102c52e024013ab6d6d38cbaf0165f8 Mon Sep 17 00:00:00 2001 From: xuliwenwenwen <74528885+xuliwenwenwen@users.noreply.github.com> Date: Fri, 16 Aug 2024 16:35:55 +0800 Subject: [PATCH] Feat/slides (#29) * feat: slides * fix: pre get posts slides archive --- pingcap-jp/acf/acf-slides-settings.php | 243 ++++++++++++++++++ pingcap-jp/acf/acf-slides.php | 101 ++++++++ pingcap-jp/bootstrap/api.php | 26 ++ pingcap-jp/bootstrap/pre-get-posts.php | 15 +- pingcap-jp/bootstrap/theme-settings-pages.php | 8 + .../css/components/cards/card-slides.scss | 26 ++ .../css/components/posts-list/posts-list.scss | 2 + pingcap-jp/css/master.scss | 1 + pingcap-jp/inc/PingCAP/CPT/Slides.php | 149 +++++++++++ .../Banners/BannerResourceArchive.php | 3 + .../PingCAP/Components/Cards/CardSlides.php | 47 ++++ .../Components/PostsList/PostsListFilter.php | 2 +- pingcap-jp/inc/PingCAP/Constants/ACF.php | 1 + pingcap-jp/inc/PingCAP/Constants/CPT.php | 1 + .../inc/PingCAP/Constants/QueryParams.php | 2 + pingcap-jp/post-types/slides.php | 46 ++++ pingcap-jp/templates/archive-slides.php | 37 +++ 17 files changed, 708 insertions(+), 2 deletions(-) create mode 100644 pingcap-jp/acf/acf-slides-settings.php create mode 100644 pingcap-jp/acf/acf-slides.php create mode 100644 pingcap-jp/css/components/cards/card-slides.scss create mode 100644 pingcap-jp/inc/PingCAP/CPT/Slides.php create mode 100644 pingcap-jp/inc/PingCAP/Components/Cards/CardSlides.php create mode 100644 pingcap-jp/post-types/slides.php create mode 100644 pingcap-jp/templates/archive-slides.php diff --git a/pingcap-jp/acf/acf-slides-settings.php b/pingcap-jp/acf/acf-slides-settings.php new file mode 100644 index 0000000..bcf0d61 --- /dev/null +++ b/pingcap-jp/acf/acf-slides-settings.php @@ -0,0 +1,243 @@ + 'group_' . $acf_group, + 'title' => 'slides Settings', + 'fields' => array ( + /** + * Tab: slides Archive + */ + array ( + 'key' => 'field_' . $acf_group . '_tab_video_archive', + 'label' => 'slides Archive', + 'name' => 'tab_video_archive', + 'type' => 'tab', + 'instructions' => '', + 'required' => 0, + 'conditional_logic' => 0, + 'wrapper' => array ( + 'width' => '', + 'class' => '', + 'id' => '', + ), + 'placement' => 'top', + 'endpoint' => 0, // end tabs to start a new group + ), + array ( + 'key' => 'field_' . $acf_group . '_archive_title', + 'label' => 'Archive Title', + 'name' => $acf_group . '_archive_title', + 'type' => 'text', + 'instructions' => '', + 'required' => 1, + 'conditional_logic' => 0, + 'wrapper' => array ( + 'width' => '', + 'class' => '', + 'id' => '', + ), + 'default_value' => 'slides', + 'placeholder' => '', + 'formatting' => 'none', // none | html + 'prepend' => '', + 'append' => '', + 'maxlength' => '', + 'readonly' => 0, + 'disabled' => 0, + ), + array ( + 'key' => 'field_' . $acf_group . '_override_posts_per_page', + 'label' => 'Override Default Posts Per Page Value', + 'name' => $acf_group . '_override_posts_per_page', + 'type' => 'true_false', + 'instructions' => 'Enabling this option will allow you to override the default value under Settings / Reading for this archive.', + 'required' => 0, + 'conditional_logic' => 0, + 'wrapper' => array ( + 'width' => '50', + 'class' => '', + 'id' => '', + ), + 'message' => '', + 'ui' => 1, + 'ui_on_text' => 'Yes', + 'ui_off_text' => 'No', + 'default_value' => 0, + ), + array ( + 'key' => 'field_' . $acf_group . '_custom_posts_per_page', + 'label' => 'Custom Posts Per Page Count', + 'name' => $acf_group . '_custom_posts_per_page', + 'type' => 'number', + 'instructions' => '', + 'required' => 0, + 'conditional_logic' => array ( + array ( + array ( + 'field' => 'field_' . $acf_group . '_override_posts_per_page', + 'operator' => '==', + 'value' => 1, + ), + ), + ), + 'wrapper' => array ( + 'width' => '50', + 'class' => '', + 'id' => '', + ), + 'default_value' => 12, + 'placeholder' => '', + 'prepend' => '', + 'append' => '', + 'min' => 1, + 'max' => '', + 'step' => '', + 'readonly' => 0, + 'disabled' => 0, + ), + array ( + 'key' => 'field_' . $acf_group . '_no_results_message', + 'label' => 'No Results Message', + 'name' => $acf_group . '_no_results_message', + 'type' => 'text', + 'instructions' => '', + 'required' => 1, + 'conditional_logic' => 0, + 'wrapper' => array ( + 'width' => '', + 'class' => '', + 'id' => '', + ), + 'default_value' => PingCAP\Constants\DefaultValues::ARCHIVE_NO_RESULTS_MESSAGE, + 'placeholder' => '', + 'formatting' => 'none', // none | html + 'prepend' => '', + 'append' => '', + 'maxlength' => '', + 'readonly' => 0, + 'disabled' => 0, + ), + array ( + 'key' => 'field_' . $acf_group . '_featured_post', + 'label' => 'Featured Post', + 'name' => $acf_group . '_featured_post', + 'type' => 'post_object', + 'instructions' => '', + 'required' => 0, + 'conditional_logic' => 0, + 'wrapper' => array ( + 'width' => '', + 'class' => '', + 'id' => '', + ), + 'post_type' => PingCAP\Constants\CPT::SLIDES, + 'taxonomy' => array (), + 'allow_null' => 1, + 'multiple' => 0, + 'return_format' => 'id', // object | id + 'ui' => 1, + ), + array ( + 'key' => 'field_' . $acf_group . '_video_archive_blocks', + 'label' => 'slides Archive', + 'name' => $acf_group . '_video_archive_blocks', + 'type' => 'clone', + 'instructions' => '', + 'required' => 0, + 'conditional_logic' => 0, + 'wrapper' => array ( + 'width' => '', + 'class' => '', + 'id' => '', + ), + 'clone' => array ( + 0 => 'group_grav_blocks', + ), + 'display' => 'seamless', + 'layout' => 'block', + 'prefix_label' => 1, + 'prefix_name' => 1, + ), + + /** + * Tab: Images + */ + array ( + 'key' => 'field_' . $acf_group . '_tab_images', + 'label' => 'Images', + 'name' => $acf_group . '_tab_images', + 'type' => 'tab', + 'instructions' => '', + 'required' => 0, + 'conditional_logic' => 0, + 'wrapper' => array ( + 'width' => '', + 'class' => '', + 'id' => '', + ), + 'placement' => 'top', + 'endpoint' => 0, // end tabs to start a new group + ), + array ( + 'key' => 'field_' . $acf_group . '_default_featured_image', + 'label' => 'Default Featured Image', + 'name' => $acf_group . '_default_featured_image', + 'instructions' => '', + 'type' => 'image', + 'required' => 0, + 'conditional_logic' => 0, + 'wrapper' => array ( + 'width' => '', + 'class' => '', + 'id' => '', + ), + 'return_format' => 'object', // array | url | id + 'preview_size' => 'medium', + 'library' => 'all', // all | uploadedTo + 'min_width' => '', + 'min_height' => '', + 'min_size' => '', + 'max_width' => '', + 'max_height' => '', + 'max_size' => '', + 'mime_types' => '', + ) + ), + 'location' => array ( + array ( + array ( + 'param' => 'options_page', // post_type | post | page | page_template | post_category | taxonomy | options_page + 'operator' => '==', + 'value' => 'slides-settings', // if options_page then use: acf-options | if page_template then use: template-example.php + 'order_no' => 0, + 'group_no' => 1, + ), + ), + ), + 'menu_order' => 0, + 'position' => 'normal', // side | normal | acf_after_title + 'style' => 'seamless', // default | seamless + 'label_placement' => 'top', // top | left + 'instruction_placement' => 'label', // label | field + 'hide_on_screen' => array ( + // 0 => 'permalink', + // 1 => 'the_content', + // 2 => 'excerpt', + // 3 => 'custom_fields', + // 4 => 'discussion', + // 5 => 'comments', + // 6 => 'revisions', + // 7 => 'slug', + // 8 => 'author', + // 9 => 'format', + // 10 => 'featured_image', + // 11 => 'categories', + // 12 => 'tags', + // 13 => 'send-trackbacks', + ), + 'active' => 1, + 'description' => '', +)); diff --git a/pingcap-jp/acf/acf-slides.php b/pingcap-jp/acf/acf-slides.php new file mode 100644 index 0000000..49b7807 --- /dev/null +++ b/pingcap-jp/acf/acf-slides.php @@ -0,0 +1,101 @@ + 'group_' . $acf_group, + 'title' => 'Slides Settings', + 'fields' => array_merge( + WPUtil\Vendor\BlueprintBlocks::safe_get_link_fields([ + 'label' => 'slides Download Link', + 'name' => 'slides_url', + 'key_modifier' => $acf_group . '_slides_url', + 'includes' => [ + 'file' => 'File Download', + 'url' => 'URL', + ], + 'show_text' => false, + 'supports_button_styles' => false, + ]), + array( + array( + 'key' => 'field_' . $acf_group . '_slides_image', + 'label' => 'Slides Image', + 'name' => 'slides_image', + 'instructions' => '', + 'type' => 'image', + 'required' => 1, + 'conditional_logic' => 0, + 'wrapper' => array( + 'width' => '', + 'class' => '', + 'id' => '', + ), + 'return_format' => 'object', // array | url | id + 'preview_size' => 'medium', + 'library' => 'all', // all | uploadedTo + 'min_width' => '', + 'min_height' => '', + 'min_size' => '', + 'max_width' => '', + 'max_height' => '', + 'max_size' => '', + 'mime_types' => '', + ), + array( + 'key' => 'field_' . $acf_group . '_slides_content', + 'label' => 'Slides Content', + 'name' => 'slides_content', + 'type' => 'wysiwyg', + 'instructions' => '', + 'required' => 0, + 'conditional_logic' => 0, + 'wrapper' => array( + 'width' => '', + 'class' => '', + 'id' => '', + ), + 'default_value' => '', + 'tabs' => 'all', // all | visual | text + 'toolbar' => 'full', // full | basic + 'media_upload' => 0, + ), + ) + ), + 'location' => array( + array( + array( + 'param' => 'post_type', // post_type | post | page | page_template | post_category | taxonomy | options_page + 'operator' => '==', + 'value' => Constants\CPT::SLIDES, // if options_page then use: acf-options | if page_template then use: template-example.php + 'order_no' => 0, + 'group_no' => 1 + ) + ) + ), + 'menu_order' => 0, + 'position' => 'normal', // side | normal | acf_after_title + 'style' => 'default', // default | seamless + 'label_placement' => 'top', // top | left + 'instruction_placement' => 'label', // label | field + 'hide_on_screen' => array( + // 0 => 'permalink', + // 1 => 'the_content', + // 2 => 'excerpt', + // 3 => 'custom_fields', + // 4 => 'discussion', + // 5 => 'comments', + // 6 => 'revisions', + // 7 => 'slug', + // 8 => 'author', + // 9 => 'format', + // 10 => 'featured_image', + // 11 => 'categories', + // 12 => 'tags', + // 13 => 'send-trackbacks' + ), + 'active' => 1, + 'description' => '' +)); diff --git a/pingcap-jp/bootstrap/api.php b/pingcap-jp/bootstrap/api.php index 8b18bf3..0b30305 100644 --- a/pingcap-jp/bootstrap/api.php +++ b/pingcap-jp/bootstrap/api.php @@ -139,6 +139,19 @@ ) ]); + /** + * Add a 'card_markup' field to the results returned by the + * /wp/v2/slides endpoint + */ + register_rest_field(Constants\CPT::SLIDES, 'card_markup', [ + 'get_callback' => fn ($post) => WPUtil\Component::render_to_string( + Components\Cards\CardSlides::class, + [ + 'post_id' => $post['id'] + ] + ) + ]); + /** * Add a 'card_markup' field to the results returned by the * /wp/v2/search endpoint @@ -341,6 +354,19 @@ return $args; }, 10, 2); + /** + * Add filters to slides post queries from the "load more" requests + */ + add_filter('rest_' . Constants\CPT::SLIDES . '_query', function ($args, $request) { + $args['posts_per_page'] = CPT\Slides::getPostsPerPageCount(); // phpcs:ignore + + $args = CPT\Slides::modifyQueryWithFilters($args, [ + 'category' => $request->get_param('category_slug') ?? '', + ]); + + return $args; + }, 10, 2); + /** * Add industry slug support to case studies endpoint */ diff --git a/pingcap-jp/bootstrap/pre-get-posts.php b/pingcap-jp/bootstrap/pre-get-posts.php index eb8f86e..2058c49 100644 --- a/pingcap-jp/bootstrap/pre-get-posts.php +++ b/pingcap-jp/bootstrap/pre-get-posts.php @@ -142,12 +142,25 @@ $query->set('posts_per_page', PingCAP\CPT\Video::getPostsPerPageCount()); // phpcs:disable WordPress.Security.NonceVerification.Recommended - $query = PingCAP\CPT\VIDEO::modifyQueryWithFilters($query, [ + $query = PingCAP\CPT\Video::modifyQueryWithFilters($query, [ 'category' => sanitize_text_field(wp_unslash($_GET[PingCAP\Constants\QueryParams::VIDEO_ARCHIVE_FILTER_CATEGORY] ?? '')), ]); // phpcs:enable WordPress.Security.NonceVerification.Recommended } + /** + * Slides archive filtering + */ + if ($query->is_post_type_archive(PingCAP\Constants\CPT::SLIDES)) { + $query->set('posts_per_page', PingCAP\CPT\Slides::getPostsPerPageCount()); + + // phpcs:disable WordPress.Security.NonceVerification.Recommended + $query = PingCAP\CPT\Slides::modifyQueryWithFilters($query, [ + 'category' => sanitize_text_field(wp_unslash($_GET[PingCAP\Constants\QueryParams::SLIDES_ARCHIVE_FILTER_CATEGORY] ?? '')), + ]); + // phpcs:enable WordPress.Security.NonceVerification.Recommended + } + /** * Case Study archive filtering */ diff --git a/pingcap-jp/bootstrap/theme-settings-pages.php b/pingcap-jp/bootstrap/theme-settings-pages.php index fb53db9..3e1d584 100644 --- a/pingcap-jp/bootstrap/theme-settings-pages.php +++ b/pingcap-jp/bootstrap/theme-settings-pages.php @@ -107,4 +107,12 @@ 'menu_slug' => 'video-settings', 'parent' => 'edit.php?post_type=' . PingCAP\Constants\CPT::VIDEO ]); + + // slides options page + acf_add_options_sub_page([ + 'page_title' => 'Slides Settings', + 'menu_title' => 'Slides Settings', + 'menu_slug' => 'slides-settings', + 'parent' => 'edit.php?post_type=' . PingCAP\Constants\CPT::SLIDES + ]); } diff --git a/pingcap-jp/css/components/cards/card-slides.scss b/pingcap-jp/css/components/cards/card-slides.scss new file mode 100644 index 0000000..0942c2e --- /dev/null +++ b/pingcap-jp/css/components/cards/card-slides.scss @@ -0,0 +1,26 @@ +.card-slides { + &__image-container { + position: relative; + height: 0; + padding-top: 56.25%; + display: block; + } + &__image { + @include image-cover-entire-container; + + display: block; + border-radius: var(--card-border-radius); + } + &__category { + font-size: 1.4rem; + margin-top: 1.6rem; + } + &__title { + margin-bottom: 1.6rem; + margin-top: 0.8rem; + a { + text-decoration: none; + color: #303eab; + } + } +} diff --git a/pingcap-jp/css/components/posts-list/posts-list.scss b/pingcap-jp/css/components/posts-list/posts-list.scss index 607ef9e..0424920 100644 --- a/pingcap-jp/css/components/posts-list/posts-list.scss +++ b/pingcap-jp/css/components/posts-list/posts-list.scss @@ -144,6 +144,7 @@ } } +.post-type-archive-slides, .post-type-archive-video { .posts-list__archive-filters { grid-template-columns: 1fr; @@ -186,6 +187,7 @@ } } +.post-type-archive-slides, .post-type-archive-news, .post-type-archive-video, body.post-type-archive-event { diff --git a/pingcap-jp/css/master.scss b/pingcap-jp/css/master.scss index 964cc1c..54c0155 100644 --- a/pingcap-jp/css/master.scss +++ b/pingcap-jp/css/master.scss @@ -88,6 +88,7 @@ Components @import "components/cards/card-tier"; @import "components/cards/card-media"; @import "components/cards/card-event"; +@import "components/cards/card-slides"; @import "components/archive/load-more"; @import "components/archive/navigation"; diff --git a/pingcap-jp/inc/PingCAP/CPT/Slides.php b/pingcap-jp/inc/PingCAP/CPT/Slides.php new file mode 100644 index 0000000..e05246f --- /dev/null +++ b/pingcap-jp/inc/PingCAP/CPT/Slides.php @@ -0,0 +1,149 @@ + Constants\CPT::SLIDES, + 'post_status' => 'publish', + 'posts_per_page' => self::getPostsPerPageCount() // phpcs:ignore + ], $add_params); + + $params = self::modifyQueryWithFilters($params, [ + 'category' => sanitize_text_field(wp_unslash($_GET[Constants\QueryParams::SLIDES_ARCHIVE_FILTER_CATEGORY] ?? '')), + ]); + + return new WP_Query($params); + } + + /** + * Modifies a posts query object with the event archive filter parameters. + * Can take either or a WP_Query object (used in "pre_get_posts") or an array + * (used in "rest_post_query") + * + * @param \WP_Query|array $query + * @param array $filters + * @return \WP_Query|array + */ + public static function modifyQueryWithFilters($query, array $filters) + { + $filters = array_merge([ + 'category' => '', + ], $filters); + + if ($filters['category']) { + $query = Query::setQueryValue($query, 'category_name', $filters['category']); + } + + return $query; + } + + /** + * Return the featured event post id + * + * @return int + */ + public static function getFeaturedId(): int + { + return ACF::get_field_int( + Constants\ACF::SLIDES_SETTINGS_BASE . '_featured_post', + 'option' + ); + } + + /** + * Return the custom posts per page archive settings value or default to the + * standard "posts_per_page" value if it isn't enabled or found + * + * @return integer + */ + public static function getPostsPerPageCount(): int + { + $value = 0; + + $override_enabled = ACF::get_field_int( + Constants\ACF::SLIDES_SETTINGS_BASE . '_override_posts_per_page', + 'option' + ); + + if ($override_enabled) { + $value = ACF::get_field_int( + Constants\ACF::SLIDES_SETTINGS_BASE . '_custom_posts_per_page', + 'option' + ); + } + + if (!$value) { + $value = intval(get_option('posts_per_page')); + } + + return $value; + } + + /** + * Get the first category label attached to a event post + * + * @param integer $post_id + * @return string + */ + public static function getPostCategoryText(int $post_id): string + { + $terms = get_the_category($post_id); + + if (!is_array($terms) || !count($terms)) { + return ''; + } + + return $terms[0]->name ?? ''; + } + + /** + * Return the default image ACF object as set under "Events / Event Settings / Images / Default Featured Image" + * + * @return array + */ + public static function getDefaultCardImage(): array + { + $cache_key = 'slides_default_featured_image'; + + $default_image = StaticCache::get($cache_key); + + if (!is_array($default_image)) { + $default_image = ACF::get_field_array(Constants\ACF::SLIDES_SETTINGS_BASE . '_default_featured_image', 'option'); + + StaticCache::set($cache_key, $default_image); + } + + return $default_image; + } + + /** + * Return the archive page title + * + * @return string + */ + public static function getArchiveTitle(): string + { + return ACF::get_field_string( + Constants\ACF::SLIDES_SETTINGS_BASE . '_archive_title', + 'option' + ); + } +} diff --git a/pingcap-jp/inc/PingCAP/Components/Banners/BannerResourceArchive.php b/pingcap-jp/inc/PingCAP/Components/Banners/BannerResourceArchive.php index f6dc128..d181fbf 100644 --- a/pingcap-jp/inc/PingCAP/Components/Banners/BannerResourceArchive.php +++ b/pingcap-jp/inc/PingCAP/Components/Banners/BannerResourceArchive.php @@ -68,6 +68,9 @@ protected function getTitle(): string case Constants\CPT::VIDEO: return CPT\Video::getArchiveTitle(); + case Constants\CPT::SLIDES: + return CPT\Slides::getArchiveTitle(); + default: break; } diff --git a/pingcap-jp/inc/PingCAP/Components/Cards/CardSlides.php b/pingcap-jp/inc/PingCAP/Components/Cards/CardSlides.php new file mode 100644 index 0000000..9b2c568 --- /dev/null +++ b/pingcap-jp/inc/PingCAP/Components/Cards/CardSlides.php @@ -0,0 +1,47 @@ +post_id = Arrays::get_value_as_int($params, 'post_id', fn() => get_the_ID()); + $this->slides_image = Arrays::get_value_as_array($params, 'slides_image', fn() => ACF::get_field_array('slides_image', $this->post_id)); + $this->category = Arrays::get_value_as_string($params, 'category', fn() => CPT\Slides::getPostCategoryText($this->post_id)); + $this->title = Arrays::get_value_as_string($params, 'title', fn() => get_the_title($this->post_id)); + $this->slides_content = Arrays::get_value_as_string($params, 'slides_content', fn() => ACF::get_field_string('slides_content', $this->post_id)); + $this->slides_url = Arrays::get_value_as_string($params, 'slides_url', fn() => BlueprintBlocks::get_button_field_values('slides_url', $this->post_id)->link); + } + + public function render(): void + { +?> +
+ + slides_image, ['class' => 'card-slides__image']); + ?> + +
category; ?>
+
title; ?>
+ Read Now +
+ - post_type !== Constants\CPT::VIDEO) { ?> + post_type !== Constants\CPT::VIDEO && $this->post_type !== Constants\CPT::SLIDES) { ?>