Skip to content

Commit

Permalink
feat: new Curated List block, block pattern, and map functionality (#3)
Browse files Browse the repository at this point in the history
* feat: initial post type and block setup

Sets up custom post types and Listing block prototype.

* feat: improvements to block structure and meta

Instead of just registering a single Listing block and selecting the type in the parent post, this registers a separate block for each listing type (all of which use the same code).

* fix: error after fetching post

* feat: handle meta programmatically, add permalink prefix

* fix: pull request feedback; refactor post types config

Addresses pull request feedback and refactors post types config into a more DRY treatment.

* chore: use permalink slugs defined in constant; spaces in JSON

* feat: add Curated List block; remove Curated List CPT

This removes the Curated List CPT in favor of a wrapper block that can be inserted into any other post or page. This block can contain Listing blocks to create curated lists anywhere, and can be converted to a Reusable Block if it needs to be reusable.

* chore: update class docblocks, move blocks to newspack category

* chore: remove unused block_categories filter

* fix: remove fse action

* feat: listing InnerBlocks inherit parent Curated List attributes

Lays out a method of passing attributes data from the Curated List block to its child Listing inner blocks, without relying on contexts. We basically duplicate parent block attributes on each child block and sync the values of those attributes.

* fix: wrong selector in sidebar JS

* feat: change curated list to dynamic render

* feat: add "business" block pattern for Marketplace listings

This establishes a pattern for providing block patterns for particular listings CPTs. This might let us provide structured content without having to register metadata fields for listing content.

* feat: map functionality via Jetpack Maps block

Adds support for location-based data using the jetpack/maps block. If a listing CPT of any type contains a jetpack/map block with location data, the location data is used to show the listing on a map for any Curated List blocks containing the listing post.

* feat: check for jetpack/maps block before using

* feat: add Jetpack Contact Info block to Business Listing block pattern

* feat: sync block content to post meta

Sets up a sync from certain content blocks to post meta fields. This will help us more easily implement search/filter functionality for listing posts on a large scale.

* fix: use listing post meta to get locations in curated list block

* chore: phpdoc types should be lowercase

* feat: don't register Curated List block in listings CPTs

We want to avoid letting editors nest Curated Lists inside list items which could be nested inside Curated Lists which could be inside list items which could be... etc.

* fix: css fixes for compatibility with core block editor (sans plugin)

* fix: listing block parent should be list container, not curated list

* fix: callable for settings fields

* fix: block patterns for core WP

Block patterns and block pattern categories can only be registered on init or admin_init hooks in WP 5.5.

* chore: remove redundant docblock comment

* fix: flush permalinks only after registering CPTs
  • Loading branch information
dkoo authored Oct 27, 2020
1 parent 47dc0c1 commit 9be6e7e
Show file tree
Hide file tree
Showing 35 changed files with 1,524 additions and 639 deletions.
43 changes: 26 additions & 17 deletions includes/class-newspack-listings-api.php
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
<?php
/**
* Newspack Listings Core.
* Newspack Listings API.
*
* Registers custom post types and taxonomies.
* Custom API endpoints for Newspack Listings.
*
* @package Newspack_Listings
*/

namespace Newspack_Listings;

use \Newspack_Listings\Newspack_Listings_Core as Core;
use \Newspack_Listings\Utils as Utils;

defined( 'ABSPATH' ) || exit;

Expand Down Expand Up @@ -115,26 +116,34 @@ public static function get_items( $request ) {
return new \WP_REST_Response(
array_map(
function( $post ) use ( $fields ) {
$response = [
'id' => $post->ID,
'title' => $post->post_title,
];

// If $fields includes meta, get all Newspack Listings meta fields.
$post_meta = [];
// If $fields includes excerpt, get the post excerpt.
if ( in_array( 'excerpt', $fields ) ) {
$response['excerpt'] = wpautop( get_the_excerpt( $post->ID ) );
}

// If $fields includes media, get the featured image + caption.
if ( in_array( 'media', $fields ) ) {
$response['media'] = [
'image' => get_the_post_thumbnail_url( $post->ID, 'medium' ),
'caption' => get_the_post_thumbnail_caption( $post->ID ),
];
}

// If $fields includes meta, get all Newspack Listings meta fields.
if ( in_array( 'meta', $fields ) ) {
$post_meta = array_filter(
get_post_meta( $post->ID ),
function( $key ) {
return is_numeric( strpos( $key, 'newspack_listings_' ) );
},
ARRAY_FILTER_USE_KEY
);
$post_meta = Core::get_meta_values( $post->ID, $post->post_type );

if ( ! empty( $post_meta ) ) {
$response['meta'] = $post_meta;
}
}

return [
'id' => $post->ID,
'title' => $post->post_title,
'content' => wpautop( get_the_excerpt( $post->ID ) ),
'meta' => $post_meta,
];
return $response;
},
$query->posts
),
Expand Down
135 changes: 88 additions & 47 deletions includes/class-newspack-listings-blocks.php
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<?php
/**
* Newspack Listings Core.
* Newspack Listings Blocks.
*
* Registers custom post types and taxonomies.
* Custom Gutenberg Blocks for Newspack Listings.
*
* @package Newspack_Listings
*/
Expand All @@ -18,6 +18,10 @@
* Sets up custom blocks for listings.
*/
final class Newspack_Listings_Blocks {
/**
* Slug for the block pattern category.
*/
const NEWSPACK_LISTINGS_BLOCK_PATTERN_CATEGORY = 'newspack-listings-patterns';

/**
* The single instance of the class.
Expand All @@ -43,53 +47,53 @@ public static function instance() {
* Constructor.
*/
public function __construct() {
add_filter( 'block_categories', [ __CLASS__, 'update_block_categories' ] );
add_action( 'enqueue_block_editor_assets', [ __CLASS__, 'manage_editor_assets' ] );
add_action( 'admin_init', [ __CLASS__, 'register_block_pattern_category' ], 10 );
add_action( 'admin_init', [ __CLASS__, 'register_block_patterns' ], 11 );
add_action( 'init', [ __CLASS__, 'manage_view_assets' ] );
}

/**
* Enqueue editor assets.
*/
public static function manage_editor_assets() {
if ( Core::is_curated_list() || Core::is_listing() ) {
wp_enqueue_script(
'newspack-listings-editor',
NEWSPACK_LISTINGS_URL . 'dist/editor.js',
[],
NEWSPACK_LISTINGS_VERSION,
true
);

$post_type = get_post_type();

wp_localize_script(
'newspack-listings-editor',
'newspack_listings_data',
[
'post_type' => get_post_type_object( $post_type )->labels->singular_name,
'post_types' => Core::NEWSPACK_LISTINGS_POST_TYPES,
'meta_fields' => Core::get_meta_fields( $post_type ),
]
);

wp_register_style(
'newspack-listings-editor',
plugins_url( '../dist/editor.css', __FILE__ ),
[],
NEWSPACK_LISTINGS_VERSION
);
wp_style_add_data( 'newspack-listings-editor', 'rtl', 'replace' );
wp_enqueue_style( 'newspack-listings-editor' );
}
wp_enqueue_script(
'newspack-listings-editor',
NEWSPACK_LISTINGS_URL . 'dist/editor.js',
[],
NEWSPACK_LISTINGS_VERSION,
true
);

$post_type = get_post_type();

wp_localize_script(
'newspack-listings-editor',
'newspack_listings_data',
[
'post_type_label' => get_post_type_object( $post_type )->labels->singular_name,
'post_type' => $post_type,
'post_types' => Core::NEWSPACK_LISTINGS_POST_TYPES,
'meta_fields' => Core::get_meta_fields( $post_type ),
]
);

wp_register_style(
'newspack-listings-editor',
plugins_url( '../dist/editor.css', __FILE__ ),
[],
NEWSPACK_LISTINGS_VERSION
);
wp_style_add_data( 'newspack-listings-editor', 'rtl', 'replace' );
wp_enqueue_style( 'newspack-listings-editor' );
}

/**
* Enqueue front-end assets.
*/
public static function manage_view_assets() {
// Do nothing in editor environment.
if ( is_admin() ) {
// In editor environment, do nothing.
return;
}

Expand Down Expand Up @@ -127,22 +131,59 @@ public static function manage_view_assets() {
}

/**
* Add custom block category.
*
* @param array $categories Default Gutenberg categories.
* @return array
* Register custom block pattern category for Newspack Listings.
*/
public static function update_block_categories( $categories ) {
return array_merge(
$categories,
[
[
'slug' => 'newspack-listings',
'title' => __( 'Newspack Listings', 'newspack-listings' ),
],
]
public static function register_block_pattern_category() {
return register_block_pattern_category(
self::NEWSPACK_LISTINGS_BLOCK_PATTERN_CATEGORY,
[ 'label' => __( 'Newspack Listings', 'newspack-listings' ) ]
);
}

/**
* Register custom block patterns for Newspack Listings.
* These patterns should only be available for certain CPTs.
*/
public static function register_block_patterns() {
// Block pattern config.
$block_patterns = [
'business' => [
'post_types' => [
Core::NEWSPACK_LISTINGS_POST_TYPES['marketplace'],
Core::NEWSPACK_LISTINGS_POST_TYPES['place'],
],
'settings' => [
'title' => __( 'Business Listing', 'newspack-listings' ),
'categories' => [ self::NEWSPACK_LISTINGS_BLOCK_PATTERN_CATEGORY ],
'description' => _x(
'Business description, website and social media links, and hours of operation.',
'Block pattern description',
'newspack-listings'
),
'content' => '<!-- wp:columns --><div class="wp-block-columns"><!-- wp:column {"width":66.66} --><div class="wp-block-column" style="flex-basis:66.66%"><!-- wp:paragraph --><p>Consectetur a urna hendrerit scelerisque suspendisse inceptos scelerisque neque parturient a mi adipiscing euismod mus. Ad felis morbi magna augue consectetur eleifend sit sem habitant suspendisse posuere amet felis adipiscing a himenaeos ipsum vivamus dictum vestibulum lacus consectetur vestibulum erat dignissim per sem integer. Cras class ac adipiscing inceptos a enim porta a elit scelerisque tincidunt hac ad netus accumsan parturient conubia vestibulum nec quisque parturient interdum fringilla curabitur cras sociosqu interdum. Porta aenean id a mus consectetur lacus lacus ut parturient sapien ut a sociosqu potenti ridiculus non tristique cursus a at parturient condimentum a duis convallis per. Dictum elementum ultricies ac risus vestibulum adipiscing placerat imperdiet malesuada scelerisque dictum mus adipiscing a at at fermentum scelerisque nisl a dignissim suscipit sapien taciti nulla curabitur vestibulum.</p><!-- /wp:paragraph --></div><!-- /wp:column --><!-- wp:column {"width":33.33} --><div class="wp-block-column" style="flex-basis:33.33%"><!-- wp:jetpack/map {"mapCenter":{"lng":-122.41941550000001,"lat":37.7749295},"mapHeight":null} -->
<div class="wp-block-jetpack-map" data-map-style="default" data-map-details="true" data-points="[]" data-zoom="13" data-map-center="{&quot;lng&quot;:-122.41941550000001,&quot;lat&quot;:37.7749295}" data-marker-color="red" data-show-fullscreen-button="true"></div>
<!-- /wp:jetpack/map --><!-- wp:jetpack/contact-info --><div class="wp-block-jetpack-contact-info"><!-- wp:jetpack/address /--><!-- wp:jetpack/email /--><!-- wp:jetpack/phone /--></div><!-- /wp:jetpack/contact-info --><!-- wp:buttons --><div class="wp-block-buttons"><!-- wp:button {"className":"is-style-fill"} --><div class="wp-block-button is-style-fill"><a class="wp-block-button__link" href="https://newspack.pub">Visit our website</a></div><!-- /wp:button --></div><!-- /wp:buttons --><!-- wp:social-links --><ul class="wp-block-social-links"><!-- wp:social-link {"url":"https://newspack.pub","service":"wordpress"} /--><!-- wp:social-link {"url":"https://facebook.com","service":"facebook"} /--><!-- wp:social-link {"url":"https://twitter.com","service":"twitter"} /--><!-- wp:social-link {"url":"https://instagram.com","service":"instagram"} /--><!-- wp:social-link {"service":"linkedin"} /--><!-- wp:social-link {"service":"youtube"} /--></ul><!-- /wp:social-links --><!-- wp:separator {"className":"is-style-wide"} --><hr class="wp-block-separator is-style-wide"/><!-- /wp:separator --><!-- wp:heading {"level":4} --><h4>Hours of Operation</h4><!-- /wp:heading --><!-- wp:jetpack/business-hours /--></div><!-- /wp:column --></div><!-- /wp:columns -->',
],
],
];

/**
* Register block patterns for particular post types. We need to get the post type using the
* post ID from $_REQUEST since the global $post is not available inside the admin_init hook.
* If we can't determine the current post type, just register the patterns anyway.
*/
$post_id = isset( $_REQUEST['post'] ) ? sanitize_text_field( $_REQUEST['post'] ) : null; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
$current_post_type = ! empty( $post_id ) && function_exists( 'get_post_type' ) ? get_post_type( $post_id ) : null;

foreach ( $block_patterns as $pattern_name => $config ) {
if ( empty( $current_post_type ) || in_array( $current_post_type, $config['post_types'] ) ) {
$pattern = register_block_pattern(
'newspack-listings/' . $pattern_name,
$config['settings']
);
}
}
}
}

Newspack_Listings_Blocks::instance();
Loading

0 comments on commit 9be6e7e

Please sign in to comment.