Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
21 changes: 21 additions & 0 deletions lib/client-assets.php
Original file line number Diff line number Diff line change
Expand Up @@ -677,3 +677,24 @@ function gutenberg_extend_block_editor_preload_paths( $preload_paths, $post ) {
return $preload_paths;
}
add_filter( 'block_editor_preload_paths', 'gutenberg_extend_block_editor_preload_paths', 10, 2 );

/**
* Extends block editor settings to include a list of image dimensions per size.
*
* @param array $settings Default editor settings.
*
* @return array Filtered editor settings.
*/
function gutenberg_extend_settings_image_dimensions( $settings ) {
$image_dimensions = array();
$all_sizes = wp_get_registered_image_subsizes();
foreach ( $settings['imageSizes'] as $size ) {
$key = $size['slug'];
if ( isset( $all_sizes[ $key ] ) ) {
$image_dimensions[ $key ] = $all_sizes[ $key ];
}
}
$settings['imageDimensions'] = $image_dimensions;
return $settings;
}
add_filter( 'block_editor_settings', 'gutenberg_extend_settings_image_dimensions' );
147 changes: 141 additions & 6 deletions packages/block-library/src/latest-posts/edit.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
/**
* External dependencies
*/
import { isUndefined, pickBy } from 'lodash';
import { get, isUndefined, pickBy } from 'lodash';
import classnames from 'classnames';

