@automattic/newspack-blocks 4.24.1 → 4.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -0
- package/dist/author-profile/view-rtl.css +1 -1
- package/dist/author-profile/view.asset.php +1 -1
- package/dist/author-profile/view.css +1 -1
- package/dist/blocks/author-list/block.json +2 -1
- package/dist/blocks/author-profile/block.json +18 -1
- package/dist/blocks/carousel/block.json +2 -1
- package/dist/blocks/donate/block.json +2 -1
- package/dist/blocks/homepage-articles/block.json +2 -1
- package/dist/blocks/iframe/block.json +2 -1
- package/dist/editor-rtl.css +2 -2
- package/dist/editor.asset.php +1 -1
- package/dist/editor.css +2 -2
- package/dist/editor.js +23 -19
- package/dist/placeholder_blocks.asset.php +1 -1
- package/dist/placeholder_blocks.js +1 -1
- package/includes/class-modal-checkout.php +43 -11
- package/includes/class-newspack-blocks-caching.php +13 -1
- package/includes/class-newspack-blocks.php +14 -7
- package/languages/newspack-blocks-de_DE-2d52b39fdbc5d6c94b3514803f3720b8.json +1 -1
- package/languages/newspack-blocks-de_DE-34e5c64f90b1444f3fc735376442eada.json +1 -1
- package/languages/newspack-blocks-de_DE-4fdea541976076f02d56139fb35e5b42.json +1 -1
- package/languages/newspack-blocks-de_DE-53e2a1d5945b8d2b1c35e81ae1e532f3.json +1 -1
- package/languages/newspack-blocks-de_DE-78456b164809d080adecb4d2b3895802.json +1 -1
- package/languages/newspack-blocks-de_DE-9ef9b2c60c897ad79f92951e6e9949a1.json +1 -1
- package/languages/newspack-blocks-de_DE-eccbc51a43c04f59165364eda71e0be7.json +1 -1
- package/languages/newspack-blocks-de_DE-fbe7f8c598cf05d4603ba49fec909ded.json +1 -1
- package/languages/newspack-blocks-de_DE.po +594 -493
- package/languages/newspack-blocks-es_ES-2d52b39fdbc5d6c94b3514803f3720b8.json +1 -1
- package/languages/newspack-blocks-es_ES-34e5c64f90b1444f3fc735376442eada.json +1 -1
- package/languages/newspack-blocks-es_ES-4fdea541976076f02d56139fb35e5b42.json +1 -1
- package/languages/newspack-blocks-es_ES-53e2a1d5945b8d2b1c35e81ae1e532f3.json +1 -1
- package/languages/newspack-blocks-es_ES-78456b164809d080adecb4d2b3895802.json +1 -1
- package/languages/newspack-blocks-es_ES-9ef9b2c60c897ad79f92951e6e9949a1.json +1 -1
- package/languages/newspack-blocks-es_ES-eccbc51a43c04f59165364eda71e0be7.json +1 -1
- package/languages/newspack-blocks-es_ES-fbe7f8c598cf05d4603ba49fec909ded.json +1 -1
- package/languages/newspack-blocks-es_ES.po +594 -493
- package/languages/newspack-blocks-fr_BE-2d52b39fdbc5d6c94b3514803f3720b8.json +1 -1
- package/languages/newspack-blocks-fr_BE-34e5c64f90b1444f3fc735376442eada.json +1 -1
- package/languages/newspack-blocks-fr_BE-4fdea541976076f02d56139fb35e5b42.json +1 -1
- package/languages/newspack-blocks-fr_BE-53e2a1d5945b8d2b1c35e81ae1e532f3.json +1 -1
- package/languages/newspack-blocks-fr_BE-78456b164809d080adecb4d2b3895802.json +1 -1
- package/languages/newspack-blocks-fr_BE-9ef9b2c60c897ad79f92951e6e9949a1.json +1 -1
- package/languages/newspack-blocks-fr_BE-eccbc51a43c04f59165364eda71e0be7.json +1 -1
- package/languages/newspack-blocks-fr_BE-fbe7f8c598cf05d4603ba49fec909ded.json +1 -1
- package/languages/newspack-blocks-fr_BE.po +594 -493
- package/languages/newspack-blocks-nb_NO-2d52b39fdbc5d6c94b3514803f3720b8.json +1 -1
- package/languages/newspack-blocks-nb_NO-34e5c64f90b1444f3fc735376442eada.json +1 -1
- package/languages/newspack-blocks-nb_NO-4fdea541976076f02d56139fb35e5b42.json +1 -1
- package/languages/newspack-blocks-nb_NO-53e2a1d5945b8d2b1c35e81ae1e532f3.json +1 -1
- package/languages/newspack-blocks-nb_NO-78456b164809d080adecb4d2b3895802.json +1 -1
- package/languages/newspack-blocks-nb_NO-9ef9b2c60c897ad79f92951e6e9949a1.json +1 -1
- package/languages/newspack-blocks-nb_NO-eccbc51a43c04f59165364eda71e0be7.json +1 -1
- package/languages/newspack-blocks-nb_NO-fbe7f8c598cf05d4603ba49fec909ded.json +1 -1
- package/languages/newspack-blocks-nb_NO.po +594 -493
- package/languages/newspack-blocks-pt_PT-2d52b39fdbc5d6c94b3514803f3720b8.json +1 -1
- package/languages/newspack-blocks-pt_PT-34e5c64f90b1444f3fc735376442eada.json +1 -1
- package/languages/newspack-blocks-pt_PT-4fdea541976076f02d56139fb35e5b42.json +1 -1
- package/languages/newspack-blocks-pt_PT-53e2a1d5945b8d2b1c35e81ae1e532f3.json +1 -1
- package/languages/newspack-blocks-pt_PT-78456b164809d080adecb4d2b3895802.json +1 -1
- package/languages/newspack-blocks-pt_PT-9ef9b2c60c897ad79f92951e6e9949a1.json +1 -1
- package/languages/newspack-blocks-pt_PT-eccbc51a43c04f59165364eda71e0be7.json +1 -1
- package/languages/newspack-blocks-pt_PT-fbe7f8c598cf05d4603ba49fec909ded.json +1 -1
- package/languages/newspack-blocks-pt_PT.po +594 -493
- package/languages/newspack-blocks.pot +806 -671
- package/newspack-blocks.php +5 -5
- package/package.json +1 -1
- package/src/blocks/author-list/block.json +3 -2
- package/src/blocks/author-list/edit.js +15 -8
- package/src/blocks/author-list/index.js +4 -3
- package/src/blocks/author-list/view.php +1 -0
- package/src/blocks/author-profile/block.json +16 -2
- package/src/blocks/author-profile/class-wp-rest-newspack-authors-controller.php +180 -9
- package/src/blocks/author-profile/context.js +26 -0
- package/src/blocks/author-profile/edit.js +847 -84
- package/src/blocks/author-profile/editor.scss +18 -14
- package/src/blocks/author-profile/index.js +14 -9
- package/src/blocks/author-profile/single-author.js +6 -2
- package/src/blocks/author-profile/view.php +386 -15
- package/src/blocks/author-profile/view.scss +48 -19
- package/src/blocks/carousel/block.json +2 -1
- package/src/blocks/carousel/edit.js +120 -117
- package/src/blocks/carousel/index.js +2 -1
- package/src/blocks/carousel/view.php +1 -0
- package/src/blocks/donate/block.json +3 -2
- package/src/blocks/donate/edit/FrequencyBasedLayout.tsx +2 -3
- package/src/blocks/donate/edit/index.tsx +56 -39
- package/src/blocks/donate/index.js +2 -1
- package/src/blocks/donate/view.php +1 -0
- package/src/blocks/homepage-articles/block.json +2 -1
- package/src/blocks/homepage-articles/edit.tsx +42 -37
- package/src/blocks/homepage-articles/index.js +2 -1
- package/src/blocks/homepage-articles/view.php +13 -1
- package/src/blocks/iframe/block.json +3 -2
- package/src/blocks/iframe/edit.js +36 -34
- package/src/blocks/iframe/index.js +2 -1
- package/src/blocks/iframe/view.php +1 -0
- package/src/blocks/video-playlist/edit.js +22 -15
- package/src/blocks/video-playlist/index.js +1 -0
- package/src/blocks/video-playlist/view.php +1 -0
- package/src/setup/placeholder-blocks.js +1 -0
- package/vendor/composer/installed.php +2 -2
|
@@ -1,31 +1,30 @@
|
|
|
1
|
-
@use "view";
|
|
2
1
|
@use "../../shared/sass/mixins";
|
|
3
2
|
|
|
4
3
|
.editor-styles-wrapper {
|
|
5
|
-
|
|
4
|
+
// Author Profile block disabled state (custom byline active)
|
|
5
|
+
.newspack-author-profile-disabled {
|
|
6
6
|
.components-notice {
|
|
7
|
-
margin: 0
|
|
8
|
-
width: 100%;
|
|
7
|
+
margin: 0;
|
|
9
8
|
}
|
|
9
|
+
}
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
// Mode selector buttons in placeholder
|
|
12
|
+
.newspack-blocks-author-profile {
|
|
13
|
+
.components-placeholder__fieldset {
|
|
12
14
|
align-items: center;
|
|
13
|
-
|
|
15
|
+
}
|
|
16
|
+
}
|
|
14
17
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
.wp-block-newspack-blocks-author-profile {
|
|
19
|
+
.components-notice {
|
|
20
|
+
margin: 0 0 2rem;
|
|
21
|
+
width: 100%;
|
|
19
22
|
}
|
|
20
23
|
|
|
21
24
|
a.no-op {
|
|
22
25
|
pointer-events: none;
|
|
23
26
|
}
|
|
24
27
|
|
|
25
|
-
p {
|
|
26
|
-
font-size: 1em;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
28
|
&__bio {
|
|
30
29
|
@include mixins.media( mobile ) {
|
|
31
30
|
flex: 4;
|
|
@@ -54,4 +53,9 @@
|
|
|
54
53
|
}
|
|
55
54
|
}
|
|
56
55
|
}
|
|
56
|
+
|
|
57
|
+
// Prevent flex layout on the block wrapper (flex is for individual author cards).
|
|
58
|
+
[data-type="newspack-blocks/author-profile"]:not(.is-nested-mode) {
|
|
59
|
+
display: block;
|
|
60
|
+
}
|
|
57
61
|
}
|
|
@@ -6,7 +6,8 @@ import colors from 'newspack-colors';
|
|
|
6
6
|
/**
|
|
7
7
|
* WordPress dependencies
|
|
8
8
|
*/
|
|
9
|
-
import {
|
|
9
|
+
import { InnerBlocks } from '@wordpress/block-editor';
|
|
10
|
+
import { __ } from '@wordpress/i18n';
|
|
10
11
|
import { postAuthor } from '@wordpress/icons';
|
|
11
12
|
|
|
12
13
|
/**
|
|
@@ -20,7 +21,7 @@ import edit from './edit';
|
|
|
20
21
|
import './editor.scss';
|
|
21
22
|
import './view.scss';
|
|
22
23
|
import metadata from './block.json';
|
|
23
|
-
const { name, attributes, category } = metadata;
|
|
24
|
+
const { name, attributes, apiVersion, category } = metadata;
|
|
24
25
|
|
|
25
26
|
// Name must be exported separately.
|
|
26
27
|
export { name };
|
|
@@ -37,23 +38,27 @@ authorCustomFields.forEach( field => {
|
|
|
37
38
|
} );
|
|
38
39
|
|
|
39
40
|
export const settings = {
|
|
41
|
+
apiVersion,
|
|
40
42
|
title,
|
|
41
43
|
icon: {
|
|
42
44
|
src: postAuthor,
|
|
43
45
|
foreground: colors[ 'primary-400' ],
|
|
44
46
|
},
|
|
45
|
-
keywords: [ __( 'author', 'newspack-blocks' ), __( 'profile', 'newspack-blocks' ) ],
|
|
46
|
-
description: __( 'Display an author profile card.', 'newspack-blocks' ),
|
|
47
|
-
styles: [
|
|
48
|
-
{ name: 'default', label: _x( 'Default', 'block style', 'newspack-blocks' ), isDefault: true },
|
|
49
|
-
{ name: 'center', label: _x( 'Centered', 'block style', 'newspack-blocks' ) },
|
|
50
|
-
],
|
|
51
47
|
attributes,
|
|
52
48
|
category,
|
|
49
|
+
keywords: [ __( 'author', 'newspack-blocks' ), __( 'profile', 'newspack-blocks' ) ],
|
|
50
|
+
description: __( 'Display an author profile card.', 'newspack-blocks' ),
|
|
53
51
|
supports: {
|
|
54
52
|
html: false,
|
|
55
53
|
default: '',
|
|
56
54
|
},
|
|
57
55
|
edit,
|
|
58
|
-
|
|
56
|
+
// Save inner blocks for nested mode (layoutVersion 2).
|
|
57
|
+
// For flat mode (layoutVersion 1), return null to use server-side rendering only.
|
|
58
|
+
save: props => {
|
|
59
|
+
if ( props.attributes.layoutVersion === 2 ) {
|
|
60
|
+
return <InnerBlocks.Content />;
|
|
61
|
+
}
|
|
62
|
+
return null;
|
|
63
|
+
},
|
|
59
64
|
};
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* WordPress dependencies
|
|
5
5
|
*/
|
|
6
|
-
import { __ } from '@wordpress/i18n';
|
|
6
|
+
import { __, sprintf } from '@wordpress/i18n';
|
|
7
7
|
import { RawHTML } from '@wordpress/element';
|
|
8
8
|
import { autop } from '@wordpress/autop';
|
|
9
9
|
|
|
@@ -79,7 +79,11 @@ export const SingleAuthor = ( { author, attributes } ) => {
|
|
|
79
79
|
<RawHTML>{ autop( author.bio ) } </RawHTML>
|
|
80
80
|
{ showArchiveLink && (
|
|
81
81
|
<a href="#" className="no-op">
|
|
82
|
-
{
|
|
82
|
+
{ sprintf(
|
|
83
|
+
/* translators: %s: author name. */
|
|
84
|
+
__( 'More by %s', 'newspack-blocks' ),
|
|
85
|
+
author.name
|
|
86
|
+
) }
|
|
83
87
|
</a>
|
|
84
88
|
) }
|
|
85
89
|
</p>
|
|
@@ -5,6 +5,68 @@
|
|
|
5
5
|
* @package WordPress
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* Register block bindings source for author data.
|
|
10
|
+
*
|
|
11
|
+
* This allows core blocks to bind their content to author fields using:
|
|
12
|
+
* {"metadata":{"bindings":{"content":{"source":"newspack-blocks/author","args":{"key":"name"}}}}}
|
|
13
|
+
*
|
|
14
|
+
* Supported keys: name, bio, url, archive_url, archive_link_text, newspack_job_title, newspack_role, newspack_employer
|
|
15
|
+
*/
|
|
16
|
+
function newspack_blocks_register_author_bindings_source() {
|
|
17
|
+
// Block bindings require WordPress 6.5+.
|
|
18
|
+
if ( ! function_exists( 'register_block_bindings_source' ) ) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
register_block_bindings_source(
|
|
23
|
+
'newspack-blocks/author',
|
|
24
|
+
[
|
|
25
|
+
'label' => __( 'Author Profile', 'newspack-blocks' ),
|
|
26
|
+
'get_value_callback' => 'newspack_blocks_get_author_binding_value',
|
|
27
|
+
'uses_context' => [ 'newspack-blocks/author' ],
|
|
28
|
+
]
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
add_action( 'init', 'newspack_blocks_register_author_bindings_source' );
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Get a value from the author context for block bindings.
|
|
35
|
+
*
|
|
36
|
+
* @param array $source_args Array containing 'key' for the author field to retrieve.
|
|
37
|
+
* @param WP_Block $block_instance The block instance.
|
|
38
|
+
* @param string $attribute_name The attribute being bound.
|
|
39
|
+
* @return mixed The value for the binding, or null if not found.
|
|
40
|
+
*/
|
|
41
|
+
function newspack_blocks_get_author_binding_value( $source_args, $block_instance, $attribute_name ) {
|
|
42
|
+
$author = $block_instance->context['newspack-blocks/author'] ?? null;
|
|
43
|
+
|
|
44
|
+
if ( ! $author || empty( $source_args['key'] ) ) {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
$key = $source_args['key'];
|
|
49
|
+
|
|
50
|
+
// Handle special cases.
|
|
51
|
+
switch ( $key ) {
|
|
52
|
+
case 'archive_url':
|
|
53
|
+
case 'url':
|
|
54
|
+
return $author['url'] ?? '';
|
|
55
|
+
|
|
56
|
+
case 'archive_link_text':
|
|
57
|
+
$name = $author['name'] ?? '';
|
|
58
|
+
if ( ! $name ) {
|
|
59
|
+
return '';
|
|
60
|
+
}
|
|
61
|
+
/* translators: %s: author name */
|
|
62
|
+
return sprintf( __( 'More by %s', 'newspack-blocks' ), $name );
|
|
63
|
+
|
|
64
|
+
default:
|
|
65
|
+
// Empty string prevents saved editor placeholders from leaking to frontend.
|
|
66
|
+
return $author[ $key ] ?? '';
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
8
70
|
/**
|
|
9
71
|
* Dynamic block registration.
|
|
10
72
|
*/
|
|
@@ -27,10 +89,38 @@ function newspack_blocks_register_author_profile() {
|
|
|
27
89
|
register_block_type(
|
|
28
90
|
'newspack-blocks/' . $block_json['name'],
|
|
29
91
|
[
|
|
30
|
-
'
|
|
31
|
-
'
|
|
92
|
+
'api_version' => $block_json['apiVersion'],
|
|
93
|
+
'attributes' => $block_json['attributes'],
|
|
94
|
+
'render_callback' => 'newspack_blocks_render_block_author_profile',
|
|
95
|
+
'uses_context' => $block_json['usesContext'] ?? [],
|
|
96
|
+
// Note: provides_context is declared here for registration but the actual
|
|
97
|
+
// context injection happens in newspack_blocks_render_nested_author_profile()
|
|
98
|
+
// via new WP_Block() with a merged context array.
|
|
99
|
+
'provides_context' => [
|
|
100
|
+
'newspack-blocks/author' => 'author',
|
|
101
|
+
],
|
|
32
102
|
]
|
|
33
103
|
);
|
|
104
|
+
|
|
105
|
+
// Register layout styles only for classic themes. Block themes use
|
|
106
|
+
// InnerBlocks (nested mode) for layout control instead.
|
|
107
|
+
if ( ! wp_is_block_theme() ) {
|
|
108
|
+
register_block_style(
|
|
109
|
+
'newspack-blocks/author-profile',
|
|
110
|
+
[
|
|
111
|
+
'name' => 'default',
|
|
112
|
+
'label' => _x( 'Default', 'block style', 'newspack-blocks' ),
|
|
113
|
+
'is_default' => true,
|
|
114
|
+
]
|
|
115
|
+
);
|
|
116
|
+
register_block_style(
|
|
117
|
+
'newspack-blocks/author-profile',
|
|
118
|
+
[
|
|
119
|
+
'name' => 'center',
|
|
120
|
+
'label' => _x( 'Centered', 'block style', 'newspack-blocks' ),
|
|
121
|
+
]
|
|
122
|
+
);
|
|
123
|
+
}
|
|
34
124
|
}
|
|
35
125
|
|
|
36
126
|
/**
|
|
@@ -96,35 +186,316 @@ function newspack_blocks_get_author_or_guest_author( $author_id, $avatar_size =
|
|
|
96
186
|
}
|
|
97
187
|
|
|
98
188
|
/**
|
|
99
|
-
*
|
|
189
|
+
* Check if custom byline is active for a post.
|
|
100
190
|
*
|
|
191
|
+
* @param int $post_id Post ID to check.
|
|
192
|
+
* @return bool True if custom byline is active.
|
|
193
|
+
*/
|
|
194
|
+
function newspack_blocks_is_custom_byline_active( $post_id ) {
|
|
195
|
+
return (bool) get_post_meta( $post_id, '_newspack_byline_active', true );
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Get authors for a post (CAP or default).
|
|
200
|
+
*
|
|
201
|
+
* @param int $post_id Post ID to get authors for.
|
|
101
202
|
* @param array $attributes Block attributes.
|
|
203
|
+
* @return array Array of author data.
|
|
102
204
|
*/
|
|
103
|
-
function
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
205
|
+
function newspack_blocks_get_post_authors( $post_id, $attributes ) {
|
|
206
|
+
$authors = [];
|
|
207
|
+
$avatar_size = intval( $attributes['avatarSize'] ?? 128 );
|
|
208
|
+
$hide_default = $attributes['avatarHideDefault'] ?? false;
|
|
209
|
+
|
|
210
|
+
// Try Co-Authors Plus first. When CAP is active, always return its result
|
|
211
|
+
// and never fall back to post_author, which could show the wrong person.
|
|
212
|
+
if ( function_exists( 'get_coauthors' ) ) {
|
|
213
|
+
$coauthors = get_coauthors( $post_id );
|
|
214
|
+
foreach ( $coauthors as $coauthor ) {
|
|
215
|
+
$author = newspack_blocks_get_contextual_author( $coauthor, $attributes );
|
|
216
|
+
if ( $author ) {
|
|
217
|
+
$authors[] = $author;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
return $authors;
|
|
107
221
|
}
|
|
108
222
|
|
|
109
|
-
//
|
|
110
|
-
$
|
|
223
|
+
// Fallback to default author.
|
|
224
|
+
$author_id = get_post_field( 'post_author', $post_id );
|
|
225
|
+
if ( $author_id ) {
|
|
226
|
+
$author = newspack_blocks_get_author_or_guest_author(
|
|
227
|
+
$author_id,
|
|
228
|
+
$avatar_size,
|
|
229
|
+
$hide_default,
|
|
230
|
+
false // Not a guest author.
|
|
231
|
+
);
|
|
232
|
+
if ( $author ) {
|
|
233
|
+
$authors[] = $author;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
111
236
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
237
|
+
return $authors;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Convert a WP_User, WP_Post (guest author), or stdClass to the expected format.
|
|
242
|
+
*
|
|
243
|
+
* Note: get_coauthors() returns stdClass objects, not WP_User.
|
|
244
|
+
* Guest authors from get_queried_object() are WP_Post objects.
|
|
245
|
+
*
|
|
246
|
+
* @param object $author_obj Author object from WP_User, WP_Post, or stdClass.
|
|
247
|
+
* @param array $attributes Block attributes.
|
|
248
|
+
* @return array|null Author data array or null if invalid.
|
|
249
|
+
*/
|
|
250
|
+
function newspack_blocks_get_contextual_author( $author_obj, $attributes ) {
|
|
251
|
+
$avatar_size = intval( $attributes['avatarSize'] ?? 128 );
|
|
252
|
+
$hide_default = $attributes['avatarHideDefault'] ?? false;
|
|
253
|
+
|
|
254
|
+
// WP_Post object - guest author from get_queried_object() on author archives.
|
|
255
|
+
if ( $author_obj instanceof WP_Post && 'guest-author' === $author_obj->post_type ) {
|
|
256
|
+
return newspack_blocks_get_author_or_guest_author(
|
|
257
|
+
$author_obj->ID,
|
|
258
|
+
$avatar_size,
|
|
259
|
+
$hide_default,
|
|
260
|
+
true // Is guest author.
|
|
261
|
+
);
|
|
115
262
|
}
|
|
116
263
|
|
|
117
|
-
|
|
264
|
+
// WP_User object - regular author from get_queried_object() on author archives.
|
|
265
|
+
if ( $author_obj instanceof WP_User ) {
|
|
266
|
+
return newspack_blocks_get_author_or_guest_author(
|
|
267
|
+
$author_obj->ID,
|
|
268
|
+
$avatar_size,
|
|
269
|
+
$hide_default,
|
|
270
|
+
false
|
|
271
|
+
);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// stdClass from get_coauthors() - check 'type' property to determine guest vs user.
|
|
275
|
+
if ( is_object( $author_obj ) && isset( $author_obj->ID ) ) {
|
|
276
|
+
$is_guest = isset( $author_obj->type ) && 'guest-author' === $author_obj->type;
|
|
277
|
+
return newspack_blocks_get_author_or_guest_author(
|
|
278
|
+
$author_obj->ID,
|
|
279
|
+
$avatar_size,
|
|
280
|
+
$hide_default,
|
|
281
|
+
$is_guest
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
return null;
|
|
286
|
+
}
|
|
118
287
|
|
|
119
|
-
|
|
288
|
+
/**
|
|
289
|
+
* Render a single author profile card.
|
|
290
|
+
*
|
|
291
|
+
* @param array $author Author data array.
|
|
292
|
+
* @param array $attributes Block attributes.
|
|
293
|
+
* @return string Rendered HTML.
|
|
294
|
+
*/
|
|
295
|
+
function newspack_blocks_render_author_profile_card( $author, $attributes ) {
|
|
296
|
+
return Newspack_Blocks::template_include(
|
|
120
297
|
'author-profile-card',
|
|
121
298
|
[
|
|
122
299
|
'attributes' => $attributes,
|
|
123
300
|
'author' => $author,
|
|
124
301
|
]
|
|
125
302
|
);
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Block render callback.
|
|
307
|
+
*
|
|
308
|
+
* @param array $attributes Block attributes.
|
|
309
|
+
* @param string $content Block inner content.
|
|
310
|
+
* @param WP_Block $block Block instance.
|
|
311
|
+
* @return string Rendered block HTML.
|
|
312
|
+
*/
|
|
313
|
+
function newspack_blocks_render_block_author_profile( $attributes, $content, $block ) {
|
|
314
|
+
$layout_version = $attributes['layoutVersion'] ?? 1;
|
|
315
|
+
|
|
316
|
+
// Get authors based on mode.
|
|
317
|
+
$authors = newspack_blocks_get_authors_for_render( $attributes, $block );
|
|
318
|
+
|
|
319
|
+
if ( empty( $authors ) ) {
|
|
320
|
+
return '';
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
Newspack_Blocks::enqueue_view_assets( 'author-profile' );
|
|
324
|
+
|
|
325
|
+
// NESTED MODE: Determined by layoutVersion attribute, not theme type.
|
|
326
|
+
// Once a block is created in nested mode (layoutVersion 2), it stays nested.
|
|
327
|
+
// Block themes automatically set layoutVersion 2 for NEW blocks.
|
|
328
|
+
// Fall back to flat rendering if a v2 block is used in a classic theme.
|
|
329
|
+
if ( 2 === $layout_version && ! empty( $block->inner_blocks ) ) {
|
|
330
|
+
$registry = WP_Block_Type_Registry::get_instance();
|
|
331
|
+
$has_nested_blocks = $registry->is_registered( 'newspack/avatar' ) && $registry->is_registered( 'newspack/author-profile-social' );
|
|
332
|
+
if ( ! wp_is_block_theme() || ! $has_nested_blocks ) {
|
|
333
|
+
return newspack_blocks_render_flat_author_profiles( $authors, $attributes );
|
|
334
|
+
}
|
|
335
|
+
return newspack_blocks_render_nested_author_profile( $authors, $attributes, $block );
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// FLAT MODE: Use existing template rendering.
|
|
339
|
+
return newspack_blocks_render_flat_author_profiles( $authors, $attributes );
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Get authors for rendering based on block mode.
|
|
344
|
+
*
|
|
345
|
+
* @param array $attributes Block attributes.
|
|
346
|
+
* @param WP_Block $block Block instance.
|
|
347
|
+
* @return array Array of author data.
|
|
348
|
+
*/
|
|
349
|
+
function newspack_blocks_get_authors_for_render( $attributes, $block ) {
|
|
350
|
+
$is_contextual = ! empty( $attributes['isContextual'] );
|
|
351
|
+
|
|
352
|
+
// SPECIFIC MODE: Get single author by ID.
|
|
353
|
+
if ( ! $is_contextual ) {
|
|
354
|
+
if ( empty( $attributes['authorId'] ) ) {
|
|
355
|
+
return [];
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
$author = newspack_blocks_get_author_or_guest_author(
|
|
359
|
+
intval( $attributes['authorId'] ),
|
|
360
|
+
intval( $attributes['avatarSize'] ),
|
|
361
|
+
$attributes['avatarHideDefault'],
|
|
362
|
+
$attributes['isGuestAuthor']
|
|
363
|
+
);
|
|
364
|
+
|
|
365
|
+
return $author ? [ $author ] : [];
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// CONTEXTUAL MODE: Auto-detect authors.
|
|
369
|
+
$post_id = $block->context['postId'] ?? get_the_ID();
|
|
370
|
+
|
|
371
|
+
// On author archives: render the queried author.
|
|
372
|
+
if ( is_author() ) {
|
|
373
|
+
$queried = get_queried_object();
|
|
374
|
+
$author = newspack_blocks_get_contextual_author( $queried, $attributes );
|
|
375
|
+
return $author ? [ $author ] : [];
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
// On single posts: if custom byline is active, show the referenced authors (if any).
|
|
379
|
+
if ( newspack_blocks_is_custom_byline_active( $post_id ) ) {
|
|
380
|
+
if ( class_exists( 'Newspack\Bylines' ) ) {
|
|
381
|
+
$byline_authors = \Newspack\Bylines::get_post_byline_authors( $post_id );
|
|
382
|
+
$authors = [];
|
|
383
|
+
foreach ( $byline_authors as $wp_user ) {
|
|
384
|
+
if ( $wp_user instanceof WP_User ) {
|
|
385
|
+
$author = newspack_blocks_get_contextual_author( $wp_user, $attributes );
|
|
386
|
+
if ( $author ) {
|
|
387
|
+
$authors[] = $author;
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
return $authors;
|
|
392
|
+
}
|
|
393
|
+
// Bylines class unavailable: byline is active so don't show post authors.
|
|
394
|
+
return [];
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// Get authors (CAP or default).
|
|
398
|
+
return newspack_blocks_get_post_authors( $post_id, $attributes );
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
* Render author profiles using flat template (existing behavior).
|
|
403
|
+
*
|
|
404
|
+
* @param array $authors Array of author data.
|
|
405
|
+
* @param array $attributes Block attributes.
|
|
406
|
+
* @return string Rendered HTML.
|
|
407
|
+
*/
|
|
408
|
+
function newspack_blocks_render_flat_author_profiles( $authors, $attributes ) {
|
|
409
|
+
$output = '';
|
|
410
|
+
$show_empty_bio = $attributes['showEmptyBio'] ?? false;
|
|
411
|
+
|
|
412
|
+
foreach ( $authors as $author ) {
|
|
413
|
+
// Skip authors with no bio if configured.
|
|
414
|
+
if ( empty( $author['bio'] ) && ! $show_empty_bio ) {
|
|
415
|
+
continue;
|
|
416
|
+
}
|
|
417
|
+
$output .= newspack_blocks_render_author_profile_card( $author, $attributes );
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
return $output;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* Render author profiles using nested inner blocks.
|
|
425
|
+
*
|
|
426
|
+
* Renders the full inner block tree (including core/columns) and post-processes
|
|
427
|
+
* the HTML to wrap specific paragraphs in links.
|
|
428
|
+
*
|
|
429
|
+
* @param array $authors Array of author data.
|
|
430
|
+
* @param array $attributes Block attributes.
|
|
431
|
+
* @param WP_Block $block Block instance.
|
|
432
|
+
* @return string Rendered HTML.
|
|
433
|
+
*/
|
|
434
|
+
function newspack_blocks_render_nested_author_profile( $authors, $attributes, $block ) {
|
|
435
|
+
$output = '';
|
|
436
|
+
$show_empty_bio = $attributes['showEmptyBio'] ?? false;
|
|
437
|
+
|
|
438
|
+
foreach ( $authors as $author ) {
|
|
439
|
+
if ( empty( $author['bio'] ) && ! $show_empty_bio ) {
|
|
440
|
+
continue;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
$extra_classes = [ 'is-nested-mode' ];
|
|
444
|
+
$classes = Newspack_Blocks::block_classes( 'author-profile', $attributes, $extra_classes );
|
|
445
|
+
|
|
446
|
+
// Render entire inner block tree with author context.
|
|
447
|
+
// WP_Block propagates available_context to all descendants automatically
|
|
448
|
+
// through core/columns > core/column > child blocks.
|
|
449
|
+
$author_html = '';
|
|
450
|
+
foreach ( $block->inner_blocks as $inner_block ) {
|
|
451
|
+
$inner_block_instance = new WP_Block(
|
|
452
|
+
$inner_block->parsed_block,
|
|
453
|
+
array_merge(
|
|
454
|
+
$block->context,
|
|
455
|
+
[
|
|
456
|
+
'newspack-blocks/author' => array_merge(
|
|
457
|
+
$author,
|
|
458
|
+
[ 'avatarHideDefault' => ! empty( $attributes['avatarHideDefault'] ) ]
|
|
459
|
+
),
|
|
460
|
+
]
|
|
461
|
+
)
|
|
462
|
+
);
|
|
463
|
+
$author_html .= $inner_block_instance->render();
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
// Post-process: wrap archive link paragraph in anchor tag.
|
|
467
|
+
$author_html = newspack_blocks_wrap_author_archive_link( $author_html, $author );
|
|
468
|
+
|
|
469
|
+
$output .= '<div class="' . esc_attr( $classes ) . '">' . $author_html . '</div>';
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
return $output;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
/**
|
|
476
|
+
* Post-process rendered HTML to wrap the archive link paragraph in an anchor tag.
|
|
477
|
+
*
|
|
478
|
+
* @param string $html Rendered HTML from inner blocks.
|
|
479
|
+
* @param array $author Author data array.
|
|
480
|
+
* @return string Processed HTML with archive link wrapped.
|
|
481
|
+
*/
|
|
482
|
+
function newspack_blocks_wrap_author_archive_link( $html, $author ) {
|
|
483
|
+
$url = $author['url'] ?? '';
|
|
484
|
+
if ( $url ) {
|
|
485
|
+
$html = preg_replace_callback(
|
|
486
|
+
'/(<p[^>]*class="[^"]*author-archive-link[^"]*"[^>]*>)(.*?)(<\/p>)/s',
|
|
487
|
+
function ( $matches ) use ( $url ) {
|
|
488
|
+
// Avoid creating nested anchors if the paragraph already contains a link.
|
|
489
|
+
if ( false !== stripos( $matches[2], '<a ' ) ) {
|
|
490
|
+
return $matches[0];
|
|
491
|
+
}
|
|
492
|
+
return $matches[1] . '<a href="' . esc_url( $url ) . '">' . wp_kses_post( $matches[2] ) . '</a>' . $matches[3];
|
|
493
|
+
},
|
|
494
|
+
$html
|
|
495
|
+
);
|
|
496
|
+
}
|
|
126
497
|
|
|
127
|
-
return $
|
|
498
|
+
return $html;
|
|
128
499
|
}
|
|
129
500
|
|
|
130
501
|
add_action( 'init', 'newspack_blocks_register_author_profile' );
|
|
@@ -2,32 +2,57 @@
|
|
|
2
2
|
@use "../../shared/sass/mixins";
|
|
3
3
|
|
|
4
4
|
.wp-block-newspack-blocks-author-profile {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
/* Default mode */
|
|
6
|
+
&:not(.is-nested-mode) {
|
|
7
|
+
@include mixins.media( mobile ) {
|
|
8
|
+
display: flex;
|
|
9
|
+
}
|
|
8
10
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
11
|
+
h3 {
|
|
12
|
+
margin-bottom: 0.5em;
|
|
13
|
+
}
|
|
12
14
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
p {
|
|
16
|
+
font-size: 1em;
|
|
17
|
+
}
|
|
16
18
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
19
|
+
&.text-size-small {
|
|
20
|
+
font-size: 0.75em;
|
|
21
|
+
}
|
|
20
22
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
23
|
+
&.text-size-large {
|
|
24
|
+
font-size: 1.25em;
|
|
25
|
+
}
|
|
24
26
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
+
&.text-size-extra-large {
|
|
28
|
+
font-size: 1.5em;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
+ .wp-block-newspack-blocks-author-profile {
|
|
32
|
+
margin-top: 2.5rem;
|
|
33
|
+
}
|
|
27
34
|
}
|
|
28
35
|
|
|
29
|
-
|
|
30
|
-
|
|
36
|
+
/* Nested mode */
|
|
37
|
+
&.is-nested-mode {
|
|
38
|
+
// Dynamic column sizing: avatar column fits content, content column flexes to fill.
|
|
39
|
+
.author-profile-columns {
|
|
40
|
+
.author-profile-avatar-column {
|
|
41
|
+
flex-basis: auto;
|
|
42
|
+
flex-grow: 0;
|
|
43
|
+
flex-shrink: 0;
|
|
44
|
+
width: fit-content; // Prevents expansion when vertical alignment (align-self) is set.
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.author-profile-content-column {
|
|
48
|
+
flex-basis: auto;
|
|
49
|
+
flex-grow: 1;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
p:empty {
|
|
54
|
+
display: none;
|
|
55
|
+
}
|
|
31
56
|
}
|
|
32
57
|
|
|
33
58
|
&__avatar {
|
|
@@ -87,6 +112,10 @@
|
|
|
87
112
|
display: block;
|
|
88
113
|
}
|
|
89
114
|
|
|
115
|
+
a:hover {
|
|
116
|
+
color: var(--wp--preset--color--contrast-2, inherit);
|
|
117
|
+
}
|
|
118
|
+
|
|
90
119
|
svg {
|
|
91
120
|
fill: currentcolor;
|
|
92
121
|
}
|