PluginProbe
Content Control – The Ultimate Content Restriction Plugin! Restrict Content, Create Conditional Blocks & More / trunk
Content Control – The Ultimate Content Restriction Plugin! Restrict Content, Create Conditional Blocks & More vtrunk
trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.1.10 1.1.2 1.1.3 1.1.4 1.1.5 1.1.6 1.1.7 1.1.8 2.0.0 2.0.1 2.0.10 2.0.11 2.0.12 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 All 47 releases
content-control / classes / Controllers / Shortcodes.php

Shortcodes.php in Content Control – The Ultimate Content Restriction Plugin! Restrict Content, Create Conditional Blocks & More trunk, at classes/Controllers/Shortcodes.php

143 lines 3.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Shortcode setup.
4 *
5 * @copyright (c) 2023, Code Atlantic LLC.
6 * @package ContentControl
7 */
8
9 namespace ContentControl\Controllers;
10
11 use ContentControl\Base\Controller;
12
13 use function ContentControl\user_meets_requirements;
14
15 defined( 'ABSPATH' ) || exit;
16
17 /**
18 * Class Shortcodes
19 *
20 * @package ContentControl
21 */
22 class Shortcodes extends Controller {
23
24 /**
25 * Initialize Widgets
26 */
27 public function init() {
28 add_shortcode( 'content_control', [ $this, 'content_control' ] );
29 }
30
31 /**
32 * Process the [content_control] shortcode.
33 *
34 * When access is allowed, nested shortcode content is intentionally returned
35 * as rendered HTML. Applying KSES after `do_shortcode()` would break forms,
36 * embeds, SVG, and script-backed output produced by otherwise-authorized
37 * nested shortcodes.
38 *
39 * @param array<string,string|int|null> $atts Array or shortcode attributes.
40 * @param string $content Content inside shortcode.
41 *
42 * @return string
43 */
44 public function content_control( $atts, $content = '' ) {
45 // Deprecated.
46 $deprecated_atts = shortcode_atts( [
47 'logged_out' => null, // @deprecated 2.0.
48 'roles' => null, // @deprecated 2.0.
49 ], $atts );
50
51 $atts = shortcode_atts( [
52 'status' => 'logged_in', // 'logged_in' or 'logged_out
53 'allowed_roles' => null,
54 'excluded_roles' => null,
55 'class' => '',
56 'inline' => false,
57 'message' => $this->container->get_option( 'defaultDenialMessage', '' ),
58 ], $this->normalize_empty_atts( $atts ), 'content_control' );
59
60 // Handle old args.
61 if ( isset( $deprecated_atts['logged_out'] ) ) {
62 $atts['status'] = (bool) $deprecated_atts['logged_out'] ? 'logged_out' : 'logged_in';
63 }
64
65 if ( isset( $deprecated_atts['roles'] ) && ! empty( $deprecated_atts['roles'] ) ) {
66 $atts['allowed_roles'] = $deprecated_atts['roles'];
67 }
68
69 $user_roles = [];
70 $match_type = 'any';
71
72 // Normalize args.
73 if ( ! empty( $atts['excluded_roles'] ) ) {
74 $user_roles = $atts['excluded_roles'];
75 $match_type = 'exclude';
76 } elseif ( ! empty( $atts['allowed_roles'] ) ) {
77 $user_roles = $atts['allowed_roles'];
78 $match_type = 'match';
79 }
80
81 // Convert classes to array.
82 $classes = ! empty( $atts['class'] ) ? explode( ' ', $atts['class'] ) : [];
83
84 $classes[] = 'content-control-container';
85 // @deprecated 2.0.0
86 $classes[] = 'jp-cc';
87
88 $tag = wp_validate_boolean( $atts['inline'] ) ? 'span' : 'div';
89
90 if ( user_meets_requirements( $atts['status'], $user_roles, $match_type ) ) {
91 $classes[] = 'content-control-accessible';
92 // @deprecated 2.0.0
93 $classes[] = 'jp-cc-accessible';
94 // Keep nested shortcode output intact; KSES here would strip functional rendered markup.
95 $output = do_shortcode( $content );
96 } else {
97 $classes[] = 'content-control-not-accessible';
98 // @deprecated 2.0.0
99 $classes[] = 'jp-cc-not-accessible';
100 // Denial messages are shortcode attributes and intentionally limited to post-safe HTML.
101 $output = wp_kses_post( do_shortcode( $atts['message'] ) );
102 }
103
104 $classes = implode( ' ', $classes );
105
106 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Contains intentional rendered nested-shortcode HTML.
107 return sprintf(
108 '<%1$s class="%2$s">%3$s</%1$s>',
109 $tag,
110 esc_attr( $classes ),
111 $output
112 );
113 }
114
115 /**
116 * Takes set but empty attributes and sets them to true.
117 *
118 * These are typically valueless boolean attributes.
119 *
120 * @param array<string|int,string|int|null> $atts Array of shortcode attributes.
121 *
122 * @return (int|null|string|true)[]
123 *
124 * @psalm-return array<int|string, int|null|string|true>
125 */
126 public function normalize_empty_atts( $atts = [] ) {
127 // Sanity check to ensure $atts is an array.
128 // @phpstan-ignore-next-line .
129 if ( ! is_array( $atts ) || empty( $atts ) ) {
130 $atts = [];
131 }
132
133 foreach ( $atts as $attribute => $value ) {
134 if ( is_int( $attribute ) ) {
135 $atts[ strtolower( $value ) ] = true;
136 unset( $atts[ $attribute ] );
137 }
138 }
139
140 return $atts;
141 }
142 }
143