PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 7.3.4
Jetpack – WP Security, Backup, Speed, & Growth v7.3.4
16.2-beta 12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 13.7.2 13.8.3 13.9.2 14.0.1 14.1.1 14.2.2 14.3.1 All 501 releases
jetpack / modules / shortcodes / quiz.php

quiz.php in Jetpack – WP Security, Backup, Speed, & Growth 7.3.4, at modules/shortcodes/quiz.php

310 lines 7.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php //phpcs:ignore WordPress.Files.FileName.InvalidClassFileNam
2 /**
3 * Quiz shortcode.
4 *
5 * Usage:
6 *
7 * [quiz]
8 * [question]What's the right answer?[/question]
9 * [wrong]This one?[explanation]Nope[/explanation][/wrong]
10 * [answer]Yes, this is the one![explanation]Yay![/explanation][/answer]
11 * [wrong]Maybe this one[explanation]Keep trying[/explanation][/wrong]
12 * [wrong]How about this one?[explanation]Try again[/explanation][/wrong]
13 * [/quiz]
14 */
15 class Quiz_Shortcode {
16
17 /**
18 * Parameters admitted by [quiz] shortcode.
19 *
20 * @since 4.5.0
21 *
22 * @var array
23 */
24 private static $quiz_params = array();
25
26 /**
27 * Whether the scripts were enqueued.
28 *
29 * @since 4.5.0
30 *
31 * @var bool
32 */
33 private static $scripts_enqueued = false;
34
35 /**
36 * In a8c training, store user currently logged in.
37 *
38 * @since 4.5.0
39 *
40 * @var null
41 */
42 private static $username = null;
43
44 /**
45 * Whether the noscript tag was already printed.
46 *
47 * @since 4.5.0
48 *
49 * @var bool
50 */
51 private static $noscript_info_printed = false;
52
53 /**
54 * Whether JavaScript is available.
55 *
56 * @since 4.5.0
57 *
58 * @var null
59 */
60 private static $javascript_unavailable = null;
61
62 /**
63 * Register all shortcodes.
64 *
65 * @since 4.5.0
66 */
67 public static function init() {
68 add_shortcode( 'quiz', array( __CLASS__, 'shortcode' ) );
69 add_shortcode( 'question', array( __CLASS__, 'question_shortcode' ) );
70 add_shortcode( 'answer', array( __CLASS__, 'answer_shortcode' ) );
71 add_shortcode( 'wrong', array( __CLASS__, 'wrong_shortcode' ) );
72 add_shortcode( 'explanation', array( __CLASS__, 'explanation_shortcode' ) );
73 }
74
75 /**
76 * Enqueue assets needed by the quiz,
77 *
78 * @since 4.5.0
79 */
80 private static function enqueue_scripts() {
81 wp_enqueue_style( 'quiz', plugins_url( 'css/quiz.css', __FILE__ ), array(), JETPACK__VERSION );
82 wp_enqueue_script(
83 'quiz',
84 Jetpack::get_file_url_for_environment( '_inc/build/shortcodes/js/quiz.min.js', 'modules/shortcodes/js/quiz.js' ),
85 array( 'jquery' ),
86 JETPACK__VERSION,
87 true
88 );
89 }
90
91 /**
92 * Check if this is a feed and thus JS is unavailable.
93 *
94 * @since 4.5.0
95 *
96 * @return bool|null
97 */
98 private static function is_javascript_unavailable() {
99 if ( ! is_null( self::$javascript_unavailable ) ) {
100 return self::$javascript_unavailable;
101 }
102
103 if ( is_feed() ) {
104 self::$javascript_unavailable = true;
105 return self::$javascript_unavailable;
106 }
107
108 self::$javascript_unavailable = false;
109 return self::$javascript_unavailable;
110 }
111
112 /**
113 * Display message when JS is not available.
114 *
115 * @since 4.5.0
116 *
117 * @return string
118 */
119 private static function noscript_info() {
120 if ( self::$noscript_info_printed ) {
121 return '';
122 }
123 self::$noscript_info_printed = true;
124 return '<noscript><div><i>' . esc_html__( 'Please view this post in your web browser to complete the quiz.', 'jetpack' ) . '</i></div></noscript>';
125 }
126
127 /**
128 * Check if we're in WordPress.com.
129 *
130 * @since 4.5.0
131 *
132 * @return bool
133 */
134 public static function is_wpcom() {
135 return defined( 'IS_WPCOM' ) && IS_WPCOM;
136 }
137
138 /**
139 * Parse shortcode arguments and render its output.
140 *
141 * @since 4.5.0
142 *
143 * @param array $atts Shortcode parameters.
144 * @param string $content Content enclosed by shortcode tags.
145 *
146 * @return string
147 */
148 public static function shortcode( $atts, $content = null ) {
149
150 // There's nothing to do if there's nothing enclosed.
151 if ( empty( $content ) ) {
152 return '';
153 }
154
155 $id = '';
156
157 if ( self::is_javascript_unavailable() ) {
158 // in an e-mail print the question and the info sentence once per question, too.
159 self::$noscript_info_printed = false;
160 } else {
161
162 if ( ! self::$scripts_enqueued ) {
163 // lazy enqueue cannot use the wp_enqueue_scripts action anymore.
164 self::enqueue_scripts();
165 self::$scripts_enqueued = true;
166 }
167
168 $default_atts = self::is_wpcom()
169 ? array(
170 'trackid' => '',
171 'a8ctraining' => '',
172 )
173 : array(
174 'trackid' => '',
175 );
176
177 self::$quiz_params = shortcode_atts( $default_atts, $atts );
178
179 if ( ! empty( self::$quiz_params['trackid'] ) ) {
180 $id .= ' data-trackid="' . esc_attr( self::$quiz_params['trackid'] ) . '"';
181 }
182 if ( self::is_wpcom() && ! empty( self::$quiz_params['a8ctraining'] ) ) {
183 if ( is_null( self::$username ) ) {
184 self::$username = wp_get_current_user()->user_login;
185 }
186 $id .= ' data-a8ctraining="' . esc_attr( self::$quiz_params['a8ctraining'] ) . '" data-username="' . esc_attr( self::$username ) . '"';
187 }
188 }
189
190 $quiz = self::do_shortcode( $content );
191 return '<div class="jetpack-quiz quiz"' . $id . '>' . $quiz . '</div>';
192 }
193
194 /**
195 * Strip line breaks, restrict allowed HTML to a few whitelisted tags and execute nested shortcodes.
196 *
197 * @since 4.5.0
198 *
199 * @param string $content Post content.
200 *
201 * @return mixed|string
202 */
203 private static function do_shortcode( $content ) {
204 // strip autoinserted line breaks.
205 $content = preg_replace( '#(<(?:br /|/?p)>\n?)*(\[/?[a-z]+\])(<(?:br /|/?p)>\n?)*#', '$2', $content );
206
207 // Add internal parameter so it's only rendered when it has it.
208 $content = preg_replace( '/\[(question|answer|wrong|explanation)\]/i', '[$1 quiz_item="true"]', $content );
209 $content = do_shortcode( $content );
210 $content = wp_kses(
211 $content,
212 array(
213 'tt' => array(),
214 'a' => array( 'href' => true ),
215 'pre' => array(),
216 'strong' => array(),
217 'i' => array(),
218 'br' => array(),
219 'img' => array( 'src' => true ),
220 'div' => array(
221 'class' => true,
222 'data-correct' => 1,
223 'data-track-id' => 1,
224 'data-a8ctraining' => 1,
225 'data-username' => 1,
226 ),
227 )
228 );
229 return $content;
230 }
231
232 /**
233 * Render question.
234 *
235 * @since 4.5.0
236 *
237 * @param array $atts Shortcode attributes.
238 * @param null $content Post content.
239 *
240 * @return string
241 */
242 public static function question_shortcode( $atts, $content = null ) {
243 return isset( $atts['quiz_item'] )
244 ? '<div class="jetpack-quiz-question question">' . self::do_shortcode( $content ) . '</div>'
245 : '';
246 }
247
248 /**
249 * Render correct answer.
250 *
251 * @since 4.5.0
252 *
253 * @param array $atts Shortcode attributes.
254 * @param null $content Post content.
255 *
256 * @return string
257 */
258 public static function answer_shortcode( $atts, $content = null ) {
259 if ( self::is_javascript_unavailable() ) {
260 return self::noscript_info();
261 }
262
263 return isset( $atts['quiz_item'] )
264 ? '<div class="jetpack-quiz-answer answer" data-correct="1">' . self::do_shortcode( $content ) . '</div>'
265 : '';
266 }
267
268 /**
269 * Render wrong response.
270 *
271 * @since 4.5.0
272 *
273 * @param array $atts Shortcode attributes.
274 * @param null $content Post content.
275 *
276 * @return string
277 */
278 public static function wrong_shortcode( $atts, $content = null ) {
279 if ( self::is_javascript_unavailable() ) {
280 return self::noscript_info();
281 }
282
283 return isset( $atts['quiz_item'] )
284 ? '<div class="jetpack-quiz-answer answer">' . self::do_shortcode( $content ) . '</div>'
285 : '';
286 }
287
288 /**
289 * Render explanation for wrong or right answer.
290 *
291 * @since 4.5.0
292 *
293 * @param array $atts Shortcode attributes.
294 * @param null $content Post content.
295 *
296 * @return string
297 */
298 public static function explanation_shortcode( $atts, $content = null ) {
299 if ( self::is_javascript_unavailable() ) {
300 return self::noscript_info();
301 }
302
303 return isset( $atts['quiz_item'] )
304 ? '<div class="jetpack-quiz-explanation explanation">' . self::do_shortcode( $content ) . '</div>'
305 : '';
306 }
307 }
308
309 Quiz_Shortcode::init();
310