diff --git a/README.md b/README.md index 0b6eb04..949f066 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,7 @@ The plugin tracks the pages, posts and custom post types that visitors click thr ### Key features * __Automatic__: The plugin will start displaying visited posts on your posts and pages automatically after the content when you activate the plugin +* __Block editor support__: Easy to use block for the block editor. Find it under widgets or using "followed posts" or "where did they go from here" * __Shortcode__: Use `[wherego]` to display the followed posts * __Multi-Widget support__: Find the __Followed posts__ widget to display the posts in your theme's sidebar or any other area that supports widgets. You can use the widget multiple times with different settings for each * __Manual install__: Want more control over placement? Check the [FAQ](https://wordpress.org/plugins/where-did-they-go-from-here/#faq) on which functions are available for manual install diff --git a/includes/admin/class-admin.php b/includes/admin/class-admin.php index 569ffdd..103bcf2 100644 --- a/includes/admin/class-admin.php +++ b/includes/admin/class-admin.php @@ -124,7 +124,7 @@ public function admin_enqueue_scripts() { 'wherego-admin-columns', false, array(), - WZP_VERSION + WFP_VERSION ); } diff --git a/includes/class-main.php b/includes/class-main.php index 015bd3c..0fd7b0a 100644 --- a/includes/class-main.php +++ b/includes/class-main.php @@ -60,6 +60,15 @@ final class Main { */ public $tracker; + /** + * Blocks. + * + * @since 3.1.0 + * + * @var object Blocks. + */ + public $blocks; + /** * Styles. * @@ -103,6 +112,7 @@ private function init() { $this->language = new Frontend\Language_Handler(); $this->tracker = new Tracker(); $this->shortcodes = new Frontend\Shortcodes(); + $this->blocks = new Frontend\Blocks\Blocks(); $this->styles = new Frontend\Styles_Handler(); $this->hooks(); diff --git a/includes/css/grid.css b/includes/css/grid.css index 6d470c8..4180792 100644 --- a/includes/css/grid.css +++ b/includes/css/grid.css @@ -1,15 +1,15 @@ -.wherego_related { +.wz-followed-posts.wz-followed-posts-grid { clear: both; margin: 10px 0; width: 100%; } -.wherego_related h3 { +.wz-followed-posts.wz-followed-posts-grid h3 { margin: 0; clear: both; } -.wherego_related ul { +.wz-followed-posts.wz-followed-posts-grid ul { list-style: none; margin: 0; padding: 0; @@ -18,7 +18,7 @@ grid-gap: 10px; } -.wherego_related ul li { +.wz-followed-posts.wz-followed-posts-grid ul li { text-align: center; line-height: 120%; border: 1px solid #ddd; @@ -27,7 +27,7 @@ transition: ease 0.3s; } -.wherego_related ul li a { +.wz-followed-posts.wz-followed-posts-grid ul li a { display: flex; flex-direction: column; height: 100%; @@ -35,12 +35,12 @@ color: #fff; } -.wherego_related ul li a img { +.wz-followed-posts.wz-followed-posts-grid ul li a img { margin: 0 auto; max-width: 100%; } -.wherego_related ul li a span.wherego_title { +.wz-followed-posts.wz-followed-posts-grid ul li a span.wherego_title { background-color: rgba(0, 0, 0, 0.5); padding: 5px; color: #fff; @@ -53,11 +53,11 @@ word-break: break-word; } -.wherego_related ul li a span.wherego_title:hover { +.wz-followed-posts.wz-followed-posts-grid ul li a span.wherego_title:hover { background-color: #333; } -.wherego_related ul li:hover { +.wz-followed-posts.wz-followed-posts-grid ul li:hover { background-color: #ccc; } diff --git a/includes/css/grid.min.css b/includes/css/grid.min.css index 07d766c..89b4e54 100644 --- a/includes/css/grid.min.css +++ b/includes/css/grid.min.css @@ -1 +1 @@ -.wherego_related{clear:both;margin:10px 0;width:100%}.wherego_related h3{margin:0;clear:both}.wherego_related ul{list-style:none;margin:0;padding:0;display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));grid-gap:10px}.wherego_related ul li{text-align:center;line-height:120%;border:1px solid #ddd;border-radius:5px;list-style:none;transition:ease .3s}.wherego_related ul li a{display:flex;flex-direction:column;height:100%;text-decoration:none!important;color:#fff}.wherego_related ul li a img{margin:0 auto;max-width:100%}.wherego_related ul li a span.wherego_title{background-color:rgba(0,0,0,.5);padding:5px;color:#fff;border-radius:5px;display:flex;justify-content:center;align-items:center;flex:1 1 auto;transition:ease .3s}.wherego_related ul li a span.wherego_title:hover{background-color:#333}.wherego_related ul li:hover{background-color:#ccc}.wherego_clear{clear:both}.wherego_title:visited{color:#fff!important} \ No newline at end of file +.wz-followed-posts.wz-followed-posts-grid{clear:both;margin:10px 0;width:100%;}.wz-followed-posts.wz-followed-posts-grid h3{margin:0;clear:both;}.wz-followed-posts.wz-followed-posts-grid ul{list-style:none;margin:0;padding:0;display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));grid-gap:10px;}.wz-followed-posts.wz-followed-posts-grid ul li{text-align:center;line-height:120%;border:1px solid #ddd;border-radius:5px;list-style:none;transition:ease .3s;}.wz-followed-posts.wz-followed-posts-grid ul li a{display:flex;flex-direction:column;height:100%;text-decoration:none!important;color:#fff;}.wz-followed-posts.wz-followed-posts-grid ul li a img{margin:0 auto;max-width:100%;}.wz-followed-posts.wz-followed-posts-grid ul li a span.wherego_title{background-color:rgba(0,0,0,.5);padding:5px;color:#fff;border-radius:5px;display:flex;justify-content:center;align-items:center;flex:1 1 auto;transition:ease .3s;word-break:break-word;}.wz-followed-posts.wz-followed-posts-grid ul li a span.wherego_title:hover{background-color:#333;}.wz-followed-posts.wz-followed-posts-grid ul li:hover{background-color:#ccc;}.wherego_clear{clear:both;}.wherego_title:visited{color:#fff!important;} \ No newline at end of file diff --git a/includes/frontend/blocks/class-blocks.php b/includes/frontend/blocks/class-blocks.php new file mode 100644 index 0000000..d8e0295 --- /dev/null +++ b/includes/frontend/blocks/class-blocks.php @@ -0,0 +1,122 @@ + array( __CLASS__, 'render_block' ), + ) + ); + } + + + /** + * Renders the `webberzone/followed-posts` block on server. + * + * @since 3.1.0 + * @param array $attributes The block attributes. + * + * @return string Returns the post content with followed posts added. + */ + public static function render_block( $attributes ) { + + $attributes['extra_class'] = esc_attr( $attributes['className'] ); + + $arguments = array_merge( + $attributes, + array( + 'is_block' => 1, + ) + ); + + $arguments = wp_parse_args( $attributes['other_attributes'], $arguments ); + + /** + * Filters arguments passed to get_wfp for the block. + * + * @since 3.1.0 + * + * @param array $arguments WebberZone Followed Posts arguments. + * @param array $attributes Block attributes array. + */ + $arguments = apply_filters( 'whergo_block_options', $arguments, $attributes ); + + // Enqueue the stylesheet for the selected style for this block. + $style_array = \WebberZone\WFP\Frontend\Styles_Handler::get_style( $arguments['wherego_styles'] ); + + if ( ! empty( $style_array['name'] ) ) { + $style = $style_array['name']; + $extra_css = $style_array['extra_css']; + + wp_register_style( + "whergo-style-{$style}", + plugins_url( "css/{$style}.min.css", WHEREGO_PLUGIN_FILE ), + array(), + WFP_VERSION + ); + wp_enqueue_style( "whergo-style-{$style}" ); + wp_add_inline_style( "whergo-style-{$style}", $extra_css ); + } + + return \WebberZone\WFP\Frontend\Display::followed_posts( $arguments ); + } + + /** + * Enqueue scripts and styles for the block editor. + * + * @since 3.1.0 + */ + public static function enqueue_block_editor_assets() { + + $style_array = \WebberZone\WFP\Frontend\Styles_Handler::get_style(); + $file_prefix = ( defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ) ? '' : '.min'; + + if ( ! empty( $style_array['name'] ) ) { + $style = $style_array['name']; + $extra_css = $style_array['extra_css']; + + wp_enqueue_style( + 'followed-posts-block-editor', + plugins_url( "css/{$style}{$file_prefix}.css", WHEREGO_PLUGIN_FILE ), + array( 'wp-edit-blocks' ), + filemtime( WHEREGO_PLUGIN_DIR . "css/{$style}{$file_prefix}.css" ) + ); + wp_add_inline_style( 'followed-posts-block-editor', $extra_css ); + } + } +} diff --git a/includes/frontend/blocks/followed-posts/block.json b/includes/frontend/blocks/followed-posts/block.json new file mode 100644 index 0000000..3b04e34 --- /dev/null +++ b/includes/frontend/blocks/followed-posts/block.json @@ -0,0 +1,58 @@ +{ + "$schema": "https://schemas.wp.org/trunk/block.json", + "apiVersion": 2, + "name": "webberzone/followed-posts", + "version": "1.0.0", + "title": "WebberZone Followed Posts", + "category": "widgets", + "icon": "editor-ul", + "keywords": ["followed posts", "posts", "where did they go from here"], + "description": "Display the Followed Posts", + "supports": { + "html": false + }, + "attributes": { + "className": { + "type": "string", + "default": "" + }, + "heading": { + "type": "boolean", + "default": false + }, + "title": { + "type": "string", + "default": "

