Skip to content

Commit 1bcb917

Browse files
authored
Merge pull request #31 from BeAPI/fix/bugbot-2.1.0
Fix/bugbot 2.1.0
2 parents 5ca1d88 + 9bdccb9 commit 1bcb917

2 files changed

Lines changed: 120 additions & 27 deletions

File tree

includes/Services/Seopress_Seo_Service.php

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,14 +126,59 @@ private function merge_block_faq_into_schema( array $json ): ?array {
126126
return null;
127127
}
128128

129+
$existing_questions = $this->normalize_main_entity( $json['mainEntity'] ?? [] );
130+
$merged_questions = array_merge( $existing_questions, $questions );
131+
129132
$json['@type'] = 'FAQPage';
130-
$json['mainEntity'] = $questions;
133+
$json['mainEntity'] = $this->renumber_question_positions( $merged_questions );
131134
$json['@context'] = $json['@context'] ?? 'https://schema.org';
132135
$json['inLanguage'] = $json['inLanguage'] ?? get_bloginfo( 'language' );
133136

134137
return $json;
135138
}
136139

140+
/**
141+
* Normalize FAQPage mainEntity to a list of Question entries.
142+
*
143+
* @param mixed $main_entity FAQPage mainEntity value.
144+
*
145+
* @return array<int, array<string, mixed>>
146+
*/
147+
private function normalize_main_entity( $main_entity ): array {
148+
if ( empty( $main_entity ) || ! is_array( $main_entity ) ) {
149+
return [];
150+
}
151+
152+
if ( isset( $main_entity['@type'] ) ) {
153+
return [ $main_entity ];
154+
}
155+
156+
return array_values(
157+
array_filter(
158+
$main_entity,
159+
static fn( $question ) => is_array( $question ) && ! empty( $question )
160+
)
161+
);
162+
}
163+
164+
/**
165+
* Ensure sequential position values on merged FAQ questions.
166+
*
167+
* @param array<int, array<string, mixed>> $questions Question entries.
168+
*
169+
* @return array<int, array<string, mixed>>
170+
*/
171+
private function renumber_question_positions( array $questions ): array {
172+
$position = 1;
173+
174+
foreach ( $questions as $index => $question ) {
175+
$questions[ $index ]['position'] = $position;
176+
++$position;
177+
}
178+
179+
return $questions;
180+
}
181+
137182
/**
138183
* Create a schema generator from the current singular post.
139184
*

src/faq/edit.js

Lines changed: 74 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import {
66
useBlockProps,
77
useInnerBlocksProps,
88
InspectorControls,
9-
useBlockEditContext,
109
store as blockEditorStore,
1110
} from '@wordpress/block-editor';
1211
import {
@@ -30,7 +29,7 @@ import {
3029
import { useDispatch, useSelect } from '@wordpress/data';
3130
import { createBlock } from '@wordpress/blocks';
3231
import { __, sprintf } from '@wordpress/i18n';
33-
import { useEffect } from '@wordpress/element';
32+
import { useEffect, useLayoutEffect } from '@wordpress/element';
3433

3534
const QUESTION_BLOCK = 'blockparty/faq-question';
3635
const HEADING_LEVELS = [ 2, 3, 4, 5, 6 ];
@@ -53,9 +52,27 @@ function collectQuestionBlocks( blocks ) {
5352
} );
5453
}
5554

56-
function useSyncQuestionHeadingLevels( headingLevel, isAccordion ) {
57-
const { clientId } = useBlockEditContext();
58-
const { updateBlockAttributes } = useDispatch( blockEditorStore );
55+
function syncQuestionHeadingLevels(
56+
clientId,
57+
headingLevel,
58+
isAccordion,
59+
{ getBlocksByClientId, updateBlockAttributes }
60+
) {
61+
if ( ! isAccordion ) {
62+
return;
63+
}
64+
65+
const [ faqBlock ] = getBlocksByClientId( clientId );
66+
const questionBlocks = collectQuestionBlocks( faqBlock?.innerBlocks || [] );
67+
68+
questionBlocks.forEach( ( block ) => {
69+
if ( block.attributes.headingLevel !== headingLevel ) {
70+
updateBlockAttributes( block.clientId, { headingLevel } );
71+
}
72+
} );
73+
}
74+
75+
function useSyncQuestionHeadingLevels( clientId, headingLevel, isAccordion ) {
5976
const questionBlocks = useSelect(
6077
( select ) => {
6178
const { getBlocksByClientId } = select( blockEditorStore );
@@ -65,18 +82,25 @@ function useSyncQuestionHeadingLevels( headingLevel, isAccordion ) {
6582
},
6683
[ clientId ]
6784
);
85+
const { getBlocksByClientId } = useSelect(
86+
( select ) => select( blockEditorStore ),
87+
[]
88+
);
89+
const { updateBlockAttributes } = useDispatch( blockEditorStore );
6890

69-
useEffect( () => {
70-
if ( ! isAccordion ) {
71-
return;
72-
}
73-
74-
questionBlocks.forEach( ( block ) => {
75-
if ( block.attributes.headingLevel !== headingLevel ) {
76-
updateBlockAttributes( block.clientId, { headingLevel } );
77-
}
91+
useLayoutEffect( () => {
92+
syncQuestionHeadingLevels( clientId, headingLevel, isAccordion, {
93+
getBlocksByClientId,
94+
updateBlockAttributes,
7895
} );
79-
}, [ headingLevel, isAccordion, questionBlocks, updateBlockAttributes ] );
96+
}, [
97+
clientId,
98+
headingLevel,
99+
isAccordion,
100+
questionBlocks,
101+
getBlocksByClientId,
102+
updateBlockAttributes,
103+
] );
80104
}
81105

82106
export default function Edit( { clientId, attributes, setAttributes } ) {
@@ -89,13 +113,14 @@ export default function Edit( { clientId, attributes, setAttributes } ) {
89113
} );
90114

91115
const { insertBlock, updateBlockAttributes } =
92-
useDispatch( 'core/block-editor' );
93-
const { getBlocks } = useSelect(
94-
( select ) => select( 'core/block-editor' ),
116+
useDispatch( blockEditorStore );
117+
const blockEditor = useSelect(
118+
( select ) => select( blockEditorStore ),
95119
[]
96120
);
121+
const { getBlocks, getBlocksByClientId } = blockEditor;
97122

98-
useSyncQuestionHeadingLevels( headingLevel, isAccordion );
123+
useSyncQuestionHeadingLevels( clientId, headingLevel, isAccordion );
99124

100125
// Synchronize isAccordion attribute to all child blocks
101126
useEffect( () => {
@@ -149,9 +174,21 @@ export default function Edit( { clientId, attributes, setAttributes } ) {
149174
'blockparty-faq'
150175
) }
151176
checked={ isAccordion }
152-
onChange={ ( value ) =>
153-
setAttributes( { isAccordion: value } )
154-
}
177+
onChange={ ( value ) => {
178+
setAttributes( { isAccordion: value } );
179+
180+
if ( value ) {
181+
syncQuestionHeadingLevels(
182+
clientId,
183+
headingLevel,
184+
true,
185+
{
186+
getBlocksByClientId,
187+
updateBlockAttributes,
188+
}
189+
);
190+
}
191+
} }
155192
__nextHasNoMarginBottom
156193
/>
157194
{ isAccordion && (
@@ -167,11 +204,22 @@ export default function Edit( { clientId, attributes, setAttributes } ) {
167204
value={ headingLevel }
168205
isBlock
169206
__next40pxDefaultSize
170-
onChange={ ( value ) =>
207+
onChange={ ( value ) => {
208+
const newHeadingLevel = Number( value );
209+
171210
setAttributes( {
172-
headingLevel: Number( value ),
173-
} )
174-
}
211+
headingLevel: newHeadingLevel,
212+
} );
213+
syncQuestionHeadingLevels(
214+
clientId,
215+
newHeadingLevel,
216+
isAccordion,
217+
{
218+
getBlocksByClientId,
219+
updateBlockAttributes,
220+
}
221+
);
222+
} }
175223
>
176224
{ HEADING_LEVELS.map( ( level ) => (
177225
<ToggleGroupControlOptionIcon

0 commit comments

Comments
 (0)