1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* Dialogue Block. |
4
|
|
|
* |
5
|
|
|
* @since 9.3.0 |
6
|
|
|
* |
7
|
|
|
* @package Jetpack |
8
|
|
|
*/ |
9
|
|
|
|
10
|
|
|
namespace Automattic\Jetpack\Extensions\Dialogue; |
11
|
|
|
|
12
|
|
|
use Automattic\Jetpack\Blocks; |
13
|
|
|
use Jetpack_Gutenberg; |
14
|
|
|
|
15
|
|
|
const FEATURE_NAME = 'dialogue'; |
16
|
|
|
const BLOCK_NAME = 'jetpack/' . FEATURE_NAME; |
17
|
|
|
|
18
|
|
|
/** |
19
|
|
|
* Registers the block for use in Gutenberg |
20
|
|
|
* This is done via an action so that we can disable |
21
|
|
|
* registration if we need to. |
22
|
|
|
*/ |
23
|
|
View Code Duplication |
function register_block() { |
|
|
|
|
24
|
|
|
$deprecated = function_exists( 'gutenberg_get_post_from_context' ); |
25
|
|
|
$uses = $deprecated ? 'context' : 'uses_context'; |
26
|
|
|
Blocks::jetpack_register_block( |
27
|
|
|
BLOCK_NAME, |
28
|
|
|
array( |
29
|
|
|
'render_callback' => __NAMESPACE__ . '\render_block', |
30
|
|
|
$uses => array( |
31
|
|
|
'jetpack/conversation-participants', |
32
|
|
|
'jetpack/conversation-showTimestamps', |
33
|
|
|
), |
34
|
|
|
) |
35
|
|
|
); |
36
|
|
|
} |
37
|
|
|
add_action( 'init', __NAMESPACE__ . '\register_block' ); |
38
|
|
|
|
39
|
|
|
/** |
40
|
|
|
* Helper function to filter dialogue content, |
41
|
|
|
* in order to provide a safe markup. |
42
|
|
|
* |
43
|
|
|
* @param string $content Dialogue content. |
44
|
|
|
* @return string Safe dialgue content markup. |
45
|
|
|
*/ |
46
|
|
|
function filter_content( $content ) { |
47
|
|
|
if ( empty( $content ) ) { |
48
|
|
|
return ''; |
49
|
|
|
} |
50
|
|
|
|
51
|
|
|
return wp_kses( |
52
|
|
|
$content, |
53
|
|
|
array( |
54
|
|
|
'small' => true, |
55
|
|
|
'strong' => true, |
56
|
|
|
'b' => true, |
57
|
|
|
'em' => true, |
58
|
|
|
'br' => true, |
59
|
|
|
) |
60
|
|
|
); |
61
|
|
|
} |
62
|
|
|
|
63
|
|
|
/** |
64
|
|
|
* Helper to check dialogue block attributes. |
65
|
|
|
* |
66
|
|
|
* @param array $attrs Dialogue block attributes. |
67
|
|
|
* @param object $block Block object data. |
68
|
|
|
* @return array Checked block attribues. |
69
|
|
|
*/ |
70
|
|
|
function check_dialogue_attrs( $attrs, $block ) { |
71
|
|
|
return array( |
72
|
|
|
'slug' => isset( $attrs['participantSlug'] ) ? $attrs['participantSlug'] : null, |
73
|
|
|
'label' => isset( $attrs['participant'] ) ? $attrs['participant'] : null, |
74
|
|
|
'timestamp' => isset( $attrs['timestamp'] ) ? esc_attr( $attrs['timestamp'] ) : '00:00', |
75
|
|
|
'show_timestamp' => isset( $block->context['jetpack/conversation-showTimestamps'] ), |
76
|
|
|
'content' => ! empty( $attrs['content'] ) ? filter_content( $attrs['content'] ) : '', |
77
|
|
|
); |
78
|
|
|
} |
79
|
|
|
/** |
80
|
|
|
* Return participant list. |
81
|
|
|
* It will try to pick them up from the block context. |
82
|
|
|
* Otherwise, it will return the default participants list. |
83
|
|
|
* |
84
|
|
|
* @param object $block Block object data. |
85
|
|
|
* @param array $default Default conversation data. |
86
|
|
|
* @return array dialogue participants list. |
87
|
|
|
*/ |
88
|
|
|
function get_participantes_list( $block, $default ) { |
89
|
|
|
return ! empty( $block->context['jetpack/conversation-participants'] ) |
90
|
|
|
? $block->context['jetpack/conversation-participants'] |
91
|
|
|
: $default['list']; |
92
|
|
|
} |
93
|
|
|
|
94
|
|
|
/** |
95
|
|
|
* Return participan slug, |
96
|
|
|
* dependng on the slug and label fo the dialogue block, |
97
|
|
|
* and default slug defined in the conversation data. |
98
|
|
|
* |
99
|
|
|
* @param array $attrs Checked dialogue attributes array. |
100
|
|
|
* @param object $block Block object data. |
101
|
|
|
* @param array $default Default conversation data. |
102
|
|
|
* @return array Dialoge slug if it's defined. Otherwise, default conversation slug. |
103
|
|
|
*/ |
104
|
|
|
function get_participant_slug( $attrs, $block, $default ) { |
105
|
|
|
return ! $attrs['slug'] && ! $attrs['label'] |
106
|
|
|
? $default['slug'] |
107
|
|
|
: $attrs['slug']; |
108
|
|
|
} |
109
|
|
|
|
110
|
|
|
/** |
111
|
|
|
* Helper function to pick the dialogie participant object. |
112
|
|
|
* |
113
|
|
|
* @param array $participants Dialogue participants. |
114
|
|
|
* @param string $slug participant slug. |
115
|
|
|
* @return array Dialogue participant when exists. Otherwise, False. |
116
|
|
|
*/ |
117
|
|
|
function get_current_participant( $participants, $slug ) { |
118
|
|
|
// Participant names map. |
119
|
|
|
$participant_names_map = array(); |
120
|
|
|
foreach ( $participants as $participant ) { |
121
|
|
|
$participant_names_map[ $participant['participantSlug'] ] = $participant; |
122
|
|
|
} |
123
|
|
|
|
124
|
|
|
return isset( $participant_names_map[ $slug ] ) |
125
|
|
|
? $participant_names_map[ $slug ] |
126
|
|
|
: false; |
127
|
|
|
} |
128
|
|
|
|
129
|
|
|
/** |
130
|
|
|
* Helper function to get the participant name. |
131
|
|
|
* |
132
|
|
|
* @param array $participants Dialogue participants. |
133
|
|
|
* @param string $slug participant slug. |
134
|
|
|
* @param array $attrs checked dialogue block atteributes. |
135
|
|
|
* @return string Participant name. |
136
|
|
|
*/ |
137
|
|
|
function get_participant_name( $participants, $slug, $attrs ) { |
138
|
|
|
// Try to pick up participant data from context. |
139
|
|
|
$participant = get_current_participant( $participants, $slug ); |
140
|
|
|
|
141
|
|
|
return isset( $participant['participant'] ) |
142
|
|
|
? esc_attr( $participant['participant'] ) |
143
|
|
|
: $attrs['label']; |
144
|
|
|
} |
145
|
|
|
|
146
|
|
|
/** |
147
|
|
|
* Helper function to build CSS class, |
148
|
|
|
* for the given participant. |
149
|
|
|
* |
150
|
|
|
* @param array $participants Dialogue participants. |
151
|
|
|
* @param string $slug participant slug. |
152
|
|
|
* @param array $attrs checked dialogue block atteributes. |
153
|
|
|
* @param string $css_class Base dialogue block CSS classname. |
154
|
|
|
* @return string Participant CSS classnames. |
155
|
|
|
*/ |
156
|
|
|
function build_participant_css_classes( $participants, $slug, $attrs, $css_class ) { |
157
|
|
|
$is_custom_speaker = $attrs['label'] && ! $attrs['slug']; |
158
|
|
|
$current_participant = get_current_participant( $participants, $slug ); |
159
|
|
|
|
160
|
|
|
$participant_has_bold_style = $is_custom_speaker && isset( $attrs['hasBoldStyle'] ) |
161
|
|
|
? $attrs['hasBoldStyle'] |
162
|
|
|
: ( |
163
|
|
|
isset( $current_participant['hasBoldStyle'] ) |
164
|
|
|
? $current_participant['hasBoldStyle'] |
165
|
|
|
: false |
166
|
|
|
); |
167
|
|
|
|
168
|
|
|
$participant_has_italic_style = $is_custom_speaker && isset( $attrs['hasItalicStyle'] ) |
169
|
|
|
? $attrs['hasItalicStyle'] |
170
|
|
|
: ( |
171
|
|
|
isset( $current_participant['hasItalicStyle'] ) |
172
|
|
|
? $current_participant['hasItalicStyle'] |
173
|
|
|
: false |
174
|
|
|
); |
175
|
|
|
|
176
|
|
|
$participant_has_uppercase_style = $is_custom_speaker && isset( $attrs['hasUppercaseStyle'] ) |
177
|
|
|
? $attrs['hasUppercaseStyle'] |
178
|
|
|
: ( |
179
|
|
|
isset( $current_participant['hasUppercaseStyle'] ) |
180
|
|
|
? $current_participant['hasUppercaseStyle'] |
181
|
|
|
: false |
182
|
|
|
); |
183
|
|
|
|
184
|
|
|
$participant_css_classes = array( $css_class . '__participant' ); |
185
|
|
|
if ( $participant_has_bold_style ) { |
186
|
|
|
array_push( $participant_css_classes, 'has-bold-style' ); |
187
|
|
|
} |
188
|
|
|
|
189
|
|
|
if ( $participant_has_italic_style ) { |
190
|
|
|
array_push( $participant_css_classes, 'has-italic-style' ); |
191
|
|
|
} |
192
|
|
|
|
193
|
|
|
if ( $participant_has_uppercase_style ) { |
194
|
|
|
array_push( $participant_css_classes, 'has-uppercase-style' ); |
195
|
|
|
} |
196
|
|
|
|
197
|
|
|
return implode( ' ', $participant_css_classes ); |
198
|
|
|
} |
199
|
|
|
|
200
|
|
|
/** |
201
|
|
|
* Dialogue block registration/dependency declaration. |
202
|
|
|
* |
203
|
|
|
* @param array $dialogue_attrs Array containing the Dialogue block attributes. |
204
|
|
|
* @param string $block_content String containing the Dialogue block content. |
205
|
|
|
* @param object $block Block object data. |
206
|
|
|
* |
207
|
|
|
* @return string |
208
|
|
|
*/ |
209
|
|
|
function render_block( $dialogue_attrs, $block_content, $block ) { |
210
|
|
|
Jetpack_Gutenberg::load_assets_as_required( FEATURE_NAME ); |
211
|
|
|
|
212
|
|
|
// Pick up conversation data from context. |
213
|
|
|
$default_participants = json_decode( |
214
|
|
|
// phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents |
215
|
|
|
file_get_contents( JETPACK__PLUGIN_DIR . 'extensions/blocks/conversation/participants.json' ), |
216
|
|
|
true |
217
|
|
|
); |
218
|
|
|
|
219
|
|
|
// Dialogue Attributes. |
220
|
|
|
$attrs = check_dialogue_attrs( $dialogue_attrs, $block ); |
221
|
|
|
|
222
|
|
|
// Conversation/Dialogue data. |
223
|
|
|
$participants = get_participantes_list( $block, $default_participants ); |
224
|
|
|
$participant_slug = get_participant_slug( $attrs, $block, $default_participants ); |
225
|
|
|
$participant_name = get_participant_name( $participants, $participant_slug, $attrs ); |
226
|
|
|
|
227
|
|
|
// CSS classes and inline styles. |
228
|
|
|
$css_classname = Blocks::classes( FEATURE_NAME, $dialogue_attrs ); |
229
|
|
|
$participant_css_classes = build_participant_css_classes( $participants, $participant_slug, $attrs, $css_classname ); |
230
|
|
|
|
231
|
|
|
// Markup. |
232
|
|
|
return '<div class="' . $css_classname . '" >' . |
233
|
|
|
'<div class="' . $css_classname . '__meta">' . |
234
|
|
|
'<div class="' . $participant_css_classes . '">' . |
235
|
|
|
$participant_name . |
236
|
|
|
'</div>' . |
237
|
|
|
( $attrs['show_timestamp'] |
238
|
|
|
? '<div class="' . $css_classname . '__timestamp">' . |
239
|
|
|
$attrs['timestamp'] . |
240
|
|
|
'</div>' |
241
|
|
|
: '' |
242
|
|
|
) . |
243
|
|
|
'</div>' . |
244
|
|
|
'<div>' . $attrs['content'] . '</div>' . |
245
|
|
|
'</div>'; |
246
|
|
|
} |
247
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.