Formidable Forms – Form Builder for WordPress - Version 5.0

Version Description

  • Increased WP version requirement to 5.0.
  • New: Fields can now be dragged beside each other and grid layouts will be automatically applied.
  • New: Added the option to quickly set layouts for a full row of fields at once.
  • New: Fields can now be multiselected using the command, control, and shift keys. Selected field groups can be merged into rows and deleted in batches.
  • New: Added additional formatting to calculations to avoid issues with comparisons getting stripped when spaces are left out.
  • New: Permissions are now updated right away when a formidable license is activated to avoid issues with certain pro features not being available right away.
  • Fix: Updated styling rules for repeater button icons to avoid issues with file upload icons getting styled as well.
  • Fix: The confirmation pop up title was displaying as inline when trying to delete a section.
  • Fix: Updated styling for new fields that are about to be dropped into a form.
Download this release

Release Info

Developer formidableforms
Plugin Icon 128x128 Formidable Forms – Form Builder for WordPress
Version 5.0
Comparing to
See all releases

Code changes from version 4.11.05 to 5.0

classes/controllers/FrmAddonsController.php CHANGED
@@ -11,16 +11,15 @@ class FrmAddonsController {
11
  }
12
 
13
  $label = __( 'Add-Ons', 'formidable' );
14
- if ( FrmAppHelper::pro_is_installed() ) {
15
- $label = '<span style="color:#fe5a1d">' . $label . '</span>';
16
- }
17
  add_submenu_page( 'formidable', 'Formidable | ' . __( 'Add-Ons', 'formidable' ), $label, 'frm_view_forms', 'formidable-addons', 'FrmAddonsController::list_addons' );
18
 
