| @@ -4,8 +4,9 @@ | ||
| 4 | 4 | |
| 5 | 5 | use FluentForm\App\Modules\Component\Component; |
| 6 | 6 | use FluentForm\App\Modules\Acl\Acl; |
| 7 | 7 | use FluentForm\App\Helpers\Helper; |
| 8 | +use FluentForm\App\Services\FormBuilder\LegacyDateConfigDecoder; | |
| 8 | 9 | use FluentForm\Framework\Helpers\ArrayHelper; |
| 9 | 10 | |
| 10 | 11 | /** |
| 11 | 12 | * All registered action's handlers should be in app\Hooks\Handlers, |
| @@ -71,8 +72,23 @@ | ||
| 71 | 72 | (new \FluentForm\App\Modules\Renderer\GlobalSettings\Settings($app))->render(); |
| 72 | 73 | } |
| 73 | 74 | ); |
| 74 | 75 | |
| 76 | +/** | |
| 77 | + * Pro 6.2.13+ supplies the REST API used by Free's Vue license screen. Older | |
| 78 | + * Pro versions keep rendering their PHP page through this component action. | |
| 79 | + */ | |
| 80 | +$app->addAction( | |
| 81 | + 'fluentform/global_settings_component_license_page', | |
| 82 | + function () use ($app) { | |
| 83 | + if (!defined('FLUENTFORMPRO_VERSION') || version_compare(FLUENTFORMPRO_VERSION, '6.2.13', '<')) { | |
| 84 | + return; | |
| 85 | + } | |
| 86 | + | |
| 87 | + (new \FluentForm\App\Modules\Renderer\GlobalSettings\Settings($app))->render('license'); | |
| 88 | + } | |
| 89 | +); | |
| 90 | + | |
| 75 | 91 | // Register DefaultStyleApplicator on init so it works for REST API requests too |
| 76 | 92 | add_action('init', function () { |
| 77 | 93 | new \FluentForm\App\Modules\Form\DefaultStyleApplicator(); |
| 78 | 94 | }, 9); |
| @@ -282,8 +298,50 @@ | ||
| 282 | 298 | if (!isset($element['settings']['dynamic_default_value'])) { |
| 283 | 299 | $element['settings']['dynamic_default_value'] = ''; |
| 284 | 300 | } |
| 285 | 301 | |
| 302 | + // The editor only renders a rule the field already carries, so forms | |
| 303 | + // built before selection limits existed need the keys backfilled. | |
| 304 | + $isMultiSelect = 'select' == $upgradeElement | |
| 305 | + && \FluentForm\Framework\Helpers\ArrayHelper::get($element, 'attributes.multiple'); | |
| 306 | + | |
| 307 | + if ('input_checkbox' == $upgradeElement || $isMultiSelect) { | |
| 308 | + $rules = \FluentForm\Framework\Helpers\ArrayHelper::get($element, 'settings.validation_rules', []); | |
| 309 | + | |
| 310 | + foreach (['max_selection', 'min_selection'] as $selectionRule) { | |
| 311 | + if (isset($rules[$selectionRule])) { | |
| 312 | + continue; | |
| 313 | + } | |
| 314 | + | |
| 315 | + $globalMessage = \FluentForm\App\Helpers\Helper::getGlobalDefaultMessage($selectionRule); | |
| 316 | + | |
| 317 | + // Carry the legacy ceiling across, or the editor would show | |
| 318 | + // "no limit" on a form that has one and drop it on save. | |
| 319 | + $value = ''; | |
| 320 | + if ('max_selection' === $selectionRule && $isMultiSelect) { | |
| 321 | + $value = \FluentForm\Framework\Helpers\ArrayHelper::get($element, 'settings.max_selection', ''); | |
| 322 | + } | |
| 323 | + | |
| 324 | + $rules[$selectionRule] = [ | |
| 325 | + 'value' => $value, | |
| 326 | + 'message' => $globalMessage, | |
| 327 | + 'global_message' => $globalMessage, | |
| 328 | + 'global' => true, | |
| 329 | + ]; | |
| 330 | + } | |
| 331 | + | |
| 332 | + // Key order is the panel's layout order. Rebuilt rather than | |
| 333 | + // appended, so forms saved by an earlier build get it too. | |
| 334 | + $ordered = []; | |
| 335 | + foreach (['required', 'max_selection', 'min_selection'] as $key) { | |
| 336 | + if (isset($rules[$key])) { | |
| 337 | + $ordered[$key] = $rules[$key]; | |
| 338 | + } | |
| 339 | + } | |
| 340 | + | |
| 341 | + $element['settings']['validation_rules'] = $ordered + $rules; | |
| 342 | + } | |
| 343 | + | |
| 286 | 344 | if ('select_country' != $upgradeElement && !isset($element['settings']['randomize_options'])) { |
| 287 | 345 | $element['settings']['randomize_options'] = 'no'; |
| 288 | 346 | } |
| 289 | 347 | |
| @@ -402,8 +460,13 @@ | ||
| 402 | 460 | add_filter('fluentform/editor_init_element_input_date', function ($item) { |
| 403 | 461 | if (!isset($item['settings']['date_config'])) { |
| 404 | 462 | $item['settings']['date_config'] = ''; |
| 405 | 463 | } |
| 464 | + // Show the executable form of any legacy 6.2.7-6.2.12 tokens; only a trusted author's verbatim save persists it (restricted saves keep the stored value). | |
| 465 | + $decoded = LegacyDateConfigDecoder::decode((string) $item['settings']['date_config']); | |
| 466 | + if (null !== $decoded) { | |
| 467 | + $item['settings']['date_config'] = $decoded; | |
| 468 | + } | |
| 406 | 469 | return $item; |
| 407 | 470 | }); |
| 408 | 471 | |
| 409 | 472 | add_filter('fluentform/editor_init_element_ratings', function ($item) { |
| @@ -478,8 +541,17 @@ | ||
| 478 | 541 | } |
| 479 | 542 | |
| 480 | 543 | return $item; |
| 481 | 544 | }); |
| 545 | + | |
| 546 | + foreach (['input_text', 'input_email', 'textarea', 'input_number', 'select', 'input_url', 'input_password', 'input_date', 'input_name', 'address', 'phone'] as $autocompleteElement) { | |
| 547 | + add_filter('fluentform/editor_init_element_' . $autocompleteElement, function ($item) { | |
| 548 | + if (!isset($item['attributes']['autocomplete'])) { | |
| 549 | + $item['attributes']['autocomplete'] = ''; | |
| 550 | + } | |
| 551 | + return $item; | |
| 552 | + }); | |
| 553 | + } | |
| 482 | 554 | |
| 483 | 555 | add_filter('fluentform/editor_init_element_input_mask', function ($item) { |
| 484 | 556 | if (!isset($item['settings']['mobile_keyboard_type'])) { |
| 485 | 557 | $item['settings']['mobile_keyboard_type'] = ''; |