Fixed the survey PDF export ("Export Charts" and "Export without Charts" in the Saved Surveys export menu) and all other survey exports (CSV, JSON, XML, XLS, TXT) doing nothing, with the browser console reporting "ReferenceError: export_survey is not defined". The export_survey function in templates/assets/js/modal_survey_admin.js had been accidentally renamed to "questio", so every export button called a function that no longer existed. The function name has been restored. Personal…
Fixed "TypeError: modalSurveyChart.generateLegend is not a function" when preparing charts for the PDF export. generateLegend was removed in Chart.js v3, and the plugin ships Chart.js v4.5.1 (msChart.min.js). The color legend for each answer in the PDF is now built directly from the chart's own colors, so each answer in the PDF again shows a color swatch matching its slice in the chart.
Fixed a bug where the Participants admin page ("Votes" column) could show one participant with a wildly inflated vote count (e.g. 174) while unrelated, differently-named participants were missing entirely. The visitor-tracking cookie (ms-uid) is read on every survey submission and used to look up/create a row in the participants table via "WHERE id = ...". Whenever that cookie failed to reach the server for any reason (blocked by the browser/an extension, cleared, or the page load never set…
Hardened how the ms-uid tracking cookie's value is generated: it previously reused PHP's own session_id, which is tied to a shorter-lived, unrelated session mechanism and could occasionally return the same value for different visitors. It's now a dedicated random token, and the plugin no longer starts a PHP session on every anonymous page view (which could also prevent full-page caching on pages containing a survey).
Fixed category score totals being unexpectedly inflated (or otherwise wrong) whenever a category tag used the ":weight" syntax (e.g. "[Depression Indicators:5]") on an answer that also had a legacy per-answer "score" value set. Previously the two were multiplied together (score * weight * count), so a legacy score left over from before the weighting feature existed would silently distort every weighted category's total, only "working" if that legacy score happened to be exactly 1. Category…
Fixed a scoring/results accumulation bug where participant answer scores could become misaligned and add up incorrectly, and where the admin Participants page could show a "Undefined array key" PHP warning (modal_survey.php around the participants/scoring code, called from templates/settings_participants.php). Two parallel internal arrays used to reconstruct each participant's per-question answers and their associated score values were built out of step with each other whenever an answer's…
Fixed radar/pie/doughnut/polar/bar/line chart shortcodes ([survey_answers style="radarchart"], etc.) failing to render on the front end with browser console errors "Cannot read properties of undefined (reading 'register')" and "Cannot set properties of undefined (setting 'legend')". The shipped templates/assets/js/modal_survey_answer.min.js file was a stale, pre-Chart.js-v4 build that still called the old Chart.js v2 plugin registration API (Chart.pluginService.register), which no longer…
Fixed PHP warnings ("Trying to access array offset on value of type null" and "Uninitialized string offset 142") when rendering the [survey_answers]/[modalsurvey] shortcode on the front end. The grid-columns setting (options index 142) was being read from a raw character offset of the still-JSON-encoded options string instead of the decoded options array, which produced garbage/undefined results and warnings whenever the options string was shorter than 143 characters. The options are now…
Fixed a critical bug where the entire Modal Survey admin screen could silently stop working: the Save button did nothing (no request was ever sent), and creating a new survey would hang and then create a bogus survey with ID 0. The admin JavaScript wrapped all of its button handlers in the deprecated jQuery(window).load(function {...}) shorthand. In modern jQuery this is not treated as an event binding; jQuery.fn.load unconditionally tries to read the first argument as a URL string…
Fixed fatal PHP 8.x TypeError (Unsupported operand types: string / int) on line 546 of settings_savedforms.php, which crashed the Saved Surveys page when opening a survey whose options array did not contain a stored animation speed (options[11]) or end delay (options[23]). This affected older surveys that pre-dated these settings. The fix adds numeric defaults (400ms and 0ms respectively) in the options initialisation block so division by 1000 is always safe.
Fixed PHP warning "Attempt to read property 'display_name' on bool" appearing 22 times in the Saved Surveys list (settings_savedforms.php). When a survey's owner account has been deleted, get_user_by returns false; the code now checks instanceof WP_User before accessing display_name, showing 'Unknown' as a fallback instead.
Versão 2.0.2.2.8
1 novidade1 melhoria
Novidade
Added optional per-category score weighting: category tags in the answer/question brackets now support an optional ":weight" suffix (e.g. "[sensing/feeling (+sc):2]"). When present, the answer's score is multiplied by this weight before being added to that category's total, instead of every category always contributing with the same weight of 1. Existing category tags without a weight suffix keep working exactly as before.
Melhoria
Category Weighting Release
Versão 2.0.2.2.7
1 melhoria5 correções
Melhoria
UI Fix Release
Correção
Fixed survey answer text indentation: answer labels are now properly left-aligned. The first line of each answer choice no longer shows a leading blank space caused by the default text-align on the label container.
Fixed paragraph breaks in open-text answers: users can now press Enter to add paragraph breaks in their responses. The open-answer save function now preserves newlines (sanitize_textarea_field), and results are rendered with nl2br so each line break appears correctly in the output.
Enlarged survey result images: result images in the [survey_answers] shortcode (progressbar / linebar styles) are enlarged from 50 px to 80 px.
Improved survey result layout: when an answer image is present, the image is now placed on the left and the answer label with its progress bar is placed on the right, using a flex row layout instead of the previous inline layout.
Updated plugin version constant (MODAL_SURVEY_VERSION) and plugin header to 2.0.2.2.7.
Versão 2.0.2.2.6
2 novidades3 melhorias1 correção
Novidade
PHP 8.4: Added explicit nullable type hints (?string, ?int) to functions using implicit nullable parameters, which are deprecated in PHP 8.4.
PHP 8.0+: Added ['allowed_classes' => false] option to all unserialize calls across modal_survey.php, settings.php, all export modules (csv, txt, xml, xls, pdf), and third-party API integrations (ymlp, benchmark, mailingboss, klicktipp). Also removed @ error suppression from the export_xls unserialize call.
Melhoria
Security & Compatibility Release
PHP 8.4: Replaced removed utf8_encode with mb_convert_encoding in campaignmonitor/serialisation.php.
WordPress 5.3+: Replaced deprecated current_time('timestamp') with time in the database maintenance routine.
Correção
Critical: Fixed REST API participant PII disclosure. The /user/, /allusers/, and /userresult/ endpoints now always require manage_options (administrator) regardless of the setting_restapi_privileges setting. Previously any subscriber-level user could enumerate all participant records (name, email, IP, survey history) by incrementing the uid parameter, and setting privileges to "public" removed the permission_callback entirely, allowing unauthenticated access to participant PII.
Versão 2.0.2.2.4
2 novidades1 melhoria8 reforços de segurança
Novidade
Critical: Added current_user_can('manage_options') capability check to manual plugin updater; previously any WP user could trigger a plugin overwrite.
Critical: Added version downgrade protection to manual updater; uploading an older plugin version is now rejected.
Melhoria
Critical: Removed print_r($this->temp_path) debug statement disclosing the absolute server filesystem path on the Update admin page.
Segurança
Security Release
Added esc_html around version strings and esc_html around changelog content read from uploaded ZIP in the updater.
Changed throw_error to use wp_kses_post instead of raw echo.
Added ['allowed_classes' => false] + is_array guard to all unserialize calls on participant .custom field data in settings_participants.php, settings.php (send_admin_email, send_autoresponse), and all four export modules (csv, xls, txt, xml).
Added wp_verify_nonce CSRF protection to all three participant delete operations (delete_samesession, delete_incomplete, bulk delete_participants).
Escaped survey name with esc_html in settings_savedforms.php survey title output.
Wrapped all custom-field configuration properties ($cf->id, $cf->name, $cf->warning, $cf->minlength, $cf->position) with esc_attr in the survey editor.
Replaced plugin_dir_path server path disclosure in import error message with a safe relative path.
Critical: Fixed logic bug where assignment operator was used instead of equality check for survey style detection, causing all surveys to incorrectly use the 'click' branch.
Fixed incorrect number_format call in survey_answers average-score path; third argument was the decimal count instead of the decimal separator, producing garbled output.
Fixed undefined variable warnings in survey_open_answers, survey_records, and survey_compare_chart shortcode handlers when results are absent or labels/sessions are not set.
Segurança
Critical: Fixed path traversal vulnerability in campaign module loader; allowed module names are now strictly whitelisted.
Critical: Sanitized cookie-sourced survey_viewed arrays with absint before use in SQL IN clauses to prevent injection via crafted cookie values.
All plugin cookies (ms-uid, ms-session, modal_survey) now set secure=is_ssl and httponly=true, including legacy fallback setcookie calls.
Replaced insecure mt_rand -based session ID generation with cryptographically secure bin2hex(random_bytes(16)).
Escaped featured image URL with esc_url in Open Graph meta output.
Fixed unsanitized direct $_COOKIE['ms-uid'] access in ajax_survey_back; now uses sanitize_text_field/wp_unslash with isset guard.
Reduced export directory permissions from 0777 to 0755.
Versão 2.0.2.2.2
1 novidade
Novidade
Added live font family preview in the survey style configuration panel: selecting a font now displays a sample of the font name rendered in the chosen typeface directly below the selector.
Versão 2.0.2.2.1
3 melhorias3 correções1 reforço de segurança
Melhoria
Improved completion-mail flow reliability after participant form submission.
Removed duplicate chart output in personal PDFs and disabled unnecessary global-chart duplication in that flow.
Cleaned up temporary debug instrumentation after verification.
Correção
Fixed end-content email timing so chartless PDFs are no longer sent prematurely; final emails are sent after chart capture is ready.
Fixed chart capture/render timing so PDF attachments receive actual chart images consistently.
Fixed PDF embedding of chart images (base64 handling, temp image lifecycle, and rendering behavior).
Segurança
Hardened backend chart-payload validation to accept only real image data, not empty JSON placeholders.
Added client-side canvas snapshot capture: survey result charts are now captured as base64 PNG data before mail/PDF generation begins.
Melhoria
Refactored survey completion flow to separate lightweight answer saving from mail/PDF finalization, reducing timeout risk for large exports.
Implemented new finalize AJAX endpoint in settings.php to trigger mail and PDF exports after charts have been fully rendered on the client.
Enhanced front-end chart initialization with MutationObserver fallback to handle late-injected markup and delayed script loading gracefully.
Updated modal_survey.js to track pending completion mail state and conditionally defer mail sending until after chart rendering completes.
Improved modal_survey_answer.js with window.ModalSurveyCaptureChartData helper to extract chart canvases as base64 payloads for PDF embedding.
Result charts in generated PDFs now display the exact chart rendered to the user, eliminating missing or placeholder images.
Split completion request into two lightweight phases, improving reliability on servers with stricter timeout limits.
Chart images are now properly embedded in PDF exports by capturing rendered Chart.js canvases on the client side.
Bootstrap logic for answer charts is now resilient to DOM delays and late script injection, common in page builders and AJAX-heavy themes.
Versão 2.0.2.1.9
3 correções
Correção
Resolved Database Automatic Cleanup Loop: Fixed a bug in modal_survey.php where setting the automated cleanup to "Never" would incorrectly evaluate to 0 days, causing the cleanup routine to continuously trigger every 12 hours. The plugin now fully respects the "Never" configuration and stops the cleanup cycle entirely.
Fixed Blank Results Chart Rendering: Resolved a JavaScript error in modal_survey_answer.js where sparse or object-shaped PHP arrays broke the frontend chart initializer. Data sets are now fully normalized before rendering to guarantee the chart displays properly instead of appearing blank.
Chart Shortcode Clarification: When utilizing the [survey_answers] shortcode, ensure you pass style="barchart" if your goal is to render a bar chart. Using style="piechart" will explicitly generate a pie chart visualization.
The form branch in ajax_survey_answer now unslashes and sanitizes each customfieldsarray key before using it as an array key.
Empty keys are skipped.
Corresponding values are unslashed and sanitized before save.
Prevented undefined index behavior for the Summary tab when there are no sessions
Segurança
Implemented a direct mitigation for the reported unauthenticated stored XSS path, covering both ingestion and rendering.
Sanitized attacker-controlled custom field keys before storage.
Escaped legacy and current participant custom data on admin output in settings_participants.php
Hardened the participant details view and list rendering so custom field labels/values are escaped before HTML output, this blocks execution even for already-poisoned records stored in the database.
Escaped other participant-derived fields shown in the same page (name, email, IP, survey title links, session attributes).
Added a retry-based bootstrap loop (polling with timeout) instead of immediate execution.
Added dependency checks before init: jQuery exists, plugin method exists (pmsresults or modalsurvey), localized params exist (ms_answer_init_params or ms_init_params), for answer init, waits for Chart only when chart styles are present
Added graceful timeout with console warning instead of throwing hard errors.
Added fallback mounting to body if .entry-content is missing (answer init).
Melhoria
Kept DOMContentLoaded-safe startup for both scripts.