Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new RSS Block #7966

Merged
merged 49 commits into from
Jan 25, 2019
Merged
Show file tree
Hide file tree
Changes from 39 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
d7aebf0
Add new RSS Block
Soean Jul 14, 2018
ecd088e
Small improvements
Soean Jul 14, 2018
79dae56
Better error handling
Soean Jul 14, 2018
a4742cb
Show errors
Soean Jul 14, 2018
f011250
Add Grid
Soean Jul 14, 2018
306b927
Dont call own domain
Soean Jul 14, 2018
8dc68e6
Add tests
Soean Jul 15, 2018
f7367bb
Better error handling
Soean Jul 15, 2018
3d6d6d0
Add Disable around SSR
Soean Jul 16, 2018
1cebeb3
Rename post to item
Soean Jul 16, 2018
c6af0b5
Fix small bugs
Soean Jul 16, 2018
3127274
Merge master
Soean Oct 8, 2018
bde9cdf
Move files to npm package
Soean Oct 8, 2018
9b6fa9b
Fix Stylelint error
Soean Oct 8, 2018
2ea6af7
update tests
Soean Oct 9, 2018
b62d3de
Merge branch 'master' into add/rss-block
Soean Oct 9, 2018
5cd2d19
Adjust new folder structure
Soean Oct 9, 2018
8592be5
Remove scss from Js
Soean Oct 9, 2018
f4c7fd4
check if function exists in core
Soean Dec 17, 2018
050691a
Merge branch 'master' into add/rss-block
Soean Dec 17, 2018
9322f7e
Merge master
Soean Dec 17, 2018
b1bff5b
Update tests
Soean Dec 17, 2018
43968d5
Merge branch 'add/rss-block' of https://github.com/WordPress/gutenber…
Soean Dec 17, 2018
5296a22
remove manifest
Soean Dec 17, 2018
25af2cf
manifest
Soean Dec 17, 2018
2cea7c2
Merge branch 'master' into add/rss-block
Soean Jan 7, 2019
41f2be7
Merge branch 'master' into add/rss-block
Soean Jan 21, 2019
d13685d
Fix phpcs error
Soean Jan 21, 2019
75813f6
catch empty url
Soean Jan 22, 2019
0f24169
review changes part 1
Soean Jan 23, 2019
7cdaf0e
Add keywords
Soean Jan 23, 2019
99ccab3
Review changes
Soean Jan 23, 2019
e342195
review changes
Soean Jan 23, 2019
62f56e5
classes check
Soean Jan 23, 2019
b2c1c0e
Remove filter_var functions
Soean Jan 23, 2019
8daef24
Remove `render_rss_error_message`
Soean Jan 23, 2019
275c12d
fix regression
Soean Jan 23, 2019
4d66b91
remove class from error message
Soean Jan 23, 2019
7f9ee11
Toolbar controls
Soean Jan 23, 2019
0514204
php improvements
Soean Jan 24, 2019
10fdc94
remove defaults in render function
Soean Jan 24, 2019
25b87d0
php improvement
Soean Jan 24, 2019
163d69f
Fix phpcs warnings
Soean Jan 24, 2019
010ac1e
remove unnecessary code
Soean Jan 24, 2019
16a4d9f
Remove old code for PHP 5.2
Soean Jan 24, 2019
ccd5fb7
PHP 5.2 compatibility
Soean Jan 24, 2019
e8f0f89
Add comment fot PHP 5.2
Soean Jan 24, 2019
08e8302
Fix PHPCS
Soean Jan 24, 2019
5cfcbeb
Change package to WordPress
Soean Jan 24, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions lib/load.php
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,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';
}
1 change: 1 addition & 0 deletions packages/block-library/src/editor.scss
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down
2 changes: 2 additions & 0 deletions packages/block-library/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -85,6 +86,7 @@ export const registerCoreBlocks = () => {
nextpage,
preformatted,
pullquote,
rss,
separator,
reusableBlock,
spacer,
Expand Down
172 changes: 172 additions & 0 deletions packages/block-library/src/rss/edit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
/**
* 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 (
<Placeholder
icon="rss"
label="RSS"
>
<form onSubmit={ this.onSubmitURL }>
<TextControl
placeholder={ __( 'Enter URL here…' ) }
value={ feedURL }
onChange={ ( value ) => setAttributes( { feedURL: value } ) }
className={ 'components-placeholder__input' }
/>
<Button
isLarge
type="submit">
Soean marked this conversation as resolved.
Show resolved Hide resolved
{ __( 'Use URL' ) }
</Button>
</form>
</Placeholder>
);
}

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 (
<Fragment>
<BlockControls>
<Toolbar controls={ toolbarControls } />
</BlockControls>
<InspectorControls>
<PanelBody title={ __( 'RSS Settings' ) }>
<RangeControl
label={ __( 'Number of items' ) }
value={ itemsToShow }
onChange={ ( value ) => setAttributes( { itemsToShow: value } ) }
min={ DEFAULT_MIN_ITEMS }
max={ DEFAULT_MAX_ITEMS }
/>
<ToggleControl
label={ __( 'Display author' ) }
checked={ displayAuthor }
onChange={ this.toggleAttribute( 'displayAuthor' ) }
/>
<ToggleControl
label={ __( 'Display date' ) }
checked={ displayDate }
onChange={ this.toggleAttribute( 'displayDate' ) }
/>
<ToggleControl
label={ __( 'Display excerpt' ) }
checked={ displayExcerpt }
onChange={ this.toggleAttribute( 'displayExcerpt' ) }
/>
{ displayExcerpt &&
<RangeControl
label={ __( 'Max length of the excerpt' ) }
value={ excerptLength }
onChange={ ( value ) => setAttributes( { excerptLength: value } ) }
min={ 0 }
max={ 100 }
step={ 1 }
Soean marked this conversation as resolved.
Show resolved Hide resolved
/>
}
{ blockLayout === 'grid' &&
<RangeControl
label={ __( 'Columns' ) }
value={ columns }
onChange={ ( value ) => setAttributes( { columns: value } ) }
min={ 2 }
max={ 6 }
/>
}
</PanelBody>
</InspectorControls>
<Disabled>
<ServerSideRender
block="core/rss"
attributes={ this.props.attributes }
/>
</Disabled>
</Fragment>
);
}
}

export default RSSEdit;
6 changes: 6 additions & 0 deletions packages/block-library/src/rss/editor.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.block-editor .wp-block-rss {
padding-left: 2.5em;
&.is-grid {
padding-left: 0;
}
}
33 changes: 33 additions & 0 deletions packages/block-library/src/rss/index.js
Original file line number Diff line number Diff line change
@@ -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;
},
};
144 changes: 144 additions & 0 deletions packages/block-library/src/rss/index.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
<?php
/**
* Server-side rendering of the `core/rss` block.
*
* @package gutenberg
Soean marked this conversation as resolved.
Show resolved Hide resolved
*/

/**
* Renders the `core/rss` block on server.
*
* @param array $attributes The block attributes.
*
* @return string Returns the block content with received rss items.
*/
function render_block_core_rss( $attributes ) {

if ( ! isset( $attributes['feedURL'] ) ) {
return;
}

$rss = fetch_feed( $attributes['feedURL'] );

if ( is_wp_error( $rss ) ) {
return '<div class="components-placeholder"><div class="notice notice-error"><strong>' . __( 'RSS Error:', 'gutenberg' ) . '</strong> ' . $rss->get_error_message() . '</div></div>';
}

if ( ! $rss->get_item_quantity() ) {
$rss->__destruct();
Soean marked this conversation as resolved.
Show resolved Hide resolved
unset( $rss );
Soean marked this conversation as resolved.
Show resolved Hide resolved
return '<div class="components-placeholder"><div class="notice notice-error">' . __( 'An error has occurred, which probably means the feed is down. Try again later.', 'gutenberg' ) . '</div></div>';
}

$items = (int) $attributes['itemsToShow'];
if ( $items < 1 || 10 < $items ) {
$items = 5;
Soean marked this conversation as resolved.
Show resolved Hide resolved
}

$list_items = '';
foreach ( $rss->get_items( 0, $items ) as $item ) {
$title = esc_html( trim( strip_tags( $item->get_title() ) ) );
if ( empty( $title ) ) {
$title = __( '(Untitled)', 'gutenberg' );
}

$link = $item->get_link();
$link = esc_url( strip_tags( $link ) );
Soean marked this conversation as resolved.
Show resolved Hide resolved
if ( $link ) {
$title = "<a href='$link'>$title</a>";
}

$title = "<div class='wp-block-rss__item-title'>$title</div>";

$date = '';
if ( $attributes['displayDate'] ) {
$date = $item->get_date( 'U' );

if ( $date ) {
$date = sprintf(
'<time datetime="%1$s" class="wp-block-rss__item-publish-date">%2$s</time> ',
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 = '<span class="wp-block-rss__item-author">' . __( 'by', 'gutenberg' ) . ' ' . esc_html( strip_tags( $author ) ) . '</span>';
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do you feel about combining the author and date into a single sentence and capitalising the b in by when the author is enabled but the date is disabled?

$date = '';
if ( $attributes['displayDate'] ) {
	$date = $item->get_date( 'U' );

	if ( $date ) {
		$date = sprintf(
			'<time datetime="%1$s">%2$s</time> ',
			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 = esc_html( strip_tags( $author ) );
	}
}

$byline = '';
if ( $date && $author ) {
	$byline = '<span class="wp-block-rss__byline>' . sprintf( __( '%s by %s' ), $date, $author ) . '</span>';
} elseif ( $date ) {
	$byline = '<span class="wp-block-rss__byline>' . $date . '</span>';
} elseif( $author ) {
	$byline = '<span class="wp-block-rss__byline>' . sprintf( __( 'By %s' ), $author ) . '</span>';
}


$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'], ' [&hellip;]' ) );

// Change existing [...] to [&hellip;].
if ( '[...]' == substr( $excerpt, -5 ) ) {
$excerpt = substr( $excerpt, 0, -5 ) . '[&hellip;]';
}

$excerpt = '<div class="wp-block-rss__item-excerpt">' . esc_html( $excerpt ) . '</div>';
}

$list_items .= "<li class='wp-block-rss__item'>{$title}{$date}{$author}{$excerpt}</li>";
}

$classes = 'grid' === $attributes['blockLayout'] ? 'is-grid columns-' . $attributes['columns'] : '';

$list_items_markup = "<ul class='wp-block-rss {$classes}'>{$list_items}</ul>";

$rss->__destruct();
unset( $rss );
Soean marked this conversation as resolved.
Show resolved Hide resolved
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',
),
'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' );
Loading