diff --git a/includes/class-newspack.php b/includes/class-newspack.php index 26aab9a957..47d50e65af 100644 --- a/includes/class-newspack.php +++ b/includes/class-newspack.php @@ -235,6 +235,9 @@ private function includes() { // Filter by authors in the Posts page. include_once NEWSPACK_ABSPATH . 'includes/author-filter/class-author-filter.php'; + // Display tags as labels. + include_once NEWSPACK_ABSPATH . 'includes/tag-labels/class-tag-labels.php'; + // Load the general Newspack UI front-end styles. include_once NEWSPACK_ABSPATH . 'includes/class-newspack-ui.php'; include_once NEWSPACK_ABSPATH . 'includes/class-newspack-ui-icons.php'; diff --git a/includes/tag-labels/class-tag-labels.php b/includes/tag-labels/class-tag-labels.php new file mode 100644 index 0000000000..560aa8ca4d --- /dev/null +++ b/includes/tag-labels/class-tag-labels.php @@ -0,0 +1,318 @@ +term_id ) { + return false; + } + return ! empty( get_term_meta( $term->term_id, self::TAG_LABEL_META_KEY, true ) ); + } + + /** + * Given a term, return the flag (text) of its label and + * the link to the term archive. + * + * Will return null if label isn't enabled for the term. + * + * @param WP_Term $term Term to check. + * + * @return array|null As ['flag' => FLAG_NAME, 'link' => TERM_LINK]. + */ + public static function get_tag_label_for_term( $term ) { + if ( ! $term || ! $term->term_id || ! self::has_label( $term ) ) { + return null; + } + + // A little fancy in case someone wants to give a tag a + // falsy label flag. Empty string still gets default value. + $term_label_flag = get_term_meta( $term->term_id, self::TAG_LABEL_FLAG_META_KEY, true ); + if ( '' === $term_label_flag ) { + $term_label_flag = $term->name; + } + + $term_label_link = get_term_link( $term->term_id ); + if ( is_wp_error( $term_label_link ) ) { + return null; + } + + return [ + 'flag' => $term_label_flag, + 'link' => $term_label_link, + ]; + } + + /** + * Given a post ID, grab array of tag labels (if any) for it. + * + * @param int|WP_Post|null $post Post to check. + * + * @return array|null Elements as ['flag' => FLAG_NAME, 'link' => TERM_LINK]. + */ + public static function get_labels_for_post( $post ) { + if ( ! $post ) { + return null; + } + + $post_id = ( is_a( $post, 'WP_Post' ) ? $post->ID : (int) $post ); + $post_terms = get_the_terms( $post_id, 'post_tag' ); + + if ( empty( $post_terms ) || is_wp_error( $post_terms ) ) { + return []; + } + + return array_filter( + array_map( + function( $term ) { + return self::get_tag_label_for_term( $term ); + }, + $post_terms + ) + ); + } + + /** + * Generates HTML for given tag labels. + * + * @param array $labels Labels to display. + * @param bool $links Whether to include links to tag archives. + * @param array $outer_classes Classes to apply to the outer container. + * @param array $inner_classes Classes to apply to the inner container. + * @param string $outer_element HTML element to use for the outer container. + * + * @return string Tag labels as HTML. + */ + public static function generate_html( $labels = null, $links = true, $outer_classes = array( 'tag-labels' ), $inner_classes = array( 'tag-label', 'flag' ), $outer_element = 'span' ) { + if ( empty( $labels ) ) { + return ''; + } + + $outer_element = in_array( $outer_element, [ 'span', 'div' ], true ) ? $outer_element : 'span'; + + $labels_html = ''; + $labels_html .= '<' . $outer_element . ' class="' . join( ' ', array_map( 'esc_attr', $outer_classes ) ) . '">'; + foreach ( $labels as $label ) { + if ( $links && isset( $label['flag'] ) && $label['link'] ) { + $labels_html .= '' . esc_html( $label['flag'] ) . ''; + } elseif ( isset( $label['flag'] ) ) { + $labels_html .= '' . esc_html( $label['flag'] ) . ''; + } + } + $labels_html .= '' . $outer_element . '>'; + + return $labels_html; + } + + /** + * Outputs HTML for given tag labels. + * + * @param array $labels Labels to display. + * @param bool $links Whether to include links to tag archives. + * @param string $outer_element HTML element to use for the outer container. + * + * @return void + */ + public static function display( $labels = null, $links = true, $outer_element = 'span' ) { + if ( empty( $labels ) ) { + return; + } + + echo wp_kses_post( self::generate_html( $labels, $links, array( 'tag-labels', 'cat-links' ), array( 'tag-label', 'flag' ), $outer_element ) . ' ' ); + } + + /** + * Initialize hooks. + */ + public static function init() { + add_action( 'post_tag_pre_add_form', array( __CLASS__, 'enqueue_scripts' ) ); + add_action( 'post_tag_term_edit_form_top', array( __CLASS__, 'enqueue_scripts' ) ); + + add_action( 'post_tag_add_form_fields', [ __CLASS__, 'add_term' ] ); + add_action( 'post_tag_edit_form_fields', [ __CLASS__, 'edit_term' ] ); + + add_action( 'created_post_tag', [ __CLASS__, 'save_term' ] ); + add_action( 'edited_post_tag', [ __CLASS__, 'save_term' ] ); + } + + /** + * Enqueues js script + * + * @return void + */ + public static function enqueue_scripts() { + wp_enqueue_script( + 'newspack_tag_labels', + Newspack::plugin_url() . '/dist/other-scripts/tag-labels.js', + [ 'jquery' ], + NEWSPACK_PLUGIN_VERSION, + true + ); + } + + /** + * Term creation fields. + * + * Toggle to determine if the term is a label. + * Also, override for flag (text used on label). + */ + public static function add_term() { + $checkbox_id = self::TAG_LABEL_META_KEY; + ?> +
+ +
++ +
+