Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support Newspack Sponsors for listings #65

Merged
merged 5 commits into from
Jun 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
184 changes: 113 additions & 71 deletions includes/class-newspack-listings-api.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@
* Sets up API endpoints and handlers for listings.
*/
final class Newspack_Listings_Api {
/**
* REST route namespace.
*
* @var Newspack_Listings_Api
*/
protected static $namespace = 'newspack-listings/v1';

/**
* The single instance of the class.
Expand Down Expand Up @@ -56,20 +62,50 @@ public static function register_routes() {

// GET listings posts by ID, query args, or title search term.
register_rest_route(
'newspack-listings/v1',
self::$namespace,
'listings',
[
[
'methods' => \WP_REST_Server::READABLE,
'callback' => [ __CLASS__, 'get_items' ],
'args' => [
'query' => [
'sanitize_callback' => '\Newspack_Listings\Utils\sanitize_array',
],
'id' => [
'sanitize_callback' => 'absint',
],
'type' => [
'sanitize_callback' => '\Newspack_Listings\Utils\sanitize_array',
],
'attributes' => [
'sanitize_callback' => '\Newspack_Listings\Utils\sanitize_array',
],
'offset' => [
'sanitize_callback' => 'absint',
],
'page' => [
'sanitize_callback' => 'absint',
],
'per_page' => [
'sanitize_callback' => 'absint',
],
'search' => [
'sanitize_callback' => 'sanitize_text_field',
],
'_fields' => [
'sanitize_callback' => 'sanitize_text_field',
],

],
'permission_callback' => '__return_true',
],
]
);

// GET listings taxonomy terms by name search term.
register_rest_route(
'newspack-listings/v1',
self::$namespace,
'terms',
[
[
Expand All @@ -82,7 +118,7 @@ public static function register_routes() {

// GET listings taxonomy terms by name search term.
register_rest_route(
'newspack-listings/v1',
self::$namespace,
'children',
[
[
Expand All @@ -95,7 +131,7 @@ public static function register_routes() {

// Set listings taxonomy terms.
register_rest_route(
'newspack-listings/v1',
self::$namespace,
'children',
[
[
Expand Down Expand Up @@ -254,6 +290,7 @@ public static function build_listings_query( $query, $args = [] ) {
* @return WP_REST_Response.
*/
public static function get_items( $request ) {
$response = [];
$params = $request->get_params();
$fields = explode( ',', $params['_fields'] );
$search = ! empty( $params['search'] ) ? $params['search'] : null;
Expand Down Expand Up @@ -297,81 +334,88 @@ public static function get_items( $request ) {
$listings_query = new \WP_Query( $args );

if ( $listings_query->have_posts() ) {
$response = new \WP_REST_Response(
array_map(
function( $post ) use ( $attributes, $fields, $is_amp, $next_page, $query ) {
$item = [
'id' => $post->ID,
'title' => $post->post_title,
];

// if $fields includes html, get rendered HTML for the post.
if ( in_array( 'html', $fields ) && ! empty( $attributes ) ) {
$html = Utils\template_include(
'listing',
[
'attributes' => $attributes,
'post' => $post,
]
);

// If an AMP page, convert to valid AMP HTML.
if ( $is_amp ) {
$html = Utils\generate_amp_partial( $html );
}

$item['html'] = $html;
$listings = array_map(
function( $post ) use ( $attributes, $fields, $is_amp, $next_page, $query ) {
$item = [
'id' => $post->ID,
'title' => $post->post_title,
];

// if $fields includes html, get rendered HTML for the post.
if ( in_array( 'html', $fields ) && ! empty( $attributes ) ) {
$html = Utils\template_include(
'listing',
[
'attributes' => $attributes,
'post' => $post,
]
);

// If an AMP page, convert to valid AMP HTML.
if ( $is_amp ) {
$html = Utils\generate_amp_partial( $html );
}

// If $fields includes category, get the post categories.
if ( in_array( 'category', $fields ) ) {
$item['category'] = get_the_terms( $post->ID, 'category' );
}

// If $fields includes tags, get the post tags.
if ( in_array( 'tags', $fields ) ) {
$item['tags'] = get_the_terms( $post->ID, 'post_tag' );
}
$item['html'] = $html;
}

// If $fields includes category, get the post categories.
if ( in_array( 'category', $fields ) ) {
$item['category'] = get_the_terms( $post->ID, 'category' );
}

// If $fields includes tags, get the post tags.
if ( in_array( 'tags', $fields ) ) {
$item['tags'] = get_the_terms( $post->ID, 'post_tag' );
}

// If $fields includes excerpt, get the post excerpt.
if ( in_array( 'excerpt', $fields ) ) {
$item['excerpt'] = Utils\get_listing_excerpt( $post );
}

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

// If $fields includes author and the post isn't set to hide author, get the post author.
if ( in_array( 'author', $fields ) && empty( get_post_meta( $post->ID, 'newspack_listings_hide_author', true ) ) ) {
$item['author'] = get_the_author_meta( 'display_name', $post->post_author );
}
// If $fields includes meta, get all Newspack Listings meta fields.
if ( in_array( 'meta', $fields ) || in_array( 'author', $fields ) ) {
$item['meta'] = [];
$post_meta = Core::get_meta_values( $post->ID, $post->post_type );

// If $fields includes excerpt, get the post excerpt.
if ( in_array( 'excerpt', $fields ) ) {
$item['excerpt'] = Utils\get_listing_excerpt( $post );
if ( ! empty( $post_meta ) ) {
$item['meta'] = $post_meta;
}
}

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

// If $fields includes meta, get all Newspack Listings meta fields.
if ( in_array( 'meta', $fields ) ) {
$post_meta = Core::get_meta_values( $post->ID, $post->post_type );
// If $fields includes author and the post isn't set to hide author, get the post author.
if ( in_array( 'author', $fields ) && empty( get_post_meta( $post->ID, 'newspack_listings_hide_author', true ) ) ) {
$item['author'] = get_the_author_meta( 'display_name', $post->post_author );
}

if ( ! empty( $post_meta ) ) {
$item['meta'] = $post_meta;
}
}
$item['test'] = 'Brody';

// If $fields includes type, get the post type.
if ( in_array( 'type', $fields ) ) {
$item['type'] = $post->post_type;
}
// If $fields includes sponsors include sponsors info.
if ( in_array( 'sponsors', $fields ) ) {
$item['sponsors'] = Utils\get_sponsors( $post->ID, 'native' );
}

return $item;
},
$listings_query->posts
),
200
return $item;
},
$listings_query->posts
);

$response = new \WP_REST_Response( $listings );

// Provide next URL if there are more pages.
if ( $next_page <= $listings_query->max_num_pages ) {
$next_url = add_query_arg(
Expand All @@ -382,18 +426,16 @@ function( $post ) use ( $attributes, $fields, $is_amp, $next_page, $query ) {
'amp' => $is_amp,
'_fields' => 'html',
],
rest_url( '/newspack-listings/v1/listings' )
rest_url( '/' . self::$namespace . '/listings' )
);
}

if ( ! empty( $next_url ) ) {
$response->header( 'next-url', $next_url );
}

return $response;
}

return new \WP_REST_Response( [] );
return rest_ensure_response( $response );
}

/**
Expand Down
14 changes: 14 additions & 0 deletions includes/class-newspack-listings-core.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ public function __construct() {
add_filter( 'newspack_listings_hide_author', [ __CLASS__, 'hide_author' ] );
add_filter( 'newspack_listings_hide_publish_date', [ __CLASS__, 'hide_publish_date' ] );
add_filter( 'newspack_theme_featured_image_post_types', [ __CLASS__, 'support_featured_image_options' ] );
add_filter( 'newspack_sponsors_post_types', [ __CLASS__, 'support_newspack_sponsors' ] );
register_activation_hook( NEWSPACK_LISTINGS_FILE, [ __CLASS__, 'activation_hook' ] );
}

Expand Down Expand Up @@ -827,6 +828,19 @@ public static function activation_hook() {
flush_rewrite_rules(); // phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions.flush_rewrite_rules_flush_rewrite_rules
}

/**
* If using the Newspack Sponsors plugin, add support for sponsors to all listings.
*
* @param array $post_types Array of supported post types.
* @return array Filtered array of supported post types.
*/
public static function support_newspack_sponsors( $post_types ) {
return array_merge(
$post_types,
array_values( self::NEWSPACK_LISTINGS_POST_TYPES )
);
}

/**
* Convert legacy custom taxonomies to regular post categories and tags.
* Helpful for sites that have been using v1 of the Listings plugin.
Expand Down
22 changes: 22 additions & 0 deletions includes/newspack-listings-utils.php
Original file line number Diff line number Diff line change
Expand Up @@ -346,3 +346,25 @@ function generate_amp_partial( $html ) {
}
return \AMP_DOM_Utils::get_content_from_dom( $dom );
}

/**
* Get sponsors for the given listing.
*
* @param int $post_id ID of the listing.
* @param string $scope 'Native' or 'underwritten'.
* @param string $type 'Post' or 'archive'.
*
* @return array|boolean Array of sponsors, or false if none.
*/
function get_sponsors( $post_id = null, $scope = null, $type = 'post' ) {
// Bail if we don't have the Sponsors plugin.
if ( ! function_exists( '\Newspack_Sponsors\get_all_sponsors' ) ) {
return false;
}

if ( null === $post_id ) {
$post_id = get_the_ID();
}

return \Newspack_Sponsors\get_all_sponsors( $post_id, $scope, $type );
}
31 changes: 19 additions & 12 deletions src/assets/shared/listing.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@

.newspack-listings {
&__listing-post {
display: block;

@media only screen and ( min-width: $tablet_width ) {
.media-position-left &,
.media-position-right & {
display: flex;
}
}

+ .is-link {
padding-left: 0;
padding-right: 0;
Expand Down Expand Up @@ -50,18 +59,6 @@
}
}

&__listing-post,
&__listing-link {
display: block;

@media only screen and ( min-width: $tablet_width ) {
.media-position-left &,
.media-position-right & {
display: flex;
}
}
}

&__listing-title {
margin-top: 0.5rem;

Expand Down Expand Up @@ -125,4 +122,14 @@
&__column-reverse {
flex-direction: row-reverse;
}

&__sponsors {
align-items: center;
display: flex;

.sponsor-logos {
border-right: 1px solid var( --newspack-listings--grey-light );
margin-right: 0.75rem;
}
}
}
2 changes: 1 addition & 1 deletion src/blocks/curated-list/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ const CuratedListEditorComponent = ( {
const posts = await apiFetch( {
path: addQueryArgs( '/newspack-listings/v1/listings', {
query: { ...query, maxItems: MAX_EDITOR_ITEMS }, // Get up to MAX_EDITOR_ITEMS listings in the editor so we can show all locations.
_fields: 'id,title,author,category,tags,excerpt,media,meta,type',
_fields: 'id,title,author,category,tags,excerpt,media,meta,type,sponsors',
} ),
} );
setAttributes( { listingIds: posts.map( post => post.id ) } );
Expand Down
2 changes: 1 addition & 1 deletion src/blocks/listing/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ const ListingEditorComponent = ( {
path: addQueryArgs( '/newspack-listings/v1/listings', {
per_page: 100,
id: listingId,
_fields: 'id,title,author,category,tags,excerpt,media,meta',
_fields: 'id,title,author,category,tags,excerpt,media,meta,sponsors',
} ),
} );

Expand Down
Loading