diff --git a/includes/class-core.php b/includes/class-core.php index 8b99805..31f28e3 100644 --- a/includes/class-core.php +++ b/includes/class-core.php @@ -106,6 +106,15 @@ public static function init() { self::create_shadow_relationship(); } + /** + * Is the current post a sponsor? + * + * @return boolean True if a sponsor. + */ + public static function is_sponsor() { + return self::NEWSPACK_SPONSORS_CPT === get_post_type(); + } + /** * Registers Sponsors custom post type. */ @@ -212,7 +221,6 @@ public static function register_meta() { 'post', 'newspack_sponsor_sponsorship_scope', [ - 'object_subtype' => self::NEWSPACK_SPONSORS_CPT, 'description' => __( 'Scope of sponsorship this sponsor offers (native content vs. underwritten).', 'newspack-sponsors' ), 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field', @@ -223,6 +231,66 @@ public static function register_meta() { }, ] ); + register_meta( + 'post', + 'newspack_sponsor_native_byline_display', + [ + 'description' => __( 'Display the sponsorship only, the author byline only, or both.', 'newspack-sponsors' ), + 'type' => 'string', + 'default' => self::is_sponsor() ? 'sponsor' : 'inherit', + 'sanitize_callback' => 'sanitize_text_field', + 'single' => true, + 'show_in_rest' => true, + 'auth_callback' => function() { + return current_user_can( 'edit_posts' ); + }, + ] + ); + register_meta( + 'post', + 'newspack_sponsor_native_category_display', + [ + 'description' => __( 'Display the sponsor only, or display categories alongside the sponsor.', 'newspack-sponsors' ), + 'type' => 'string', + 'default' => self::is_sponsor() ? 'sponsor' : 'inherit', + 'sanitize_callback' => 'sanitize_text_field', + 'single' => true, + 'show_in_rest' => true, + 'auth_callback' => function() { + return current_user_can( 'edit_posts' ); + }, + ] + ); + register_meta( + 'post', + 'newspack_sponsor_underwriter_style', + [ + 'description' => __( 'Display the underwriter blurb in standard or simple-text format.', 'newspack-sponsors' ), + 'type' => 'string', + 'default' => self::is_sponsor() ? 'standard' : 'inherit', + 'sanitize_callback' => 'sanitize_text_field', + 'single' => true, + 'show_in_rest' => true, + 'auth_callback' => function() { + return current_user_can( 'edit_posts' ); + }, + ] + ); + register_meta( + 'post', + 'newspack_sponsor_underwriter_placement', + [ + 'description' => __( 'Display the underwriter blurb at the top or bottom of the post.', 'newspack-sponsors' ), + 'type' => 'string', + 'default' => self::is_sponsor() ? 'top' : 'inherit', + 'sanitize_callback' => 'sanitize_text_field', + 'single' => true, + 'show_in_rest' => true, + 'auth_callback' => function() { + return current_user_can( 'edit_posts' ); + }, + ] + ); register_meta( 'post', 'newspack_sponsor_only_direct', @@ -268,6 +336,11 @@ public static function register_tax() { ]; $tax_args = [ + 'capabilities' => [ + 'manage_terms' => '', + 'edit_terms' => '', + 'delete_terms' => '', + ], 'hierarchical' => true, 'labels' => $labels, 'public' => true, diff --git a/includes/class-editor.php b/includes/class-editor.php index 2966094..727b1fa 100644 --- a/includes/class-editor.php +++ b/includes/class-editor.php @@ -68,18 +68,19 @@ public static function disable_yoast_primary_category_picker( $taxonomies, $post return $taxonomies; } - /** - * Is editing a sponsor? - */ - public static function is_editing_sponsor() { - return Core::NEWSPACK_SPONSORS_CPT === get_post_type(); - } - /** * Load up JS/CSS for editor. */ public static function enqueue_block_editor_assets() { - if ( ! self::is_editing_sponsor() && 'post' !== get_post_type() ) { + $allowed_post_types = apply_filters( + 'newspack_sponsors_post_types', + [ 'post', 'page' ] + ); + + $allowed_post_types[] = Core::NEWSPACK_SPONSORS_CPT; + + // Only enqueue assets for allowed post types. + if ( ! in_array( get_post_type(), $allowed_post_types, true ) ) { return; } @@ -95,8 +96,11 @@ public static function enqueue_block_editor_assets() { 'newspack-sponsors-editor', 'newspack_sponsors_data', [ - 'settings' => Settings::get_settings(), - 'defaults' => Settings::get_default_settings(), + 'post_type' => get_post_type(), + 'settings' => Settings::get_settings(), + 'defaults' => Settings::get_default_settings(), + 'cpt' => Core::NEWSPACK_SPONSORS_CPT, + 'tax' => Core::NEWSPACK_SPONSORS_TAX, ] ); diff --git a/includes/theme-helpers.php b/includes/theme-helpers.php index e3aebda..f9f585e 100644 --- a/includes/theme-helpers.php +++ b/includes/theme-helpers.php @@ -356,12 +356,16 @@ function convert_post_to_sponsor( $post, $type = 'direct', $logo_options = [] ) $sponsor_sitewide_settings = Settings::get_settings(); - $sponsor_byline = get_post_meta( $post->ID, 'newspack_sponsor_byline_prefix', true ); - $sponsor_url = get_post_meta( $post->ID, 'newspack_sponsor_url', true ); - $sponsor_flag = get_post_meta( $post->ID, 'newspack_sponsor_flag_override', true ); - $sponsor_scope = get_post_meta( $post->ID, 'newspack_sponsor_sponsorship_scope', true ); - $sponsor_disclaimer = get_post_meta( $post->ID, 'newspack_sponsor_disclaimer_override', true ); - $sponsor_logo = get_logo_info( $post->ID, $logo_options ); + $sponsor_byline = get_post_meta( $post->ID, 'newspack_sponsor_byline_prefix', true ); + $sponsor_url = get_post_meta( $post->ID, 'newspack_sponsor_url', true ); + $sponsor_flag = get_post_meta( $post->ID, 'newspack_sponsor_flag_override', true ); + $sponsor_scope = get_post_meta( $post->ID, 'newspack_sponsor_sponsorship_scope', true ); + $sponsor_byline_display = get_post_meta( $post->ID, 'newspack_sponsor_native_byline_display', true ); + $sponsor_category_display = get_post_meta( $post->ID, 'newspack_sponsor_native_category_display', true ); + $sponsor_underwriter_style = get_post_meta( $post->ID, 'newspack_sponsor_underwriter_style', true ); + $sponsor_underwriter_placement = get_post_meta( $post->ID, 'newspack_sponsor_underwriter_placement', true ); + $sponsor_disclaimer = get_post_meta( $post->ID, 'newspack_sponsor_disclaimer_override', true ); + $sponsor_logo = get_logo_info( $post->ID, $logo_options ); // Check for single-sponsor overrides, default to site-wide options. if ( empty( $sponsor_byline ) ) { @@ -374,7 +378,7 @@ function convert_post_to_sponsor( $post, $type = 'direct', $logo_options = [] ) $sponsor_disclaimer = str_replace( '[sponsor name]', $post->post_title, $sponsor_sitewide_settings['disclaimer'] ); } - return [ + $sponsor = [ 'sponsor_type' => $type, 'sponsor_id' => $post->ID, 'sponsor_name' => $post->post_title, @@ -387,6 +391,16 @@ function convert_post_to_sponsor( $post, $type = 'direct', $logo_options = [] ) 'sponsor_scope' => ! empty( $sponsor_scope ) ? $sponsor_scope : 'native', // Default: native, not underwritten. 'sponsor_disclaimer' => $sponsor_disclaimer, ]; + + if ( 'native' === $sponsor['sponsor_scope'] ) { + $sponsor['sponsor_byline_display'] = $sponsor_byline_display; + $sponsor['sponsor_category_display'] = $sponsor_category_display; + } else { + $sponsor['sponsor_underwriter_style'] = $sponsor_underwriter_style; + $sponsor['sponsor_underwriter_placement'] = $sponsor_underwriter_placement; + } + + return $sponsor; } /** @@ -423,3 +437,69 @@ function get_logo_info( $sponsor_id, $logo_options = [] ) { return $logo_info; } + +/** + * If at least one native sponsor is set to display both sponsors and authors, show the authors. + * + * @param array $sponsors Array of sponsors. + * + * @return boolean True if we should display both sponsors and categories, false if we should display only sponsors. + */ +function newspack_display_sponsors_and_authors( $sponsors ) { + if ( ! is_array( $sponsors ) ) { + return false; + } + + // If the post is set to display author, show it. + $override = get_post_meta( get_the_ID(), 'newspack_sponsor_native_byline_display', true ); + if ( 'author' === $override ) { + return true; + } + if ( 'sponsor' === $override ) { + return false; + } + + return array_reduce( + $sponsors, + function( $acc, $sponsor ) { + if ( isset( $sponsor['sponsor_byline_display'] ) && 'author' === $sponsor['sponsor_byline_display'] ) { + $acc = true; + } + return $acc; + }, + false + ); +} + +/** + * If at least one native sponsor is set to display both sponsors and categories, show the categories. + * + * @param array $sponsors Array of sponsors. + * + * @return boolean True if we should display both sponsors and categories, false if we should display only sponsors. + */ +function newspack_display_sponsors_and_categories( $sponsors ) { + if ( ! is_array( $sponsors ) ) { + return false; + } + + // If the post is set to display categories, show them. + $override = get_post_meta( get_the_ID(), 'newspack_sponsor_native_category_display', true ); + if ( 'category' === $override ) { + return true; + } + if ( 'sponsor' === $override ) { + return false; + } + + return array_reduce( + $sponsors, + function( $acc, $sponsor ) { + if ( isset( $sponsor['sponsor_category_display'] ) && 'category' === $sponsor['sponsor_category_display'] ) { + $acc = true; + } + return $acc; + }, + false + ); +} diff --git a/src/editor/index.js b/src/editor/index.js index 3b0513c..f420cdc 100644 --- a/src/editor/index.js +++ b/src/editor/index.js @@ -1,8 +1,10 @@ /** * WordPress dependencies */ +import { __ } from '@wordpress/i18n'; import { addFilter } from '@wordpress/hooks'; import { registerPlugin } from '@wordpress/plugins'; +import { PluginDocumentSettingPanel } from '@wordpress/edit-post'; /** * Internal dependencies @@ -10,6 +12,8 @@ import { registerPlugin } from '@wordpress/plugins'; import { Sidebar } from './sidebar'; import { TaxonomyPanel } from './taxonomy-panel'; +const { post_type: postType, cpt } = window.newspack_sponsors_data; + /** * Filter the PostTaxonomies component. */ @@ -17,8 +21,20 @@ addFilter( 'editor.PostTaxonomyType', 'newspack-sponsors-editor', TaxonomyPanel /** * Register plugin editor settings. + * For sponsor posts, this is a separate sidebar panel. + * For all other post types, it is pre-pended to the Sponsors sidebar panel. */ -registerPlugin( 'newspack-sponsors-editor', { - render: Sidebar, - icon: null, -} ); +if ( cpt === postType ) { + registerPlugin( 'newspack-sponsors-editor', { + render: () => ( + + + + ), + icon: null, + } ); +} diff --git a/src/editor/sidebar/index.js b/src/editor/sidebar/index.js index 5533141..23265c4 100644 --- a/src/editor/sidebar/index.js +++ b/src/editor/sidebar/index.js @@ -5,7 +5,6 @@ import { __ } from '@wordpress/i18n'; import { SelectControl, TextareaControl, TextControl, ToggleControl } from '@wordpress/components'; import { compose } from '@wordpress/compose'; import { withDispatch, withSelect } from '@wordpress/data'; -import { PluginDocumentSettingPanel } from '@wordpress/edit-post'; /** * Internal dependencies @@ -13,110 +12,211 @@ import { PluginDocumentSettingPanel } from '@wordpress/edit-post'; import './style.scss'; const SidebarComponent = props => { - if ( props.postType !== 'newspack_spnsrs_cpt' ) { - return null; - } - const { meta, title, updateMetaValue } = props; const { newspack_sponsor_url, newspack_sponsor_flag_override, newspack_sponsor_byline_prefix, newspack_sponsor_sponsorship_scope, + newspack_sponsor_native_byline_display, + newspack_sponsor_native_category_display, + newspack_sponsor_underwriter_style, + newspack_sponsor_underwriter_placement, newspack_sponsor_only_direct, newspack_sponsor_disclaimer_override, } = meta; - const { settings, defaults } = window.newspack_sponsors_data; + const { settings, defaults, post_type: postType, cpt } = window.newspack_sponsors_data; + const isSponsor = cpt === postType; // True if the post being edited is a sponsor, false if a post type that can be sponsored. + + // If the post is not a sponsor but a post that can be sponsored, add default options to inherit values from the sponsor. + const scopeDefault = isSponsor ? 'native' : ''; + const scopeOptions = [ + { value: 'native', label: __( 'Native content', 'newspack-sponsors' ) }, + { value: 'underwritten', label: __( 'Underwritten content', 'newspack-sponsors' ) }, + ]; + const bylineDefault = isSponsor ? 'sponsor' : 'inherit'; + const bylineOptions = [ + { value: 'sponsor', label: __( 'Sponsor only', 'newspack-sponsors' ) }, + { value: 'author', label: __( 'Both sponsor and author byline', 'newspack-sponsors' ) }, + ]; + const categoryDefault = isSponsor ? 'sponsor' : 'inherit'; + const categoryOptions = [ + { value: 'sponsor', label: __( 'Sponsor only', 'newspack-sponsors' ) }, + { value: 'category', label: __( 'Sponsor and categories', 'newspack-sponsors' ) }, + ]; + const underwriterStyleDefault = isSponsor ? 'standard' : 'inherit'; + const underwriterStyleOptions = [ + { value: 'standard', label: __( 'Standard', 'newspack-sponsors' ) }, + { value: 'simple', label: __( 'Simple', 'newspack-sponsors' ) }, + ]; + const underwriterPlacementDefault = isSponsor ? 'top' : 'inherit'; + const underwriterPlacementOptions = [ + { value: 'top', label: __( 'Top', 'newspack-sponsors' ) }, + { value: 'bottom', label: __( 'Bottom', 'newspack-sponsors' ) }, + ]; + if ( ! isSponsor ) { + const defaultOption = { + value: 'inherit', + label: __( 'Inherit from sponsor', 'newspack-sponsors' ), + }; + scopeOptions.unshift( defaultOption ); + bylineOptions.unshift( defaultOption ); + categoryOptions.unshift( defaultOption ); + underwriterStyleOptions.unshift( defaultOption ); + underwriterPlacementOptions.unshift( defaultOption ); + } return ( - + <> + { ! isSponsor && ( + <> +

{ __( 'Sponsor Display Overrides', 'newspack-sponsors' ) }

+

+ + { __( + 'The following settings optionally override the settings of assigned sponsors.', + 'newspack-sponsors' + ) } + +

+ + ) } updateMetaValue( 'newspack_sponsor_sponsorship_scope', value ) } help={ __( 'Generally, native content is authored by the sponsor, while underwritten content is authored by editorial staff but supported by the sponsor. This option allows you to select a different visual treatment for native vs. underwitten content.', 'newspack-sponsors' ) } /> - updateMetaValue( 'newspack_sponsor_url', value ) } - /> - updateMetaValue( 'newspack_sponsor_flag_override', value ) } - /> - updateMetaValue( 'newspack_sponsor_disclaimer_override', value ) } - /> - updateMetaValue( 'newspack_sponsor_byline_prefix', value ) } - /> - updateMetaValue( 'newspack_sponsor_only_direct', value ) } - /> -
+ { ( 'native' === newspack_sponsor_sponsorship_scope || + ( isSponsor && ! newspack_sponsor_sponsorship_scope ) || + ! isSponsor ) && ( + <> + updateMetaValue( 'newspack_sponsor_native_byline_display', value ) } + help={ __( 'Show the sponsor, the author byline, or both.', 'newspack-sponsors' ) } + /> + + updateMetaValue( 'newspack_sponsor_native_category_display', value ) + } + help={ __( + 'Show the sponsor only, or the post’s categories alongside the "sponsored" flag.', + 'newspack-sponsors' + ) } + /> + + ) } + { ( 'underwritten' === newspack_sponsor_sponsorship_scope || ! isSponsor ) && ( + <> + updateMetaValue( 'newspack_sponsor_underwriter_style', value ) } + help={ __( + 'Show the underwriter blurb in a standard or simplified style.', + 'newspack-sponsors' + ) } + /> + updateMetaValue( 'newspack_sponsor_underwriter_placement', value ) } + help={ __( + 'Show the underwriter blurb at the top or bottom of the post.', + 'newspack-sponsors' + ) } + /> + + ) } + { isSponsor && ( + <> + updateMetaValue( 'newspack_sponsor_url', value ) } + /> + updateMetaValue( 'newspack_sponsor_flag_override', value ) } + /> + updateMetaValue( 'newspack_sponsor_disclaimer_override', value ) } + /> + updateMetaValue( 'newspack_sponsor_byline_prefix', value ) } + /> + updateMetaValue( 'newspack_sponsor_only_direct', value ) } + /> + + ) } + ); }; const mapStateToProps = select => { - const { getCurrentPostType, getEditedPostAttribute } = select( 'core/editor' ); + const { getEditedPostAttribute } = select( 'core/editor' ); return { meta: getEditedPostAttribute( 'meta' ), - postType: getCurrentPostType(), title: getEditedPostAttribute( 'title' ), }; }; diff --git a/src/editor/taxonomy-panel/index.js b/src/editor/taxonomy-panel/index.js index 737b1c1..23095cb 100644 --- a/src/editor/taxonomy-panel/index.js +++ b/src/editor/taxonomy-panel/index.js @@ -1,9 +1,13 @@ /** - * WordPress dependencies + * WordPress dependencies. */ import { __, sprintf } from '@wordpress/i18n'; -import { select } from '@wordpress/data'; -import { Fragment } from '@wordpress/element'; +import { useSelect } from '@wordpress/data'; + +/** + * Internal dependencies. + */ +import { Sidebar } from '../sidebar'; /** * Filters the PostTaxonomies component to add explanations unique to Newspack Sponsor posts. @@ -14,13 +18,30 @@ import { Fragment } from '@wordpress/element'; */ export const TaxonomyPanel = PostTaxonomies => { const OriginalComponent = props => { - const postType = select( 'core/editor' ).getCurrentPostType(); + const { post_type: postType, cpt, tax } = window.newspack_sponsors_data; + const { slug } = props; + const isSponsorsTax = tax === slug; + const hasAssignedSponsors = useSelect( select => { + const sponsors = select( 'core/editor' ).getEditedPostAttribute( tax ); + return Array.isArray( sponsors ) && 0 < sponsors.length; + } ); - if ( 'newspack_spnsrs_cpt' !== postType && 'post' !== postType ) { + // Only filter compoent for sponsors, tax, categories, and tags. + if ( 'category' !== slug && 'post_tag' !== slug && ! isSponsorsTax ) { return ; } - const { slug } = props; + // Append sponsor settings panel to Sponsors taxonomy panel. + if ( isSponsorsTax ) { + return ( + <> +

{ __( 'Select one or more sponsors:', 'newspack-sponsors' ) }

+ + { hasAssignedSponsors && } + + ); + } + const hierarchical = 'category' === slug; const label = 'category' === slug @@ -39,18 +60,14 @@ export const TaxonomyPanel = PostTaxonomies => { ); return ( - - { 'newspack_spnsrs_cpt' === postType && ( slug === 'category' || slug === 'post_tag' ) && ( + <> + { cpt === postType && ( slug === 'category' || slug === 'post_tag' ) && (

{ message }

) } - -
+ + ); };