diff --git a/assets/widget.css b/assets/widget.css index 6b79999..ed7dc48 100644 --- a/assets/widget.css +++ b/assets/widget.css @@ -24,8 +24,7 @@ display: block; } -.side-widget.republication_tracker_tool button.republication-tracker-tool-button, -.widget.republication_tracker_tool button.republication-tracker-tool-button { +button.republication-tracker-tool-button { width:100%; background-color: #5499db; border: 1px solid #2863a7; @@ -39,8 +38,7 @@ text-shadow: 1px 1px 1px #2863a7; } -.side-widget.republication_tracker_tool button.republication-tracker-tool-button:hover, -.widget.republication_tracker_tool button.republication-tracker-tool-button:hover { +button.republication-tracker-tool-button:hover { background-color: #2863a7; text-decoration: none; cursor: pointer; @@ -116,4 +114,4 @@ .modal-open-disallow-scrolling { overflow: hidden; -} \ No newline at end of file +} diff --git a/blocks/button.php b/blocks/button.php new file mode 100644 index 0000000..0195af2 --- /dev/null +++ b/blocks/button.php @@ -0,0 +1,56 @@ + array( + 'label' => array( + 'type' => 'string', + ), + ), + 'editor_script' => 'button-block-editor', + 'editor_style' => 'button-block-editor', + 'style' => 'republication-tracker-tool-css', + 'script' => 'republication-tracker-tool-js', + 'render_callback' => array( 'Republication_Tracker_Tool_Shortcodes', 'button_shortcode' ), + ) ); +} +add_action( 'init', 'republication_tracker_tool_button_block_init' ); diff --git a/blocks/button/editor.css b/blocks/button/editor.css new file mode 100644 index 0000000..5ef7b9d --- /dev/null +++ b/blocks/button/editor.css @@ -0,0 +1,20 @@ +.wp-block-republication-tracker-tool-button.components-placeholder { + min-height: unset; +} +.wp-block-republication-tracker-tool-button .components-base-control__field { + display: flex; + flex-direction: row; + width: 100%; +} +.wp-block-republication-tracker-tool-button .components-base-control__field label { + display: flex; + align-items: center; + margin-right: 10px; + white-space: nowrap; + flex-shrink: 0; + + margin-bottom: 0; +} +.wp-block-republication-tracker-tool-button .components-base-control__field input { + flex-grow: 1; +} diff --git a/blocks/button/index.js b/blocks/button/index.js new file mode 100644 index 0000000..fbe1545 --- /dev/null +++ b/blocks/button/index.js @@ -0,0 +1,101 @@ +( function( wp ) { + /** + * Registers a new block provided a unique name and an object defining its behavior. + * @see https://wordpress.org/gutenberg/handbook/designers-developers/developers/block-api/#registering-a-block + */ + var registerBlockType = wp.blocks.registerBlockType; + /** + * Returns a new element of given type. Element is an abstraction layer atop React. + * @see https://wordpress.org/gutenberg/handbook/designers-developers/developers/packages/packages-element/ + */ + var el = wp.element.createElement; + /** + * Retrieves the translation of text. + * @see https://wordpress.org/gutenberg/handbook/designers-developers/developers/packages/packages-i18n/ + */ + var __ = wp.i18n.__; + + var TextControl = wp.components.TextControl; + var Placeholder = wp.components.Placeholder; + + /** + * Every block starts by registering a new block type definition. + * @see https://wordpress.org/gutenberg/handbook/designers-developers/developers/block-api/#registering-a-block + */ + registerBlockType( 'republication-tracker-tool/button', { + /** + * This is the display title for your block, which can be translated with `i18n` functions. + * The block inserter will show this name. + */ + title: __( 'Republication Modal Button', 'republication-tracker-tool' ), + + /** + * Describe the block for the block inspector + */ + description: __( 'Add a button which opens the Republication Tracker Tool sharing modal.', 'republication-tracker-tool' ), + + /** + * An icon property should be specified to make it easier to identify a block. + * These can be any of WordPress’ Dashicons, or a custom svg element. + */ + icon: 'button', + + /** + * Blocks are grouped into categories to help users browse and discover them. + * The categories provided by core are `common`, `embed`, `formatting`, `layout` and `widgets`. + */ + category: 'widgets', + + /** + * Optional block extended support features. + */ + supports: { + align: false, + alignWide: false, + anchor: false, + customClassName: false, + className: true, + html: false, + multiple: true, + reusable: false, + }, + + /** + * The edit function describes the structure of your block in the context of the editor. + * This represents what the editor will render when the block is used. + * @see https://wordpress.org/gutenberg/handbook/designers-developers/developers/block-api/block-edit-save/#edit + * + * @param {Object} [props] Properties passed from the editor. + * @return {Element} Element to render. + */ + edit: function( props ) { + return el( + Placeholder, + { + className: props.className + ' republication-tracker-tool-button', + label: __( 'Republication Modal Button', 'republication-tracker-tool' ), + }, + el ( TextControl, { + label: __( 'Button Label', 'republication-tracker-tool' ), + value: props.attributes.label, + placeholder: __( 'Republish This Story', 'republication-tracker-tool' ), + onChange: ( value ) => { props.setAttributes( { label: value } ); }, + } ) + ); + }, + + /** + * The save function defines the way in which the different attributes should be combined + * into the final markup, which is then serialized by Gutenberg into `post_content`. + * @see https://wordpress.org/gutenberg/handbook/designers-developers/developers/block-api/block-edit-save/#save + * + * @return {null} There is no element to render + */ + save: function( props ) { + // no element created here, but this function is needed in order to let the props get passed along. + return null; + } + } ); +} )( + window.wp +); diff --git a/docs/adding-republish-button-to-posts.md b/docs/adding-republish-button-to-posts.md index 3f86302..62c4799 100644 --- a/docs/adding-republish-button-to-posts.md +++ b/docs/adding-republish-button-to-posts.md @@ -1,5 +1,7 @@ # Adding Republish button to posts +## The Republication Tracker Tool Widget + In order to add your `Republish` button to your posts, you will need to add the `Republication Tracker Tool` widget to the sidebar or widget area of your choice. Once this plugin is installed and activated, navigate to `Appearance` -> `Widgets`. ![navigating to widgets](img/widgets.png) @@ -18,4 +20,14 @@ Once you have added the `Republication Tracker Tool` widget to a widget area, yo ![default republish button](img/default-republish-button.png) -If you'd like to place the republication button within a post, but not in a sidebar, INN Labs' [Super Cool Ad Inserter Plugin](https://largo.inn.org/guides/administrators/plugins/super-cool-ad-inserter-plugin/) may be of use to you. +If you'd like to place the republication widget within a post, but not in a sidebar, INN Labs' [Super Cool Ad Inserter Plugin](https://largo.inn.org/guides/administrators/plugins/super-cool-ad-inserter-plugin/) may be of use to you. + +## The `[republication_modal_button]` shortcode + +Adding a `[republication_modal_button]` shortcode gets you just the button from the widget. This button will still open the modal. + +Change the button's label like so: `[republication_modal_button label="A custom label!"]` + +## The Republication Modal Button Block + +As an alternative to the shortcode, users of the Block Editor can add a Republication Modal Button Block to posts, and configure the button's label. diff --git a/includes/class-shortcodes.php b/includes/class-shortcodes.php new file mode 100644 index 0000000..847f487 --- /dev/null +++ b/includes/class-shortcodes.php @@ -0,0 +1,46 @@ +'; - echo sprintf( - '

', - esc_html__( 'Republish This Story', 'republication-tracker-tool' ) - ); + echo $this->button_output(); echo sprintf( '

%s

', esc_html__( 'Creative Commons License', 'republication-tracker-tool' ), @@ -85,20 +76,74 @@ public function widget( $args, $instance ) { echo wp_kses_post( $args['after_widget'] ); + echo $this->maybe_print_modal_content(); + } + + /** + * Consider whether to output the markup for the button, and if so, do so + * + * @uses $this::print_modal_content() + * @return String Empty string if there is no need to output the modal contents, or + * the output of $this::print_modal_content() if there is a need. + */ + public static function maybe_print_modal_content() { + /** + * The parent singleton class, grabbed here so that we can check whether an instance already exists + */ + $Republication_Tracker_Tool = Republication_Tracker_Tool::get_instance(); + // if has_instance is false, we can continue with displaying the modal - if( isset( $this->has_instance ) && false === $this->has_instance ){ + if( isset( $Republication_Tracker_Tool->has_instance ) && false === $Republication_Tracker_Tool->has_instance ){ // update has_instance so the next time the widget is created on the same page, it does not create a second modal - $this->has_instance = true; + $Republication_Tracker_Tool->has_instance = true; - printf( - '', - esc_attr( $post->ID ), - esc_attr( plugins_url() ), - esc_html( include_once( $republication_plugin_path . 'shareable-content.php' ) ) - ); + return Republication_Tracker_Tool_Widget::modal_content(); + } else { + return ''; + } + } + /** + * Output the markup for the button + * + * @global $post; + * @return String HTML of the modal contents. + */ + public static function modal_content() { + global $post; + if ( ! is_a( $post, 'WP_Post' ) ) { + return; } + + // define our path to grab file content from + $republication_plugin_path = plugin_dir_path( __FILE__ ); + + ob_start(); + printf( + '', + esc_attr( $post->ID ), + esc_attr( plugins_url() ), + esc_html( include_once( $republication_plugin_path . 'shareable-content.php' ) ) + ); + return ob_get_clean(); + } + + /** + * Output the modal-opening button. + * + * @param String $label The label for the button. Defaults to "Republish This Story". + * @return String HTML for the button. + */ + public static function button_output( $label = '' ) { + if ( empty( trim( $label ) ) ) { + $label = __( 'Republish This Story', 'republication-tracker-tool' ); + } + + return sprintf( + '

', + esc_html( $label ) + ); } /** diff --git a/readme.txt b/readme.txt index cd24bd3..ad880ce 100644 --- a/readme.txt +++ b/readme.txt @@ -31,6 +31,16 @@ In this plugin, the tracking is achieved through an image element included insid == Changelog == += Unreleased changes = + +- Adds the "Republication Modal Button" block, with configurable label, which opens the Republication modal. Pull request TKTK for https://github.com/INN/republication-tracker-tool/issues/66, sponsored by [the Center for Public Integrity](https://publicintegrity.org/). +- Adds the `[republication_modal_button]` shortcode, with optional `label=""` parameter, which opens the Republication modal. Pull request TKTK for https://github.com/INN/republication-tracker-tool/issues/66, sponsored by [the Center for Public Integrity](https://publicintegrity.org/). +- Adds static function `Republication_Tracker_Tool_Widget::button_output( $label = '' );` to return the button markup, and `Republication_Tracker_Tool_Widget::maybe_print_modal_content();` to enqueue the modal markup. Pull request TKTK for https://github.com/INN/republication-tracker-tool/issues/66, sponsored by [the Center for Public Integrity](https://publicintegrity.org/). +- Reduces selector specificity for widget-provided styles on `button.republication-tracker-tool-button`. Pull request TKTK. + +Potentially-breaking changes: +- The property `Republication_Tracker_Tool_Widget->has_instance` is now `Republication_Tracker_Tool->has_instance`. + = 1.0.2 = - Sets a default width for the site icon that is displayed at the bottom of republished articles. Previously it did not have a width set which was causing some sites to experience larger than expected images at the end of their republished articles. diff --git a/republication-tracker-tool.php b/republication-tracker-tool.php index c620c5c..197b059 100644 --- a/republication-tracker-tool.php +++ b/republication-tracker-tool.php @@ -14,6 +14,8 @@ require plugin_dir_path( __FILE__ ).'includes/class-settings.php'; require plugin_dir_path( __FILE__ ).'includes/class-article-settings.php'; require plugin_dir_path( __FILE__ ).'includes/class-widget.php'; +require plugin_dir_path( __FILE__ ).'includes/class-shortcodes.php'; +require plugin_dir_path( __FILE__ ).'blocks/button.php'; /** * Main initiation class. @@ -70,6 +72,11 @@ final class Republication_Tracker_Tool { */ protected $settings; + /** + * Has a widget or button been output upon the page? + */ + public $has_instance = false; + /** * Creates or returns an instance of this class. *