PluginProbe
Kit (formerly ConvertKit) – Email Newsletter, Email Marketing, Membership, Subscribers and Landing Pages / 2.4.1
Kit (formerly ConvertKit) – Email Newsletter, Email Marketing, Membership, Subscribers and Landing Pages v2.4.1
3.4.1 3.4.0 3.3.9 3.3.8 3.3.7 3.3.6 3.3.5 3.3.4 3.3.3 3.3.2 3.3.1 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.2.6 2.2.7 2.2.8 2.2.9 2.3.0 2.3.1 2.3.2 2.3.3 All 194 releases
convertkit / includes / class-convertkit-resource-forms.php

class-convertkit-resource-forms.php in Kit (formerly ConvertKit) – Email Newsletter, Email Marketing, Membership, Subscribers and Landing Pages 2.4.1, at includes/class-convertkit-resource-forms.php

332 lines 9.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * ConvertKit Forms Resource class.
4 *
5 * @package ConvertKit
6 * @author ConvertKit
7 */
8
9 /**
10 * Reads ConvertKit Forms from the options table, and refreshes
11 * ConvertKit Forms data stored locally from the API.
12 *
13 * @since 1.9.6
14 */
15 class ConvertKit_Resource_Forms extends ConvertKit_Resource {
16
17 /**
18 * Holds the Settings Key that stores site wide ConvertKit settings
19 *
20 * @var string
21 */
22 public $settings_name = 'convertkit_forms';
23
24 /**
25 * The type of resource
26 *
27 * @var string
28 */
29 public $type = 'forms';
30
31 /**
32 * Constructor.
33 *
34 * @since 1.9.8.4
35 *
36 * @param bool|string $context Context.
37 */
38 public function __construct( $context = false ) {
39
40 // Initialize the API if the API Key and Secret have been defined in the Plugin Settings.
41 $settings = new ConvertKit_Settings();
42 if ( $settings->has_api_key_and_secret() ) {
43 $this->api = new ConvertKit_API(
44 $settings->get_api_key(),
45 $settings->get_api_secret(),
46 $settings->debug_enabled(),
47 $context
48 );
49 }
50
51 // Call parent initialization function.
52 parent::init();
53
54 }
55
56 /**
57 * Returns all non-inline forms based on the sort order.
58 *
59 * @since 2.2.4
60 *
61 * @return bool|array
62 */
63 public function get_non_inline() {
64
65 // If the ConvertKit WordPress Libraries are < 1.3.6 (e.g. loaded by an outdated
66 // addon), or a WordPress site updates this Plugin before other ConvertKit Plugins,
67 // get_by() won't be available and will cause an E_ERROR, crashing the site.
68 // @see https://wordpress.org/support/topic/error-1795/.
69 if ( ! method_exists( $this, 'get_by' ) ) {
70 return false;
71 }
72
73 return $this->get_by( 'format', array( 'modal', 'slide in', 'sticky bar' ) );
74
75 }
76
77
78 /**
79 * Returns whether any non-inline forms exist in the options table.
80 *
81 * @since 2.2.4
82 *
83 * @return bool
84 */
85 public function non_inline_exist() {
86
87 if ( ! $this->get_non_inline() ) {
88 return false;
89 }
90
91 return true;
92
93 }
94
95 /**
96 * Returns a <select> field populated with all forms, based on the given parameters.
97 *
98 * @since 2.3.9
99 *
100 * @param string $name Name.
101 * @param string $id ID.
102 * @param bool|array $css_classes <select> CSS class(es).
103 * @param string $selected_option <option> value to mark as selected.
104 * @param bool|array $prepend_options <option> elements to prepend before resources.
105 * @param bool|array $attributes <select> attributes.
106 * @param bool|string|array $description Description.
107 * @return string HTML Select Field
108 */
109 public function get_select_field_all( $name, $id, $css_classes, $selected_option, $prepend_options = false, $attributes = false, $description = false ) {
110
111 return $this->get_select_field(
112 $this->get(),
113 $name,
114 $id,
115 $css_classes,
116 $selected_option,
117 $prepend_options,
118 $attributes,
119 $description
120 );
121
122 }
123
124 /**
125 * Returns a <select> field populated with all non-inline forms, based on the given parameters.
126 *
127 * @since 2.3.9
128 *
129 * @param string $name Name.
130 * @param string $id ID.
131 * @param bool|array $css_classes <select> CSS class(es).
132 * @param string $selected_option <option> value to mark as selected.
133 * @param bool|array $prepend_options <option> elements to prepend before resources.
134 * @param bool|array $attributes <select> attributes.
135 * @param bool|string|array $description Description.
136 * @return string HTML Select Field
137 */
138 public function get_select_field_non_inline( $name, $id, $css_classes, $selected_option, $prepend_options = false, $attributes = false, $description = false ) {
139
140 return $this->get_select_field(
141 $this->get_non_inline(),
142 $name,
143 $id,
144 $css_classes,
145 $selected_option,
146 $prepend_options,
147 $attributes,
148 $description
149 );
150
151 }
152
153 /**
154 * Returns a <select> field populated with the resources, based on the given parameters.
155 *
156 * @since 2.3.9
157 *
158 * @param array $forms Forms.
159 * @param string $name Name.
160 * @param string $id ID.
161 * @param bool|array $css_classes <select> CSS class(es).
162 * @param string $selected_option <option> value to mark as selected.
163 * @param bool|array $prepend_options <option> elements to prepend before resources.
164 * @param bool|array $attributes <select> attributes.
165 * @param bool|string|array $description Description.
166 * @return string HTML Select Field
167 */
168 private function get_select_field( $forms, $name, $id, $css_classes, $selected_option, $prepend_options = false, $attributes = false, $description = false ) {
169
170 $html = sprintf(
171 '<select name="%s" id="%s" class="%s"',
172 esc_attr( $name ),
173 esc_attr( $id ),
174 esc_attr( ( is_array( $css_classes ) ? implode( ' ', $css_classes ) : '' ) )
175 );
176
177 // Append any attributes.
178 if ( $attributes ) {
179 foreach ( $attributes as $key => $value ) {
180 $html .= sprintf(
181 ' %s="%s"',
182 esc_attr( $key ),
183 esc_attr( $value )
184 );
185 }
186 }
187
188 // Close select tag.
189 $html .= '>';
190
191 // If any prepended options exist, add them now.
192 if ( $prepend_options ) {
193 foreach ( $prepend_options as $value => $label ) {
194 $html .= sprintf(
195 '<option value="%s" data-preserve-on-refresh="1"%s>%s</option>',
196 esc_attr( $value ),
197 selected( $selected_option, $value, false ),
198 esc_attr( $label )
199 );
200 }
201 }
202
203 // Iterate through resources, if they exist, building <option> elements.
204 if ( $forms ) {
205 foreach ( $forms as $form ) {
206 // Legacy forms don't include a `format` key, so define them as inline.
207 $html .= sprintf(
208 '<option value="%s"%s>%s [%s]</option>',
209 esc_attr( $form['id'] ),
210 selected( $selected_option, $form['id'], false ),
211 esc_attr( $form['name'] ),
212 ( ! empty( $form['format'] ) ? esc_attr( $form['format'] ) : 'inline' )
213 );
214 }
215 }
216
217 // Close select.
218 $html .= '</select>';
219
220 // If no description is provided, return the select field now.
221 if ( ! $description ) {
222 return $html;
223 }
224
225 // Append description before returning field.
226 if ( ! is_array( $description ) ) {
227 return $html . '<p class="description">' . $description . '</p>';
228 }
229
230 // Return description lines in a paragraph, using breaklines for each description entry in the array.
231 return $html . '<p class="description">' . implode( '<br />', $description ) . '</p>';
232
233 }
234
235 /**
236 * Returns the HTML/JS markup for the given Form ID.
237 *
238 * Legacy Forms will return HTML.
239 * Current Forms will return a <script> embed string.
240 *
241 * @since 1.9.6
242 *
243 * @param int $id Form ID.
244 * @return WP_Error|string
245 */
246 public function get_html( $id ) {
247
248 // Cast ID to integer.
249 $id = absint( $id );
250
251 // Bail if the resources are a WP_Error.
252 if ( is_wp_error( $this->resources ) ) {
253 return $this->resources;
254 }
255
256 // Bail if the resource doesn't exist.
257 if ( ! isset( $this->resources[ $id ] ) ) {
258 return new WP_Error(
259 'convertkit_resource_forms_get_html',
260 sprintf(
261 /* translators: ConvertKit Form ID */
262 __( 'ConvertKit Form ID %s does not exist on ConvertKit.', 'convertkit' ),
263 $id
264 )
265 );
266 }
267
268 // If no uid is present in the Form API data, this is a legacy form that's served by directly fetching the HTML
269 // from forms.convertkit.com.
270 if ( ! isset( $this->resources[ $id ]['uid'] ) ) {
271 // Initialize Settings.
272 $settings = new ConvertKit_Settings();
273
274 // Bail if no API Key is specified in the Plugin Settings.
275 if ( ! $settings->has_api_key() ) {
276 return new WP_Error(
277 'convertkit_resource_forms_get_html',
278 __( 'ConvertKit Legacy Form could not be fetched as no API Key specified in Plugin Settings', 'convertkit' )
279 );
280 }
281
282 // Initialize the API.
283 $api = new ConvertKit_API( $settings->get_api_key(), $settings->get_api_secret(), $settings->debug_enabled(), 'output_form' );
284
285 // Return Legacy Form HTML.
286 return $api->get_form_html( $id );
287 }
288
289 // If the form's format is not an inline form, add the inline script before the closing </body> tag.
290 // This prevents a modal form's overlay being constrained by the WordPress Theme's styles,
291 // and accidentally embedding the same non-inline form twice, which would result in e.g. the same modal form
292 // displaying twice.
293 if ( $this->resources[ $id ]['format'] !== 'inline' ) {
294 add_filter(
295 'convertkit_output_scripts_footer',
296 function ( $scripts ) use ( $id ) {
297
298 $scripts[] = array(
299 'async' => true,
300 'data-uid' => $this->resources[ $id ]['uid'],
301 'src' => $this->resources[ $id ]['embed_js'],
302 );
303
304 return $scripts;
305
306 }
307 );
308
309 // Sanity check we're not in the WordPress Admin interface.
310 // Some third party REST API Plugins seem to load frontend Posts, which would result in a wp_die() as
311 // the output Plugin class (rightly) isn't initialized in the backend.
312 if ( is_admin() ) {
313 return '';
314 }
315
316 // Don't output the global non-inline form, if defined, because
317 // a non-inline form was specified at either Post/Page default level, Post/Page level
318 // or Post Category level.
319 // This prevents multiple non-inline forms loading.
320 remove_action( 'wp_footer', array( WP_ConvertKit()->get_class( 'output' ), 'output_global_non_inline_form' ), 1 );
321
322 // Don't return a script for output, as it'll be output in the site's footer.
323 return '';
324 }
325
326 // If here, return Form <script> embed now, as we want the inline form to display at this specific point of the content.
327 return '<script async data-uid="' . esc_attr( $this->resources[ $id ]['uid'] ) . '" src="' . esc_url( $this->resources[ $id ]['embed_js'] ) . '"></script>';
328
329 }
330
331 }
332