| @@ -64,8 +64,17 @@ | ||
| 64 | 64 | */ |
| 65 | 65 | private static $shortcode_queue = array(); |
| 66 | 66 | |
| 67 | 67 | /** |
| 68 | + * Widgets contents. | |
| 69 | + * | |
| 70 | + * @since 4.7.1 | |
| 71 | + * | |
| 72 | + * @var array | |
| 73 | + */ | |
| 74 | + private static $widgets_contents = array(); | |
| 75 | + | |
| 76 | + /** | |
| 68 | 77 | * Adds shortcodes. |
| 69 | 78 | */ |
| 70 | 79 | public static function init() { |
| 71 | 80 | // login |
| @@ -88,8 +97,10 @@ | ||
| 88 | 97 | add_filter( 'render_block', array( __CLASS__, 'render_block' ), 0, 3 ); |
| 89 | 98 | // @since 4.7.0 shortcode queue ops |
| 90 | 99 | add_filter( 'pre_do_shortcode_tag', array( __CLASS__, 'pre_do_shortcode_tag' ), PHP_INT_MAX, 4 ); |
| 91 | 100 | add_filter( 'do_shortcode_tag', array( __CLASS__, 'do_shortcode_tag' ), PHP_INT_MAX, 4 ); |
| 101 | + // @since 4.7.1 shortcodes in widgets | |
| 102 | + add_filter( 'widget_display_callback', array( __CLASS__, 'widget_display_callback' ), PHP_INT_MAX, 3 ); | |
| 92 | 103 | } |
| 93 | 104 | |
| 94 | 105 | /** |
| 95 | 106 | * Renders the Groups login form. |
| @@ -326,9 +337,9 @@ | ||
| 326 | 337 | $user = new Groups_User( $user_id ); |
| 327 | 338 | $groups = $user->get_groups(); |
| 328 | 339 | |
| 329 | 340 | if ( !empty( $groups ) ) { |
| 330 | - // group attr | |
| 341 | + // group attr | |
| 331 | 342 | if ( $options['group'] !== null ) { |
| 332 | 343 | $groups = array(); |
| 333 | 344 | $groups_incl = explode( ',', $options['group'] ); |
| 334 | 345 | foreach ( $groups_incl as $group_incl ) { |
| @@ -1188,9 +1199,11 @@ | ||
| 1188 | 1199 | if ( !self::is_processing( $tag, $atts ) ) { |
| 1189 | 1200 | return true; |
| 1190 | 1201 | } |
| 1191 | 1202 | |
| 1192 | - $valid = isset( $post ) && !empty( $post->ID ) && !empty( $post->post_content ); | |
| 1203 | + $valid = | |
| 1204 | + isset( $post ) && !empty( $post->ID ) && ( !empty( $post->post_excerpt ) || !empty( $post->post_content ) ) || | |
| 1205 | + !empty( self::$widgets_contents ); | |
| 1193 | 1206 | |
| 1194 | 1207 | if ( $valid ) { |
| 1195 | 1208 | $valid = ! ( |
| 1196 | 1209 | defined( 'REST_API_REQUEST' ) && REST_API_REQUEST || |
| @@ -1206,11 +1219,31 @@ | ||
| 1206 | 1219 | } |
| 1207 | 1220 | |
| 1208 | 1221 | if ( $valid ) { |
| 1209 | 1222 | $valid = false; |
| 1210 | - if ( !empty( $post->post_content ) && has_shortcode( $post->post_content, $tag ) ) { | |
| 1223 | + | |
| 1224 | + // @since 4.7.1 also consider the excerpt and widgets | |
| 1225 | + $contents = ( $post->post_excerpt ?? '' ) . ( $post->post_content ?? '' ); | |
| 1226 | + if ( !empty( self::$widgets_contents ) ) { | |
| 1227 | + $contents .= implode( ' ', self::$widgets_contents ); | |
| 1228 | + } | |
| 1229 | + /** | |
| 1230 | + * Allow to filter the contents considered for shortcode validation. | |
| 1231 | + * | |
| 1232 | + * @since 4.7.1 | |
| 1233 | + * | |
| 1234 | + * @param string $contents contents considered | |
| 1235 | + * @param string $tag shortcode tag | |
| 1236 | + * @param array $atts shortcode attributes | |
| 1237 | + * @param string $content shortcode content | |
| 1238 | + * | |
| 1239 | + * @return string | |
| 1240 | + */ | |
| 1241 | + $contents = apply_filters( 'groups_shortcodes_validate_contents', $contents, $tag, $atts, $content ); | |
| 1242 | + | |
| 1243 | + if ( !empty( $contents ) && has_shortcode( $contents, $tag ) ) { | |
| 1211 | 1244 | $matches = null; |
| 1212 | - preg_match_all( '@\[([^<>&/\[\]\x00-\x20=]++)@', $post->post_content, $matches ); | |
| 1245 | + preg_match_all( '@\[([^<>&/\[\]\x00-\x20=]++)@', $contents, $matches ); | |
| 1213 | 1246 | if ( !empty( $matches[1] ) && is_array( $matches[1] ) && count( $matches[1] ) > 0 ) { |
| 1214 | 1247 | $tags = array_intersect( array( $tag ), $matches[1] ); |
| 1215 | 1248 | if ( !empty( $tags ) ) { |
| 1216 | 1249 | // - does not support nested shortcodes |
| @@ -1216,9 +1249,9 @@ | ||
| 1216 | 1249 | // - does not support nested shortcodes |
| 1217 | 1250 | // - Groups shortcodes do not support nesting |
| 1218 | 1251 | $pattern = '@' . get_shortcode_regex( $tags ) . '@'; |
| 1219 | 1252 | $m = null; |
| 1220 | - preg_match_all( $pattern, $post->post_content, $m ); | |
| 1253 | + preg_match_all( $pattern, $contents, $m ); | |
| 1221 | 1254 | // shortcode arguments list |
| 1222 | 1255 | if ( isset( $m[3] ) && is_array( $m[3] ) && count( $m[3] ) > 0 ) { |
| 1223 | 1256 | $found = false; |
| 1224 | 1257 | foreach ( $m[3] as $args ) { |
| @@ -1293,8 +1326,53 @@ | ||
| 1293 | 1326 | } |
| 1294 | 1327 | } |
| 1295 | 1328 | self::$shortcode_queue = $queue; |
| 1296 | 1329 | return $output; |
| 1330 | + } | |
| 1331 | + | |
| 1332 | + /** | |
| 1333 | + * Use callback filter to gather shortcodes in widgets. | |
| 1334 | + * | |
| 1335 | + * @since 4.7.1 | |
| 1336 | + * | |
| 1337 | + * @param array $instance widget instance settings | |
| 1338 | + * @param WP_Widget $widget widget object | |
| 1339 | + * @param array $args widget arguments | |
| 1340 | + * | |
| 1341 | + * @return array | |
| 1342 | + */ | |
| 1343 | + public static function widget_display_callback( $instance, $widget, $args ) { | |
| 1344 | + if ( !empty( $instance ) && is_array( $instance ) ) { | |
| 1345 | + if ( is_object( $widget ) ) { | |
| 1346 | + if ( $widget instanceof WP_Widget_Text ) { | |
| 1347 | + if ( isset( $instance['text'] ) && is_string( $instance['text'] ) ) { | |
| 1348 | + self::$widgets_contents[] = $instance['text']; | |
| 1349 | + } | |
| 1350 | + } else if ( $widget instanceof WP_Widget_Block ) { | |
| 1351 | + if ( isset( $instance['content'] ) && is_string( $instance['content'] ) ) { | |
| 1352 | + self::$widgets_contents[] = $instance['content']; | |
| 1353 | + } | |
| 1354 | + } else { | |
| 1355 | + /** | |
| 1356 | + * Allow widgets to provide content that should be checked during shortcode validation. | |
| 1357 | + * | |
| 1358 | + * @since 4.7.1 | |
| 1359 | + * | |
| 1360 | + * @param string|null $content widget content to check for shortcodes | |
| 1361 | + * @param array $instance widget instance settings | |
| 1362 | + * @param WP_Widget $widget widget object | |
| 1363 | + * @param array $args widget arguments | |
| 1364 | + * | |
| 1365 | + * @return string|null string content of the widget or null if widget's content should not be considered | |
| 1366 | + */ | |
| 1367 | + $content = apply_filters( 'groups_shortcodes_widget_display_callback_widget_content', null, $instance, $widget, $args ); | |
| 1368 | + if ( is_string( $content ) ) { | |
| 1369 | + self::$widgets_contents[] = $content; | |
| 1370 | + } | |
| 1371 | + } | |
| 1372 | + } | |
| 1373 | + } | |
| 1374 | + return $instance; | |
| 1297 | 1375 | } |
| 1298 | 1376 | |
| 1299 | 1377 | /** |
| 1300 | 1378 | * Is processing shortcode tag with given attributes. |