Followed Posts

" + }, + "limit": { + "type": "string", + "default": 6 + }, + "show_excerpt": { + "type": "boolean", + "default": false + }, + "show_author": { + "type": "boolean", + "default": false + }, + "show_date": { + "type": "boolean", + "default": false + }, + "wherego_styles": { + "type": "string", + "default": "no_style" + }, + "post_thumb_op": { + "type": "string", + "default": "inline" + }, + "other_attributes": { + "type": "string", + "default": "" + } + }, + "textdomain": "where-did-they-go-from-here", + "editorScript": "file:./build/index.js" +} diff --git a/includes/frontend/blocks/followed-posts/build/index.asset.php b/includes/frontend/blocks/followed-posts/build/index.asset.php new file mode 100644 index 0000000..967ef26 --- /dev/null +++ b/includes/frontend/blocks/followed-posts/build/index.asset.php @@ -0,0 +1 @@ + array('wp-block-editor', 'wp-blocks', 'wp-components', 'wp-element', 'wp-i18n', 'wp-server-side-render'), 'version' => 'd763022e25787b52c39f'); diff --git a/includes/frontend/blocks/followed-posts/build/index.js b/includes/frontend/blocks/followed-posts/build/index.js new file mode 100644 index 0000000..222d9f6 --- /dev/null +++ b/includes/frontend/blocks/followed-posts/build/index.js @@ -0,0 +1 @@ +!function(){"use strict";var e={n:function(t){var o=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(o,{a:o}),o},d:function(t,o){for(var l in o)e.o(o,l)&&!e.o(t,l)&&Object.defineProperty(t,l,{enumerable:!0,get:o[l]})},o:function(e,t){return Object.prototype.hasOwnProperty.call(e,t)}},t=window.wp.blocks,o=window.wp.element,l=window.wp.i18n,r=window.wp.serverSideRender,n=e.n(r),h=window.wp.blockEditor,a=window.wp.components;(0,t.registerBlockType)("webberzone/followed-posts",{edit:function({attributes:e,setAttributes:t}){const r=null===wp.data.select("core/editor")?0:wp.data.select("core/editor").getCurrentPostId(),{heading:d,title:i,limit:s,show_excerpt:_,show_author:w,show_date:m,wherego_styles:u,post_thumb_op:c,other_attributes:f}=e,g=(0,h.useBlockProps)();return(0,o.createElement)(o.Fragment,null,(0,o.createElement)(h.InspectorControls,null,(0,o.createElement)(a.PanelBody,{title:(0,l.__)("Followed Posts Settings","where-did-they-go-from-here"),initialOpen:!0},(0,o.createElement)(a.PanelRow,null,(0,o.createElement)("fieldset",null,(0,o.createElement)(a.ToggleControl,{label:(0,l.__)("Show heading","where-did-they-go-from-here"),help:d?(0,l.__)("Heading displayed","where-did-they-go-from-here"):(0,l.__)("No Heading displayed","where-did-they-go-from-here"),checked:d,onChange:()=>{t({heading:!d})}}))),d&&(0,o.createElement)(a.PanelRow,null,(0,o.createElement)(a.TextControl,{label:(0,l.__)("Heading of posts","where-did-they-go-from-here"),value:i,onChange:e=>{t({title:void 0===e?"":e})},help:(0,l.__)("Displayed before the list of the posts as a master heading. HTML allowed.","where-did-they-go-from-here")})),(0,o.createElement)(a.PanelRow,null,(0,o.createElement)("fieldset",null,(0,o.createElement)(a.TextControl,{label:(0,l.__)("Number of posts","where-did-they-go-from-here"),value:s,onChange:e=>{t({limit:void 0===e?"":e})},help:(0,l.__)("Maximum number of posts to display","where-did-they-go-from-here")}))),(0,o.createElement)(a.PanelRow,null,(0,o.createElement)("fieldset",null,(0,o.createElement)(a.ToggleControl,{label:(0,l.__)("Show excerpt","where-did-they-go-from-here"),help:_?(0,l.__)("Excerpt displayed","where-did-they-go-from-here"):(0,l.__)("No excerpt","where-did-they-go-from-here"),checked:_,onChange:()=>{t({show_excerpt:!_})}}))),(0,o.createElement)(a.PanelRow,null,(0,o.createElement)("fieldset",null,(0,o.createElement)(a.ToggleControl,{label:(0,l.__)("Show author","where-did-they-go-from-here"),help:w?(0,l.__)('"by Author Name" displayed',"where-did-they-go-from-here"):(0,l.__)("No author displayed","where-did-they-go-from-here"),checked:w,onChange:()=>{t({show_author:!w})}}))),(0,o.createElement)(a.PanelRow,null,(0,o.createElement)("fieldset",null,(0,o.createElement)(a.ToggleControl,{label:(0,l.__)("Show date","where-did-they-go-from-here"),help:m?(0,l.__)("Date of post displayed","where-did-they-go-from-here"):(0,l.__)("Date of post not displayed","where-did-they-go-from-here"),checked:m,onChange:()=>{t({show_date:!m})}}))),(0,o.createElement)(a.PanelRow,null,(0,o.createElement)("fieldset",null,(0,o.createElement)(a.SelectControl,{label:(0,l.__)("Styles","where-did-they-go-from-here"),value:u,onChange:e=>{t({wherego_styles:e})},help:(0,l.__)("Select the style of the Followed Posts","where-did-they-go-from-here"),options:[{value:"no_style",label:(0,l.__)("No styles","where-did-they-go-from-here")},{value:"text_only",label:(0,l.__)("Text only","where-did-they-go-from-here")},{value:"grid",label:(0,l.__)("Grid Thumbnails","where-did-they-go-from-here")}]}))),(0,o.createElement)(a.PanelRow,null,(0,o.createElement)("fieldset",null,(0,o.createElement)(a.SelectControl,{label:(0,l.__)("Thumbnail option","where-did-they-go-from-here"),value:c,onChange:e=>{t({post_thumb_op:e})},help:(0,l.__)("Location of the post thumbnail","where-did-they-go-from-here"),options:[{value:"inline",label:(0,l.__)("Before title","where-did-they-go-from-here")},{value:"after",label:(0,l.__)("After title","where-did-they-go-from-here")},{value:"thumbs_only",label:(0,l.__)("Only thumbnail","where-did-they-go-from-here")},{value:"text_only",label:(0,l.__)("Only text","where-did-they-go-from-here")}]}))),(0,o.createElement)(a.PanelRow,null,(0,o.createElement)("fieldset",null,(0,o.createElement)(a.TextareaControl,{label:(0,l.__)("Other attributes","where-did-they-go-from-here"),value:f,onChange:e=>{t({other_attributes:void 0===e?"":e})},help:(0,l.__)("Enter other attributes in a URL-style string-query. e.g. post_types=post,page&link_nofollow=1&exclude_post_ids=5,6","where-did-they-go-from-here")}))))),(0,o.createElement)("div",{...g},r?(0,o.createElement)(a.Disabled,null,(0,o.createElement)(n(),{block:"webberzone/followed-posts",attributes:e})):(0,o.createElement)(a.Placeholder,{icon:"editor-ul",label:(0,l.__)("Followed Posts","where-did-they-go-from-here"),instructions:(0,l.__)("This is a placeholder for the followed posts block. Visit the front end of your site to see the followed posts.","where-did-they-go-from-here")})))},save(){return null}})}(); \ No newline at end of file diff --git a/includes/frontend/blocks/followed-posts/src/edit.js b/includes/frontend/blocks/followed-posts/src/edit.js new file mode 100644 index 0000000..1ace219 --- /dev/null +++ b/includes/frontend/blocks/followed-posts/src/edit.js @@ -0,0 +1,280 @@ +/** + * Retrieves the translation of text. + * + * @see https://developer.wordpress.org/block-editor/packages/packages-i18n/ + */ +import { __ } from '@wordpress/i18n'; + +import ServerSideRender from '@wordpress/server-side-render'; + +/** + * React hook that is used to mark the block wrapper element. + * It provides all the necessary props like the class name. + * + * @see https://developer.wordpress.org/block-editor/packages/packages-block-editor/#useBlockProps + */ +import { useBlockProps, InspectorControls } from '@wordpress/block-editor'; + +import { + Disabled, + TextControl, + TextareaControl, + ToggleControl, + PanelBody, + PanelRow, + SelectControl, + RadioControl, + Placeholder, +} from '@wordpress/components'; + +/** + * Lets webpack process CSS, SASS or SCSS files referenced in JavaScript files. + * Those files can contain any CSS code that gets applied to the editor. + * + * @see https://www.npmjs.com/package/@wordpress/scripts#using-css + */ +//import './editor.scss'; + +/** + * 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://developer.wordpress.org/block-editor/developers/block-api/block-edit-save/#edit + * + * @return {WPElement} Element to render. + */ +export default function Edit({ attributes, setAttributes }) { + const postId = + null === wp.data.select('core/editor') + ? 0 + : wp.data.select('core/editor').getCurrentPostId(); + const { + heading, + title, + limit, + show_excerpt, + show_author, + show_date, + wherego_styles, + post_thumb_op, + other_attributes, + } = attributes; + + const blockProps = useBlockProps(); + const toggleHeading = () => { + setAttributes({ heading: !heading }); + }; + const onChangeTitle = (newTitle) => { + setAttributes({ + title: undefined === newTitle ? '' : newTitle, + }); + }; + const onChangeLimit = (newLimit) => { + setAttributes({ + limit: undefined === newLimit ? '' : newLimit, + }); + }; + const toggleShowExcerpt = () => { + setAttributes({ show_excerpt: !show_excerpt }); + }; + const toggleShowAuthor = () => { + setAttributes({ show_author: !show_author }); + }; + const toggleShowDate = () => { + setAttributes({ show_date: !show_date }); + }; + const onChangeThumbnail = (newThumbnailLoc) => { + setAttributes({ post_thumb_op: newThumbnailLoc }); + }; + const onChangePostStyle = (newPostStyle) => { + setAttributes({ wherego_styles: newPostStyle }); + }; + const onChangeOtherAttributes = (newOtherAttributes) => { + setAttributes({ + other_attributes: + undefined === newOtherAttributes ? '' : newOtherAttributes, + }); + }; + + return ( + <> + + + +
+ +
+
+ {heading && ( + + + + )} + +
+ +
+
+ +
+ +
+
+ +
+ +
+
+ +
+ +
+
+ +
+ +
+
+ +
+ +
+
+ +
+ +
+
+
+
+ +
+ {!postId ? ( + + ) : ( + + + + )} +
+ + ); +} diff --git a/includes/frontend/blocks/followed-posts/src/index.js b/includes/frontend/blocks/followed-posts/src/index.js new file mode 100644 index 0000000..0a1dddf --- /dev/null +++ b/includes/frontend/blocks/followed-posts/src/index.js @@ -0,0 +1,27 @@ +/** + * Registers a new block provided a unique name and an object defining its behavior. + * + * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/ + */ +import { registerBlockType } from '@wordpress/blocks'; + +/** + * Internal dependencies + */ +import Edit from './edit'; + +/** + * Every block starts by registering a new block type definition. + * + * @see https://developer.wordpress.org/block-editor/reference-guides/block-api/block-registration/ + */ +registerBlockType('webberzone/followed-posts', { + /** + * @see ./edit.js + */ + edit: Edit, + + save() { + return null; + }, +}); diff --git a/includes/frontend/blocks/index.php b/includes/frontend/blocks/index.php new file mode 100644 index 0000000..8142269 --- /dev/null +++ b/includes/frontend/blocks/index.php @@ -0,0 +1 @@ + false, 'echo' => true, 'heading' => true, + 'extra_class' => '', ); $defaults = array_merge( $defaults, wherego_settings_defaults(), $wherego_settings ); @@ -99,10 +100,19 @@ public static function followed_posts( $args = array() ) { */ $results = apply_filters( 'get_wherego_posts_id', (array) $results, $args ); - $widget_class = $args['is_widget'] ? 'wherego_related_widget' : 'wherego_related '; - $shortcode_class = $args['is_shortcode'] ? 'wherego_related_shortcode ' : ''; - - $post_classes = $widget_class . $shortcode_class; + // Override wherego_styles if post_thumb_op is text_only. + $args['wherego_styles'] = ( 'text_only' === $args['post_thumb_op'] ) ? 'text_only' : $args['wherego_styles']; + $style_array = Styles_Handler::get_style( $args['wherego_styles'] ); + + $post_classes = array( + 'main' => 'wz-followed-posts', + 'widget' => $args['is_widget'] ? 'wherego_related_widget wz-followed-posts-widget' : 'wherego_related', + 'shortcode' => $args['is_shortcode'] ? 'wherego_related_shortcode wz-followed-posts-shortcode' : '', + 'block' => $args['is_block'] ? 'wz-followed-posts-block' : '', + 'extra_class' => $args['extra_class'], + 'style' => ! empty( $style_array['name'] ) ? 'wz-followed-posts-' . $style_array['name'] : '', + ); + $post_classes = join( ' ', $post_classes ); /** * Filter the classes added to the div wrapper of the WebberZone Followed Posts. @@ -183,12 +193,20 @@ public static function followed_posts( $args = array() ) { } else { $output .= ( $args['blank_output'] ) ? ' ' : '

' . $args['blank_output_text'] . '

'; + $output .= $args['is_block'] ? __( + 'This is a placeholder for the followed posts block. There are no followed posts to display.', + 'where-did-they-go-from-here' + ) : ''; }// End if. // Check if the opening list tag is missing in the output, it means all of our results were eliminated cause of the category filter. if ( false === ( strpos( $output, $args['before_list_item'] ) ) ) { $output = ''; // Closing div of 'wherego_related'. diff --git a/includes/frontend/class-styles-handler.php b/includes/frontend/class-styles-handler.php index efd5ff1..72d3b05 100644 --- a/includes/frontend/class-styles-handler.php +++ b/includes/frontend/class-styles-handler.php @@ -43,7 +43,7 @@ public static function register_styles() { "wherego-style-{$style}", plugins_url( "includes/css/{$style}{$minimize}.css", WHEREGO_PLUGIN_FILE ), array(), - WZP_VERSION + WFP_VERSION ); wp_enqueue_style( "wherego-style-{$style}" ); wp_add_inline_style( "wherego-style-{$style}", $extra_css ); @@ -54,7 +54,7 @@ public static function register_styles() { 'wherego-custom-css', false, array(), - WZP_VERSION + WFP_VERSION ); // Load Custom CSS. diff --git a/readme.txt b/readme.txt index e1089cd..93163a5 100644 --- a/readme.txt +++ b/readme.txt @@ -23,6 +23,7 @@ __If you're looking for a plugin that displays posts related to the content, loo = Key features = * **Automatic**: The plugin will start displaying visited posts on your posts and pages automatically after the content when you activate the plugin +* **Block editor support**: Easy to use block for the block editor. Find it under widgets or using "followed posts" or "where did they go from here" * **Shortcode**: Use `[wherego]` to display the followed posts * **Multi-Widget support**: Find the __Followed posts__ widget to display the posts in your theme's sidebar or any other area that supports widgets. You can use the widget multiple times with different settings for each * **Manual install**: Want more control over placement? Check the [FAQ](https://wordpress.org/plugins/where-did-they-go-from-here/#faq) on which functions are available for manual install @@ -104,6 +105,7 @@ You can also use this function to display posts on any type of page generated by Complete plugin rewrite to use classes and autoloading. * Features + * New block for the block editor. Find it under widgets or using "followed posts" or "where did they go from here" * New functions `get_wfp()` and `the_wfp()` replace `get_wherego()` and `echo_wherego()`. The latter two will throw deprecated notices * New shortcode `[wfp]` replaces `[wherego]`. The latter will continue to work but it is recommended that you replace the shortcode * New tools page can be found under Tools > WFP Tools. Import/Export settings and clear the cache from there