/**
* WordPress dependencies
*/
import { Component, RawHTML } from '@wordpress/element';
import {
BaseControl,
PanelBody,
Placeholder,
QueryControls,
Expand All @@ -22,7 +23,12 @@ import apiFetch from '@wordpress/api-fetch';
import { addQueryArgs } from '@wordpress/url';
import { __ } from '@wordpress/i18n';
import { dateI18n, format, __experimentalGetSettings } from '@wordpress/date';
import { InspectorControls, BlockControls } from '@wordpress/block-editor';
import {
InspectorControls,
BlockAlignmentToolbar,
BlockControls,
__experimentalImageSizeControl as ImageSizeControl,
} from '@wordpress/block-editor';
import { withSelect } from '@wordpress/data';

/**
Expand Down Expand Up @@ -63,9 +69,17 @@ class LatestPostsEdit extends Component {
}

render() {
const { attributes, setAttributes, latestPosts } = this.props;
const {
attributes,
setAttributes,
imageSizeOptions,
latestPosts,
defaultImageWidth,
defaultImageHeight,
} = this.props;
const { categoriesList } = this.state;
const {
displayFeaturedImage,
displayPostContentRadio,
displayPostContent,
displayPostDate,
Expand All @@ -76,6 +90,10 @@ class LatestPostsEdit extends Component {
categories,
postsToShow,
excerptLength,
featuredImageAlign,
featuredImageSizeSlug,
featuredImageSizeWidth,
featuredImageSizeHeight,
} = attributes;

const inspectorControls = (
Expand Down Expand Up @@ -130,6 +148,62 @@ class LatestPostsEdit extends Component {
/>
</PanelBody>

<PanelBody title={ __( 'Featured Image Settings' ) }>
<ToggleControl
label={ __( 'Display featured image' ) }
checked={ displayFeaturedImage }
onChange={ ( value ) =>
setAttributes( { displayFeaturedImage: value } )
}
/>
{ displayFeaturedImage && (
<>
<ImageSizeControl
onChange={ ( value ) => {
const newAttrs = {};
if ( value.hasOwnProperty( 'width' ) ) {
newAttrs.featuredImageSizeWidth =
value.width;
}
if ( value.hasOwnProperty( 'height' ) ) {
newAttrs.featuredImageSizeHeight =
value.height;
}
setAttributes( newAttrs );
} }
slug={ featuredImageSizeSlug }
width={ featuredImageSizeWidth }
height={ featuredImageSizeHeight }
imageWidth={ defaultImageWidth }
imageHeight={ defaultImageHeight }
imageSizeOptions={ imageSizeOptions }
onChangeImage={ ( value ) =>
setAttributes( {
featuredImageSizeSlug: value,
featuredImageSizeWidth: undefined,
featuredImageSizeHeight: undefined,
} )
}
/>
<BaseControl>
<BaseControl.VisualLabel>
{ __( 'Image Alignment' ) }
</BaseControl.VisualLabel>
<BlockAlignmentToolbar
value={ featuredImageAlign }
onChange={ ( value ) =>
setAttributes( {
featuredImageAlign: value,
} )
}
controls={ [ 'left', 'center', 'right' ] }
isCollapsed={ false }
/>
</BaseControl>
</>
) }
</PanelBody>

<PanelBody title={ __( 'Sorting and filtering' ) }>
<QueryControls
{ ...{ order, orderBy } }
Expand Down Expand Up @@ -236,12 +310,35 @@ class LatestPostsEdit extends Component {

const excerptElement = document.createElement( 'div' );
excerptElement.innerHTML = excerpt;

excerpt =
excerptElement.textContent ||
excerptElement.innerText ||
'';

const imageSourceUrl = post.featuredImageSourceUrl;

const imageClasses = classnames( {
'wp-block-latest-posts__featured-image': true,
[ `align${ featuredImageAlign }` ]: !! featuredImageAlign,
} );

return (
<li key={ i }>
{ displayFeaturedImage && (
<div className={ imageClasses }>
{ imageSourceUrl && (
<img
src={ imageSourceUrl }
alt=""
style={ {
maxWidth: featuredImageSizeWidth,
maxHeight: featuredImageSizeHeight,
} }
/>
) }
</div>
) }
<a
href={ post.link }
target="_blank"
Expand Down Expand Up @@ -314,8 +411,16 @@ class LatestPostsEdit extends Component {
}

export default withSelect( ( select, props ) => {
const { postsToShow, order, orderBy, categories } = props.attributes;
const { getEntityRecords } = select( 'core' );
const {
featuredImageSizeSlug,
postsToShow,
order,
orderBy,
categories,
} = props.attributes;
const { getEntityRecords, getMedia } = select( 'core' );
const { getSettings } = select( 'core/block-editor' );
const { imageSizes, imageDimensions } = getSettings();
const latestPostsQuery = pickBy(
{
categories,
Expand All @@ -325,7 +430,37 @@ export default withSelect( ( select, props ) => {
},
( value ) => ! isUndefined( value )
);

const posts = getEntityRecords( 'postType', 'post', latestPostsQuery );
const imageSizeOptions = imageSizes
.filter( ( { slug } ) => slug !== 'full' )
.map( ( { name, slug } ) => ( { value: slug, label: name } ) );

return {
latestPosts: getEntityRecords( 'postType', 'post', latestPostsQuery ),
defaultImageWidth: imageDimensions[ featuredImageSizeSlug ].width,
defaultImageHeight: imageDimensions[ featuredImageSizeSlug ].height,
imageSizeOptions,
latestPosts: ! Array.isArray( posts )
? posts
: posts.map( ( post ) => {
if ( post.featured_media ) {
const image = getMedia( post.featured_media );
let url = get(
image,
[
'media_details',
'sizes',
featuredImageSizeSlug,
'source_url',
],
null
);
if ( ! url ) {
url = get( image, 'source_url', null );
}
return { ...post, featuredImageSourceUrl: url };
}
return post;
} ),
};
} )( LatestPostsEdit );
51 changes: 50 additions & 1 deletion packages/block-library/src/latest-posts/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,41 @@ function render_block_core_latest_posts( $attributes ) {
$list_items_markup = '';

foreach ( $recent_posts as $post ) {
$list_items_markup .= '<li>';

if ( $attributes['displayFeaturedImage'] && has_post_thumbnail( $post ) ) {
$image_style = '';
if ( isset( $attributes['featuredImageSizeWidth'] ) ) {
$image_style .= sprintf( 'max-width:%spx;', $attributes['featuredImageSizeWidth'] );
}
if ( isset( $attributes['featuredImageSizeHeight'] ) ) {
$image_style .= sprintf( 'max-height:%spx;', $attributes['featuredImageSizeHeight'] );
}

$image_classes = 'wp-block-latest-posts__featured-image';
if ( isset( $attributes['featuredImageAlign'] ) ) {
$image_classes .= ' align' . $attributes['featuredImageAlign'];
}

$list_items_markup .= sprintf(
'<div class="%1$s">%2$s</div>',
$image_classes,
get_the_post_thumbnail(
$post,
$attributes['featuredImageSizeSlug'],
array(
'style' => $image_style,
)
)
);
}

$title = get_the_title( $post );
if ( ! $title ) {
$title = __( '(no title)' );
}
$list_items_markup .= sprintf(
'<li><a href="%1$s">%2$s</a>',
'<a href="%1$s">%2$s</a>',
esc_url( get_permalink( $post ) ),
$title
);
Expand Down Expand Up @@ -164,6 +193,26 @@ function register_block_core_latest_posts() {
'type' => 'string',
'default' => 'date',
),
'displayFeaturedImage' => array(
'type' => 'boolean',
'default' => false,
),
'featuredImageAlign' => array(
'type' => 'string',
'enum' => array( 'left', 'center', 'right' ),
),
'featuredImageSizeSlug' => array(
'type' => 'string',
'default' => 'thumbnail',
),
'featuredImageSizeWidth' => array(
'type' => 'number',
'default' => null,
),
'featuredImageSizeHeight' => array(
'type' => 'number',
'default' => null,
),
),
'render_callback' => 'render_block_core_latest_posts',
)
Expand Down
23 changes: 23 additions & 0 deletions packages/block-library/src/latest-posts/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
}
&.wp-block-latest-posts__list {
list-style: none;

li {
clear: both;
}
}
&.is-grid {
display: flex;
Expand Down Expand Up @@ -40,3 +44,22 @@
margin-top: $grid-size;
margin-bottom: $grid-size-large;
}

.wp-block-latest-posts__featured-image {
img {
height: auto;
width: auto;
}
&.alignleft {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The alignleft and alignright classes are intended to be used with CSS float styles (and they probably shouldn't be called alignleft and alignright, but that's a whole other topic). This class style override is inconsistent with the usage of the class name elsewhere.

/*rtl:ignore*/
margin-right: 1em;
}
&.alignright {
/*rtl:ignore*/
margin-left: 1em;
}
&.aligncenter {
margin-bottom: 1em;
text-align: center;
}
}
1 change: 1 addition & 0 deletions packages/editor/src/components/provider/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ class EditorProvider extends Component {
'hasFixedToolbar',
'hasPermissionsToManageWidgets',
'imageSizes',
'imageDimensions',
'isRTL',
'maxWidth',
'styles',
Expand Down