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

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