diff --git a/includes/class-newspack.php b/includes/class-newspack.php
index ac3464af7c..9056771890 100644
--- a/includes/class-newspack.php
+++ b/includes/class-newspack.php
@@ -114,6 +114,7 @@ private function includes() {
include_once NEWSPACK_ABSPATH . 'includes/authors/class-authors-custom-fields.php';
include_once NEWSPACK_ABSPATH . 'includes/optional-modules/class-rss.php';
+ include_once NEWSPACK_ABSPATH . 'includes/optional-modules/class-media-partners.php';
include_once NEWSPACK_ABSPATH . 'includes/starter_content/class-starter-content-provider.php';
include_once NEWSPACK_ABSPATH . 'includes/starter_content/class-starter-content-generated.php';
@@ -375,7 +376,6 @@ public static function load_common_assets() {
[],
NEWSPACK_PLUGIN_VERSION
);
-
}
}
Newspack::instance();
diff --git a/includes/optional-modules/class-media-partners.php b/includes/optional-modules/class-media-partners.php
new file mode 100644
index 0000000000..cb3ddaa859
--- /dev/null
+++ b/includes/optional-modules/class-media-partners.php
@@ -0,0 +1,526 @@
+ true,
+ 'labels' => [
+ 'name' => esc_html_x( 'Media Partners', 'taxonomy general name', 'newspack-plugin' ),
+ 'singular_name' => esc_html_x( 'Media Partner', 'taxonomy singular name', 'newspack-plugin' ),
+ 'search_items' => esc_html__( 'Search Media Partners', 'newspack-plugin' ),
+ 'all_items' => esc_html__( 'All Media Partners', 'newspack-plugin' ),
+ 'parent_item' => esc_html__( 'Parent Media Partner', 'newspack-plugin' ),
+ 'parent_item_colon' => esc_html__( 'Parent Media Partner:', 'newspack-plugin' ),
+ 'edit_item' => esc_html__( 'Edit Media Partner', 'newspack-plugin' ),
+ 'view_item' => esc_html__( 'View Media Partner', 'newspack-plugin' ),
+ 'update_item' => esc_html__( 'Update Media Partner', 'newspack-plugin' ),
+ 'add_new_item' => esc_html__( 'Add New Media Partner', 'newspack-plugin' ),
+ 'new_item_name' => esc_html__( 'New Media Partner Name', 'newspack-plugin' ),
+ 'menu_name' => esc_html__( 'Media Partners' ),
+ ],
+ 'public' => true,
+ 'show_admin_column' => true,
+ 'show_in_nav_menus' => true,
+ 'query_var' => true,
+ 'rewrite' => [ 'slug' => 'partners' ],
+ 'show_in_rest' => true,
+ ]
+ );
+ }
+
+ /**
+ * Render a settings field.
+ *
+ * @param string $key The key for the field.
+ * @param string $label The label for the field.
+ * @param array $partner The partner data.
+ * @param string $context The context for the field.
+ */
+ private static function render_settings_field( $key, $label, $partner = [], $context = 'new_partner' ) {
+ $tag = 'input';
+ $value = isset( $partner[ $key ] ) ? $partner[ $key ] : '';
+ if ( in_array( $key, [ 'attribution_message' ] ) ) {
+ $tag = 'textarea';
+ }
+
+ ob_start();
+ if ( 'textarea' === $tag ) {
+ ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+ __( 'This story also appeared in', 'newspack-plugin' ),
+ ];
+ }
+
+ /**
+ * Get partner logo upload setting JS script.
+ */
+ private static function get_logo_upload_script() {
+ ob_start()
+ ?>
+
+
+
+
+ term_id, 'logo', true );
+ $logo = '';
+ if ( $logo_id ) {
+ $logo_atts = wp_get_attachment_image_src( $logo_id );
+ if ( $logo_atts ) {
+ $logo = $logo_atts[0];
+ }
+ }
+
+ ?>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ esc_url( get_term_meta( $partner->term_id, 'partner_homepage_url', true ) ),
+ 'attribution_message' => get_term_meta( $partner->term_id, 'attribution_message', true ),
+ ];
+ if ( ! metadata_exists( 'term', $partner->term_id, 'attribution_message' ) ) {
+ $partner_settings['attribution_message'] = $defaults['attribution_message'];
+ }
+ return $partner_settings;
+ }
+
+ /**
+ * Save the meta fields for the Partner taxonomy.
+ *
+ * @param int $term_id Term ID.
+ */
+ public static function save_partner_meta_fields( $term_id ) {
+ if ( ! current_user_can( 'edit_posts' ) ) {
+ return;
+ }
+
+ $partner_logo = filter_input( INPUT_POST, 'partner_logo', FILTER_SANITIZE_NUMBER_INT );
+ if ( $partner_logo ) {
+ update_term_meta( $term_id, 'logo', (int) $partner_logo );
+ } else {
+ delete_term_meta( $term_id, 'logo' );
+ }
+
+ $partner_url = filter_input( INPUT_POST, 'partner_url', FILTER_SANITIZE_STRING );
+ if ( $partner_url ) {
+ update_term_meta( $term_id, 'partner_homepage_url', esc_url( $partner_url ) );
+ }
+
+ $attribution_message = filter_input( INPUT_POST, 'attribution_message', FILTER_SANITIZE_STRING );
+ if ( $attribution_message ) {
+ update_term_meta( $term_id, 'attribution_message', $attribution_message );
+ }
+ }
+
+ /**
+ * Register the 'partners' shortcode.
+ * Can be inserted into a post or page to display a list of partners.
+ */
+ public static function add_partners_shortcode() {
+ add_shortcode( 'partners', [ __CLASS__, 'render_partners_shortcode' ] );
+ }
+
+ /**
+ * Get partner logo, if set to be displayed.
+ *
+ * @param WP_Term $partner The partner object.
+ */
+ private static function get_partner_logo( $partner ) {
+ return get_term_meta( $partner->term_id, 'logo', true );
+ }
+
+ /**
+ * Render the 'partners' shortcode.
+ */
+ public static function render_partners_shortcode() {
+ $partners = get_terms(
+ [
+ 'taxonomy' => 'partner',
+ 'hide_empty' => false,
+ ]
+ );
+
+ ob_start();
+
+ ?>
+
+ term_id, 'partner_homepage_url', true );
+
+ if ( $partner_logo ) {
+ $logo_html = '';
+ $logo_atts = wp_get_attachment_image_src( $partner_logo, 'full' );
+ $logo_alt = $partner->name;
+
+ if ( $partner_url ) {
+ $logo_alt = sprintf(
+ /* translators: replaced with the name of the Media Partner */
+ __( 'Website for %s', 'newspack-plugin' ),
+ $partner->name
+ );
+ }
+
+ if ( $logo_atts ) {
+ $logo_html = ' ';
+ }
+
+ if ( $logo_html && $partner_url ) {
+ $logo_html = '' . $logo_html . ' ';
+ }
+
+ $partner_html .= $logo_html;
+ }
+
+ $partner_name = $partner->name;
+ if ( $partner_url ) {
+ $partner_name = '' . $partner_name . ' ';
+ }
+ $partner_html .= '' . $partner_name . '
';
+
+ $elements[] = $partner_html;
+ }
+
+ $num_columns = 3;
+ $current = 0;
+ $container_closed = true;
+ foreach ( $elements as $element ) {
+ if ( 0 == $current ) {
+ echo '';
+ $container_closed = false;
+ }
+
+ echo '
';
+ echo wp_kses_post( $element );
+ echo '
';
+
+ ++$current;
+
+ if ( $num_columns == $current ) {
+ echo '
';
+ $current = 0;
+ $container_closed = true;
+ }
+ }
+
+ // Close last div if needed.
+ if ( ! $container_closed ) {
+ echo ' ';
+ }
+
+ return ob_get_clean();
+ }
+
+ /**
+ * Filter in a partner logo on posts that have partners.
+ *
+ * @param string $content The post content.
+ * @return string Modified $content.
+ */
+ public static function add_content_partner_logo( $content ) {
+ $id = get_the_ID();
+ $partners = get_the_terms( $id, 'partner' );
+ if ( ! $partners ) {
+ return $content;
+ }
+
+ $partner_images = [];
+ $partner_names = [];
+ foreach ( $partners as $partner ) {
+ $partner_image_id = self::get_partner_logo( $partner );
+ $partner_url = esc_url( get_term_meta( $partner->term_id, 'partner_homepage_url', true ) );
+ $image = '';
+ $image_alt = $partner->name;
+
+ if ( $partner_url ) {
+ $image_alt = sprintf(
+ /* translators: replaced with the name of the Media Partner */
+ __( 'Website for %s', 'newspack-plugin' ),
+ $partner->name
+ );
+ }
+
+ if ( $partner_image_id ) {
+ $image = wp_get_attachment_image( $partner_image_id, [ 200, 999 ], false, [ 'alt' => esc_attr( $image_alt ) ] );
+ if ( $image && $partner_url ) {
+ $image = '' . $image . ' ';
+ }
+ }
+
+ $partner_images[] = $image;
+
+ $partner_name = $partner->name;
+ if ( $partner_url ) {
+ $partner_name = '' . $partner_name . ' ';
+ }
+ $partner_names[] = $partner_name;
+ }
+
+ $partner_settings = self::get_partner_config( $partner );
+
+ // Skip partners in RSS feed.
+ $settings = self::get_settings();
+ if ( $settings['skip_in_feeds'] && is_feed() ) {
+ return $content;
+ }
+
+ ob_start();
+ ?>
+
+
+ \s*#', $content, 2 );
+
+ // Just append it to the top if a good injection spot can't be found..
+ if ( 1 === count( $content_halves ) ) {
+ $content = $partner_html . $content;
+ } else {
+ $content = $content_halves[0] . '
' . $partner_html . '' . $content_halves[1];
+ }
+
+ return $content;
+ }
+
+ /**
+ * Add global settings UI.
+ */
+ public static function add_global_settings() {
+ $settings = self::get_settings();
+ ?>
+
+ get_option( 'newspack_media_partners_skip_in_feeds', false ),
+ ];
+ }
+
+ /**
+ * Handle settings update.
+ */
+ public static function handle_settings_update() { // phpcs:ignore WordPressVIPMinimum.Hooks.AlwaysReturnInFilter.MissingReturnStatement
+ $media_partners_settings = filter_input( INPUT_POST, 'media_partners_settings', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
+ if ( ! current_user_can( 'manage_options' ) || ! $media_partners_settings ) {
+ return true;
+ }
+ if ( ! wp_verify_nonce( filter_input( INPUT_POST, '_wpnonce_partners-settings', FILTER_SANITIZE_FULL_SPECIAL_CHARS ), 'partners-settings' ) ) {
+ return true;
+ }
+
+ $skip_in_feeds = filter_input( INPUT_POST, 'skip_in_feeds', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
+ update_option( 'newspack_media_partners_skip_in_feeds', boolval( $skip_in_feeds ) );
+
+ wp_safe_redirect( admin_url( 'edit-tags.php?taxonomy=partner' ) );
+ exit;
+ }
+}
+Media_Partners::init();
diff --git a/includes/wizards/class-settings.php b/includes/wizards/class-settings.php
index 05c9a3613f..73230224c3 100644
--- a/includes/wizards/class-settings.php
+++ b/includes/wizards/class-settings.php
@@ -47,9 +47,10 @@ public function __construct() {
*/
private static function get_settings() {
$default_settings = [
- self::MODULE_ENABLED_PREFIX . 'rss' => false,
+ self::MODULE_ENABLED_PREFIX . 'rss' => false,
+ self::MODULE_ENABLED_PREFIX . 'media-partners' => false,
];
- return get_option( self::SETTINGS_OPTION_NAME, $default_settings );
+ return wp_parse_args( get_option( self::SETTINGS_OPTION_NAME ), $default_settings );
}
/**
diff --git a/tests/unit-tests/settings.php b/tests/unit-tests/settings.php
index a3db0a905d..8730f011ce 100644
--- a/tests/unit-tests/settings.php
+++ b/tests/unit-tests/settings.php
@@ -24,7 +24,10 @@ public function set_up() {
public function test_settings_defaults() {
self::assertEquals(
Settings::api_get_settings(),
- [ 'module_enabled_rss' => false ],
+ [
+ 'module_enabled_rss' => false,
+ 'module_enabled_media-partners' => false,
+ ],
'Default settings are as expected.'
);
}
@@ -38,7 +41,10 @@ public function test_settings_update() {
Settings::api_update_settings( $request );
self::assertEquals(
Settings::api_get_settings(),
- [ 'module_enabled_rss' => true ],
+ [
+ 'module_enabled_rss' => true,
+ 'module_enabled_media-partners' => false,
+ ],
'Settings is updated.'
);
@@ -46,7 +52,10 @@ public function test_settings_update() {
Settings::api_update_settings( $request );
self::assertEquals(
Settings::api_get_settings(),
- [ 'module_enabled_rss' => true ],
+ [
+ 'module_enabled_rss' => true,
+ 'module_enabled_media-partners' => false,
+ ],
'A non-existent setting is not saved.'
);
}