From be9870de7d289fd5edb9e935cc46f7f8ba228cca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6ren=20Wrede?= Date: Fri, 25 Jan 2019 10:09:41 +0100 Subject: [PATCH] Add new RSS Block (#7966) --- lib/load.php | 3 + packages/block-library/src/editor.scss | 1 + packages/block-library/src/index.js | 2 + packages/block-library/src/rss/edit.js | 169 ++++++++++++++++++ packages/block-library/src/rss/editor.scss | 6 + packages/block-library/src/rss/index.js | 33 ++++ packages/block-library/src/rss/index.php | 137 ++++++++++++++ packages/block-library/src/rss/style.scss | 35 ++++ packages/block-library/src/style.scss | 1 + .../full-content/fixtures/core__rss.html | 1 + .../full-content/fixtures/core__rss.json | 10 ++ .../fixtures/core__rss.parsed.json | 26 +++ .../fixtures/core__rss.serialized.html | 1 + 13 files changed, 425 insertions(+) create mode 100644 packages/block-library/src/rss/edit.js create mode 100644 packages/block-library/src/rss/editor.scss create mode 100644 packages/block-library/src/rss/index.js create mode 100644 packages/block-library/src/rss/index.php create mode 100644 packages/block-library/src/rss/style.scss create mode 100644 test/integration/full-content/fixtures/core__rss.html create mode 100644 test/integration/full-content/fixtures/core__rss.json create mode 100644 test/integration/full-content/fixtures/core__rss.parsed.json create mode 100644 test/integration/full-content/fixtures/core__rss.serialized.html diff --git a/lib/load.php b/lib/load.php index 8306f6f030f83b..ada0850ce4163f 100644 --- a/lib/load.php +++ b/lib/load.php @@ -43,6 +43,9 @@ if ( ! function_exists( 'render_block_core_latest_posts' ) ) { require dirname( __FILE__ ) . '/../packages/block-library/src/latest-posts/index.php'; } +if ( ! function_exists( 'render_block_core_rss' ) ) { + require dirname( __FILE__ ) . '/../packages/block-library/src/rss/index.php'; +} if ( ! function_exists( 'render_block_core_shortcode' ) ) { require dirname( __FILE__ ) . '/../packages/block-library/src/shortcode/index.php'; } diff --git a/packages/block-library/src/editor.scss b/packages/block-library/src/editor.scss index eb2dea826189bd..9fb94f40bdef7c 100644 --- a/packages/block-library/src/editor.scss +++ b/packages/block-library/src/editor.scss @@ -22,6 +22,7 @@ @import "./preformatted/editor.scss"; @import "./pullquote/editor.scss"; @import "./quote/editor.scss"; +@import "./rss/editor.scss"; @import "./shortcode/editor.scss"; @import "./spacer/editor.scss"; @import "./subhead/editor.scss"; diff --git a/packages/block-library/src/index.js b/packages/block-library/src/index.js index ecb354f8c373e5..5dd3fee7b2a29d 100644 --- a/packages/block-library/src/index.js +++ b/packages/block-library/src/index.js @@ -38,6 +38,7 @@ import * as nextpage from './nextpage'; import * as preformatted from './preformatted'; import * as pullquote from './pullquote'; import * as reusableBlock from './block'; +import * as rss from './rss'; import * as separator from './separator'; import * as shortcode from './shortcode'; import * as spacer from './spacer'; @@ -85,6 +86,7 @@ export const registerCoreBlocks = () => { nextpage, preformatted, pullquote, + rss, separator, reusableBlock, spacer, diff --git a/packages/block-library/src/rss/edit.js b/packages/block-library/src/rss/edit.js new file mode 100644 index 00000000000000..9ebfa94491533b --- /dev/null +++ b/packages/block-library/src/rss/edit.js @@ -0,0 +1,169 @@ +/** + * WordPress dependencies + */ +import { Component, Fragment } from '@wordpress/element'; +import { + Button, + Disabled, + PanelBody, + Placeholder, + RangeControl, + ServerSideRender, + TextControl, + ToggleControl, + Toolbar, +} from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; +import { + BlockControls, + InspectorControls, +} from '@wordpress/editor'; + +const DEFAULT_MIN_ITEMS = 1; +const DEFAULT_MAX_ITEMS = 10; + +class RSSEdit extends Component { + constructor() { + super( ...arguments ); + + this.state = { + editing: ! this.props.attributes.feedURL, + }; + + this.toggleAttribute = this.toggleAttribute.bind( this ); + this.onSubmitURL = this.onSubmitURL.bind( this ); + } + + toggleAttribute( propName ) { + return () => { + const value = this.props.attributes[ propName ]; + const { setAttributes } = this.props; + + setAttributes( { [ propName ]: ! value } ); + }; + } + + onSubmitURL( event ) { + event.preventDefault(); + + const { feedURL } = this.props.attributes; + if ( feedURL ) { + this.setState( { editing: false } ); + } + } + + render() { + const { + blockLayout, + columns, + displayAuthor, + displayExcerpt, + displayDate, + excerptLength, + feedURL, + itemsToShow, + } = this.props.attributes; + const { setAttributes } = this.props; + + if ( this.state.editing ) { + return ( + +
+ setAttributes( { feedURL: value } ) } + className={ 'components-placeholder__input' } + /> + + +
+ ); + } + + const toolbarControls = [ + { + icon: 'edit', + title: __( 'Edit RSS URL' ), + onClick: () => this.setState( { editing: true } ), + }, + { + icon: 'list-view', + title: __( 'List View' ), + onClick: () => setAttributes( { blockLayout: 'list' } ), + isActive: blockLayout === 'list', + }, + { + icon: 'grid-view', + title: __( 'Grid View' ), + onClick: () => setAttributes( { blockLayout: 'grid' } ), + isActive: blockLayout === 'grid', + }, + ]; + + return ( + + + + + + + setAttributes( { itemsToShow: value } ) } + min={ DEFAULT_MIN_ITEMS } + max={ DEFAULT_MAX_ITEMS } + /> + + + + { displayExcerpt && + setAttributes( { excerptLength: value } ) } + min={ 0 } + max={ 100 } + /> + } + { blockLayout === 'grid' && + setAttributes( { columns: value } ) } + min={ 2 } + max={ 6 } + /> + } + + + + + + + ); + } +} + +export default RSSEdit; diff --git a/packages/block-library/src/rss/editor.scss b/packages/block-library/src/rss/editor.scss new file mode 100644 index 00000000000000..8632c5e101b005 --- /dev/null +++ b/packages/block-library/src/rss/editor.scss @@ -0,0 +1,6 @@ +.block-editor .wp-block-rss { + padding-left: 2.5em; + &.is-grid { + padding-left: 0; + } +} diff --git a/packages/block-library/src/rss/index.js b/packages/block-library/src/rss/index.js new file mode 100644 index 00000000000000..6a0f916c7d6e5b --- /dev/null +++ b/packages/block-library/src/rss/index.js @@ -0,0 +1,33 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import edit from './edit'; + +export const name = 'core/rss'; + +export const settings = { + title: __( 'RSS' ), + + description: __( 'Display entries from any RSS or Atom feed.' ), + + icon: 'rss', + + category: 'widgets', + + keywords: [ __( 'atom' ), __( 'feed' ) ], + + supports: { + html: false, + }, + + edit, + + save() { + return null; + }, +}; diff --git a/packages/block-library/src/rss/index.php b/packages/block-library/src/rss/index.php new file mode 100644 index 00000000000000..b5fe3abaf563be --- /dev/null +++ b/packages/block-library/src/rss/index.php @@ -0,0 +1,137 @@ +
' . __( 'RSS Error:' ) . ' ' . $rss->get_error_message() . '
'; + } + + if ( ! $rss->get_item_quantity() ) { + // PHP 5.2 compatibility. See: http://simplepie.org/wiki/faq/i_m_getting_memory_leaks. + $rss->__destruct(); + unset( $rss ); + + return '
' . __( 'An error has occurred, which probably means the feed is down. Try again later.' ) . '
'; + } + + $rss_items = $rss->get_items( 0, $attributes['itemsToShow'] ); + $list_items = ''; + foreach ( $rss_items as $item ) { + $title = esc_html( trim( strip_tags( $item->get_title() ) ) ); + if ( empty( $title ) ) { + $title = __( '(Untitled)' ); + } + $link = $item->get_link(); + $link = esc_url( $link ); + if ( $link ) { + $title = "{$title}"; + } + $title = "
{$title}
"; + + $date = ''; + if ( $attributes['displayDate'] ) { + $date = $item->get_date( 'U' ); + + if ( $date ) { + $date = sprintf( + ' ', + date_i18n( get_option( 'c' ), $date ), + date_i18n( get_option( 'date_format' ), $date ) + ); + } + } + + $author = ''; + if ( $attributes['displayAuthor'] ) { + $author = $item->get_author(); + if ( is_object( $author ) ) { + $author = $author->get_name(); + $author = '' . __( 'by' ) . ' ' . esc_html( strip_tags( $author ) ) . ''; + } + } + + $excerpt = ''; + if ( $attributes['displayExcerpt'] ) { + $excerpt = html_entity_decode( $item->get_description(), ENT_QUOTES, get_option( 'blog_charset' ) ); + $excerpt = esc_attr( wp_trim_words( $excerpt, $attributes['excerptLength'], ' […]' ) ); + + // Change existing [...] to […]. + if ( '[...]' == substr( $excerpt, -5 ) ) { + $excerpt = substr( $excerpt, 0, -5 ) . '[…]'; + } + + $excerpt = '
' . esc_html( $excerpt ) . '
'; + } + + $list_items .= "
  • {$title}{$date}{$author}{$excerpt}
  • "; + } + + $classes = 'grid' === $attributes['blockLayout'] ? ' is-grid columns-' . $attributes['columns'] : ''; + $list_items_markup = ""; + + // PHP 5.2 compatibility. See: http://simplepie.org/wiki/faq/i_m_getting_memory_leaks. + $rss->__destruct(); + unset( $rss ); + + return $list_items_markup; +} + +/** + * Registers the `core/rss` block on server. + */ +function register_block_core_rss() { + register_block_type( 'core/rss', + array( + 'attributes' => array( + 'columns' => array( + 'type' => 'number', + 'default' => 2, + ), + 'blockLayout' => array( + 'type' => 'string', + 'default' => 'list', + ), + 'feedURL' => array( + 'type' => 'string', + 'default' => '', + ), + 'itemsToShow' => array( + 'type' => 'number', + 'default' => 5, + ), + 'displayExcerpt' => array( + 'type' => 'boolean', + 'default' => false, + ), + 'displayAuthor' => array( + 'type' => 'boolean', + 'default' => false, + ), + 'displayDate' => array( + 'type' => 'boolean', + 'default' => false, + ), + 'excerptLength' => array( + 'type' => 'number', + 'default' => 55, + ), + ), + 'render_callback' => 'render_block_core_rss', + ) + ); +} + +add_action( 'init', 'register_block_core_rss' ); diff --git a/packages/block-library/src/rss/style.scss b/packages/block-library/src/rss/style.scss new file mode 100644 index 00000000000000..a2ad8d4060dfff --- /dev/null +++ b/packages/block-library/src/rss/style.scss @@ -0,0 +1,35 @@ +.wp-block-rss { + &.alignleft { + /*rtl:ignore*/ + margin-right: 2em; + } + &.alignright { + /*rtl:ignore*/ + margin-left: 2em; + } + &.is-grid { + display: flex; + flex-wrap: wrap; + padding: 0; + list-style: none; + + li { + margin: 0 16px 16px 0; + width: 100%; + } + } + + @include break-small { + @for $i from 2 through 6 { + &.columns-#{ $i } li { + width: calc(( 100% / #{ $i } ) - 16px); + } + } + } +} + +.wp-block-rss__item-publish-date, +.wp-block-rss__item-author { + color: $dark-gray-300; + font-size: $default-font-size; +} diff --git a/packages/block-library/src/style.scss b/packages/block-library/src/style.scss index 9d9b2379696b2f..09d3a2125e378b 100644 --- a/packages/block-library/src/style.scss +++ b/packages/block-library/src/style.scss @@ -15,6 +15,7 @@ @import "./paragraph/style.scss"; @import "./pullquote/style.scss"; @import "./quote/style.scss"; +@import "./rss/style.scss"; @import "./separator/style.scss"; @import "./subhead/style.scss"; @import "./table/style.scss"; diff --git a/test/integration/full-content/fixtures/core__rss.html b/test/integration/full-content/fixtures/core__rss.html new file mode 100644 index 00000000000000..ce652528301c6f --- /dev/null +++ b/test/integration/full-content/fixtures/core__rss.html @@ -0,0 +1 @@ + diff --git a/test/integration/full-content/fixtures/core__rss.json b/test/integration/full-content/fixtures/core__rss.json new file mode 100644 index 00000000000000..89de06cd2d78d5 --- /dev/null +++ b/test/integration/full-content/fixtures/core__rss.json @@ -0,0 +1,10 @@ +[ + { + "clientId": "_clientId_0", + "name": "core/rss", + "isValid": true, + "attributes": {}, + "innerBlocks": [], + "originalContent": "" + } +] diff --git a/test/integration/full-content/fixtures/core__rss.parsed.json b/test/integration/full-content/fixtures/core__rss.parsed.json new file mode 100644 index 00000000000000..bdc596b09a5a1b --- /dev/null +++ b/test/integration/full-content/fixtures/core__rss.parsed.json @@ -0,0 +1,26 @@ +[ + { + "blockName": "core/rss", + "attrs": { + "postLayout": "grid", + "feedURL": "https://wordpress.org/news/", + "postsToShow": 4, + "displayExcerpt": true, + "displayAuthor": true, + "displayDate": true, + "excerptLength": 20 + }, + "innerBlocks": [], + "innerHTML": "", + "innerContent": [] + }, + { + "blockName": null, + "attrs": {}, + "innerBlocks": [], + "innerHTML": "\n", + "innerContent": [ + "\n" + ] + } +] diff --git a/test/integration/full-content/fixtures/core__rss.serialized.html b/test/integration/full-content/fixtures/core__rss.serialized.html new file mode 100644 index 00000000000000..c6d9be22646e74 --- /dev/null +++ b/test/integration/full-content/fixtures/core__rss.serialized.html @@ -0,0 +1 @@ +