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

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