Diff: STRATO-apps/wordpress_03/app/wp-content/plugins/fluentformpro/src/classes/Quiz/QuizController.php

Keine Baseline-Datei – Diff nur gegen leer.
Zur Liste
1 -
1 + <?php
2 +
3 +
4 + namespace FluentFormPro\classes\Quiz;
5 +
6 + use FluentForm\App\Helpers\Helper;
7 + use FluentForm\App\Modules\Acl\Acl;
8 + use FluentForm\App\Modules\Form\FormFieldsParser;
9 + use FluentForm\App\Services\FormBuilder\ShortCodeParser;
10 + use FluentForm\Framework\Helpers\ArrayHelper as Arr;
11 +
12 + class QuizController
13 + {
14 + public $metaKey = '_quiz_settings';
15 + public $key = 'quiz_addon';
16 + protected $app;
17 +
18 + public function init($app)
19 + {
20 + $this->app = $app;
21 + $enabled = $this->isEnabled();
22 +
23 + $this->addToGlobalMenu($enabled);
24 +
25 + if (!$enabled) {
26 + return;
27 + }
28 + $this->addToFormSettingsMenu();
29 +
30 + $this->maybeRandomize();
31 +
32 + $this->registerAjaxHandlers();
33 +
34 + add_filter('fluentform/all_editor_shortcodes', function ($shortCodes) {
35 + $shortCodes[] = [
36 + 'title' => __('Quiz', 'fluentformpro'),
37 + 'shortcodes' => [
38 + '{quiz_result}' => 'Quiz Result Table'
39 + ]
40 + ];
41 + return $shortCodes;
42 + });
43 +
44 + new QuizScoreComponent();
45 + add_filter('safe_style_css', function ($styles) {
46 + $style_tags = ['display'];
47 + $style_tags = apply_filters('fluentform/allowed_css_properties', $style_tags);
48 + foreach ($style_tags as $tag) {
49 + $styles[] = $tag;
50 + }
51 + return $styles;
52 + });
53 + add_filter('fluentform/shortcode_parser_callback_quiz_result', [$this, 'getQuizResultTable'], 10, 2);
54 +
55 + add_filter('fluentform/form_submission_confirmation', [$this, 'maybeAppendResult'], 10, 3);
56 +
57 + add_filter('fluentform/submission_cards', [$this, 'pushQuizResult'], 10, 3);
58 + }
59 +
60 + public function registerAjaxHandlers()
61 + {
62 + $this->app->addAdminAjaxAction('ff_get_quiz_module_settings', [$this, 'getSettingsAjax']);
63 + $this->app->addAdminAjaxAction('ff_store_quiz_module_settings', [$this, 'saveSettingsAjax']);
64 + $this->app->addAdminAjaxAction('ff_delete_quiz_module_settings', [$this, 'deleteSettingsAjax']);
65 + }
66 +
67 + public function getSettingsAjax()
68 + {
69 + $formId = intval($this->app->request->get('form_id'));
70 + Acl::verify('fluentform_forms_manager', $formId);
71 + $settings = $this->getSettings($formId);
72 + wp_send_json_success([
73 + 'settings' => $settings,
74 + 'quiz_fields' => $this->getQuizFields($formId),
75 + 'settings_fields' => QuizController::getIntegrationFields(),
76 + ]);
77 + }
78 +
79 + public function saveSettingsAjax()
80 + {
81 + $formId = intval($this->app->request->get('form_id'));
82 + Acl::verify('fluentform_forms_manager', $formId);
83 + $settings = $this->app->request->get('settings');
84 +
85 + $sanitizeMap = [
86 + 'enabled' => 'rest_sanitize_boolean',
87 + 'randomize_answer' => 'rest_sanitize_boolean',
88 + 'append_result' => 'rest_sanitize_boolean',
89 + 'randomize_question' => 'rest_sanitize_boolean',
90 + ];
91 + $settings = fluentform_backend_sanitizer($settings, $sanitizeMap);
92 +
93 + $formattedSettings = wp_unslash($settings);
94 + Helper::setFormMeta($formId, $this->metaKey, $formattedSettings);
95 +
96 + wp_send_json_success([
97 + 'message' => __('Settings successfully updated', 'fluentformpro'),
98 + ]);
99 + }
100 +
101 + public function deleteSettingsAjax()
102 + {
103 + $formId = intval($this->app->request->get('form_id'));
104 + Acl::verify('fluentform_forms_manager', $formId);
105 + Helper::deleteFormMeta($formId, $this->metaKey);
106 +
107 + wp_send_json_success([
108 + 'message' => __('Settings deleted successfully', 'fluentformpro'),
109 + ]);
110 + }
111 +
112 + public function getSettings($formId)
113 + {
114 + $settings = Helper::getFormMeta($formId, $this->metaKey, []);
115 + $form = $this->getForm($formId);
116 + $fields = $this->getQuizFields($form);
117 + $resultType = self::getScoreType($form);
118 +
119 + $defaults = [
120 + 'enabled' => false,
121 + 'randomize_answer' => false,
122 + 'append_result' => true,
123 + 'randomize_question' => false,
124 + 'saved_quiz_fields' => $fields,
125 + 'grades' => [
126 + [
127 + 'label' => 'A',
128 + 'min' => 90,
129 + 'max' => 100,
130 + ],
131 + [
132 + 'label' => 'B',
133 + 'min' => 80,
134 + 'max' => 89,
135 + ],
136 + [
137 + 'label' => 'C',
138 + 'min' => 70,
139 + 'max' => 79,
140 + ],
141 + ]
142 + ];
143 +
144 + $settings = $this->removeDeletedFields($settings, $fields);
145 +
146 + $settings = wp_parse_args($settings, $defaults);
147 + $settings['saved_quiz_fields'] = empty($settings['saved_quiz_fields']) ? [] : $settings['saved_quiz_fields'];
148 + $settings['result_type'] = $resultType;
149 + return $settings;
150 + }
151 +
152 + protected function getForm($formId)
153 + {
154 + return wpFluent()->table('fluentform_forms')->find($formId);
155 + }
156 +
157 + public static function getIntegrationFields()
158 + {
159 + return [
160 + [
161 + 'key' => 'append_result',
162 + 'label' => 'Append Result',
163 + 'component' => 'checkbox-single',
164 + 'checkbox_label' => __('Show Result on confirmation page', 'fluentformpro')
165 +
166 + ],
167 + [
168 + 'key' => 'randomize_question',
169 + 'label' => 'Randomize Questions',
170 + 'checkbox_label' => __('Questions will be randomized each time its loaded', 'fluentformpro'),
171 + 'component' => 'checkbox-single'
172 + ],
173 + [
174 + 'key' => 'randomize_answer',
175 + 'label' => 'Randomize Options',
176 + 'checkbox_label' => __('Options will be randomized each time its loaded', 'fluentformpro'),
177 + 'component' => 'checkbox-single'
178 + ],
179 +
180 + ];
181 + }
182 +
183 + public function isEnabled()
184 + {
185 + $globalModules = get_option('fluentform_global_modules_status');
186 + $quizAddon = Arr::get($globalModules, $this->key);
187 +
188 + if ($quizAddon == 'yes') {
189 + return true;
190 + }
191 +
192 + return false;
193 + }
194 +
195 + public function addToGlobalMenu($enabled)
196 + {
197 + add_filter('fluentform/global_addons', function ($addOns) use ($enabled) {
198 + $addOns[$this->key] = [
199 + 'title' => 'Quiz Module',
200 + 'description' => __('With this module, you can create quizzes and show scores with grades, points, fractions, or percentages', 'fluentformpro'),
201 + 'logo' => fluentFormMix('img/integrations/quiz-icon.svg'),
202 + 'enabled' => ($enabled) ? 'yes' : 'no',
203 + 'config_url' => '',
204 + 'category' => ''
205 + ];
206 +
207 + return $addOns;
208 + }, 9);
209 + }
210 +
211 + public function addToFormSettingsMenu()
212 + {
213 + add_filter('fluentform/form_settings_menu', function ($menu) {
214 + $menu['quiz_settings'] = [
215 + 'title' => __('Quiz Settings', 'fluentform'),
216 + 'slug' => 'form_settings',
217 + 'hash' => 'quiz_settings',
218 + 'route' => '/quiz_settings'
219 + ];
220 +
221 + return $menu;
222 + });
223 + }
224 +
225 + /**
226 + * Maybe Randomize Questions and Answers
227 + *
228 + * @return void
229 + */
230 + public function maybeRandomize()
231 + {
232 +
233 + add_filter('fluentform/rendering_form', function ($form) {
234 + $settings = $this->getSettings($form->id);
235 + $enabled = $settings['enabled'] == 'yes';
236 + if (!$enabled) {
237 + return $form;
238 + }
239 + if ($settings['randomize_answer']) {
240 + $this->randomizeCheckableInputs();
241 + }
242 + if (!$settings['randomize_question']) {
243 + return $form;
244 + }
245 + $fields = $form->fields;
246 +
247 + $quizFields = $this->getQuizFields($form);
248 + $quizFieldsKeys = array_keys($quizFields);
249 + $formQuizFields = array_filter($fields['fields'], function ($field) use ($quizFieldsKeys) {
250 + return in_array(Arr::get($field, 'attributes.name'), $quizFieldsKeys);
251 + });
252 + if (empty($formQuizFields)) {
253 + return $form;
254 + }
255 + $quizGroup = [];
256 + $i = 0;
257 + foreach ($formQuizFields as $key => $field) {
258 + $inSequence = isset($formQuizFields[$key + 1]) ? $formQuizFields[$key + 1] : false;
259 + if ($inSequence) {
260 + $quizGroup[$i][$key] = $field;
261 + } else {
262 + $quizGroup[$i][$key] = $field;
263 + $i++;
264 + }
265 + }
266 + //shuffle groups and replace their positions in the original array
267 + foreach ($quizGroup as $group) {
268 + $startIndex = Arr::get(array_keys($group), '0');
269 + shuffle($group);
270 + $length = count($group);
271 + array_splice($fields['fields'], $startIndex, $length, $group);
272 + }
273 +
274 + $form->fields = $fields;
275 +
276 + return $form;
277 + }, 10, 1);
278 + }
279 +
280 +
281 + /**
282 + * Generate Quiz Result Table
283 + *
284 + * @param $shortCode
285 + * @param ShortCodeParser $parser
286 + *
287 + * @return string|void
288 + */
289 + public function getQuizResultTable($shortCode, ShortCodeParser $parser)
290 + {
291 + $form = $parser::getForm();
292 + $entry = $parser::getEntry();
293 + $quizSettings = $this->getSettings($form->id);
294 + $quizFields = Arr::get($quizSettings,'saved_quiz_fields');
295 +
296 + if (!$entry || !$form || $quizSettings['enabled'] != 'yes') {
297 + return;
298 + }
299 +
300 + $scoreType = self::getScoreType($form);
301 + $response = json_decode($entry->response, true);
302 + $results = $this->getFormattedResults($quizSettings, $response, $form);
303 +
304 + /* For full width in single entry page */
305 + $width = defined('FLUENTFORM_RENDERING_ENTRIES') ? '' : ' width="600"';
306 + $html = '<table class="table ff_quiz_result_table" ' . $width . ' cellpadding="0" cellspacing="0" style="min-width: 100%"><tbody>';
307 + $hasRightWrongAns = !in_array($scoreType, ['total_point', 'personality']) ? true : false;
308 + $rightWrongHtml = '';
309 + $forPdf = method_exists($parser, 'getProvider') && 'pdfFeed' === $parser::getProvider();
310 +
311 + foreach ($results as $name => $result) {
312 +
313 + if( !in_array($name,array_keys($quizFields))){
314 + continue;
315 + }
316 + //question
317 +
318 + $icon = $result['correct'] == true ? self::getRightIcon($forPdf) : self::getWrongIcon($forPdf);
319 + $rightWrongHtml = $hasRightWrongAns ? "<div style='width: 20px; margin-right: 10px;'>$icon</div>" : '';
320 + $html .= "<tr class=\"field-label\">
321 + <td style=' align-items: center; padding: 6px 12px; background-color: #f8f8f8; text-align: left; clear: both; display: flex;'>
322 + {$rightWrongHtml} <div><b>{$result['label']}</b></div>
323 + </td>
324 + </tr>";
325 + //answer
326 + if ('personality' == $scoreType) {
327 + $result['user_value'] = static::labelFromValue($result['user_value'], $result['options'], $result, 'user_value');
328 + }
329 + $userValueFormatted = is_array($result['user_value']) ? join(', ', $result['user_value']) : $result['user_value'];
330 + $userValueFormatted = empty($userValueFormatted) ? '-' :$userValueFormatted;
331 + if (is_string($userValueFormatted)) {
332 + $userValueFormatted = isset($result['options'][$userValueFormatted]) ? $result['options'][$userValueFormatted] : $userValueFormatted;
333 + }
334 +
335 + $html .= sprintf(
336 + "<tr class=\"user-value\"><td style=\"padding: 6px 12px 12px 12px;\"> %s</td>",
337 + $userValueFormatted
338 + );
339 +
340 + $correctAnsFormatted = is_array($result['correct_value']) ? join(', ', $result['correct_value']) : $result['correct_value'];
341 + //skip right wrong for when total point is selected
342 + if ($scoreType == 'total_point') {
343 + $score = 0;
344 + if ($result['has_advance_scoring'] == 'yes') {
345 + $score = $result['advance_points_score'];
346 + } else {
347 + if ($result['correct']) {
348 + $score = $result['points'];
349 + }
350 + }
351 +
352 + $html .= sprintf(
353 + "<tr class=\"field-value\"><td style=\"padding: 6px 12px 12px 12px;\">%s : %s</td>",
354 + __('Point', 'fluentformpro'),
355 + $score
356 + );
357 + }
358 + else if (!$result['correct'] && $scoreType != 'total_point' && $scoreType != 'personality') {
359 + $conditionText = '';
360 + if ($result['correct_ans_condition'] == 'not_includes') {
361 + $conditionText = 'does Not includes ';
362 + } elseif ($result['correct_ans_condition'] == 'includes_any') {
363 + $conditionText = 'any of the following ';
364 + } elseif ($result['correct_ans_condition'] == 'includes_all') {
365 + $conditionText = 'all of the following ';
366 + }
367 + if($rightWrongHtml){
368 + $html .= sprintf(
369 + "<tr class=\"field-value\"><td style=\"padding: 6px 12px 12px 12px;\">%s %s: %s</td>",
370 + __('Correct answer', 'fluentformpro'),
371 + $conditionText,
372 + $correctAnsFormatted
373 + );
374 + }
375 +
376 + }
377 + $html .= '</tr>';
378 + }
379 + if ($scoreType == 'personality') {
380 +
381 + $scoreInput = self::getScoreInput($form);
382 +
383 + $personalityResult = $this->getUserSelectedValues($results);
384 + $result = QuizScoreComponent::determinePersonality($personalityResult, $scoreInput, $form);
385 + $result = Arr::get($scoreInput, "raw.options.$result", $result);
386 + $personalityLabel = apply_filters('fluentform/quiz_personality_label',__('Personality', 'fluentformpro'),$form);
387 + $html .= sprintf(
388 + "<tr class=\"field-label\"> <td style=\"display:flex;align-items: center; padding: 6px 12px; background-color: #f8f8f8; text-align: left;\"> <div><b>%s </b></div></td></tr>",
389 + $personalityLabel
390 + );
391 +
392 + $html .= sprintf(
393 + "<tr class=\"field-value\"><td style=\"padding: 6px 12px 12px 12px;\">%s</td>",
394 + $result
395 + );
396 + $html .= '</tr>';
397 +
398 + }
399 +
400 + $html .= '</tbody></table>';
401 + return apply_filters('fluentform/quiz_result_table_html', $html, $form, $results, $quizSettings, $entry);
402 + }
403 +
404 +
405 + /**
406 + * Get Available Quiz Fields
407 + *
408 + * @param $form
409 + *
410 + * @return array|mixed
411 + */
412 + protected function getQuizFields($form)
413 + {
414 + $fields = FormFieldsParser::getEntryInputs($form, ['admin_label', 'label', 'element', 'options']);
415 + $supportedQuizFields = [
416 + 'input_text',
417 + 'input_radio',
418 + 'input_checkbox',
419 + 'select',
420 + 'input_number',
421 + 'input_date',
422 + 'rangeslider'
423 + ];
424 + $fields = array_filter($fields, function ($field) use ($supportedQuizFields) {
425 + return in_array($field['element'], $supportedQuizFields);
426 + });
427 +
428 + foreach ($fields as $name => $value) {
429 + $fields[$name]['enabled'] = false;
430 + $fields[$name]['points'] = 1;
431 + $fields[$name]['correct_answer'] = [];
432 + $fields[$name]['condition'] = 'equal';
433 + $fields[$name]['has_advance_scoring'] = 'no';
434 + $fields[$name]['advance_points'] = $this->advancePoints($fields[$name]);
435 + }
436 + return $fields;
437 + }
438 +
439 + /**
440 + * Remove Deleted inputs
441 + *
442 + * @param $settings
443 + * @param $fields
444 + *
445 + * @return mixed
446 + */
447 + protected function removeDeletedFields($settings, $fields)
448 + {
449 + if (!isset($settings['saved_quiz_fields'])) {
450 + return $settings;
451 + }
452 + $savedFields = $settings['saved_quiz_fields'];
453 + foreach ($savedFields as $fieldKey => $value) {
454 + if (!isset($fields[$fieldKey])) {
455 + unset($savedFields[$fieldKey]);
456 + }
457 + if (Arr::exists($fields,$fieldKey) && Arr::exists($fields[$fieldKey], 'options')) {
458 + $savedFields[$fieldKey]['options'] = Arr::get($fields[$fieldKey], 'options');
459 + }
460 + }
461 + $settings['saved_quiz_fields'] = $savedFields;
462 +
463 + return $settings;
464 + }
465 +
466 +
467 + /**
468 + * Validate Answer
469 + *
470 + * @param $settings
471 + * @param $userValue
472 + * @param $correctValue
473 + *
474 + * @return bool
475 + */
476 +
477 + protected function isCorrect($settings, $userValue, $correctValue = '', $options = [])
478 + {
479 + $isCorrect = false;
480 + $element = $settings['element'];
481 + switch ($element) {
482 + case 'input_radio':
483 + if (!$userValue) {
484 + break;
485 + }
486 +
487 + if (in_array($userValue, $correctValue)) {
488 + $isCorrect = true;
489 + }
490 +
491 + break;
492 + case 'select':
493 + case 'input_text':
494 + case 'rangeslider':
495 + case 'input_date':
496 + case 'input_checkbox':
497 + case 'input_number':
498 + if (!$userValue) {
499 + break;
500 + }
501 + $hasAdvanceScoring = $settings['has_advance_scoring'] === 'yes';
502 + if ($hasAdvanceScoring) {
503 + //check if select is not a multiselect
504 + if ($element == 'select' && is_string($correctValue)) {
505 + $isCorrect = $userValue == $correctValue;
506 + break;
507 + }
508 +
509 + //if it has advance scoring then for right answer match all value greater than 0 with user values
510 + //else assume as wrong answer but count the scores
511 + $correctValues = static::labelFromValue($correctValue, $options, $settings, 'correct_value');
512 +
513 + return count(array_intersect($userValue, $correctValues)) == count($userValue);
514 + }
515 + $condition = Arr::get($settings, 'condition');
516 +
517 + if ($condition == 'equal') {
518 + if (is_array($correctValue)) {
519 + $correctValue = array_shift($correctValue);
520 + }
521 + if (is_array($userValue)) {
522 + $userValue = array_shift($userValue);
523 + }
524 + if (apply_filters('fluentform/quiz_case_sensitive_off', __return_false())) {
525 + $userValue = strtolower($userValue);
526 + $correctValue = strtolower($correctValue);
527 + }
528 + if ($userValue == $correctValue) {
529 + $isCorrect = true;
530 + }
531 + } elseif ($condition == 'includes_any') {
532 + //check if any user values exists in correct answers
533 + if (!is_array($userValue)) {
534 + $userValue = [$userValue];
535 + }
536 + $isCorrect = (bool)array_intersect($correctValue, $userValue);
537 + } elseif ($condition == 'includes_all') {
538 + //check if all user values exists in correct answers
539 + if (!is_array($userValue)) {
540 + $userValue = [$userValue];
541 + }
542 + $commonValue = array_intersect($correctValue, $userValue);
543 + $isCorrect = $commonValue && count($commonValue) == count($userValue) && count($correctValue) == count($commonValue);
544 + } elseif ($condition == 'not_includes') {
545 + //check if all user values not exists in correct answers
546 + if (!is_array($userValue)) {
547 + $userValue = [$userValue];
548 + }
549 + $isCorrect = !array_intersect($correctValue, $userValue);
550 + }
551 + break;
552 + }
553 +
554 + return $isCorrect;
555 + }
556 +
557 + /**
558 + * Get Formatted Quiz Result
559 + *
560 + * @param $quizFields
561 + * @param $response
562 + *
563 + * @return array
564 + */
565 + public function getFormattedResults($quizSettings, $response, $form)
566 + {
567 + $quizFields = $quizSettings['saved_quiz_fields'];
568 + $quizType = Arr::get($quizSettings,'result_type');
569 + $inputs = FormFieldsParser::getInputs($form, ['element', 'options', 'label']);
570 + $quizResults = [];
571 + $quizFields = $this->arrayReposition($quizFields, array_keys($inputs));
572 + foreach ($quizFields as $key => $settings) {
573 + if ($settings['enabled'] != true) {
574 + continue;
575 + }
576 + $correctValue = Arr::get($settings, 'correct_answer');
577 + $userValue = Arr::get($response, $key, '');
578 + $options = Arr::get($inputs, $key . '.options');
579 + $quizResults[$key] = [
580 + 'correct' => $this->isCorrect($settings, $userValue, $correctValue, $options),
581 + 'correct_value' => static::labelFromValue($correctValue, $options, $settings, 'correct_value'),
582 + 'correct_ans_condition' => $settings['condition'],
583 + 'options' => $options,
584 + 'user_value' => ($quizType != 'personality') ? static::labelFromValue($userValue, $options, $settings, 'user_value') : $userValue,
585 + 'points' => $settings['points'],
586 + 'label' => Arr::get($inputs, $key . '.label'),
587 + 'has_advance_scoring' => $settings['has_advance_scoring'],
588 + 'advance_points' => array_reduce($settings['advance_points'], function ($sum, $itemScore) {
589 + $sum += $itemScore;
590 + return $sum;
591 + }),
592 + 'advance_points_score' => $this->calcAdvancePoints($settings, $userValue),
593 + ];
594 + }
595 + return $quizResults;
596 + }
597 +
598 + /**
599 + * Calculate user selected values from quiz results.
600 + *
601 + * @param array $quizResults
602 + * @return array
603 + */
604 + public function getUserSelectedValues($quizResults)
605 + {
606 + $userSelectedValues = [];
607 + foreach ($quizResults as $result) {
608 + if(empty($result['user_value'])){
609 + continue;
610 + }
611 + if (is_array($result['user_value'])) {
612 + // If 'user_value' is an array
613 + $userSelectedValues = array_merge($userSelectedValues, $result['user_value']);
614 + } else {
615 + // If 'user_value' is a string, convert it to an array
616 + $userSelectedValues[] = $result['user_value'];
617 + }
618 + }
619 +
620 + return $userSelectedValues;
621 + }
622 + /**
623 + * Array Restructured to get Form Fields structure
624 + * @param $array
625 + * @param $keys
626 + * @return array
627 + */
628 + protected function arrayReposition($array, $keys)
629 + {
630 + $returnArray = [];
631 + foreach ($keys as $key) {
632 + if (Arr::get($array, $key)) {
633 + $returnArray[$key] = Arr::get($array, $key);
634 + }
635 + }
636 +
637 + return $returnArray;
638 + }
639 +
640 + /**
641 + * Get input label from value
642 + *
643 + * @param $targetValues
644 + * @param $options
645 + * @param $settings
646 + * @param $type
647 + * @return array|mixed
648 + */
649 + private static function labelFromValue($targetValues, $options, $settings, $type)
650 + {
651 + $hasAdvanceScoring = $settings['has_advance_scoring'] === 'yes';
652 + if ($hasAdvanceScoring && $type == 'correct_value') {
653 + $advanceScores = Arr::get($settings, 'advance_points');
654 + $correctOptions = [];
655 + foreach ($advanceScores as $label => $score) {
656 + if ($score >= 1) {
657 + $correctOptions[] = $label;
658 + }
659 + }
660 + return $correctOptions;
661 + }
662 + if (is_array($targetValues)) {
663 + $formattedValue = [];
664 + foreach ($targetValues as $value) {
665 + $formattedValue[] = isset($options[$value]) ? $options[$value] : $value;
666 + }
667 + $targetValues = $formattedValue;
668 + } else {
669 + $targetValues = isset($options[$targetValues]) ? $options[$targetValues] : $targetValues;
670 + }
671 + return $targetValues;
672 + }
673 +
674 + /**
675 + * Maybe Append quiz result
676 + *
677 + * @param $data
678 + * @param $formData
679 + * @param $form
680 + *
681 + * @return mixed
682 + */
683 + public function maybeAppendResult($data, $formData, $form)
684 + {
685 + $settings = $this->getSettings($form->id);
686 + if ($settings['append_result'] == true) {
687 + $data['messageToShow'] .= '{quiz_result}';
688 + }
689 +
690 + return $data;
691 + }
692 +
693 +
694 + /**
695 + * Adds quiz result in the single entry page
696 + * @param $cards
697 + * @param $entryData
698 + * @param $submission
699 + * @return array|mixed
700 + */
701 + public function pushQuizResult($cards, $entryData, $submission)
702 + {
703 + $formId = $submission->form_id;
704 +
705 + $settings = $this->getSettings($formId);
706 +
707 + if (($settings['enabled'] != 'yes')) {
708 + return $cards;
709 + }
710 + $form = $this->getForm($formId);
711 +
712 + $contents = '<p>{quiz_result}</p>';
713 + $resultHtml = ShortCodeParser::parse(
714 + $contents,
715 + $submission->id,
716 + $entryData,
717 + $form
718 + );
719 + $widgetData = [
720 + 'title' => __('Quiz Result', 'fluentformpro'),
721 + 'content' => $resultHtml
722 + ];
723 +
724 + $cards['quiz_result'] = $widgetData;
725 +
726 + return $cards;
727 + }
728 +
729 + /**
730 + * Wrong Answer Icon
731 + *
732 + * @return string
733 + */
734 + protected static function getWrongIcon($forPdf)
735 + {
736 + $icon = '<svg fill="#e13636" version="1.1" viewBox="0 0 32 32" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M17.459,16.014l8.239-8.194c0.395-0.391,0.395-1.024,0-1.414c-0.394-0.391-1.034-0.391-1.428,0 l-8.232,8.187L7.73,6.284c-0.394-0.395-1.034-0.395-1.428,0c-0.394,0.396-0.394,1.037,0,1.432l8.302,8.303l-8.332,8.286 c-0.394,0.391-0.394,1.024,0,1.414c0.394,0.391,1.034,0.391,1.428,0l8.325-8.279l8.275,8.276c0.394,0.395,1.034,0.395,1.428,0 c0.394-0.396,0.394-1.037,0-1.432L17.459,16.014z" /><g/><g/><g/><g/><g/><g/></svg>';
737 + if ($forPdf) {
738 + $icon = '<svg height="26" width="26" version="1.1" viewBox="0 0 32 32" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><g transform="translate(-5,-5)"><path fill="#e13636" d="M17.459,16.014l8.239-8.194c0.395-0.391,0.395-1.024,0-1.414c-0.394-0.391-1.034-0.391-1.428,0 l-8.232,8.187L7.73,6.284c-0.394-0.395-1.034-0.395-1.428,0c-0.394,0.396-0.394,1.037,0,1.432l8.302,8.303l-8.332,8.286 c-0.394,0.391-0.394,1.024,0,1.414c0.394,0.391,1.034,0.391,1.428,0l8.325-8.279l8.275,8.276c0.394,0.395,1.034,0.395,1.428,0 c0.394-0.396,0.394-1.037,0-1.432L17.459,16.014z" /></g></svg>';
739 + }
740 + return apply_filters('fluentform/quiz_wrong_ans_icon', $icon);
741 + }
742 +
743 + /**
744 + * Right Answer Icon
745 + *
746 + * @return string
747 + */
748 + protected static function getRightIcon($forPdf)
749 + {
750 + $icon = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="#1a7efb" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-check"><polyline points="20 6 9 17 4 12"></polyline></svg>';
751 + if ($forPdf) {
752 + $icon = '<svg height="26" width="26" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" class="feather feather-check"><polyline fill="none" stroke="#1a7efb" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" points="20 6 9 17 4 12"></polyline></svg>';
753 + }
754 + return apply_filters('fluentform/quiz_right_ans_icon', $icon);
755 + }
756 +
757 + public function advancePoints($options)
758 + {
759 + if (!isset($options['options'])) {
760 + return (object)[];
761 + }
762 + $formattedOptions = [];
763 + foreach ($options['options'] as $key => $value) {
764 + $formattedOptions[$key] = 0;
765 + }
766 + return $formattedOptions;
767 + }
768 +
769 + private function calcAdvancePoints($settings, $userValue)
770 + {
771 + $hasAdvancePoint = Arr::get($settings, 'has_advance_scoring');
772 + if ($hasAdvancePoint) {
773 + $advancePoints = Arr::get($settings, 'advance_points');
774 + $userValue = is_array($userValue) ? $userValue : [$userValue];
775 + $total = 0;
776 + foreach ($userValue as $value) {
777 + $value = Arr::get($advancePoints, $value, 0);
778 + if (!is_numeric($value)) {
779 + continue;
780 + }
781 + $total += $value;
782 + }
783 + return $total;
784 + } else {
785 + return Arr::get($settings, 'points');
786 + }
787 + }
788 +
789 + private static function getScoreType($form)
790 + {
791 + $scoreType = '';
792 + $scoreInput = self::getScoreInput($form);
793 + if ($scoreInput) {
794 + $scoreType = Arr::get($scoreInput, 'raw.settings.result_type');
795 + }
796 + return $scoreType;
797 + }
798 + public static function getScoreInput($form){
799 + $scoreInput = \FluentForm\App\Modules\Form\FormFieldsParser::getInputsByElementTypes($form,['quiz_score'],['raw']);
800 + if ($scoreInput) {
801 + return array_shift($scoreInput);
802 + }
803 + return false;
804 + }
805 +
806 + public function randomizeCheckableInputs()
807 + {
808 + add_filter('fluentform/rendering_field_data_input_checkbox', function ($data) {
809 + $options = $data['settings']['advanced_options'];
810 + shuffle($options);
811 + $data['settings']['advanced_options'] = $options;
812 +
813 + return $data;
814 + }, 10, 1);
815 +
816 + add_filter('fluentform/rendering_field_data_input_radio', function ($data) {
817 + $options = $data['settings']['advanced_options'];
818 + shuffle($options);
819 + $data['settings']['advanced_options'] = $options;
820 +
821 + return $data;
822 + }, 10, 1);
823 + }
824 +
825 + }
826 +