19
  if ( ! FrmAppHelper::pro_is_installed() ) {
20
  add_submenu_page(
21
  'formidable',
22
  'Formidable | ' . __( 'Upgrade', 'formidable' ),
23
- '<span style="color:#fe5a1d">' . __( 'Upgrade', 'formidable' ) . '</span>',
24
  'frm_view_forms',
25
  'formidable-pro-upgrade',
26
  'FrmAddonsController::upgrade_to_pro'
11
  }
12
 
13
  $label = __( 'Add-Ons', 'formidable' );
14
+ $label = '<span style="color:#fe5a1d">' . $label . '</span>';
15
+
 
16
  add_submenu_page( 'formidable', 'Formidable | ' . __( 'Add-Ons', 'formidable' ), $label, 'frm_view_forms', 'formidable-addons', 'FrmAddonsController::list_addons' );
17
 
18
  if ( ! FrmAppHelper::pro_is_installed() ) {
19
  add_submenu_page(
20
  'formidable',
21
  'Formidable | ' . __( 'Upgrade', 'formidable' ),
22
+ '<span class="frm-upgrade-submenu">' . __( 'Upgrade', 'formidable' ) . '</span>',
23
  'frm_view_forms',
24
  'formidable-pro-upgrade',
25
  'FrmAddonsController::upgrade_to_pro'
classes/controllers/FrmAppController.php CHANGED
@@ -440,6 +440,7 @@ class FrmAppController {
440
  'jquery-ui-sortable',
441
  'bootstrap_tooltip',
442
  'bootstrap-multiselect',
 
443
  );
444
 
445
  if ( FrmAppHelper::is_admin_page( 'formidable-styles' ) || FrmAppHelper::is_admin_page( 'formidable-styles2' ) ) {
440
  'jquery-ui-sortable',
441
  'bootstrap_tooltip',
442
  'bootstrap-multiselect',
443
+ 'wp-i18n',
444
  );
445
 
446
  if ( FrmAppHelper::is_admin_page( 'formidable-styles' ) || FrmAppHelper::is_admin_page( 'formidable-styles2' ) ) {
classes/controllers/FrmFieldsController.php CHANGED
@@ -196,13 +196,22 @@ class FrmFieldsController {
196
  $classes = isset( $field['classes'] ) ? $field['classes'] : '';
197
 
198
  // Exclude alignright for now since we aren't using widths.
199
- $classes = str_replace( ' frm_alignright ', ' ', $classes );
200
- if ( trim( $classes ) === 'frm_alignright' ) {
 
 
201
  $classes = '';
202
  }
203
 
204
- $li_classes .= ' frm_form_field frmstart ' . $classes . ' frmend';
205
- if ( ! empty( $field ) ) {
 
 
 
 
 
 
 
206
  $li_classes = apply_filters( 'frm_build_field_class', $li_classes, $field );
207
  }
208
 
196
  $classes = isset( $field['classes'] ) ? $field['classes'] : '';
197
 
198
  // Exclude alignright for now since we aren't using widths.
199
+ $classes = str_replace( ' frm_alignright ', ' ', $classes );
200
+ $classes = trim( $classes );
201
+
202
+ if ( 'frm_alignright' === $classes ) {
203
  $classes = '';
204
  }
205
 
206
+ $li_classes .= ' frm_form_field frmstart ';
207
+
208
+ if ( $classes ) {
209
+ $li_classes .= $classes . ' ';
210
+ }
211
+
212
+ $li_classes .= 'frmend';
213
+
214
+ if ( $field ) {
215
  $li_classes = apply_filters( 'frm_build_field_class', $li_classes, $field );
216
  }
217
 
classes/controllers/FrmHooksController.php CHANGED
@@ -157,6 +157,7 @@ class FrmHooksController {
157
 
158
  FrmSMTPController::load_hooks();
159
  FrmWelcomeController::load_hooks();
 
160
  }
161
 
162
  public static function load_ajax_hooks() {
157
 
158
  FrmSMTPController::load_hooks();
159
  FrmWelcomeController::load_hooks();
160
+ new FrmPluginSearch();
161
  }
162
 
163
  public static function load_ajax_hooks() {
classes/helpers/FrmAppHelper.php CHANGED
@@ -11,7 +11,7 @@ class FrmAppHelper {
11
  /**
12
  * @since 2.0
13
  */
14
- public static $plug_version = '4.11.05';
15
 
16
  /**
17
  * @since 1.07.02
@@ -1224,6 +1224,14 @@ class FrmAppHelper {
1224
  }
1225
  }
1226
 
 
 
 
 
 
 
 
 
1227
  public static function frm_capabilities( $type = 'auto' ) {
1228
  $cap = array(
1229
  'frm_view_forms' => __( 'View Forms', 'formidable' ),
@@ -1234,16 +1242,22 @@ class FrmAppHelper {
1234
  'frm_delete_entries' => __( 'Delete Entries from Admin Area', 'formidable' ),
1235
  );
1236
 
1237
- if ( ! self::pro_is_installed() && 'pro' != $type ) {
1238
  return $cap;
1239
  }
1240
 
1241
- $cap['frm_create_entries'] = __( 'Add Entries from Admin Area', 'formidable' );
1242
- $cap['frm_edit_entries'] = __( 'Edit Entries from Admin Area', 'formidable' );
1243
- $cap['frm_view_reports'] = __( 'View Reports', 'formidable' );
1244
- $cap['frm_edit_displays'] = __( 'Add/Edit Views', 'formidable' );
 
 
 
 
 
 
1245
 
1246
- return $cap;
1247
  }
1248
 
1249
  /**
@@ -1530,7 +1544,7 @@ class FrmAppHelper {
1530
  }
1531
 
1532
  public static function get_user_id_param( $user_id ) {
1533
- if ( ! $user_id || empty( $user_id ) || is_numeric( $user_id ) ) {
1534
  return $user_id;
1535
  }
1536
 
11
  /**
12
  * @since 2.0
13
  */
14
+ public static $plug_version = '5.0';
15
 
16
  /**
17
  * @since 1.07.02
1224
  }
1225
  }
1226
 
1227
+ /**
1228
+ * Gets the list of capabilities.
1229
+ *
1230
+ * @since 5.0 Parameter `$type` supports `pro_only` value.
1231
+ *
1232
+ * @param string $type Supports `auto`, `pro`, or `pro_only`.
1233
+ * @return array
1234
+ */
1235
  public static function frm_capabilities( $type = 'auto' ) {
1236
  $cap = array(
1237
  'frm_view_forms' => __( 'View Forms', 'formidable' ),
1242
  'frm_delete_entries' => __( 'Delete Entries from Admin Area', 'formidable' ),
1243
  );
1244
 
1245
+ if ( ! self::pro_is_installed() && 'pro' !== $type && 'pro_only' !== $type ) {
1246
  return $cap;
1247
  }
1248
 
1249
+ $pro_cap = array(
1250
+ 'frm_create_entries' => __( 'Add Entries from Admin Area', 'formidable' ),
1251
+ 'frm_edit_entries' => __( 'Edit Entries from Admin Area', 'formidable' ),
1252
+ 'frm_view_reports' => __( 'View Reports', 'formidable' ),
1253
+ 'frm_edit_displays' => __( 'Add/Edit Views', 'formidable' ),
1254
+ );
1255
+
1256
+ if ( 'pro_only' === $type ) {
1257
+ return $pro_cap;
1258
+ }
1259
 
1260
+ return $cap + $pro_cap;
1261
  }
1262
 
1263
  /**
1544
  }
1545
 
1546
  public static function get_user_id_param( $user_id ) {
1547
+ if ( ! $user_id || is_numeric( $user_id ) ) {
1548
  return $user_id;
1549
  }
1550
 
classes/helpers/FrmEntriesHelper.php CHANGED
@@ -385,7 +385,7 @@ class FrmEntriesHelper {
385
  */
386
  public static function maybe_set_other_validation( $field, &$value, &$args ) {
387
  $args['other'] = false;
388
- if ( ! $value || empty( $value ) || ! FrmAppHelper::pro_is_installed() ) {
389
  return;
390
  }
391
 
385
  */
386
  public static function maybe_set_other_validation( $field, &$value, &$args ) {
387
  $args['other'] = false;
388
+ if ( ! $value || ! FrmAppHelper::pro_is_installed() ) {
389
  return;
390
  }
391
 
classes/helpers/FrmFieldGridHelper.php ADDED
@@ -0,0 +1,274 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ die( 'You are not allowed to call this page directly.' );
4
+ }
5
+
6
+ class FrmFieldGridHelper {
7
+
8
+ private $parent_li;
9
+
10
+ /**
11
+ * @var int
12
+ */
13
+ private $current_list_size;
14
+
15
+ /**
16
+ * @var int
17
+ */
18
+ private $current_field_count;
19
+
20
+ /**
21
+ * @var string
22
+ */
23
+ private $field_layout_class;
24
+
25
+ /**
26
+ * @var int
27
+ */
28
+ private $active_field_size;
29
+
30
+ /**
31
+ * @var bool $is_frm_first flagged while calling get_field_layout_class, true if classes contain frm_first class.
32
+ */
33
+ private $is_frm_first;
34
+
35
+ /**
36
+ * @var stdClass
37
+ */
38
+ private $field;
39
+
40
+ /**
41
+ * @var FrmFieldGridHelper $section_helper
42
+ */
43
+ private $section_helper;
44
+
45
+ /**
46
+ * @var bool $nested
47
+ */
48
+ private $nested;
49
+
50
+ /**
51
+ * @var int $section_size
52
+ */
53
+ private $section_size;
54
+
55
+ private $section_is_open = false;
56
+
57
+ public function __construct( $nested = false ) {
58
+ $this->parent_li = false;
59
+ $this->current_list_size = 0;
60
+ $this->current_field_count = 0;
61
+ $this->nested = $nested;
62
+ }
63
+
64
+ /**
65
+ * @param stdClass $field
66
+ */
67
+ public function set_field( $field ) {
68
+ $this->field = $field;
69
+
70
+ if ( ! empty( $this->section_helper ) && 'end_divider' !== $field->type ) {
71
+ $this->section_helper->set_field( $field );
72
+ return;
73
+ }
74
+
75
+ if ( 'end_divider' === $field->type ) {
76
+ $this->field_layout_class = '';
77
+ $this->active_field_size = $this->section_size;
78
+ $this->section_is_open = false;
79
+ $this->maybe_close_section_helper();
80
+ } else {
81
+ $this->field_layout_class = $this->get_field_layout_class();
82
+ $this->active_field_size = $this->get_size_of_class( $this->field_layout_class );
83
+ }
84
+
85
+ if ( 'divider' === $field->type && empty( $this->nested ) ) {
86
+ $this->section_size = $this->active_field_size;
87
+ $this->active_field_size = 0;
88
+ $this->section_helper = new self( true );
89
+ }
90
+ }
91
+
92
+ private function maybe_close_section_helper() {
93
+ if ( empty( $this->section_helper ) ) {
94
+ return;
95
+ }
96
+ $this->section_helper->force_close_field_wrapper();
97
+ $this->section_helper = null;
98
+ }
99
+
100
+ /**
101
+ * @return string
102
+ */
103
+ public function get_field_layout_class() {
104
+ $field = FrmFieldsHelper::setup_edit_vars( $this->field );
105
+
106
+ if ( empty( $field['classes'] ) ) {
107
+ return '';
108
+ }
109
+
110
+ $split = explode( ' ', $field['classes'] );
111
+ $this->is_frm_first = in_array( 'frm_first', $split, true );
112
+ $classes = self::get_grid_classes();
113
+
114
+ foreach ( $classes as $class ) {
115
+ if ( in_array( $class, $split, true ) ) {
116
+ return $class;
117
+ }
118
+ }
119
+
120
+ return '';
121
+ }
122
+
123
+ public function maybe_begin_field_wrapper() {
124
+ if ( $this->should_first_close_the_active_field_wrapper() ) {
125
+ $this->close_field_wrapper();
126
+ }
127
+
128
+ if ( false === $this->parent_li && 'end_divider' !== $this->field->type ) {
129
+ $this->begin_field_wrapper();
130
+ }
131
+
132
+ if ( ! empty( $this->section_helper ) && $this->section_is_open ) {
133
+ $this->section_helper->maybe_begin_field_wrapper();
134
+ }
135
+ }
136
+
137
+ /**
138
+ * @return bool
139
+ */
140
+ private function should_first_close_the_active_field_wrapper() {
141
+ if ( false === $this->parent_li || ! empty( $this->section_helper ) ) {
142
+ return false;
143
+ }
144
+ if ( 'end_divider' === $this->field->type ) {
145
+ return false;
146
+ }
147
+ return ! $this->can_support_current_layout() || $this->is_frm_first;
148
+ }
149
+
150
+ private function begin_field_wrapper() {
151
+ echo '<li class="frm_field_box"><ul class="frm_grid_container frm_sorting">';
152
+ $this->parent_li = true;
153
+ $this->current_list_size = 0;
154
+ $this->current_field_count = 0;
155
+ }
156
+
157
+ /**
158
+ * @param string $class
159
+ * @return int
160
+ */
161
+ private static function get_size_of_class( $class ) {
162
+ switch ( $class ) {
163
+ case 'frm_half':
164
+ return 6;
165
+ case 'frm_third':
166
+ return 4;
167
+ case 'frm_two_thirds':
168
+ return 8;
169
+ case 'frm_fourth':
170
+ return 3;
171
+ case 'frm_three_fourths':
172
+ return 9;
173
+ case 'frm_sixth':
174
+ return 2;
175
+ }
176
+
177
+ if ( 0 === strpos( $class, 'frm' ) ) {
178
+ $substr = substr( $class, 3 );
179
+ if ( is_numeric( $substr ) ) {
180
+ return (int) $substr;
181
+ }
182
+ }
183
+
184
+ // Anything missing a layout class should be a full width row.
185
+ return 12;
186
+ }
187
+
188
+ public function sync_list_size() {
189
+ if ( ! isset( $this->field ) ) {
190
+ return;
191
+ }
192
+
193
+ if ( 'divider' === $this->field->type ) {
194
+ $this->section_is_open = true;
195
+ }
196
+
197
+ if ( ! empty( $this->section_helper ) ) {
198
+ $this->section_helper->sync_list_size();
199
+ if ( 'end_divider' === $this->field->type ) {
200
+ $this->maybe_close_section_helper();
201
+ }
202
+ return;
203
+ }
204
+
205
+ if ( false !== $this->parent_li ) {
206
+ $this->current_field_count ++;
207
+ $this->current_list_size += $this->active_field_size;
208
+ if ( 12 === $this->current_list_size ) {
209
+ $this->close_field_wrapper();
210
+ }
211
+ }
212
+ }
213
+
214
+ /**
215
+ * It is possible that there was still space for another field so the wrapper could still be open after looping the fields.
216
+ * If it is, make sure it's closed now.
217
+ */
218
+ public function force_close_field_wrapper() {
219
+ if ( false !== $this->parent_li ) {
220
+ $this->close_field_wrapper();
221
+ }
222
+ }
223
+
224
+ private function close_field_wrapper() {
225
+ $this->maybe_close_section_helper();
226
+ echo '</ul></li>';
227
+ $this->parent_li = false;
228
+ $this->current_list_size = 0;
229
+ $this->current_field_count = 0;
230
+ }
231
+
232
+ private function can_support_current_layout() {
233
+ if ( 'end_divider' === $this->field->type ) {
234
+ return true;
235
+ }
236
+ return $this->can_support_an_additional_layout( $this->field_layout_class );
237
+ }
238
+
239
+ /**
240
+ * @param string $class
241
+ * @return bool
242
+ */
243
+ private function can_support_an_additional_layout( $class ) {
244
+ $size = $this->get_size_of_class( $class );
245
+ return $this->current_list_size + $size <= 12;
246
+ }
247
+
248
+ /**
249
+ * @return array<string>
250
+ */
251
+ private static function get_grid_classes() {
252
+ return array(
253
+ 'frm_full',
254
+ 'frm_half',
255
+ 'frm_third',
256
+ 'frm_two_thirds',
257
+ 'frm_fourth',
258
+ 'frm_three_fourths',
259
+ 'frm_sixth',
260
+ 'frm1',
261
+ 'frm2',
262
+ 'frm3',
263
+ 'frm4',
264
+ 'frm5',
265
+ 'frm6',
266
+ 'frm7',
267
+ 'frm8',
268
+ 'frm9',
269
+ 'frm10',
270
+ 'frm11',
271
+ 'frm12',
272
+ );
273
+ }
274
+ }
classes/helpers/FrmFormsHelper.php CHANGED
@@ -75,7 +75,7 @@ class FrmFormsHelper {
75
  }
76
 
77
  /**
78
- * @param string|object $selected - The label for the placeholder, or the form object.
79
  */
80
  public static function form_switcher( $selected = false ) {
81
  $where = apply_filters( 'frm_forms_dropdown', array(), '' );
@@ -751,7 +751,7 @@ BEFORE_HTML;
751
  }
752
 
753
  public static function submit_button_label( $submit ) {
754
- if ( ! $submit || empty( $submit ) ) {
755
  $frm_settings = FrmAppHelper::get_settings();
756
  $submit = $frm_settings->submit_value;
757
  }
75
  }
76
 
77
  /**
78
+ * @param string|object|false $selected - The label for the placeholder, or the form object.
79
  */
80
  public static function form_switcher( $selected = false ) {
81
  $where = apply_filters( 'frm_forms_dropdown', array(), '' );
751
  }
752
 
753
  public static function submit_button_label( $submit ) {
754
+ if ( ! $submit ) {
755
  $frm_settings = FrmAppHelper::get_settings();
756
  $submit = $frm_settings->submit_value;
757
  }
classes/models/FrmAddon.php CHANGED
@@ -238,6 +238,36 @@ class FrmAddon {
238
  update_option( $this->option_name . 'active', $is_active );
239
  $this->delete_cache();
240
  FrmAppHelper::save_combined_js();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
241
  }
242
 
243
  /**
238
  update_option( $this->option_name . 'active', $is_active );
239
  $this->delete_cache();
240
  FrmAppHelper::save_combined_js();
241
+ $this->update_pro_capabilities();
242
+ }
243
+
244
+ /**
245
+ * Updates roles capabilities after pro license is active.
246
+ *
247
+ * @since 5.0
248
+ */
249
+ protected function update_pro_capabilities() {
250
+ global $wp_roles;
251
+
252
+ $caps = FrmAppHelper::frm_capabilities( 'pro_only' );
253
+ $roles = get_editable_roles();
254
+ $settings = new FrmSettings();
255
+ foreach ( $caps as $cap => $cap_desc ) {
256
+ $cap_roles = (array) ( isset( $settings->$cap ) ? $settings->$cap : 'administrator' );
257
+
258
+ // Make sure administrators always have permissions.
259
+ if ( ! in_array( 'administrator', $cap_roles ) ) {
260
+ array_push( $cap_roles, 'administrator' );
261
+ }
262
+
263
+ foreach ( $roles as $role => $details ) {
264
+ if ( in_array( $role, $cap_roles ) ) {
265
+ $wp_roles->add_cap( $role, $cap );
266
+ } else {
267
+ $wp_roles->remove_cap( $role, $cap );
268
+ }
269
+ }
270
+ }
271
  }
272
 
273
  /**
classes/models/FrmEntry.php CHANGED
@@ -65,7 +65,7 @@ class FrmEntry {
65
  global $wpdb;
66
  $entry_exists = FrmDb::get_col( $wpdb->prefix . 'frm_items', $check_val, 'id', array( 'order_by' => 'created_at DESC' ) );
67
 
68
- if ( ! $entry_exists || empty( $entry_exists ) || ! isset( $values['item_meta'] ) ) {
69
  return false;
70
  }
71
 
65
  global $wpdb;
66
  $entry_exists = FrmDb::get_col( $wpdb->prefix . 'frm_items', $check_val, 'id', array( 'order_by' => 'created_at DESC' ) );
67
 
68
+ if ( ! $entry_exists || ! isset( $values['item_meta'] ) ) {
69
  return false;
70
  }
71
 
classes/models/FrmForm.php CHANGED
@@ -267,11 +267,7 @@ class FrmForm {
267
  private static function sanitize_field_opt( $opt, &$value ) {
268
  if ( is_string( $value ) ) {
269
  if ( $opt === 'calc' ) {
270
- $allow = array( '<= ', ' >=' ); // Allow <= and >=
271
- $temp = array( '< = ', ' > =' );
272
- $value = str_replace( $allow, $temp, $value );
273
- $value = strip_tags( $value );
274
- $value = str_replace( $temp, $allow, $value );
275
  } else {
276
  $value = FrmAppHelper::kses( $value, 'all' );
277
  }
@@ -279,6 +275,39 @@ class FrmForm {
279
  }
280
  }
281
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
282
  /**
283
  * Updating the settings page
284
  */
267
  private static function sanitize_field_opt( $opt, &$value ) {
268
  if ( is_string( $value ) ) {
269
  if ( $opt === 'calc' ) {
270
+ $value = self::sanitize_calc( $value );
 
 
 
 
271
  } else {
272
  $value = FrmAppHelper::kses( $value, 'all' );
273
  }
275
  }
276
  }
277
 
278
+ /**
279
+ * @param string $value
280
+ * @return string
281
+ */
282
+ private static function sanitize_calc( $value ) {
283
+ if ( false !== strpos( $value, '<' ) ) {
284
+ $value = self::normalize_calc_spaces( $value );
285
+ }
286
+ $allow = array( '<= ', ' >=' ); // Allow <= and >=
287
+ $temp = array( '< = ', ' > =' );
288
+ $value = str_replace( $allow, $temp, $value );
289
+ $value = strip_tags( $value );
290
+ $value = str_replace( $temp, $allow, $value );
291
+ return $value;
292
+ }
293
+
294
+ /**
295
+ * Format a comparison like 5<10 to 5 < 10. Also works on 5< 10, 5 <10, 5<=10 variations.
296
+ * This is to avoid an issue with unspaced calculations being recognized as HTML that gets removed when strip_tags is called.
297
+ *
298
+ * @param string $calc
299
+ * @return string
300
+ */
301
+ private static function normalize_calc_spaces( $calc ) {
302
+ // Check for a pattern with 5 parts
303
+ // $1 \d the first comparison digit.
304
+ // $2 a space (optional).
305
+ // $3 an equals sign (optional) that follows the < operator for <= comparisons.
306
+ // $4 another space (optional).
307
+ // $5 \d the second comparison digit.
308
+ return preg_replace( '/(\d)( ){0,1}<(=){0,1}( ){0,1}(\d)/', '$1 <$3 $5', $calc );
309
+ }
310
+
311
  /**
312
  * Updating the settings page
313
  */
classes/models/FrmPluginSearch.php ADDED
@@ -0,0 +1,363 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ if ( ! defined( 'ABSPATH' ) ) {
3
+ die( 'You are not allowed to call this page directly.' );
4
+ }
5
+
6
+ class FrmPluginSearch {
7
+
8
+ /**
9
+ * PSH slug name.
10
+ *
11
+ * @var string
12
+ */
13
+ public static $slug = 'frm-plugin-search';
14
+
15
+ /**
16
+ * Option name that holds dismissed suggestions.
17
+ *
18
+ * @var string
19
+ */
20
+ protected static $dismissed_opt = 'frm_dismissed_hints';
21
+
22
+ public function __construct() {
23
+ add_action( 'current_screen', array( $this, 'start' ) );
24
+ }
25
+
26
+ /**
27
+ * Add actions and filters only if this is the plugin installation screen and it's the first page.
28
+ *
29
+ * @param object $screen WP Screen object.
30
+ *
31
+ * @since 4.12
32
+ */
33
+ public function start( $screen ) {
34
+ // phpcs:ignore WordPress.Security.NonceVerification.Recommended
35
+ if ( 'plugin-install' === $screen->base && ( ! isset( $_GET['paged'] ) || 1 === intval( $_GET['paged'] ) ) ) {
36
+ add_filter( 'plugins_api_result', array( $this, 'inject_suggestion' ), 10, 3 );
37
+ add_filter( 'self_admin_url', array( $this, 'plugin_details' ) );
38
+ add_filter( 'plugin_install_action_links', array( $this, 'insert_related_links' ), 10, 2 );
39
+ add_action( 'admin_enqueue_scripts', array( $this, 'load_plugins_search_script' ) );
40
+ $this->maybe_dismiss();
41
+ }
42
+ }
43
+
44
+ /**
45
+ * Intercept the plugins API response and add in an appropriate card.
46
+ *
47
+ * @param object $result Plugin search results.
48
+ * @param string $action unused.
49
+ * @param object $args Search args.
50
+ */
51
+ public function inject_suggestion( $result, $action, $args ) {
52
+ // Looks like a search query; it's matching time.
53
+ if ( empty( $args->search ) ) {
54
+ return $result;
55
+ }
56
+
57
+ $addon_list = $this->get_addons();
58
+
59
+ // Lowercase, trim, remove punctuation/special chars, decode url, remove 'formidable'.
60
+ $normalized_term = $this->search_to_array( $args->search );
61
+ if ( empty( $normalized_term ) ) {
62
+ // Don't add anything extra.
63
+ return $result;
64
+ }
65
+
66
+ $matching_addon = $this->matching_addon( $addon_list, $normalized_term );
67
+
68
+ if ( empty( $matching_addon ) || ! $this->should_display_hint( $matching_addon ) ) {
69
+ return $result;
70
+ }
71
+
72
+ $inject = (array) $this->get_plugin_data();
73
+ $overrides = array(
74
+ 'plugin-search' => true, // Helps to determine if that an injected card.
75
+ 'name' => sprintf(
76
+ /* translators: Formidable addon name */
77
+ esc_html_x( 'Formidable %s', 'Formidable Addon Name', 'formidable' ),
78
+ $addon_list[ $matching_addon ]['name']
79
+ ),
80
+ 'addon' => $addon_list[ $matching_addon ]['slug'],
81
+ 'short_description' => $addon_list[ $matching_addon ]['excerpt'],
82
+ 'slug' => self::$slug,
83
+ 'version' => $addon_list[ $matching_addon ]['version'],
84
+ );
85
+
86
+ // Splice in the base addon data.
87
+ $inject = array_merge( $inject, $addon_list[ $matching_addon ], $overrides );
88
+
89
+ // Add it to the top of the list.
90
+ array_unshift( $result->plugins, $inject );
91
+
92
+ return $result;
93
+ }
94
+
95
+ /**
96
+ * Search for any addons that match the searched terms.
97
+ *
98
+ * @since 4.12
99
+ *
100
+ * @return int
101
+ */
102
+ private function matching_addon( $addon_list, $normalized_term ) {
103
+ $matching_addon = null;
104
+
105
+ // Try to match a passed search term with addon's search terms.
106
+ foreach ( $addon_list as $addon_id => $addon_opts ) {
107
+ if ( ! is_array( $addon_opts ) || empty( $addon_opts['excerpt'] ) ) {
108
+ continue;
109
+ }
110
+
111
+ /*
112
+ * Does the site's current plan support the feature?
113
+ */
114
+ $is_supported_by_plan = ! empty( $addon_opts['url'] );
115
+
116
+ if ( ! isset( $addon_opts['search_terms'] ) ) {
117
+ $addon_opts['search_terms'] = '';
118
+ }
119
+
120
+ $addon_terms = $this->search_to_array( $addon_opts['search_terms'] . ', ' . $addon_opts['name'] );
121
+
122
+ $matches = ! empty( array_intersect( $addon_terms, $normalized_term ) );
123
+
124
+ if ( $matches && $is_supported_by_plan ) {
125
+ $matching_addon = $addon_id;
126
+ break;
127
+ }
128
+ }
129
+
130
+ return $matching_addon;
131
+ }
132
+
133
+ /**
134
+ * @since 4.12
135
+ *
136
+ * @return array
137
+ */
138
+ private function get_addons() {
139
+ $api = new FrmFormApi();
140
+ return $api->get_api_info();
141
+ }
142
+
143
+ /**
144
+ * Get the plugin repo's data to populate the fields with.
145
+ *
146
+ * @return array|mixed|object|WP_Error
147
+ */
148
+ private function get_plugin_data() {
149
+ $data = get_transient( 'formidable_plugin_data' );
150
+
151
+ if ( false !== $data && ! is_wp_error( $data ) ) {
152
+ return $data;
153
+ }
154
+
155
+ include_once ABSPATH . 'wp-admin/includes/plugin-install.php';
156
+ $data = plugins_api(
157
+ 'plugin_information',
158
+ array(
159
+ 'slug' => 'formidable',
160
+ 'is_ssl' => is_ssl(),
161
+ 'fields' => array(
162
+ 'banners' => true,
163
+ 'reviews' => true,
164
+ 'active_installs' => true,
165
+ 'versions' => false,
166
+ 'sections' => false,
167
+ ),
168
+ )
169
+ );
170
+ set_transient( 'formidable_plugin_data', $data, DAY_IN_SECONDS );
171
+
172
+ return $data;
173
+ }
174
+
175
+ /**
176
+ * Modify URL used to fetch to plugin information so it pulls Formidable plugin page.
177
+ *
178
+ * @param string $url URL to load in dialog pulling the plugin page from wporg.
179
+ *
180
+ * @since 4.12
181
+ *
182
+ * @return string The URL with 'formidable' instead of 'frm-plugin-search'.
183
+ */
184
+ public function plugin_details( $url ) {
185
+ return false !== stripos( $url, 'tab=plugin-information&amp;plugin=' . self::$slug )
186
+ ? 'plugin-install.php?tab=plugin-information&amp;plugin=formidable&amp;TB_iframe=true&amp;width=600&amp;height=550'
187
+ : $url;
188
+ }
189
+
190
+ /**
191
+ * @since 4.12
192
+ */
193
+ private function maybe_dismiss() {
194
+ $addon = FrmAppHelper::get_param( 'frm-dismiss', '', 'get', 'absint' );
195
+ if ( ! empty( $addon ) ) {
196
+ $this->add_to_dismissed_hints( $addon );
197
+ }
198
+ }
199
+
200
+ /**
201
+ * Returns a list of previously dismissed hints.
202
+ *
203
+ * @since 4.12
204
+ *
205
+ * @return array List of dismissed hints.
206
+ */
207
+ protected function get_dismissed_hints() {
208
+ $dismissed_hints = get_option( self::$dismissed_opt );
209
+ return ! empty( $dismissed_hints ) && is_array( $dismissed_hints ) ? $dismissed_hints : array();
210
+ }
211
+
212
+ /**
213
+ * Save the hint in the list of dismissed hints.
214
+ *
215
+ * @since 4.12
216
+ *
217
+ * @param string $hint The hint id, which is a Formidable addon slug.
218
+ *
219
+ * @return bool Whether the card was added to the list and hence dismissed.
220
+ */
221
+ protected function add_to_dismissed_hints( $hint ) {
222
+ $hints = array_merge( $this->get_dismissed_hints(), array( $hint ) );
223
+ return update_option( self::$dismissed_opt, $hints, 'no' );
224
+ }
225
+
226
+ /**
227
+ * Checks that the addon slug passed should be displayed.
228
+ *
229
+ * A feature hint will be displayed if it has not been dismissed before or if 2 or fewer other hints have been dismissed.
230
+ *
231
+ * @since 7.2.1
232
+ *
233
+ * @param string $hint The hint id, which is a Formidable addon slug.
234
+ *
235
+ * @return bool True if $hint should be displayed.
236
+ */
237
+ protected function should_display_hint( $hint ) {
238
+ $dismissed_hints = $this->get_dismissed_hints();
239
+
240
+ // If more than 3 hints have been dismissed, then show no more.
241
+ if ( 3 < count( $dismissed_hints ) ) {
242
+ return false;
243
+ }
244
+
245
+ return ! in_array( $hint, $dismissed_hints, true );
246
+ }
247
+
248
+ /**
249
+ * Take a raw search query and return something a bit more standardized and
250
+ * easy to work with.
251
+ *
252
+ * @param string $term The raw search term.
253
+ * @return string A simplified/sanitized version.
254
+ */
255
+ private function sanitize_search_term( $term ) {
256
+ $term = strtolower( urldecode( $term ) );
257
+
258
+ // remove non-alpha/space chars.
259
+ $term = preg_replace( '/[^a-z ]/', '', $term );
260
+
261
+ // remove strings that don't help matches.
262
+ $term = trim( str_replace( array( 'formidable', 'free', 'wordpress', 'wp ', 'plugin' ), '', $term ) );
263
+
264
+ return $term;
265
+ }
266
+
267
+ /**
268
+ * @since 4.12
269
+ *
270
+ * @return array
271
+ */
272
+ private function search_to_array( $terms ) {
273
+ $terms = $this->sanitize_search_term( $terms );
274
+ return array_filter( explode( ',', $terms ) );
275
+ }
276
+
277
+ /**
278
+ * Put some more appropriate links on our custom result cards.
279
+ *
280
+ * @param array $links Related links.
281
+ * @param array $plugin Plugin result information.
282
+ */
283
+ public function insert_related_links( $links, $plugin ) {
284
+ if ( self::$slug !== $plugin['slug'] ) {
285
+ return $links;
286
+ }
287
+
288
+ // By the time this filter is applied, self_admin_url was already applied and we don't need it anymore.
289
+ remove_filter( 'self_admin_url', array( $this, 'plugin_details' ) );
290
+
291
+ $links = array();
292
+ $is_installed = $this->is_installed( $plugin['plugin'] );
293
+ $is_active = is_plugin_active( $plugin['plugin'] );
294
+ $has_access = ! empty( $plugin['url'] );
295
+
296
+ // Plugin installed, active, feature not enabled; prompt to enable.
297
+ if ( ! $is_active && $is_installed ) {
298
+ if ( current_user_can( 'activate_plugins' ) ) {
299
+ $activate_url = add_query_arg(
300
+ array(
301
+ 'action' => 'activate',
302
+ '_wpnonce' => wp_create_nonce( 'activate-plugin_' . $plugin['plugin'] ),
303
+ 'plugin' => $plugin['plugin'],
304
+ ),
305
+ admin_url( 'plugins.php' )
306
+ );
307
+ $links['frm_get_started'] = '<a href="' . esc_url( $activate_url ) . '" class="button activate-now" aria-label="Activate ' . esc_attr( $plugin['name'] ) . '">' . __( 'Activate', 'formidable' ) . '</a>';
308
+ }
309
+ } elseif ( ! $is_active && isset( $plugin['url'] ) ) {
310
+ // Go to the add-ons page to install.
311
+ $links[] = '<a
312
+ class="button-secondary"
313
+ href="' . esc_url( admin_url( 'admin.php?page=formidable-addons' ) ) . '"
314
+ >' . __( 'Install Now', 'formidable' ) . '</a>';
315
+
316
+ } elseif ( ! empty( $plugin['link'] ) ) {
317
+ // Add link pointing to a relevant doc page in formidable.com.
318
+ $links[] = '<a
319
+ class="button-primary frm-plugin-search__learn-more"
320
+ href="' . esc_url( FrmAppHelper::admin_upgrade_link( 'plugin-learn-more', $plugin['link'] ) ) . '"
321
+ target="_blank"
322
+ data-addon="' . esc_attr( $plugin['addon'] ) . '"
323
+ >' . esc_html__( 'Learn more', 'formidable' ) . '</a>';
324
+ }
325
+
326
+ // Dismiss link.
327
+ $dismiss = add_query_arg( array( 'frm-dismiss' => $plugin['id'] ) );
328
+ $links[] = '<a
329
+ href="' . $dismiss . '"
330
+ class="frm-plugin-search__dismiss"
331
+ data-addon="' . esc_attr( $plugin['addon'] ) . '"
332
+ >' . esc_html__( 'Hide this suggestion', 'formidable' ) . '</a>';
333
+
334
+ return $links;
335
+ }
336
+
337
+ protected function is_installed( $plugin ) {
338
+ if ( ! function_exists( 'get_plugins' ) ) {
339
+ require_once ABSPATH . 'wp-admin/includes/plugin.php';
340
+ }
341
+
342
+ $all_plugins = get_plugins();
343
+
344
+ return isset( $all_plugins[ $plugin ] );
345
+ }
346
+
347
+ /**
348
+ * Load the search scripts and CSS for PSH.
349
+ */
350
+ public function load_plugins_search_script() {
351
+ wp_enqueue_script( self::$slug, FrmAppHelper::plugin_url() . '/js/plugin-search.js', array(), FrmAppHelper::plugin_version(), true );
352
+ wp_localize_script(
353
+ self::$slug,
354
+ 'frmPlugSearch',
355
+ array(
356
+ 'legend' => esc_html__(
357
+ 'This suggestion was made by Formidable Forms, the form builder and application plugin already installed on your site.',
358
+ 'formidable'
359
+ ),
360
+ )
361
+ );
362
+ }
363
+ }
classes/views/frm-forms/add_field.php CHANGED
@@ -13,24 +13,36 @@ if ( ! defined( 'ABSPATH' ) ) {
13
  <div id="field_<?php echo esc_attr( $field['id'] ); ?>_inner_container" class="frm_inner_field_container">
14
  <div class="frm-field-action-icons frm-show-hover">
15
 
 
 
 
 
16
  <?php if ( $field['type'] === 'divider' ) { ?>
17
  <a href="#" class="frm-collapse-section frm-hover-icon frm_icon_font frm_arrowdown6_icon" title="<?php esc_attr_e( 'Expand/Collapse Section', 'formidable' ); ?>"></a>
18
  <?php } ?>
19
 
20
- <a href="#" class="frm_bstooltip frm-move frm-hover-icon" title="<?php esc_attr_e( 'Move Field', 'formidable' ); ?>">
21
- <?php FrmAppHelper::icon_by_class( 'frm_icon_font frm_move_icon' ); ?>
22
- </a>
23
- <a href="#" class="frm_bstooltip frm-hover-icon frm_delete_field" title="<?php esc_attr_e( 'Delete Field', 'formidable' ); ?>">
24
- <?php FrmAppHelper::icon_by_class( 'frm_icon_font frm_delete_icon' ); ?>
25
- </a>
26
-
27
- <a href="#" class="frm_bstooltip frm-hover-icon frm_clone_field" title="<?php ( $field['type'] === 'divider' ) ? esc_attr_e( 'Duplicate Section', 'formidable' ) : esc_attr_e( 'Duplicate Field', 'formidable' ); ?>">
28
- <?php FrmAppHelper::icon_by_class( 'frm_icon_font frm_clone_icon' ); ?>
29
  </a>
30
 
31
- <div class="frm-sub-label alignright">
32
- (ID <?php echo esc_html( $field['id'] ); ?>)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  </div>
 
34
  </div>
35
 
36
  <label class="frm_primary_label" id="field_label_<?php echo esc_attr( $field['id'] ); ?>">
@@ -75,10 +87,9 @@ if ( 'divider' === $field['type'] ) {
75
  ?>
76
  </div>
77
  <div class="frm_no_section_fields">
78
- <?php FrmAppHelper::icon_by_class( 'frmfont frm_plus2_icon frm-large-plus', array( 'aria-hidden' => 'true' ) ); ?>
79
- <p class="howto"><?php esc_html_e( 'Your section has no fields. Drag fields here to add them to this section.', 'formidable' ); ?></p>
80
  </div>
81
- <ul class="start_divider frm_sorting">
82
  <?php
83
  } elseif ( 'end_divider' === $field['type'] ) {
84
  ?>
13
  <div id="field_<?php echo esc_attr( $field['id'] ); ?>_inner_container" class="frm_inner_field_container">
14
  <div class="frm-field-action-icons frm-show-hover">
15
 
16
+ <div class="frm-sub-label frm-field-id">
17
+ (ID <?php echo esc_html( $field['id'] ); ?>)
18
+ </div>
19
+
20
  <?php if ( $field['type'] === 'divider' ) { ?>
21
  <a href="#" class="frm-collapse-section frm-hover-icon frm_icon_font frm_arrowdown6_icon" title="<?php esc_attr_e( 'Expand/Collapse Section', 'formidable' ); ?>"></a>
22
  <?php } ?>
23
 
24
+ <a href="#" class="frm_bstooltip frm-move frm-hover-icon" title="<?php esc_attr_e( 'Move Field', 'formidable' ); ?>" data-container="body">
25
+ <?php FrmAppHelper::icon_by_class( 'frm_icon_font frm_thick_move_icon' ); ?>
 
 
 
 
 
 
 
26
  </a>
27
 
28
+ <div class="dropdown">
29
+ <a href="#" class="frm_bstooltip frm-hover-icon frm-dropdown-toggle dropdown-toggle" title="<?php esc_attr_e( 'More Options', 'formidable' ); ?>" data-toggle="dropdown" data-container="body">
30
+ <?php FrmAppHelper::icon_by_class( 'frm_icon_font frm_thick_more_vert_icon' ); ?>
31
+ </a>
32
+ <ul class="frm-dropdown-menu" role="menu">
33
+ <li class="frm_dropdown_li frm_delete_field" href="#">
34
+ <?php FrmAppHelper::icon_by_class( 'frm_icon_font frm_delete_icon' ); ?> <?php esc_html_e( 'Delete', 'formidable' ); ?>
35
+ </li>
36
+ <li class="frm_dropdown_li frm_clone_field" href="#">
37
+ <?php FrmAppHelper::icon_by_class( 'frm_icon_font frm_clone_icon' ); ?> <?php esc_html_e( 'Duplicate', 'formidable' ); ?>
38
+ </li>
39
+ <hr>
40
+ <li class="frm_dropdown_li frm_select_field">
41
+ <?php FrmAppHelper::icon_by_class( 'frm_icon_font frm_settings_icon' ); ?> <?php esc_html_e( 'Field settings', 'formidable' ); ?>
42
+ </li>
43
+ </ul>
44
  </div>
45
+
46
  </div>
47
 
48
  <label class="frm_primary_label" id="field_label_<?php echo esc_attr( $field['id'] ); ?>">
87
  ?>
88
  </div>
89
  <div class="frm_no_section_fields">
90
+ <p class="howto"><?php esc_html_e( 'Add Fields Here', 'formidable' ); ?></p>
 
91
  </div>
92
+ <ul class="start_divider frm_sorting frm_grid_container">
93
  <?php
94
  } elseif ( 'end_divider' === $field['type'] ) {
95
  ?>
classes/views/frm-forms/edit.php CHANGED
@@ -39,3 +39,14 @@ if ( ! defined( 'ABSPATH' ) ) {
39
  </div>
40
  </div>
41
  </div>
 
 
 
 
 
 
 
 
 
 
 
39
  </div>
40
  </div>
41
  </div>
42
+ <div class="frm_hidden">
43
+ <svg id="frm_break_field_group_svg" class="frmsvg">
44
+ <use xlink:href="#frm_break_field_group_icon"></use>
45
+ </svg>
46
+ <svg id="frm_gear_svg" class="frmsvg">
47
+ <use xlink:href="#frm_gear_icon"></use>
48
+ </svg>
49
+ <svg id="frm_trash_svg" class="frmsvg">
50
+ <use xlink:href="#frm_trash_icon"></use>
51
+ </svg>
52
+ </div>
classes/views/frm-forms/form.php CHANGED
@@ -26,13 +26,19 @@ if ( ! defined( 'ABSPATH' ) ) {
26
 
27
  <ul id="frm-show-fields" class="frm_sorting inside">
28
  <?php
29
- if ( isset( $values['fields'] ) && ! empty( $values['fields'] ) ) {
 
30
  $values['count'] = 0;
31
  foreach ( $values['fields'] as $field ) {
32
  $values['count']++;
 
 
33
  FrmFieldsController::load_single_field( $field, $values );
 
34
  unset( $field );
35
  }
 
 
36
  }
37
  ?>
38
  </ul>
26
 
27
  <ul id="frm-show-fields" class="frm_sorting inside">
28
  <?php
29
+ if ( ! empty( $values['fields'] ) ) {
30
+ $grid_helper = new FrmFieldGridHelper();
31
  $values['count'] = 0;
32
  foreach ( $values['fields'] as $field ) {
33
  $values['count']++;
34
+ $grid_helper->set_field( $field );
35
+ $grid_helper->maybe_begin_field_wrapper();
36
  FrmFieldsController::load_single_field( $field, $values );
37
+ $grid_helper->sync_list_size();
38
  unset( $field );
39
  }
40
+ $grid_helper->force_close_field_wrapper();
41
+ unset( $grid_helper );
42
  }
43
  ?>
44
  </ul>
css/custom_theme.css.php CHANGED
@@ -1432,7 +1432,7 @@ select.frm_loading_lookup{
1432
  display:block;
1433
  }
1434
 
1435
- .with_frm_style .frm_repeat_sec .frm_form_field .frm_icon_font::before {
1436
  color:<?php echo esc_html( $defaults['repeat_icon_color'] . $important ); ?>;
1437
  color:var(--repeat-icon-color)<?php echo esc_html( $important ); ?>;
1438
  }
1432
  display:block;
1433
  }
1434
 
1435
+ .with_frm_style .frm_repeat_sec .frm_form_field.frm_repeat_buttons .frm_icon_font::before {
1436
  color:<?php echo esc_html( $defaults['repeat_icon_color'] . $important ); ?>;
1437
  color:var(--repeat-icon-color)<?php echo esc_html( $important ); ?>;
1438
  }
css/font_icons.css CHANGED
@@ -7,6 +7,16 @@
7
  font-style: normal;
8
  }
9
 
 
 
 
 
 
 
 
 
 
 
10
  .frmfont,
11
  .frm_icon_font,
12
  .frm_dashicon_font{
7
  font-style: normal;
8
  }
9
 
10
+ .frm-submenu-highlight {
11
+ background: #F15A24;
12
+ }
13
+
14
+ .frm-submenu-highlight a span {
15
+ color: #fff;
16
+ font-weight: 600;
17
+ }
18
+
19
+
20
  .frmfont,
21
  .frm_icon_font,
22
  .frm_dashicon_font{
css/frm_admin.css CHANGED
@@ -3201,6 +3201,18 @@ input[type="checkbox"] {
3201
  clear: both;
3202
  }
3203
 
 
 
 
 
 
 
 
 
 
 
 
 
3204
  .frm_form_settings #op-popup, /* 1Password */
3205
  .frm_form_settings com-1password-op-button,
3206
  .frm_conf_below .frm_conf_field_container .frm_primary_label,
@@ -3620,6 +3632,7 @@ label input[type="checkbox"], label input[type="radio"] {
3620
  .frm_field_box {
3621
  padding: 5px;
3622
  min-height: 20px;
 
3623
  }
3624
 
3625
  .frm_indent_opt, td.frm_indent_opt {
@@ -3636,12 +3649,28 @@ label input[type="checkbox"], label input[type="radio"] {
3636
 
3637
  .frm_single_option.ui-sortable-placeholder,
3638
  li.sortable-placeholder {
3639
- width: calc(100% - 5px) !important;
3640
- height: 0 !important;
3641
  border: none;
3642
- box-shadow: 2px -10px 0 1px var(--primary-color);
3643
  margin: 0;
3644
  visibility: visible !important;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3645
  }
3646
 
3647
  .edit_field_type_divider + li.sortable-placeholder {
@@ -3698,6 +3727,10 @@ li.ui-state-default.edit_field_type_divider .frm-show-hover {
3698
  transition: opacity .15s ease-in-out;
3699
  }
3700
 
 
 
 
 
3701
  .frm_sortable_field_opts {
3702
  margin-top: 5px;
3703
  }
@@ -3762,6 +3795,10 @@ li.ui-state-default.selected.edit_field_type_divider .divider_section_only .frm-
3762
  opacity: 100;
3763
  }
3764
 
 
 
 
 
3765
  .frm_sorting span.ui-icon {
3766
  width: 16px;
3767
  }
@@ -5200,15 +5237,40 @@ a.frm_action_icon:hover {
5200
  content: '\e606';
5201
  }
5202
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5203
  .frm-field-action-icons a {
5204
- margin-left: 15px;
5205
- float: right;
5206
  font-size: 16px;
5207
  width: 17px;
5208
  }
5209
 
 
 
 
 
 
 
 
 
5210
  .frm-field-action-icons a .frmsvg {
5211
- color: var(--primary-hover) !important;
5212
  font-size: 17px;
5213
  width: 17px;
5214
  height: 17px;
@@ -5429,12 +5491,52 @@ span.howto {
5429
  min-height: 350px;
5430
  padding: 10px 0 35px;
5431
  margin: 0;
 
5432
  }
5433
 
5434
  .frm-has-fields #frm-show-fields {
5435
  min-height: 50px;
5436
  }
5437
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5438
  .frm_sorting .no_repeat_section li.ui-state-default.edit_field_type_end_divider {
5439
  display: none !important;
5440
  }
@@ -5449,7 +5551,7 @@ span.howto {
5449
  background-color: transparent;
5450
  background-image: none;
5451
  padding: 5px;
5452
- margin: 10px 0;
5453
  box-shadow: none;
5454
  display: block;
5455
  text-align: inherit !important;
@@ -5470,10 +5572,6 @@ span.howto {
5470
  font-style: normal;
5471
  }
5472
 
5473
- .repeat_section .start_divider li:only-child {
5474
- margin-top: 50px;
5475
- }
5476
-
5477
  .show_repeat_sec {
5478
  display: none;
5479
  }
@@ -5855,7 +5953,6 @@ tr.frm_options_heading td {
5855
  padding: 20px 0 0;
5856
  width: calc( 100% - 20px );
5857
  height: 121px;
5858
- border-color: var(--grey-border);
5859
  transition: all 0.4s linear;
5860
  }
5861
 
@@ -6635,6 +6732,16 @@ ul .frm_col_two {
6635
  font-size: 15px;
6636
  }
6637
 
 
 
 
 
 
 
 
 
 
 
6638
  .frm_code_list.frm-full-hover a span {
6639
  color: var(--grey);
6640
  float: right;
@@ -6836,6 +6943,10 @@ input[disabled],
6836
  color: var(--dark-grey);
6837
  }
6838
 
 
 
 
 
6839
  /* Icon while dragging */
6840
  .frmbutton.ui-draggable-dragging,
6841
  .frmbutton.ui-draggable-dragging a {
@@ -6847,12 +6958,13 @@ input[disabled],
6847
  .frmbutton.ui-draggable-dragging a {
6848
  text-decoration: none;
6849
  height: 25px !important;
6850
- max-width: 180px;
6851
  text-align: center;
6852
  display: block !important;
6853
  background-color: var(--primary-hover) !important;
6854
- border-radius: var(--border-radius) !important;
6855
  padding: 5px 20px !important;
 
6856
  }
6857
 
6858
  .frmbutton.ui-draggable-dragging:not(.ui-sortable-helper) a {
@@ -6868,11 +6980,13 @@ input[disabled],
6868
 
6869
  #frm-show-fields .frmbutton.ui-sortable-helper i,
6870
  .frmbutton.ui-sortable-helper span,
6871
- .frmbutton.ui-draggable-dragging i {
 
6872
  color: #fff !important;
6873
  }
6874
 
6875
- .frmbutton.ui-draggable-dragging:not(.ui-sortable-helper) i {
 
6876
  color: var(--dark-grey) !important;
6877
  }
6878
 
@@ -7495,10 +7609,9 @@ button.frm_choose_image_box,
7495
  margin-right: 46%;
7496
  }
7497
 
7498
- .rtl .frm-field-action-icons a {
7499
- float: left;
7500
- margin-right: 15px;
7501
- margin-left: 0;
7502
  }
7503
 
7504
  .rtl #frm_upgrade_modal .dismiss i,
@@ -8069,3 +8182,152 @@ Responsive Design
8069
  max-width: 843px;
8070
  border-radius: 10px;
8071
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3201
  clear: both;
3202
  }
3203
 
3204
+ .frm_inner_field_container > label {
3205
+ text-overflow: ellipsis;
3206
+ overflow: hidden;
3207
+ white-space: nowrap;
3208
+ }
3209
+
3210
+ .frm_field_box:not(.edit_field_type_divider):hover > .frm_inner_field_container > label,
3211
+ .frm_field_box .divider_section_only:hover > .frm_inner_field_container > label,
3212
+ li.ui-state-default.selected > .frm_inner_field_container > label {
3213
+ max-width: calc(100% - 100px);
3214
+ }
3215
+
3216
  .frm_form_settings #op-popup, /* 1Password */
3217
  .frm_form_settings com-1password-op-button,
3218
  .frm_conf_below .frm_conf_field_container .frm_primary_label,
3632
  .frm_field_box {
3633
  padding: 5px;
3634
  min-height: 20px;
3635
+ margin: 10px 0;
3636
  }
3637
 
3638
  .frm_indent_opt, td.frm_indent_opt {
3649
 
3650
  .frm_single_option.ui-sortable-placeholder,
3651
  li.sortable-placeholder {
 
 
3652
  border: none;
 
3653
  margin: 0;
3654
  visibility: visible !important;
3655
+ box-shadow: 2px -10px 0 1px var(--primary-color);
3656
+ }
3657
+
3658
+ #frm_form_editor_container > ul > .frm_single_option.ui-sortable-placeholder,
3659
+ #frm_form_editor_container > ul > li.sortable-placeholder {
3660
+ width: calc(100% - 5px) !important;
3661
+ height: 0 !important;
3662
+ }
3663
+
3664
+ #frm_form_editor_container > ul > li > ul {
3665
+ position: relative;
3666
+ }
3667
+
3668
+ #frm_form_editor_container > ul > li > ul > .frm_single_option.ui-sortable-placeholder,
3669
+ #frm_form_editor_container > ul > li > ul > li.sortable-placeholder,
3670
+ #frm_form_editor_container ul.start_divider > li > ul > li.sortable-placeholder {
3671
+ position: absolute;
3672
+ top: 20px;
3673
+ bottom: 0;
3674
  }
3675
 
3676
  .edit_field_type_divider + li.sortable-placeholder {
3727
  transition: opacity .15s ease-in-out;
3728
  }
3729
 
3730
+ #frm-show-fields .frm-field-settings-open .frm-show-hover {
3731
+ opacity: 1;
3732
+ }
3733
+
3734
  .frm_sortable_field_opts {
3735
  margin-top: 5px;
3736
  }
3795
  opacity: 100;
3796
  }
3797
 
3798
+ li.frm_field_box > ul.frm_grid_container {
3799
+ position: relative;
3800
+ }
3801
+
3802
  .frm_sorting span.ui-icon {
3803
  width: 16px;
3804
  }
5237
  content: '\e606';
5238
  }
5239
 
5240
+ .frm-field-action-icons {
5241
+ text-align: right;
5242
+ position: absolute;
5243
+ top: 2px;
5244
+ right: 2px;
5245
+ max-width: 100%;
5246
+ }
5247
+
5248
+ .frm-field-action-icons .frm-field-id {
5249
+ display: inline-block;
5250
+ overflow: hidden;
5251
+ text-overflow: ellipsis;
5252
+ white-space: nowrap;
5253
+ width: 65px;
5254
+ max-width: calc( 100% - 50px );
5255
+ position: relative;
5256
+ top: 2px;
5257
+ }
5258
+
5259
  .frm-field-action-icons a {
 
 
5260
  font-size: 16px;
5261
  width: 17px;
5262
  }
5263
 
5264
+ .frm-field-action-icons a:hover {
5265
+ text-decoration: none;
5266
+ }
5267
+
5268
+ .frm-field-action-icons .dropdown {
5269
+ display: inline-block;
5270
+ }
5271
+
5272
  .frm-field-action-icons a .frmsvg {
5273
+ color: #9EA9B8 !important;
5274
  font-size: 17px;
5275
  width: 17px;
5276
  height: 17px;
5491
  min-height: 350px;
5492
  padding: 10px 0 35px;
5493
  margin: 0;
5494
+ position: relative;
5495
  }
5496
 
5497
  .frm-has-fields #frm-show-fields {
5498
  min-height: 50px;
5499
  }
5500
 
5501
+ #frm-show-fields .frm6 .frm-dropdown-menu {
5502
+ max-width: unset;
5503
+ min-width: 160px;
5504
+ }
5505
+
5506
+ #frm_builder_page #frm_field_group_controls {
5507
+ position: absolute;
5508
+ background: rgba(65, 153, 253, 0.07);
5509
+ padding: 5px;
5510
+ border-radius: 4px 4px 0 0;
5511
+ text-align: right;
5512
+ box-sizing: border-box;
5513
+ right: 0;
5514
+ top: -28px;
5515
+ height: 28px;
5516
+ z-index: 3; /* section dividers use z-index: 2; position above that to avoid it taking over hover control. */
5517
+ }
5518
+
5519
+ #frm_builder_page #frm_field_group_controls > span:first-child {
5520
+ margin-right: 5px;
5521
+ }
5522
+
5523
+ #frm_builder_page #frm_field_group_controls svg {
5524
+ pointer-events: none;
5525
+ }
5526
+
5527
+ #frm_field_group_controls {
5528
+ visibility: hidden;
5529
+ }
5530
+
5531
+ .frm-field-group-hover-target #frm_field_group_controls {
5532
+ visibility: visible;
5533
+ }
5534
+
5535
+ .frm-field-group-hover-target,
5536
+ .frm-has-open-field-group-popup {
5537
+ background: rgba(65, 153, 253, 0.07);
5538
+ }
5539
+
5540
  .frm_sorting .no_repeat_section li.ui-state-default.edit_field_type_end_divider {
5541
  display: none !important;
5542
  }
5551
  background-color: transparent;
5552
  background-image: none;
5553
  padding: 5px;
5554
+ margin: 0;
5555
  box-shadow: none;
5556
  display: block;
5557
  text-align: inherit !important;
5572
  font-style: normal;
5573
  }
5574
 
 
 
 
 
5575
  .show_repeat_sec {
5576
  display: none;
5577
  }
5953
  padding: 20px 0 0;
5954
  width: calc( 100% - 20px );
5955
  height: 121px;
 
5956
  transition: all 0.4s linear;
5957
  }
5958
 
6732
  font-size: 15px;
6733
  }
6734
 
6735
+ .frm-field-action-icons .frm-dropdown-menu .frm_dropdown_li {
6736
+ padding: 5px 10px;
6737
+ color: rgba(40, 47, 54, 0.85);
6738
+ cursor: pointer;
6739
+ }
6740
+
6741
+ .frm-field-action-icons .frm-dropdown-menu .frm_dropdown_li:hover {
6742
+ background: #F6F7FB;
6743
+ }
6744
+
6745
  .frm_code_list.frm-full-hover a span {
6746
  color: var(--grey);
6747
  float: right;
6943
  color: var(--dark-grey);
6944
  }
6945
 
6946
+ .frmbutton.ui-draggable-dragging {
6947
+ width: auto !important;
6948
+ }
6949
+
6950
  /* Icon while dragging */
6951
  .frmbutton.ui-draggable-dragging,
6952
  .frmbutton.ui-draggable-dragging a {
6958
  .frmbutton.ui-draggable-dragging a {
6959
  text-decoration: none;
6960
  height: 25px !important;
6961
+ width: 180px;
6962
  text-align: center;
6963
  display: block !important;
6964
  background-color: var(--primary-hover) !important;
6965
+ border-radius: 35px !important;
6966
  padding: 5px 20px !important;
6967
+ color: #fff !important;
6968
  }
6969
 
6970
  .frmbutton.ui-draggable-dragging:not(.ui-sortable-helper) a {
6980
 
6981
  #frm-show-fields .frmbutton.ui-sortable-helper i,
6982
  .frmbutton.ui-sortable-helper span,
6983
+ .frmbutton.ui-draggable-dragging i,
6984
+ .frmbutton.ui-draggable-dragging .frmsvg {
6985
  color: #fff !important;
6986
  }
6987
 
6988
+ .frmbutton.ui-draggable-dragging:not(.ui-sortable-helper) i,
6989
+ .frmbutton.ui-draggable-dragging:not(.ui-sortable-helper) .frmsvg {
6990
  color: var(--dark-grey) !important;
6991
  }
6992
 
7609
  margin-right: 46%;
7610
  }
7611
 
7612
+ .rtl .frm-field-action-icons {
7613
+ right: unset;
7614
+ left: 2px;
 
7615
  }
7616
 
7617
  .rtl #frm_upgrade_modal .dismiss i,
8182
  max-width: 843px;
8183
  border-radius: 10px;
8184
  }
8185
+
8186
+ #frm_field_group_popup {
8187
+ position: absolute;
8188
+ top: 0;
8189
+ right: 0;
8190
+ width: 366px;
8191
+ height: 231px;
8192
+ border-radius: 8px;
8193
+ background: #fff;
8194
+ box-shadow: 0px 20px 48px rgba(40, 47, 54, 0.15);
8195
+ z-index: 3;
8196
+ box-sizing: border-box;
8197
+ padding: 24px 0;
8198
+ text-align: left;
8199
+ }
8200
+
8201
+ .rtl #frm_field_group_popup {
8202
+ text-align: right;
8203
+ }
8204
+
8205
+ .frm-merge-fields-into-row #frm_field_group_popup {
8206
+ top: unset;
8207
+ bottom: 50px;
8208
+ height: 196px;
8209
+ }
8210
+
8211
+ .frm-merge-fields-into-row #frm_field_group_popup .frm-break-field-group {
8212
+ display: none;
8213
+ }
8214
+
8215
+ .frm-merge-fields-into-row > a {
8216
+ color: rgba(40, 47, 54, 0.85);
8217
+ position: relative;
8218
+ top: 2px;
8219
+ }
8220
+
8221
+ .frm-row-layout-title {
8222
+ font-weight: 600;
8223
+ font-size: 11px;
8224
+ line-height: 15px;
8225
+ text-transform: uppercase;
8226
+ color: rgba(40, 47, 54, 0.45);
8227
+ margin-bottom: 40px;
8228
+ }
8229
+
8230
+ .frm-row-layout-option {
8231
+ background: #F6F7FB;
8232
+ box-sizing: border-box;
8233
+ border-radius: 2px;
8234
+ padding: 18px 11px;
8235
+ }
8236
+
8237
+ #frm_field_group_popup .frm-row-layout-option .frm_grid_container {
8238
+ grid-gap: 0 5%;
8239
+ grid-template-columns: repeat(12, auto);
8240
+ }
8241
+
8242
+ #frm_field_group_popup .frm-row-layout-option {
8243
+ cursor: pointer;
8244
+ }
8245
+
8246
+ #frm_field_group_popup .frm-row-layout-option.frm-active-row-layout,
8247
+ #frm_field_group_popup .frm-row-layout-option:hover {
8248
+ outline: 1px solid #4199FD;
8249
+ }
8250
+
8251
+ .frm-custom-field-group-layout,
8252
+ .frm-break-field-group {
8253
+ padding: 5px 15px;
8254
+ cursor: pointer;
8255
+ font-size: 14px;
8256
+ line-height: 19px;
8257
+ color: rgba(40, 47, 54, 0.85);
8258
+ }
8259
+
8260
+ .frm-custom-field-group-layout:hover,
8261
+ .frm-break-field-group:hover {
8262
+ background-color: #f5f5f5f5;
8263
+ }
8264
+
8265
+ .frm-custom-field-group-layout svg,
8266
+ .frm-break-field-group svg {
8267
+ margin-right: 5px;
8268
+ }
8269
+
8270
+ .frm-selected-field-group {
8271
+ background: rgba(65, 153, 253, 0.07);
8272
+ position: relative;
8273
+ }
8274
+
8275
+ #frm_field_multiselect_popup {
8276
+ background: white;
8277
+ height: 48px;
8278
+ position: fixed;
8279
+ border-radius: 4px;
8280
+ box-shadow: 0px 8px 24px rgba(40, 47, 54, 0.15);
8281
+ color: rgba(40, 47, 54, 0.85);
8282
+ font-size: 13px;
8283
+ right: 30px;
8284
+ bottom: 10px;
8285
+ }
8286
+
8287
+ #frm_field_multiselect_popup > div {
8288
+ display: inline-block;
8289
+ line-height: 48px;
8290
+ vertical-align: top;
8291
+ }
8292
+
8293
+ #frm_field_multiselect_popup.frm-unmergable > .frm-merge-fields-into-row,
8294
+ #frm_field_multiselect_popup.frm-unmergable > .frm-multiselect-popup-separator {
8295
+ display: none;
8296
+ }
8297
+
8298
+ #frm_field_multiselect_popup > div:not(.frm-multiselect-popup-separator) {
8299
+ padding: 0 20px;
8300
+ cursor: pointer;
8301
+ }
8302
+
8303
+ #frm_field_multiselect_popup > div:not(.frm-multiselect-popup-separator):hover {
8304
+ background: #f5f5f5f5;
8305
+ }
8306
+
8307
+ .frm-builder-popup-heading {
8308
+ font-weight: 600;
8309
+ font-size: 12px;
8310
+ line-height: 15px;
8311
+ text-transform: uppercase;
8312
+ color: rgba(40, 47, 54, 0.45);
8313
+ }
8314
+
8315
+ .frm-builder-popup-subheading {
8316
+ font-size: 12px;
8317
+ line-height: 16px;
8318
+ color: rgba(40, 47, 54, 0.45);
8319
+ }
8320
+
8321
+ .frm-multiselect-popup-separator {
8322
+ height: 36px;
8323
+ width: 1px;
8324
+ position: relative;
8325
+ top: 6px;
8326
+ background: #C4C4C4;
8327
+ }
8328
+
8329
+
8330
+ .frm-sortable-helper,
8331
+ .frm-multiselect-key-is-down li.form-field:not(.edit_field_type_divider) {
8332
+ pointer-events: none;
8333
+ }
formidable.php CHANGED
@@ -2,7 +2,7 @@
2
  /*
3
  Plugin Name: Formidable Forms
4
  Description: Quickly and easily create drag-and-drop forms
5
- Version: 4.11.05
6
  Plugin URI: https://formidableforms.com/
7
  Author URI: https://formidableforms.com/
8
  Author: Strategy11
2
  /*
3
  Plugin Name: Formidable Forms
4
  Description: Quickly and easily create drag-and-drop forms
5
+ Version: 5.0
6
  Plugin URI: https://formidableforms.com/
7
  Author URI: https://formidableforms.com/
8
  Author: Strategy11
images/icons.svg CHANGED
@@ -933,5 +933,11 @@
933
  <symbol id="frm_case_icon" viewBox="0 0 24 24"><path d="M15 6.5a1 1 0 01-1-1V4h-4v1.5a1 1 0 01-2 0V4c0-1.1.9-2 2-2h4a2 2 0 012 2v1.5c0 .6-.4 1-1 1zM18 12.5v1c0 .3-.3.7-.8.7a.8.8 0 01-.7-.8v-.9h-9v1c0 .3-.3.7-.8.7a.8.8 0 01-.7-.8v-.9H0v6.7C0 20.8 1.2 22 2.7 22h18.5c1.6 0 2.8-1.2 2.8-2.8v-6.7h-6zM21.3 5H2.7A2.7 2.7 0 000 7.8V11h6V9.8c0-.5.3-.8.8-.8.4 0 .7.3.7.8V11h9V9.8c0-.5.3-.8.8-.8.4 0 .7.3.7.8V11h6V7.7C24 6.2 22.8 5 21.3 5z" fill="currentColor"></path></symbol>
934
  <symbol id="frm_smile_icon" viewBox="0 0 24 24"><path d="M12 0a12 12 0 100 24 12 12 0 000-24zM5 9c0-1.1.9-2 2-2a2 2 0 012 2 2 2 0 01-2 2 2 2 0 01-2-2zm12.7 9a8 8 0 01-11.4 0 1 1 0 011.4-1.5 6 6 0 008.6 0 1 1 0 011.4 1.4zm-.7-7a2 2 0 01-2-2c0-1.1.9-2 2-2a2 2 0 010 4z" fill="currentColor"></path></symbol>
935
  <symbol id="frm_user_name_icon" viewBox="0 0 24 24" fill="none"><path d="M3 21L21 21C22.1046 21 23 20.1046 23 19L23 16.75L23 13.5625L23 12.5L23 11.4375L23 8.25L23 6C23 4.89543 22.1046 4 21 4L15.1429 4L8.85714 4L3 4C1.89543 4 0.999998 4.89543 0.999998 6L0.999997 19C0.999997 20.1046 1.89543 21 3 21Z" stroke="#282F36" stroke-opacity="0.45" stroke-width="1.5"/><path fill-rule="evenodd" clip-rule="evenodd" d="M11.9313 9.93864C11.9313 11.5916 10.5987 12.8773 8.99262 12.8773C7.34168 12.8773 6.05398 11.5896 6.05398 9.93864C6.05398 8.33253 7.33964 7 8.99262 7C10.6008 7 11.9313 8.33049 11.9313 9.93864ZM10.1619 9.93864C10.1619 9.32165 9.60961 8.76932 8.99262 8.76932C8.33687 8.76932 7.8233 9.31757 7.8233 9.93864C7.8233 10.5984 8.33283 11.108 8.99262 11.108C9.61369 11.108 10.1619 10.5944 10.1619 9.93864ZM4 17.4699C4 15.4783 5.58561 13.8466 7.6233 13.8466H10.3619C12.3552 13.8466 13.9852 15.4766 13.9852 17.4699C13.9852 17.9734 13.5453 18.3546 13.1006 18.3546C12.605 18.3546 12.2159 17.9655 12.2159 17.4699C12.2159 16.4678 11.3641 15.6159 10.3619 15.6159H7.6233C6.5811 15.6159 5.76932 16.4651 5.76932 17.4699C5.76932 17.9734 5.32934 18.3546 4.88466 18.3546C4.38908 18.3546 4 17.9655 4 17.4699Z" fill="#282F36" fill-opacity="0.45"/><line x1="15.75" y1="9.25" x2="19.25" y2="9.25" stroke="#282F36" stroke-opacity="0.45" stroke-width="1.5" stroke-linecap="round"/><line x1="15.75" y1="12.25" x2="19.25" y2="12.25" stroke="#282F36" stroke-opacity="0.45" stroke-width="1.5" stroke-linecap="round"/></symbol>
 
 
 
 
 
 
936
  </defs>
937
  </svg>