PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 6.3.2
Jetpack – WP Security, Backup, Speed, & Growth v6.3.2
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 6.3.2, at modules/shortcodes/quiz.php

299 lines 6.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
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__ ) );
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 null,
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 return self::$javascript_unavailable = true;
105 }
106
107 return self::$javascript_unavailable = false;
108 }
109
110 /**
111 * Display message when JS is not available.
112 *
113 * @since 4.5.0
114 *
115 * @return string
116 */
117 private static function noscript_info() {
118 if ( self::$noscript_info_printed ) {
119 return '';
120 }
121 self::$noscript_info_printed = true;
122 return '<noscript><div><i>' . esc_html__( 'Please view this post in your web browser to complete the quiz.', 'jetpack' ) . '</i></div></noscript>';
123 }
124
125 /**
126 * Check if we're in WordPress.com.
127 *
128 * @since 4.5.0
129 *
130 * @return bool
131 */
132 public static function is_wpcom() {
133 return defined( 'IS_WPCOM' ) && IS_WPCOM;
134 }
135
136 /**
137 * Parse shortcode arguments and render its output.
138 *
139 * @since 4.5.0
140 *
141 * @param array $atts Shortcode parameters.
142 * @param string $content Content enclosed by shortcode tags.
143 *
144 * @return string
145 */
146 public static function shortcode( $atts, $content = null ) {
147
148 // There's nothing to do if there's nothing enclosed.
149 if ( null == $content ) {
150 return '';
151 }
152
153 $id = '';
154
155 if ( self::is_javascript_unavailable() ) {
156 // in an e-mail print the question and the info sentence once per question, too
157 self::$noscript_info_printed = false;
158 } else {
159
160 if ( ! self::$scripts_enqueued ) {
161 // lazy enqueue cannot use the wp_enqueue_scripts action anymore
162 self::enqueue_scripts();
163 self::$scripts_enqueued = true;
164 }
165
166 $default_atts = self::is_wpcom()
167 ? array(
168 'trackid' => '',
169 'a8ctraining' => '',
170 )
171 : array(
172 'trackid' => '',
173 );
174
175
176 self::$quiz_params = shortcode_atts( $default_atts, $atts );
177
178 if ( ! empty( self::$quiz_params[ 'trackid' ] ) ) {
179 $id .= ' data-trackid="' . esc_attr( self::$quiz_params[ 'trackid' ] ) . '"';
180 }
181 if ( self::is_wpcom() && ! empty( self::$quiz_params[ 'a8ctraining' ] ) ) {
182 if ( is_null( self::$username ) ) {
183 self::$username = wp_get_current_user()->user_login;
184 }
185 $id .= ' data-a8ctraining="'. esc_attr( self::$quiz_params[ 'a8ctraining' ] ) . '" data-username="' . esc_attr( self::$username ) . '"';
186 }
187 }
188
189 $quiz = self::do_shortcode( $content );
190 return '<div class="jetpack-quiz quiz"' . $id . '>' . $quiz . '</div>';
191 }
192
193 /**
194 * Strip line breaks, restrict allowed HTML to a few whitelisted tags and execute nested shortcodes.
195 *
196 * @since 4.5.0
197 *
198 * @param string $content
199 *
200 * @return mixed|string
201 */
202 private static function do_shortcode( $content ) {
203 // strip autoinserted line breaks
204 $content = preg_replace( '#(<(?:br /|/?p)>\n?)*(\[/?[a-z]+\])(<(?:br /|/?p)>\n?)*#', '$2', $content );
205
206 // Add internal parameter so it's only rendered when it has it
207 $content = preg_replace( '/\[(question|answer|wrong|explanation)\]/i', '[$1 quiz_item="true"]', $content );
208 $content = do_shortcode( $content );
209 $content = wp_kses( $content, array(
210 'tt' => array(),
211 'pre' => array(),
212 'strong' => array(),
213 'i' => array(),
214 'br' => array(),
215 'img' => array( 'src' => true),
216 'div' => array( 'class' => true, 'data-correct' => 1, 'data-track-id' => 1, 'data-a8ctraining' => 1, 'data-username' => 1 ),
217 ) );
218 return $content;
219 }
220
221 /**
222 * Render question.
223 *
224 * @since 4.5.0
225 *
226 * @param array $atts
227 * @param null $content
228 *
229 * @return string
230 */
231 public static function question_shortcode( $atts, $content = null ) {
232 return isset( $atts['quiz_item'] )
233 ? '<div class="jetpack-quiz-question question">' . self::do_shortcode( $content ) . '</div>'
234 : '';
235 }
236
237 /**
238 * Render correct answer.
239 *
240 * @since 4.5.0
241 *
242 * @param array $atts
243 * @param null $content
244 *
245 * @return string
246 */
247 public static function answer_shortcode( $atts, $content = null ) {
248 if ( self::is_javascript_unavailable() ) {
249 return self::noscript_info();
250 }
251
252 return isset( $atts['quiz_item'] )
253 ? '<div class="jetpack-quiz-answer answer" data-correct="1">' . self::do_shortcode( $content ) . '</div>'
254 : '';
255 }
256
257 /**
258 * Render wrong response.
259 *
260 * @since 4.5.0
261 *
262 * @param array $atts
263 * @param null $content
264 *
265 * @return string
266 */
267 public static function wrong_shortcode( $atts, $content = null ) {
268 if ( self::is_javascript_unavailable() ) {
269 return self::noscript_info();
270 }
271
272 return isset( $atts['quiz_item'] )
273 ? '<div class="jetpack-quiz-answer answer">' . self::do_shortcode( $content ) . '</div>'
274 : '';
275 }
276
277 /**
278 * Render explanation for wrong or right answer.
279 *
280 * @since 4.5.0
281 *
282 * @param array $atts
283 * @param null $content
284 *
285 * @return string
286 */
287 public static function explanation_shortcode( $atts, $content = null ) {
288 if ( self::is_javascript_unavailable() ) {
289 return self::noscript_info();
290 }
291
292 return isset( $atts['quiz_item'] )
293 ? '<div class="jetpack-quiz-explanation explanation">' . self::do_shortcode( $content ) . '</div>'
294 : '';
295 }
296 }
297
298 Quiz_Shortcode::init();
299