PluginProbe
User Profile Builder – Beautiful User Registration Forms, User Profiles & User Role Editor / 3.16.3
User Profile Builder – Beautiful User Registration Forms, User Profiles & User Role Editor v3.16.3
4.0.3 4.0.2 4.0.1 4.0.0 3.16.6 3.16.5 3.16.4 3.16.3 3.16.2 3.16.1 3.16.0 3.15.9 3.9.9 3.9.5 3.9.6 3.9.7 3.9.8 1.1.7 1.1.8 1.1.9 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 All 341 releases
profile-builder / assets / lib / wck-api / wordpress-creation-kit.php

wordpress-creation-kit.php in User Profile Builder – Beautiful User Registration Forms, User Profiles & User Role Editor 3.16.3, at assets/lib/wck-api/wordpress-creation-kit.php

1,773 lines 71.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /* Copyright 2011 Ungureanu Madalin (email : [email protected])
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2 of the License, or
6 (at your option) any later version.
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
11 You should have received a copy of the GNU General Public License
12 along with this program; if not, write to the Free Software
13 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
14 */
15
16 if( file_exists( dirname(__FILE__). '/wck-fep/wck-fep.php' ) )
17 require_once( 'wck-fep/wck-fep.php' );
18
19 if( file_exists( dirname(__FILE__). '/wck-static-metabox-api.php' ) )
20 require_once( 'wck-static-metabox-api.php' );
21
22
23 /*
24
25 Usage Example 1:
26
27
28 $fint = array(
29 array( 'type' => 'text', 'title' => 'Title', 'description' => 'Description for this input' ),
30 array( 'type' => 'textarea', 'title' => 'Description' ),
31 array( 'type' => 'upload', 'title' => 'Image', 'description' => 'Upload a image' ),
32 array( 'type' => 'select', 'title' => 'Select This', 'options' => array( 'Option 1', 'Option 2', 'Option 3' ) ),
33 array( 'type' => 'checkbox', 'title' => 'Check This', 'options' => array( 'Option 1', 'Option 2', 'Option 3' ) ),
34 array( 'type' => 'radio', 'title' => 'Radio This', 'options' => array( 'Radio 1', 'Radio 2', 'Radio 3' ) ),
35 );
36
37 $args = array(
38 'metabox_id' => 'rm_slider_content',
39 'metabox_title' => 'Slideshow Class',
40 'post_type' => 'slideshows',
41 'meta_name' => 'rmscontent',
42 'meta_array' => $fint
43 );
44
45 new Wordpress_Creation_Kit_PB( $args );
46
47
48 On the frontend:
49
50 $meta = get_post_meta( $post->ID, 'rmscontent', true );
51
52 */
53
54 class Wordpress_Creation_Kit_PB{
55
56 private $defaults = array(
57 'metabox_id' => '',
58 'metabox_title' => 'Meta Box',
59 'post_type' => 'post',
60 'meta_name' => '',
61 'meta_array' => array(),
62 'page_template' => '',
63 'post_id' => '',
64 'single' => false,
65 'unserialize_fields' => false,
66 'sortable' => true,
67 'context' => 'post_meta',
68 'mb_context' => 'normal'
69 );
70 private $args;
71
72
73 /* Constructor method for the class. */
74 function __construct( $args ) {
75
76 /* Global that will hold all the arguments for all the custom boxes */
77 global $wck_objects;
78
79 /* Merge the input arguments and the defaults. */
80 $this->args = wp_parse_args( $args, $this->defaults );
81
82 /* Add the settings for this box to the global object */
83 $wck_objects[$this->args['metabox_id']] = $this->args;
84
85 /*print scripts*/
86 add_action('admin_enqueue_scripts', array( &$this, 'wck_print_scripts' ), 9);
87 /* add our own ajaxurl because we are going to use the wck script also in frontend and we want to avoid any conflicts */
88 add_action( 'admin_head', array( &$this, 'wck_print_ajax_url' ) );
89
90 // Set up the AJAX hooks
91 add_action("wp_ajax_wck_add_meta".$this->args['meta_name'], array( &$this, 'wck_add_meta') );
92 add_action("wp_ajax_wck_update_meta".$this->args['meta_name'], array( &$this, 'wck_update_meta') );
93 add_action("wp_ajax_wck_show_update".$this->args['meta_name'], array( &$this, 'wck_show_update_form') );
94 add_action("wp_ajax_wck_refresh_list".$this->args['meta_name'], array( &$this, 'wck_refresh_list') );
95 add_action("wp_ajax_wck_remove_meta".$this->args['meta_name'], array( &$this, 'wck_remove_meta') );
96 add_action("wp_ajax_wck_reorder_meta".$this->args['meta_name'], array( &$this, 'wck_reorder_meta') );
97
98 add_action('add_meta_boxes', array( &$this, 'wck_add_metabox') );
99 add_action('wck_add_meta_boxes', array( &$this, 'wck_add_metabox') );
100
101 /* For single forms we save them the old fashion way */
102 if( $this->args['single'] ){
103 add_action('save_post', array($this, 'wck_save_single_metabox'), 10, 2);
104 /* wp_insert_post executes after save_post so at this point if we have the error global we can redirect the page
105 and add the error message and error fields urlencoded as $_GET */
106 add_action('wp_insert_post', array($this, 'wck_single_metabox_redirect_if_errors'), 10, 2);
107 /* if we have any $_GET errors alert them with js so we have consistency */
108 add_action('admin_print_footer_scripts', array($this, 'wck_single_metabox_errors_display') );
109 }
110
111 }
112
113
114 //add metabox using wordpress api
115
116 function wck_add_metabox() {
117
118 global $pb_wck_pages_hooknames;
119
120 if( $this->args['context'] == 'post_meta' ){
121 if( $this->args['post_id'] == '' && $this->args['page_template'] == '' ){
122
123 $priority = 'high';
124
125 if( !empty( $this->args['meta_name'] ) && in_array( $this->args['meta_name'], array( 'wppb_ul_settings_query', 'wppb_ul_csv_download_settings', 'wppb_rf_progress_bar_settings', 'wppb_epf_progress_bar_settings' ) ) ){
126 $priority = 'low';
127 }
128
129 add_meta_box($this->args['metabox_id'], $this->args['metabox_title'], array( &$this, 'wck_content' ), $this->args['post_type'], $this->args['mb_context'], $priority, array( 'meta_name' => $this->args['meta_name'], 'meta_array' => $this->args['meta_array']) );
130 /* add class to meta box */
131 add_filter( "postbox_classes_".$this->args['post_type']."_".$this->args['metabox_id'], array( &$this, 'wck_add_metabox_classes' ) );
132
133 }
134 else{
135 if( !empty( $_GET['post'] ) )
136 $post_id = filter_var( $_GET['post'], FILTER_SANITIZE_NUMBER_INT );
137 else if( !empty( $_POST['post_ID'] ) )
138 $post_id = filter_var( $_POST['post_ID'], FILTER_SANITIZE_NUMBER_INT );
139 else
140 $post_id = '';
141
142
143 if( $this->args['post_id'] != '' && $this->args['page_template'] != '' ){
144 $template_file = get_post_meta($post_id,'_wp_page_template',TRUE);
145 if( $this->args['post_id'] == $post_id && $template_file == $this->args['page_template'] )
146 add_meta_box($this->args['metabox_id'], $this->args['metabox_title'], array( &$this, 'wck_content' ), 'page', $this->args['mb_context'], 'high', array( 'meta_name' => $this->args['meta_name'], 'meta_array' => $this->args['meta_array'] ) );
147
148 /* add class to meta box */
149 add_filter( "postbox_classes_page_".$this->args['metabox_id'], array( &$this, 'wck_add_metabox_classes' ) );
150 }
151 else{
152
153 if( $this->args['post_id'] != '' ){
154 if( $this->args['post_id'] == $post_id ){
155 $post_type = get_post_type( $post_id );
156 add_meta_box($this->args['metabox_id'], $this->args['metabox_title'], array( &$this, 'wck_content' ), $post_type, $this->args['mb_context'], 'high', array( 'meta_name' => $this->args['meta_name'], 'meta_array' => $this->args['meta_array'] ) );
157 /* add class to meta box */
158 add_filter( "postbox_classes_".$post_type."_".$this->args['metabox_id'], array( &$this, 'wck_add_metabox_classes' ) );
159 }
160 }
161
162 if( $this->args['page_template'] != '' ){
163 $template_file = get_post_meta($post_id,'_wp_page_template',TRUE);
164 if ( $template_file == $this->args['page_template'] ){
165 add_meta_box($this->args['metabox_id'], $this->args['metabox_title'], array( &$this, 'wck_content' ), 'page', $this->args['mb_context'], 'high', array( 'meta_name' => $this->args['meta_name'], 'meta_array' => $this->args['meta_array']) );
166 /* add class to meta box */
167 add_filter( "postbox_classes_page_".$this->args['metabox_id'], array( &$this, 'wck_add_metabox_classes' ) );
168 }
169 }
170
171 }
172
173 }
174 }
175 else if( $this->args['context'] == 'option' ){
176 if( !empty( $pb_wck_pages_hooknames[$this->args['post_type']] ) ) {
177 add_meta_box($this->args['metabox_id'], $this->args['metabox_title'], array(&$this, 'wck_content'), $pb_wck_pages_hooknames[$this->args['post_type']], $this->args['mb_context'], 'high', array('meta_name' => $this->args['meta_name'], 'meta_array' => $this->args['meta_array']));
178 /* add class to meta box */
179 add_filter("postbox_classes_" . $pb_wck_pages_hooknames[$this->args['post_type']] . "_" . $this->args['metabox_id'], array(&$this, 'wck_add_metabox_classes'));
180 }
181 }
182 }
183
184 /* Function used to add classes to the wck meta boxes */
185 function wck_add_metabox_classes( $classes ){
186 array_push($classes,'wck-post-box');
187 return $classes;
188 }
189
190 function wck_content($post, $metabox){
191 if( !empty( $post->ID ) )
192 $post_id = $post->ID;
193 else
194 $post_id = '';
195
196
197
198 // output the add form or themes metabox content
199 if ($metabox['id'] == 'wppb-ul-themes-settings' ) {
200 echo $metabox['args']['meta_array']; //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
201 }
202 else self::create_add_form($metabox['args']['meta_array'], $metabox['args']['meta_name'], $post);
203
204 //output the entries only for repeater fields
205 if( !$this->args['single'] )
206 echo self::wck_output_meta_content($metabox['args']['meta_name'], $post_id, $metabox['args']['meta_array']); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
207 }
208
209 /**
210 * The function used to create a form element
211 *
212 * @since 1.0.0
213 *
214 * @param string $meta Meta name.
215 * @param array $details Contains the details for the field.
216 * @param string $value Contains input value;
217 * @param string $context Context where the function is used. Depending on it some actions are preformed.;
218 * @param int $post_id The post ID;
219 * @return string $element input element html string.
220 */
221
222 function wck_output_form_field( $meta, $details, $value = '', $context = '', $post_id = '' ){
223 $element = '';
224
225 if( $context == 'edit_form' ){
226 $edit_class = '.mb-table-container ';
227 $var_prefix = 'edit';
228 }
229 else if( $context == 'fep' ){
230 /* id prefix for frontend posting */
231 $frontend_prefix = 'fep-';
232 }
233 else{
234 if( isset( $details['default'] ) && !( $this->args['single'] == true && !is_null( $value ) ) ) {
235 $value = apply_filters("wck_default_value_{$meta}_" . Wordpress_Creation_Kit_PB::wck_generate_slug( $details['title'], $details ), $details['default']);
236 }
237 }
238
239 /* for single post meta metaboxes we need a prefix in the name attr of the input because in the case we have multiple single metaboxes on the same
240 post we need to prevent the fields from having the same name attr */
241 if( $this->args['context'] == 'post_meta' && $this->args['single'] && $context != 'fep' )
242 $single_prefix = $this->args['meta_name'].'_';
243 else
244 $single_prefix = '';
245
246 $context_slug = !empty($context) ? $context . '_' : '';
247 $label_for = esc_attr( Wordpress_Creation_Kit_PB::wck_generate_slug( $details['title'], $details ) );
248 if ( $details['type'] === 'checkbox' && !empty( $details['options'] ) && count( $details['options'] ) == 1 ) {
249 $label_for = $label_for . '_yes';
250 }
251
252 $element .= '<label class="cozmoslabs-form-field-label" for="'. $label_for .'">'. apply_filters( "wck_label_{$meta}_". Wordpress_Creation_Kit_PB::wck_generate_slug( $details['title'], $details ), ucfirst($details['title']) );
253 if( !empty( $details['required'] ) && $details['required'] )
254 $element .= '<span class="required">*</span>';
255 $element .= '</label>';
256
257
258 // Allow for appeding custom markup before the element.
259 $element .= apply_filters( 'wck_output_form_field_before_customtype_' . $details['type'], '', $value, $details, $single_prefix );
260
261 /*
262 include actual field type
263 possible field types: text, textarea, select, checkbox, radio, upload, wysiwyg editor, datepicker, country select, user select, cpt select
264 */
265
266 if( function_exists( 'wck_nr_get_repeater_boxes' ) ){
267 $cfc_titles = wck_nr_get_repeater_boxes();
268 if( in_array( $details['type'], $cfc_titles ) ){
269 $details['type'] = 'nested repeater';
270 }
271 }
272
273 if ( isset( $details['options'] ) ) {
274 // Allow to filter the options for specific field slugs.
275 $details = apply_filters( 'wck_output_form_field_options_by_slug', $details, $details['slug'], $value, $single_prefix );
276 }
277
278 if( file_exists( dirname( __FILE__ ).'/fields/'.$details['type'].'.php' ) ){
279 require( dirname( __FILE__ ).'/fields/'.$details['type'].'.php' );
280 }
281
282 // Add a filter that allows us to add support for custom field types, not just the ones defined in fields (wck api)
283 $element .= apply_filters('wck_output_form_field_customtype_' . $details['type'], '', $value, $details, $single_prefix);
284
285
286 // Allow for appeding custom markup after the element.
287 $element .= apply_filters( 'wck_output_form_field_after_customtype_' . $details['type'], '', $value, $details, $single_prefix );
288
289 if( !empty( $details['description'] ) ){
290 $element .= '<p class="cozmoslabs-description cozmoslabs-description-space-left">'. $details['description'].'</p>';
291 }
292
293 $element = apply_filters( "wck_output_form_field_{$meta}_" . Wordpress_Creation_Kit_PB::wck_generate_slug( $details['title'], $details ), $element );
294
295 return $element;
296
297 }
298
299
300 /**
301 * The function used to create the form for adding records
302 *
303 * @since 1.0.0
304 *
305 * @param array $fields Contains the desired inputs in the repeater field. Must be like: array('Key:type').
306 * Key is used for the name attribute of the field, label of the field and as the meta_key.
307 * Supported types: input, textarea, upload
308 * @param string $meta It is used in update_post_meta($id, $meta, $results);. Use '_' prefix if you don't want
309 * the meta to apear in custom fields box.
310 * @param object $post Post object
311 */
312 function create_add_form($fields, $meta, $post, $context = '' ){
313 $nonce = wp_create_nonce( 'wck-add-meta' );
314 if( !empty( $post->ID ) )
315 $post_id = $post->ID;
316 else
317 $post_id = '';
318
319 /* for single forms we need the values that are stored in the meta */
320 if( $this->args['single'] == true ) {
321 if ($this->args['context'] == 'post_meta')
322 $results = get_post_meta($post_id, $meta, true);
323 else if ($this->args['context'] == 'option')
324 $results = get_option( apply_filters( 'wck_option_meta' , $meta ));
325
326 /* Filter primary used for CFC/OPC fields in order to show/hide fields based on type */
327 $wck_update_container_css_class = apply_filters("wck_add_form_class_{$meta}", '', $meta, $results );
328 }
329 ?>
330 <div id="<?php echo esc_attr( $meta ) ?>" style="padding:10px 0;" class="wck-add-form<?php if( $this->args['single'] ) echo ' single' ?> <?php if( !empty( $wck_update_container_css_class ) ) echo esc_attr( $wck_update_container_css_class ); ?>">
331 <ul class="mb-list-entry-fields">
332 <?php
333 $element_id = 0;
334 if( !empty( $fields ) ){
335 foreach( $fields as $details ){
336
337 do_action( "wck_before_add_form_{$meta}_element_{$element_id}" );
338
339 /* set values in the case of single forms */
340 $value = '';
341 if( $this->args['single'] == true ) {
342 $value = null;
343 if (isset($results[0][Wordpress_Creation_Kit_PB::wck_generate_slug($details['title'], $details )]))
344 $value = $results[0][Wordpress_Creation_Kit_PB::wck_generate_slug($details['title'], $details )];
345 }
346
347 $extra_class = '';
348 if ( $details['type'] === 'checkbox' && !empty( $details['options'] ) ) {
349 $number_of_options = count( $details['options'] );
350
351 if ( $number_of_options == 1 )
352 $extra_class .= ' cozmoslabs-toggle-switch';
353 elseif ( $number_of_options > 1 )
354 $extra_class .= ' cozmoslabs-checkbox-list-wrapper';
355 }
356 ?>
357 <li class="row-<?php echo esc_attr( Wordpress_Creation_Kit_PB::wck_generate_slug( $details['title'], $details ) ) ?> cozmoslabs-form-field-wrapper <?php echo esc_html( apply_filters( 'wck_form_field_wrapper_extra_classes', $extra_class ) ) ?>">
358 <?php echo self::wck_output_form_field( $meta, $details, $value, $context, $post_id ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
359 </li>
360 <?php
361
362 do_action( "wck_after_add_form_{$meta}_element_{$element_id}" );
363
364 $element_id++;
365 }
366 }
367 ?>
368 <?php if( ! $this->args['single'] || $this->args['context'] == 'option' ){ ?>
369 <li class="add-entry-button cozmoslabs-button-group">
370 <a href="javascript:void(0)" class="button-primary" onclick="addMeta('<?php echo esc_js($meta); ?>', '<?php echo esc_js( $post_id ); ?>', '<?php echo esc_js($nonce); ?>')"><span><?php if( $this->args['single'] ) echo esc_html( apply_filters( 'wck_add_entry_button', __( 'Save', 'profile-builder' ), $meta, $post ) ); else echo esc_html( apply_filters( 'wck_add_entry_button', __( 'Add Entry', 'profile-builder' ), $meta, $post ) ); ?></span></a>
371 </li>
372 <?php }elseif($this->args['single'] && $this->args['context'] == 'post_meta' ){ ?>
373 <input type="hidden" name="_wckmetaname_<?php echo esc_attr( $meta ) ?>#wck" value="true">
374 <?php } ?>
375 </ul>
376 </div>
377 <script>wck_set_to_widest( '.field-label', '<?php echo esc_js( $meta ) ?>' );</script>
378 <?php
379 }
380
381 /**
382 * The function used to display a form to update a reccord from meta
383 *
384 * @since 1.0.0
385 *
386 * @param string $meta It is used in get_post_meta($id, $meta, $results);. Use '_' prefix if you don't want
387 * the meta to apear in custom fields box.
388 * @param int $id Post id
389 * @param int $element_id The id of the reccord. The meta is stored as array(array());
390 */
391 function mb_update_form($fields, $meta, $id, $element_id){
392
393 $update_nonce = wp_create_nonce( 'wck-update-entry' );
394
395 if( $this->args['context'] == 'post_meta' )
396 $results = get_post_meta($id, $meta, true);
397 else if ( $this->args['context'] == 'option' )
398 $results = get_option( apply_filters( 'wck_option_meta' , $meta ) );
399
400 /* Filter primary used for CFC/OPC fields in order to show/hide fields based on type */
401 $wck_update_container_css_class = " class='wck_update_container update_container_$meta'";
402 $wck_update_container_css_class = apply_filters("wck_update_container_class_{$meta}", $wck_update_container_css_class, $meta, $results, $element_id );
403
404 $form = '';
405 $form .= '<tr id="update_container_'.$meta.'_'.$element_id.'" ' . $wck_update_container_css_class . '><td colspan="4">';
406 if($results != null){
407 $i = 0;
408 $form .= '<ul class="mb-list-entry-fields">';
409
410 if( !empty( $fields ) ){
411 foreach( $fields as $field ){
412 $details = $field;
413 if( isset( $results[$element_id][Wordpress_Creation_Kit_PB::wck_generate_slug( $details['title'], $details )] ) )
414 $value = $results[$element_id][Wordpress_Creation_Kit_PB::wck_generate_slug( $details['title'], $details )];
415 else
416 $value = '';
417
418 $extra_class = '';
419 if ( $details['type'] === 'checkbox' && !empty( $details['options'] ) ) {
420 $number_of_options = count( $details['options'] );
421
422 if ( $number_of_options == 1 )
423 $extra_class = 'cozmoslabs-toggle-switch';
424 elseif ( $number_of_options > 1 )
425 $extra_class = 'cozmoslabs-checkbox-list-wrapper';
426 }
427
428 $form = apply_filters( "wck_before_update_form_{$meta}_element_{$i}", $form, $element_id, $value );
429
430 $form .= '<li class="row-'. esc_attr( Wordpress_Creation_Kit_PB::wck_generate_slug( $details['title'], $details ) ) .' cozmoslabs-form-field-wrapper '. apply_filters( 'wck_form_field_wrapper_extra_classes', $extra_class) .'">';
431
432 $form .= self::wck_output_form_field( $meta, $details, $value, 'edit_form', $id ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
433
434 $form .= '</li>';
435
436 $form = apply_filters( "wck_after_update_form_{$meta}_element_{$i}", $form, $element_id, $value );
437
438 $i++;
439 }
440 }
441 $form .= '<li class="cozmoslabs-button-group">';
442 $form .= '<a href="javascript:void(0)" class="button-primary" onclick=\'updateMeta("'.esc_js($meta).'", "'.esc_js($id).'", "'.esc_js($element_id).'", "'.esc_js($update_nonce).'")\'><span>'. apply_filters( 'wck_save_changes_button', __( 'Save Changes', 'profile-builder' ), $meta ) .'</span></a>';
443 $form .= '<a href="javascript:void(0)" class="button button-secondary" style="margin-left:10px;" onclick=\'removeUpdateForm("'. esc_js( 'update_container_'.$meta.'_'.$element_id ). '" )\'><span>'. apply_filters( 'wck_cancel_button', __( 'Cancel', 'profile-builder' ), $meta ) .'</span></a>';
444 $form .= '</li>';
445
446 $form .= '</ul>';
447 }
448 $form .= '</td></tr>';
449
450 return $form;
451 }
452
453
454 /**
455 * The function used to output the content of a meta
456 *
457 * @since 1.0.0
458 *
459 * @param string $meta It is used in get_post_meta($id, $meta, $results);. Use '_' prefix if you don't want
460 * the meta to apear in custom fields box.
461 * @param int $id Post id
462 */
463 function wck_output_meta_content($meta, $id, $fields, $box_args = '' ){
464 /* in fep $this->args is empty so we need it as a parameter */
465 if( !empty( $box_args ) )
466 $this->args = wp_parse_args( $box_args, $this->defaults );
467
468
469 if( $this->args['context'] == 'post_meta' || $this->args['context'] == '' )
470 $results = get_post_meta($id, $meta, true);
471 else if ( $this->args['context'] == 'option' )
472 $results = get_option( apply_filters( 'wck_option_meta' , $meta ) );
473
474 $list = '';
475 $list .= '<table id="container_'.esc_attr($meta).'" class="mb-table-container widefat';
476
477 if( $this->args['single'] ) $list .= ' single';
478 if( !$this->args['sortable'] ) $list .= ' not-sortable';
479
480 $list .= '" post="'.esc_attr($id).'">';
481
482
483 if( !empty( $results ) ){
484 $list .= apply_filters( 'wck_metabox_content_header_'.$meta , '<thead><tr><th class="wck-number">#</th><th class="wck-content">'. __( 'Content', 'profile-builder' ) .'</th><th class="wck-edit">'. __( 'Edit', 'profile-builder' ) .'</th><th class="wck-delete">'. __( 'Delete', 'profile-builder' ) .'</th></tr></thead>' );
485 $i=0;
486 foreach ($results as $result){
487
488 $list .= self::wck_output_entry_content( $meta, $id, $fields, $results, $i );
489
490 $i++;
491 }
492 }
493 $list .= apply_filters( 'wck_metabox_content_footer_'.$meta , '', $id );
494 $list .= '</table>';
495
496 $list = apply_filters('wck_metabox_content_'.$meta, $list, $id);
497 return $list;
498 }
499
500 function wck_output_entry_content( $meta, $id, $fields, $results, $element_id ){
501 $edit_nonce = wp_create_nonce( 'wck-edit-entry' );
502 $delete_nonce = wp_create_nonce( 'wck-delete-entry' );
503 $entry_nr = $element_id +1;
504
505 $wck_element_class = '';
506 $wck_element_class = apply_filters( "wck_element_class_{$meta}", $wck_element_class, $meta, $results, $element_id );
507
508 $list = '';
509 $list .= '<tr id="element_'.$element_id.'" ' . $wck_element_class . '>';
510 $list .= apply_filters( 'wck_add_content_before_columns', '', $list, $meta );
511 $list .= '<td style="text-align:center;vertical-align:middle;" class="wck-number">'. $entry_nr .'</td>';
512 $list .= '<td class="wck-content"><ul>' . "\r\n";
513
514 $j = 0;
515
516 if( !empty( $fields ) ){
517 foreach( $fields as $field ){
518 $details = $field;
519
520 if( !empty( $results[$element_id][Wordpress_Creation_Kit_PB::wck_generate_slug( $details['title'], $details )] ) )
521 $value = $results[$element_id][Wordpress_Creation_Kit_PB::wck_generate_slug( $details['title'], $details )];
522 else
523 $value ='';
524
525 /* filter display value */
526 $value = apply_filters( "wck_displayed_value_{$meta}_element_{$j}", $value );
527
528 /* display it differently based on field type*/
529 if( $details['type'] == 'upload' ){
530 $display_value = self::wck_get_entry_field_upload($value);
531 } elseif ( $details['type'] == 'user select' ) {
532 $display_value = self::wck_get_entry_field_user_select( $value ) . '</pre>';
533 } elseif ( $details['type'] == 'cpt select' ){
534 $display_value = self::wck_get_entry_field_cpt_select( $value ) . '</pre>';
535 } elseif ( $details['type'] == 'checkbox' && is_array( $value ) ){
536 $display_value = implode( ', ', $value );
537 } elseif ( $details['type'] == 'select' || $details['type'] === 'select-2' ){
538 if ( $details['slug'] === 'pble-label' || $details['slug'] === 'field'){
539 $display_value = '<pre>' . self::wck_get_entry_field_select( $value, $details ) . '</pre>';
540 } else {
541 $display_value = '<pre>' . __(self::wck_get_entry_field_select( $value, $details ), 'profile-builder') . '</pre>'; //phpcs:ignore WordPress.WP.I18n.NonSingularStringLiteralText
542 }
543 } else {
544 $display_value = '<pre>'.htmlspecialchars( $value ) . '</pre>';
545 }
546
547 $display_value = apply_filters( "wck_pre_displayed_value_{$meta}_element_{$field['slug']}", $display_value );
548
549 $list = apply_filters( "wck_before_listed_{$meta}_element_{$j}", $list, $element_id, $value );
550 /*check for nested repeater type and set it acordingly */
551 if( strpos( $details['type'], 'CFC-') === 0 )
552 $details['type'] = 'nested-repeater';
553
554 $list .= '<li class="row-'. esc_attr( Wordpress_Creation_Kit_PB::wck_generate_slug( $details['title'], $details ) ) .'" data-type="'.$details['type'].'"><strong>'.$details['title'].': </strong>'.$display_value.' </li>' . "\r\n";
555
556 $list = apply_filters( "wck_after_listed_{$meta}_element_{$j}", $list, $element_id, $value );
557
558 $j++;
559
560 /* In CFC/OPC we need the field title. Find it out and output it if found */
561 if ($meta == 'wck_cfc_fields') {
562 if( !empty( $results[$element_id][Wordpress_Creation_Kit_PB::wck_generate_slug( $details['title'], $details )] ) ){
563 $field_title = $results[$element_id][Wordpress_Creation_Kit_PB::wck_generate_slug( $details['title'], $details )];
564 if ($field_title == "Field Type")
565 $cfc_field_type = $value;
566 }
567 }
568 }
569 }
570 $list .= '</ul>';
571
572 $list = apply_filters( 'wck_after_content_element', $list, $meta, $id, $results, $element_id );
573 /* check if we have nested repeaters */
574 if( function_exists( 'wck_nr_check_for_nested_repeaters' ) ){
575 if( wck_nr_check_for_nested_repeaters( $fields ) === true ){
576 $list .= wck_nr_handle_repeaters( $meta, $id, $fields, $results, $element_id );
577 }
578 }
579
580 if( $element_id === 0 ){
581 $list .= "<script>wck_set_to_widest( 'strong', '". $meta ."' );</script>";
582 }
583
584 $list .= '</td>';
585 $list .= '<td style="text-align:center;vertical-align:middle;" class="wck-edit"><a href="javascript:void(0)" class="button button-secondary" onclick=\'showUpdateFormMeta("'.esc_js($meta).'", "'.esc_js($id).'", "'.esc_js($element_id).'", "'.esc_js($edit_nonce).'")\' title="'. __( 'Edit this item', 'profile-builder' ) .'">'. apply_filters( 'wck_edit_button', __('Edit','profile-builder'), $meta ) .'</a></td>';
586 $list .= '<td style="text-align:center;vertical-align:middle;" class="wck-delete"><a href="javascript:void(0)" class="mbdelete" onclick=\'removeMeta("'.esc_js($meta).'", "'.esc_js($id).'", "'.esc_js($element_id).'", "'.esc_js($delete_nonce).'")\' title="'. __( 'Delete this item', 'profile-builder' ) .'">'. apply_filters( 'wck_delete_button', __( 'Delete', 'profile-builder' ), $meta) .'</a></td>';
587 $list .= apply_filters( 'wck_add_content_after_columns', '', $list, $meta );
588
589 $list .= "</tr> \r\n";
590
591 return $list;
592 }
593
594 /* function to generate the output for the select field */
595 function wck_get_entry_field_select( $value, $field_details ){
596 if ( (!is_array( $field_details ) && !isset( $field_details['options']) ) || empty( $value )){
597 return $value;
598 }
599
600 //convert field_details to single array if option groups are defined.
601 if( Wordpress_Creation_Kit_PB::wck_is_multi( $field_details['options'] ) ){
602 $select_options = array();
603 foreach($field_details['options']['optgroups'] as $optgroup) {
604 foreach($optgroup['options'] as $group_option ){
605
606 if( !is_array( $group_option ) )
607 $select_options[] = $group_option;
608
609 }
610 }
611
612 $field_details['options'] = $select_options;
613 }
614
615 foreach( $field_details['options'] as $option ){
616
617 if( is_array( $option ) ){
618
619 if( !empty( $option['field_name'] ) )
620 return $option['field_name'];
621
622 } elseif ( strpos( $option, $value ) !== false ){
623 if( strpos( $option, '%' ) === false ){
624 return $value;
625 } else {
626 $option_parts = explode( '%', $option );
627 if( !empty( $option_parts ) ){
628 if( empty( $option_parts[0] ) && count( $option_parts ) == 3 ){
629 $label = $option_parts[1];
630 return $label;
631 }
632 }
633 }
634 }
635
636 }
637
638 //this was added for select-2 custom values that do not exist in the defined options
639 return $value;
640 }
641
642 /* function to generate output for upload field */
643 function wck_get_entry_field_upload($id){
644 if( !empty ( $id ) && is_numeric( $id ) ){
645 $file_src = wp_get_attachment_url($id);
646 $thumbnail = wp_get_attachment_image( $id, array( 80, 60 ), true );
647 $file_name = get_the_title( $id );
648
649 if ( preg_match( '/^.*?\.(\w+)$/', get_attached_file( $id ), $matches ) )
650 $file_type = esc_html( strtoupper( $matches[1] ) );
651 else
652 $file_type = strtoupper( str_replace( 'image/', '', get_post_mime_type( $id ) ) );
653
654 return $display_value = '<div class="upload-field-details">'. $thumbnail .'<p><span class="file-name">'. $file_name .'</span><span class="file-type">'. $file_type . '</span></p></div>';
655 } else {
656 return '';
657 }
658 }
659
660 /* function to generate output for user select */
661 function wck_get_entry_field_user_select($id){
662 if( !empty ( $id ) && is_numeric( $id ) ){
663 $user = get_user_by( 'id', $id );
664 if ( $user )
665 return '<pre>'.htmlspecialchars( $user->display_name );
666 else
667 return 'Error - User ID not found in database';
668
669 } else {
670 return '';
671 }
672 }
673
674 /* function to generate output for cpt select */
675 function wck_get_entry_field_cpt_select($id){
676 if( !empty ( $id ) && is_numeric( $id ) ){
677 $post = get_post( $id );
678
679 if ( $post != null ){
680 if ( $post->post_title == '' )
681 $post->post_title = 'No title. ID: ' . $id;
682
683 return '<pre>'.htmlspecialchars( $post->post_title );
684 }
685 else
686 return 'Error - Post ID not found in database';
687
688 } else {
689 return '';
690 }
691 }
692
693 /* enque the js/css */
694 function wck_print_scripts($hook){
695 global $pb_wck_pages_hooknames;
696
697 if( $this->args['context'] == 'post_meta' ) {
698 if( 'post.php' == $hook || 'post-new.php' == $hook){
699
700 /* only add on profile builder custom post types */
701 if( !empty( $_GET['post'] ) )
702 $post_id = filter_var( $_GET['post'], FILTER_SANITIZE_NUMBER_INT );
703 else if( !empty( $_POST['post_ID'] ) )
704 $post_id = filter_var( $_POST['post_ID'], FILTER_SANITIZE_NUMBER_INT );
705 else
706 $post_id = '';
707 if( !empty( $post_id ) ){
708 $current_post_type = get_post_type( $post_id );
709 if( strpos( $current_post_type, 'wppb-' ) === false )
710 return '';
711 }
712
713 self::wck_enqueue();
714 }
715 }
716 elseif( $this->args['context'] == 'option' ){
717 if( !empty( $pb_wck_pages_hooknames ) && isset( $this->args[ 'post_type' ] ) && isset( $pb_wck_pages_hooknames[ $this->args[ 'post_type' ] ] ) && $pb_wck_pages_hooknames[$this->args['post_type']] == $hook ){
718 self::wck_enqueue( 'options' );
719 }
720 }
721 }
722
723 /* our own ajaxurl */
724 function wck_print_ajax_url(){
725 echo '<script type="text/javascript">var wppbWckAjaxurl = "'. esc_js( apply_filters( 'wck_ajax_url', admin_url('admin-ajax.php') ) ).'";</script>';
726 }
727
728
729 /* Helper function for enqueueing scripts and styles */
730 private static function wck_enqueue( $context = '' ){
731
732 wp_enqueue_script( 'jquery-ui-draggable' );
733 wp_enqueue_script( 'jquery-ui-droppable' );
734 wp_enqueue_script( 'jquery-ui-sortable' );
735
736 if( $context == 'options' ){
737 wp_enqueue_script( 'thickbox' );
738 wp_enqueue_style( 'thickbox' );
739 }
740
741 wp_enqueue_script('wordpress-creation-kit', plugins_url('/wordpress-creation-kit.js', __FILE__), array('jquery', 'jquery-ui-draggable', 'jquery-ui-droppable', 'jquery-ui-sortable' ), PROFILE_BUILDER_VERSION );
742 wp_register_style('wordpress-creation-kit-css', plugins_url('/wordpress-creation-kit.css', __FILE__), array(), PROFILE_BUILDER_VERSION );
743 wp_enqueue_style('wordpress-creation-kit-css');
744
745 //select 2 KEEP the wppb-select2 handle so we don't include it multiple times, seeing we include it from PB as well
746 wp_enqueue_script( 'wppb-select2', plugins_url( '/assets/js/select2/select2.min.js', __FILE__ ), array(), PROFILE_BUILDER_VERSION, true );
747 wp_enqueue_script( 'wppb-select2-compat', WPPB_PLUGIN_URL . 'assets/js/select2-compat.js', array(), PROFILE_BUILDER_VERSION, true );
748 wp_enqueue_style( 'wppb-select2-style', plugins_url( '/assets/js/select2/select2.min.css', __FILE__ ), false, PROFILE_BUILDER_VERSION );
749
750 //datepicker
751 wp_enqueue_script('jquery-ui-datepicker');
752 wp_enqueue_style( 'jquery-style', plugins_url( '/assets/datepicker/datepicker.css', __FILE__ ) );
753
754
755 /* media upload */
756 wp_enqueue_media();
757 wp_enqueue_script('wck-upload-field', plugins_url('/fields/upload.js', __FILE__), array('jquery') );
758
759 }
760
761 /* Helper function for required fields */
762 function wck_test_required( $meta_array, $meta, $values, $id ){
763 $fields = apply_filters( 'wck_before_test_required', $meta_array, $meta, $values, $id );
764 $required_fields = array();
765 $required_fields_with_errors = array();
766 $required_message = '';
767
768 $errors = '';
769
770 if( !empty( $fields ) ){
771 foreach( $fields as $field ){
772 if( !empty( $field['required'] ) && $field['required'] )
773 $required_fields[Wordpress_Creation_Kit_PB::wck_generate_slug( $field['title'], $field )] = $field['title'];
774 }
775 }
776
777 if( !empty( $values ) ){
778 foreach( $values as $key => $value ){
779 if( array_key_exists( $key, $required_fields ) && apply_filters( "wck_required_test_{$meta}_{$key}", empty( $value ), $value, $id ) ){
780 $required_message .= apply_filters( "wck_required_message_{$meta}_{$key}", __( "Please enter a value for the required field ", "profile-builder" ) . "<strong>$required_fields[$key]</strong><br>", $value );
781 $required_fields_with_errors[] = $key;
782 }
783 }
784 }
785
786 $required_message .= apply_filters( "wck_extra_message", "", $fields, $required_fields, $meta, $values, $id );
787 $required_fields_with_errors = apply_filters( "wck_required_fields_with_errors", $required_fields_with_errors, $fields, $required_fields, $meta, $value, $id );
788
789 if( $required_message != '' ){
790 $errors = array( 'error' => $required_message, 'errorfields' => $required_fields_with_errors );
791 }
792
793 return $errors;
794 }
795
796 /* Checks to see wether the current user can modify data */
797 function wck_verify_user_capabilities( $context, $meta = '', $id = 0 ) {
798
799 $return = true;
800
801 // Meta is an option
802 if( $context == 'option' && !current_user_can( 'manage_options' ) )
803 $return = false;
804
805 // Meta is post related
806 if( $context == 'post_meta' && is_user_logged_in() ) {
807
808 // Current user must be able to edit posts
809 if( !current_user_can( 'edit_posts' ) )
810 $return = false;
811
812 // If the user can't edit others posts the current post must be his/hers
813 elseif( !current_user_can( 'edit_others_posts' ) ) {
814
815 $current_post = get_post( $id );
816 $current_user = wp_get_current_user();
817
818 if( $current_user->ID != $current_post->post_author )
819 $return = false;
820
821 }
822
823 }
824
825 // Return
826 if( $return )
827 return $return;
828 else
829 return array( 'error' => __( 'You are not allowed to do this.', 'profile-builder' ), 'errorfields' => '' );
830
831 }
832
833
834 /* ajax add a reccord to the meta */
835 function wck_add_meta(){
836 check_ajax_referer( "wck-add-meta" );
837
838 if( !empty( $_POST['meta'] ) )
839 $meta = sanitize_text_field( $_POST['meta'] );
840 else
841 $meta = '';
842
843 if( !empty( $_POST['id'] ) )
844 $id = absint($_POST['id']);
845 else
846 $id = '';
847
848 if( !empty( $_POST['values'] ) && is_array( $_POST['values'] ) )
849 $values = $this->wck_sanitize_associative_array( $_POST['values'] ); //phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- we sanitize with our own function
850 else
851 $values = array();
852
853 // Security checks
854 if( true !== ( $error = self::wck_verify_user_capabilities( $this->args['context'], $meta, $id ) ) ) {
855 header( 'Content-type: application/json' );
856 die( json_encode( $error ) );
857 }
858
859 $values = apply_filters( "wck_add_meta_filter_values_{$meta}", $values );
860
861 /* check required fields */
862 $errors = self::wck_test_required( $this->args['meta_array'], $meta, $values, $id );
863
864 if ( empty( $errors ) ) {
865 $errors = self::wck_maybe_add_extra_errors( $this->args['meta_array'], $meta, $values, $id );
866 }
867
868 if( $errors != '' ){
869 header( 'Content-type: application/json' );
870 die( json_encode( $errors ) );
871 }
872
873
874 if( $this->args['context'] == 'post_meta' )
875 $results = get_post_meta($id, $meta, true);
876 else if ( $this->args['context'] == 'option' )
877 $results = get_option( apply_filters( 'wck_option_meta' , $meta, $values ) );
878
879 /* we need an array here */
880 if( empty( $results ) && !is_array( $results ) )
881 $results = array();
882
883 /* for single metaboxes owerwrite entries each time so we have a maximum of one */
884 if( $this->args['single'] )
885 $results = array( $values );
886 else
887 $results[] = $values;
888
889 /* make sure this does not output anything so it won't break the json response below
890 will keep it do_action for compatibility reasons
891 */
892 ob_start();
893 do_action( 'wck_before_add_meta', $meta, $id, $values );
894 $wck_before_add_meta = ob_get_clean(); //don't output it
895
896
897 if( $this->args['context'] == 'post_meta' )
898 update_post_meta($id, $meta, $results);
899 else if ( $this->args['context'] == 'option' )
900 update_option( apply_filters( 'wck_option_meta' , $meta, $results ), wp_unslash( $results ) );
901
902 /* if unserialize_fields is true add for each entry separate post meta for every element of the form */
903 // if( $this->args['unserialize_fields'] && $this->args['context'] == 'post_meta' ){
904
905 // $meta_suffix = count( $results );
906 // if( !empty( $values ) ){
907 // foreach( $values as $name => $value ){
908 // update_post_meta($id, $meta.'_'.$name.'_'.$meta_suffix, $value);
909 // }
910 // }
911 // }
912
913 $entry_list = $this->wck_refresh_list( $meta, $id );
914 $add_form = $this->wck_add_form( $meta, $id );
915
916 header( 'Content-type: application/json' );
917 die( json_encode( array( 'entry_list' => $entry_list, 'add_form' => $add_form ) ) );
918
919 }
920
921 /* ajax update a reccord in the meta */
922 function wck_update_meta(){
923 check_ajax_referer( "wck-update-entry" );
924
925 if( !empty( $_POST['meta'] ) )
926 $meta = sanitize_text_field( $_POST['meta'] );
927 else
928 $meta = '';
929
930 if( !empty( $_POST['id'] ) )
931 $id = absint($_POST['id']);
932 else
933 $id = '';
934
935 if( isset( $_POST['element_id'] ) )
936 $element_id = absint( $_POST['element_id'] );
937 else
938 $element_id = 0;
939
940 if( !empty( $_POST['values'] ) && is_array( $_POST['values'] ) )
941 $values = $this->wck_sanitize_associative_array( $_POST['values'] ); //phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- we sanitize with our own function
942 else
943 $values = array();
944
945 // Security checks
946 if( true !== ( $error = self::wck_verify_user_capabilities( $this->args['context'], $meta, $id ) ) ) {
947 header( 'Content-type: application/json' );
948 die( json_encode( $error ) );
949 }
950
951 $values = apply_filters( "wck_update_meta_filter_values_{$meta}", $values, $element_id );
952
953 /* check required fields */
954 $errors = self::wck_test_required( $this->args['meta_array'], $meta, $values, $id );
955 if( $errors != '' ){
956 header( 'Content-type: application/json' );
957 die( json_encode( $errors ) );
958 }
959
960 if( $this->args['context'] == 'post_meta' )
961 $results = get_post_meta($id, $meta, true);
962 else if ( $this->args['context'] == 'option' )
963 $results = get_option( apply_filters( 'wck_option_meta' , $meta, $values, $element_id ) );
964
965 $results[$element_id] = $values;
966
967 /* make sure this does not output anything so it won't break the json response below
968 will keep it do_action for compatibility reasons
969 */
970 ob_start();
971 do_action( 'wck_before_update_meta', $meta, $id, $values, $element_id );
972 $wck_before_update_meta = ob_get_clean(); //don't output it
973
974
975 if( $this->args['context'] == 'post_meta' )
976 update_post_meta($id, $meta, $results);
977 else if ( $this->args['context'] == 'option' )
978 update_option( apply_filters( 'wck_option_meta' , $meta, $results, $element_id ), wp_unslash( $results ) );
979
980 /* if unserialize_fields is true update the coresponding post metas for every element of the form */
981 // if( $this->args['unserialize_fields'] && $this->args['context'] == 'post_meta' ){
982
983 // $meta_suffix = $element_id + 1;
984 // if( !empty( $values ) ){
985 // foreach( $values as $name => $value ){
986 // update_post_meta($id, $meta.'_'.$name.'_'.$meta_suffix, $value);
987 // }
988 // }
989 // }
990
991 $entry_content = $this->wck_refresh_entry( $meta, $id, $element_id );
992
993 header( 'Content-type: application/json' );
994 die( json_encode( array( 'entry_content' => $entry_content ) ) );
995 }
996
997 /* ajax to refresh the meta content | or used in other function to return the */
998 /* this is used in Repeater Fields as an ajax action so we have to keep it dual purpose */
999 function wck_refresh_list( $meta = '', $id = '' ){
1000
1001 if( !current_user_can( 'manage_options' ) )
1002 die();
1003
1004 if( isset( $_POST['meta'] ) )
1005 $meta = sanitize_text_field( $_POST['meta'] );
1006
1007 if( isset( $_POST['id'] ) )
1008 $id = absint($_POST['id']);
1009
1010 ob_start();
1011 echo self::wck_output_meta_content($meta, $id, $this->args['meta_array']); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1012 do_action( "wck_refresh_list_{$meta}", $id );
1013 $entry_list = ob_get_clean();
1014
1015 if( strpos( current_filter(), 'wp_ajax_wck_refresh_list') === 0 ){
1016 echo $entry_list; //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1017 exit;
1018 }
1019 else{
1020 return $entry_list;
1021 }
1022 }
1023
1024 /* function that returns the content of an entry */
1025 function wck_refresh_entry( $meta = '', $id = '', $element_id = '' ){
1026
1027 if( $this->args['context'] == 'post_meta' )
1028 $results = get_post_meta($id, $meta, true);
1029 else if ( $this->args['context'] == 'option' )
1030 $results = get_option( apply_filters( 'wck_option_meta' , $meta, $element_id ) );
1031
1032 ob_start();
1033 echo self::wck_output_entry_content( $meta, $id, $this->args['meta_array'], $results, $element_id ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1034 do_action( "wck_refresh_entry_{$meta}", $id );
1035 $entry_content = ob_get_clean();
1036
1037 return $entry_content;
1038 }
1039
1040 /* function that returns the add the form for single */
1041 function wck_add_form( $meta = '', $id = '' ){
1042
1043 $post = get_post($id);
1044
1045 ob_start();
1046 self::create_add_form($this->args['meta_array'], $meta, $post );
1047 do_action( "wck_ajax_add_form_{$meta}", $id );
1048 $add_form = ob_get_clean();
1049
1050 return $add_form;
1051 }
1052
1053
1054 /* ajax to show the update form */
1055 function wck_show_update_form(){
1056 check_ajax_referer( "wck-edit-entry" );
1057
1058 if( !current_user_can( 'manage_options' ) )
1059 die();
1060
1061 $meta = isset( $_POST['meta'] ) ? sanitize_text_field( $_POST['meta'] ) : '';
1062 $id = isset( $_POST['id'] ) ? absint( $_POST['id'] ) : '';
1063 $element_id = isset( $_POST['element_id'] ) ? absint( $_POST['element_id'] ) : '';
1064
1065 do_action( "wck_before_adding_form_{$meta}", $id, $element_id );
1066
1067 echo self::mb_update_form($this->args['meta_array'], $meta, $id, $element_id);//phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
1068
1069 do_action( "wck_after_adding_form", $meta, $id, $element_id );
1070 do_action( "wck_after_adding_form_{$meta}", $id, $element_id );
1071
1072 exit;
1073 }
1074
1075 /* ajax to remove a reccord from the meta */
1076 function wck_remove_meta(){
1077 check_ajax_referer( "wck-delete-entry" );
1078 if( !empty( $_POST['meta'] ) )
1079 $meta = sanitize_text_field( $_POST['meta'] );
1080 else
1081 $meta = '';
1082 if( !empty( $_POST['id'] ) )
1083 $id = absint( $_POST['id'] );
1084 else
1085 $id = '';
1086 if( isset( $_POST['element_id'] ) )
1087 $element_id = absint( $_POST['element_id'] );
1088 else
1089 $element_id = '';
1090
1091 // Security checks
1092 if( true !== ( $error = self::wck_verify_user_capabilities( $this->args['context'], $meta, $id ) ) ) {
1093 header( 'Content-type: application/json' );
1094 die( json_encode( $error ) );
1095 }
1096
1097 if( $this->args['context'] == 'post_meta' )
1098 $results = get_post_meta($id, $meta, true);
1099 else if ( $this->args['context'] == 'option' )
1100 $results = get_option( apply_filters( 'wck_option_meta' , $meta, $element_id ) );
1101
1102 $old_results = $results;
1103 unset($results[$element_id]);
1104 /* reset the keys for the array */
1105 $results = array_values($results);
1106
1107 /* make sure this does not output anything so it won't break the json response below
1108 will keep it do_action for compatibility reasons
1109 */
1110 ob_start();
1111 do_action( 'wck_before_remove_meta', $meta, $id, $element_id );
1112 $wck_before_remove_meta = ob_get_clean(); //don't output it
1113
1114 if( $this->args['context'] == 'post_meta' )
1115 update_post_meta($id, $meta, $results);
1116 else if ( $this->args['context'] == 'option' )
1117 update_option( apply_filters( 'wck_option_meta' , $meta, $results, $element_id ), wp_unslash( $results ) );
1118
1119
1120
1121 /* TODO: optimize so that it updates from the deleted element forward */
1122 /* if unserialize_fields is true delete the coresponding post metas */
1123 // if( $this->args['unserialize_fields'] && $this->args['context'] == 'post_meta' ){
1124
1125 // $meta_suffix = 1;
1126
1127 // if( !empty( $results ) ){
1128 // foreach( $results as $result ){
1129 // foreach ( $result as $name => $value){
1130 // update_post_meta($id, $meta.'_'.$name.'_'.$meta_suffix, $value);
1131 // }
1132 // $meta_suffix++;
1133 // }
1134 // }
1135
1136 // if( count( $results ) == 0 )
1137 // $results = $old_results;
1138
1139 // if( !empty( $results ) ){
1140 // foreach( $results as $result ){
1141 // foreach ( $result as $name => $value){
1142 // delete_post_meta( $id, $meta.'_'.$name.'_'.$meta_suffix );
1143 // }
1144 // break;
1145 // }
1146 // }
1147 // }
1148
1149 $entry_list = $this->wck_refresh_list( $meta, $id );
1150 $add_form = $this->wck_add_form( $meta, $id );
1151
1152 header( 'Content-type: application/json' );
1153 die( json_encode( array( 'entry_list' => $entry_list, 'add_form' => $add_form ) ) );
1154 }
1155
1156
1157 /* ajax to reorder records */
1158 function wck_reorder_meta(){
1159 if( !empty( $_POST['meta'] ) )
1160 $meta = sanitize_text_field( $_POST['meta'] );
1161 else
1162 $meta = '';
1163 if( !empty( $_POST['id'] ) )
1164 $id = absint($_POST['id']);
1165 else
1166 $id = '';
1167 if( !empty( $_POST['values'] ) && is_array( $_POST['values'] ) )
1168 $elements_id = array_map( 'absint', $_POST['values'] );
1169 else
1170 $elements_id = array();
1171
1172 // Security checks
1173 if( true !== ( $error = self::wck_verify_user_capabilities( $this->args['context'], $meta, $id ) ) ) {
1174 header( 'Content-type: application/json' );
1175 die( json_encode( $error ) );
1176 }
1177
1178 /* make sure this does not output anything so it won't break the json response below
1179 will keep it do_action for compatibility reasons
1180 */
1181 ob_start();
1182 do_action( 'wck_before_reorder_meta', $meta, $id, $elements_id );
1183 $wck_before_reorder_meta = ob_get_clean(); //don't output it
1184
1185 if( $this->args['context'] == 'post_meta' )
1186 $results = get_post_meta($id, $meta, true);
1187 else if ( $this->args['context'] == 'option' )
1188 $results = get_option( apply_filters( 'wck_option_meta' , $meta ) );
1189
1190 $new_results = array();
1191 if( !empty( $elements_id ) ){
1192 foreach($elements_id as $element_id){
1193 $new_results[] = $results[$element_id];
1194 }
1195 }
1196
1197 $results = $new_results;
1198
1199 if( $this->args['context'] == 'post_meta' )
1200 update_post_meta($id, $meta, $results);
1201 else if ( $this->args['context'] == 'option' )
1202 update_option( apply_filters( 'wck_option_meta' , $meta, $results, $element_id ), wp_unslash( $results ) );
1203
1204
1205 /* if unserialize_fields is true reorder all the coresponding post metas */
1206 // if( $this->args['unserialize_fields'] && $this->args['context'] == 'post_meta' ){
1207
1208 // $meta_suffix = 1;
1209 // if( !empty( $new_results ) ){
1210 // foreach( $new_results as $result ){
1211 // foreach ( $result as $name => $value){
1212 // update_post_meta($id, $meta.'_'.$name.'_'.$meta_suffix, $value);
1213 // }
1214 // $meta_suffix++;
1215 // }
1216 // }
1217
1218 // }
1219
1220 $entry_list = $this->wck_refresh_list( $meta, $id );
1221 header( 'Content-type: application/json' );
1222 die( json_encode( array( 'entry_list' => $entry_list ) ) );
1223 }
1224
1225 /**
1226 * Function that saves the entries for single forms on posts(no options). It is hooke on the 'save_post' hook
1227 * It is executed on each WCK object instance so we need to restrict it on only the ones that are present for that post
1228 */
1229 function wck_save_single_metabox( $post_id, $post ){
1230 if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE )
1231 return $post_id;
1232
1233 /* only go through for metaboxes defined for this post type */
1234 if( get_post_type( $post_id ) != $this->args['post_type'] )
1235 return $post_id;
1236
1237 // Check the user's permissions.
1238 if ( isset( $_POST['post_type'] ) && 'page' == $_POST['post_type'] ) {
1239 if ( ! current_user_can( 'edit_page', $post_id ) ) {
1240 return $post_id;
1241 }
1242 } else {
1243 if ( ! current_user_can( 'edit_posts', $post_id ) ) {
1244 return $post_id;
1245 }
1246 }
1247
1248 if( !empty( $_POST ) ){
1249 /* for single metaboxes we save a hidden input that contains the meta_name attr as a key so we need to search for it */
1250 foreach( $_POST as $request_key => $request_value ){
1251 $request_key = sanitize_text_field( $request_key );
1252
1253 if( strpos( $request_key, '_wckmetaname_' ) !== false && strpos( $request_key, '#wck' ) !== false ){
1254 /* found it so now retrieve the meta_name from the key formatted _wckmetaname_actuaname#wck */
1255 $request_key = str_replace( '_wckmetaname_', '', $request_key );
1256 $meta_name = str_replace( '#wck', '', $request_key );
1257 /* we have it so go through only on the WCK object instance that has this meta_name */
1258 if( $this->args['meta_name'] == $meta_name ){
1259
1260 /* get the meta values from the $_POST and store them in an array */
1261 $meta_values = array();
1262 if( !empty( $this->args['meta_array'] ) ){
1263 foreach ($this->args['meta_array'] as $meta_field){
1264 /* in the $_POST the names for the fields are prefixed with the meta_name for the single metaboxes in case there are multiple metaboxes that contain fields wit hthe same name */
1265 $field_slug = Wordpress_Creation_Kit_PB::wck_generate_slug( $meta_field['title'], $meta_field );
1266 $single_field_name = $this->args['meta_name'] .'_'. $field_slug;
1267
1268 if ( isset( $_POST[$single_field_name] ) ) {
1269 /* checkbox needs to be stored as string not array */
1270 if( $meta_field['type'] == 'checkbox' ){
1271 if( is_array($_POST[$single_field_name]) )
1272 $_POST[$single_field_name] = implode(', ', $this->wck_sanitize_value( $_POST[$single_field_name], $field_slug ) ); //phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- we sanitize with our own function
1273 else
1274 $_POST[$single_field_name] = $this->wck_sanitize_value( $_POST[$single_field_name], $field_slug ); //phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- we sanitize with our own function
1275 }
1276
1277 $meta_values[$field_slug] = $this->wck_sanitize_value( $_POST[$single_field_name], $field_slug ); //phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- we sanitize with our own function
1278 } else
1279 $meta_values[$field_slug] = '';
1280 }
1281 }
1282
1283 /* test if we have errors for the required fields */
1284 $errors = self::wck_test_required( $this->args['meta_array'], $meta_name, $meta_values, $post_id );
1285 if( !empty( $errors ) ){
1286 /* if we have errors then add them in the global. We do this so we get all errors from all single metaboxes that might be on that page */
1287 global $wck_single_forms_errors;
1288 if( !empty( $errors['errorfields'] ) ){
1289 foreach( $errors['errorfields'] as $key => $field_name ){
1290 $errors['errorfields'][$key] = $this->args['meta_name']. '_' .$field_name;
1291 }
1292 }
1293 $wck_single_forms_errors[] = $errors;
1294 }
1295 else {
1296 /* no errors so we can save */
1297 update_post_meta( $post_id, $meta_name, array( $meta_values ) );
1298
1299 /* handle unserialized fields */
1300 // if ( $this->args['unserialize_fields'] ) {
1301 // if (!empty($this->args['meta_array'])) {
1302 // foreach ($this->args['meta_array'] as $meta_field) {
1303 // update_post_meta($post_id, $meta_name . '_' . Wordpress_Creation_Kit_PB::wck_generate_slug( $meta_field['title'], $meta_field ) . '_1', array_map( 'wppb_sanitize_value', $_POST[$this->args['meta_name'] . '_' . Wordpress_Creation_Kit_PB::wck_generate_slug( $meta_field['title'], $meta_field )] ) ); //phpcs:ignore
1304 // }
1305 // }
1306 // }
1307 }
1308 break;
1309 }
1310 }
1311 }
1312 }
1313 }
1314
1315 /**
1316 * Function that checks if we have any errors in the required fields from the single metaboxes. It is executed on 'wp_insert_post' hook
1317 * that comes after 'save_post' so we should have the global errors by now. If we have errors perform a redirect and add the error messages and error fields
1318 * in the url
1319 */
1320 function wck_single_metabox_redirect_if_errors( $post_id, $post ){
1321 global $wck_single_forms_errors;
1322 if( !empty( $wck_single_forms_errors ) ) {
1323 $error_messages = '';
1324 $error_fields = '';
1325 foreach( $wck_single_forms_errors as $wck_single_forms_error ){
1326 $error_messages .= $wck_single_forms_error['error'];
1327 $error_fields .= implode( ',', $wck_single_forms_error['errorfields'] ).',';
1328 }
1329 if( isset( $_SERVER["HTTP_REFERER"] ) )
1330 wp_safe_redirect( add_query_arg( array( 'wckerrormessages' => base64_encode( urlencode( $error_messages ) ), 'wckerrorfields' => base64_encode( urlencode( $error_fields ) ) ), esc_url_raw( $_SERVER["HTTP_REFERER"] ) ) );
1331
1332 exit;
1333 }
1334 }
1335
1336 /** Function that displays the error messages, if we have any, as js alerts and marks the fields with red
1337 */
1338 function wck_single_metabox_errors_display(){
1339 /* only execute for the WCK objects defined for the current post type */
1340 global $post;
1341 if( get_post_type( $post ) != $this->args['post_type'] )
1342 return;
1343
1344 /* and only do it once */
1345 global $allready_saved;
1346 if( isset( $allready_saved ) && $allready_saved == true )
1347 return;
1348 $allready_saved = true;
1349
1350 /* mark the fields */
1351 if( isset( $_GET['wckerrorfields'] ) && !empty( $_GET['wckerrorfields'] ) ){
1352 echo '<script type="text/javascript">';
1353 $field_names = explode( ',', sanitize_text_field( urldecode( base64_decode( $_GET['wckerrorfields'] ) ) ) );//phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
1354 if( !empty( $field_names ) ) {
1355 foreach ($field_names as $field_name) {
1356 echo "jQuery( '.field-label[for=\"" . esc_js($field_name) . "\"]' ).addClass('error');";
1357 }
1358 }
1359 echo '</script>';
1360 }
1361
1362 /* alert the error messages */
1363 if( isset( $_GET['wckerrormessages'] ) ){
1364 echo '<script type="text/javascript">alert("'. str_replace( '%0A', '\n', esc_js( urldecode( base64_decode( $_GET['wckerrormessages'] ) ) ) ) .'")</script>';//phpcs:ignore
1365 }
1366 }
1367
1368 static function wck_maybe_add_extra_errors( $meta_array, $meta, $values, $id ){
1369
1370 if( strpos( $meta, 'wppb_cr_' ) === false )
1371 return '';
1372
1373 $license_status = wppb_get_serial_number_status();
1374
1375 if( $license_status == 'missing' ){
1376 return array( 'error' => sprintf( __( 'Please %1$senter your license key%2$s first, to add new custom redirects.', 'profile-builder' ), '<a href="' . admin_url( 'admin.php?page=profile-builder-general-settings' ) . '">', '</a>' ) );
1377 } else if( $license_status !== 'valid' ){
1378 return array( 'error' => sprintf( __( 'You need an active license to add new custom redirects. <br>%1$sRenew%2$s or %3$spurchase a new one here%4$s.', 'profile-builder' ), '<a href="https://www.cozmoslabs.com/account/?utm_source=pb-redirects&utm_medium=client-site&utm_campaign=pb-expired-license">', '</a>', '<a href="https://www.cozmoslabs.com/wordpress-profile-builder/?utm_source=pb-redirects&utm_medium=client-site&utm_campaign=pb-redirects-addon#pricing" target="_blank">', '</a>' ) );
1379 }
1380
1381 return '';
1382
1383 }
1384
1385
1386 /**
1387 * The function used to generate slugs in WCK
1388 *
1389 * @since 1.1.1
1390 *
1391 * @param string $string The input string from which we generate the slug
1392 * @return string $slug The henerated slug
1393 */
1394 static function wck_generate_slug( $string, $details = array() ){
1395 if( !empty( $details['slug'] ) )
1396 $slug = $details['slug'];
1397 else
1398 $slug = rawurldecode( sanitize_title_with_dashes( remove_accents( $string ) ) );
1399 return $slug;
1400 }
1401
1402 static function wck_strip_script_tags(){
1403
1404 }
1405
1406 static function wck_generate_select_option($option, $values, $i, $current_value){
1407
1408 $disabled = '';
1409
1410 if( is_array( $option ) ){
1411
1412 if( !empty( $option['field_name'] ) ){
1413 $label = $option['field_name'];
1414
1415 if( !empty( $values ) )
1416 $value_attr = $values[$i];
1417 else
1418 $value_attr = $option;
1419
1420 if( !empty( $option['disabled'] ) && $option['disabled'] == true ){
1421 $disabled = ' disabled';
1422 }
1423 }
1424
1425 } elseif( strpos( $option, '%' ) === false ){
1426 $label = $option;
1427 if( !empty( $values ) )
1428 $value_attr = $values[$i];
1429 else
1430 $value_attr = $option;
1431 } else {
1432 $option_parts = explode( '%', $option );
1433 if( !empty( $option_parts ) ){
1434 if( empty( $option_parts[0] ) && count( $option_parts ) == 3 ){
1435 $label = $option_parts[1];
1436 if( !empty( $values ) )
1437 $value_attr = $values[$i];
1438 else
1439 $value_attr = $option_parts[2];
1440 }
1441 else{
1442 $label = $option;
1443 if( !empty( $values ) )
1444 $value_attr = $values[$i];
1445 else
1446 $value_attr = $option;
1447 }
1448 }
1449 }
1450
1451 // title is set only for disabled options to let users know those fields are available in a paid version
1452 if( !empty( $disabled ) ){
1453 if( isset( $value_attr['field_name'] ) && $value_attr['field_name'] == 'Subscription Plans' )
1454 $title = esc_attr( __( 'Install the free Paid Member Subscriptions plugin to get access this field.', 'profile-builder' ) );
1455 elseif ( isset( $value_attr['field_name'] ) && $value_attr['field_name'] == 'Additional Map' )
1456 $title = esc_attr( __( 'A Map field must be created first.', 'profile-builder' ) );
1457 else
1458 $title = esc_attr( __( 'This field is available in our paid plans.', 'profile-builder' ) );
1459 }
1460
1461 if( isset( $value_attr['field_name'] ) ) {
1462 $optionOutput = '<option value="" '. esc_attr( $disabled ) . ( !empty( $disabled ) ? ' title="'. $title .'"' : '' ) . ' >'. esc_html( $label ) .'</option>';
1463 } else if ( is_array( $current_value ) ) {
1464 $is_selected = in_array( $value_attr, $current_value ) ? 'selected="selected" ' : '';
1465 $optionOutput = '<option value="'. esc_attr( $value_attr ) .'" '. $is_selected . ( !empty( $disabled ) ? ' title="'. $title .'"' : '' ) . ' >'. esc_html( $label ) .'</option>';
1466 } else
1467 $optionOutput = '<option value="'. esc_attr( $value_attr ) .'" '. selected( strip_tags( $value_attr ), $current_value, false ) . ( !empty( $disabled ) ? ' title="'. $title .'"' : '' ) . ' >'. esc_html( $label ) .'</option>';
1468
1469 return $optionOutput;
1470 }
1471
1472 static function wck_is_multi($a) {
1473 foreach ($a as $v) {
1474 if (is_array($v)) return true;
1475 }
1476 return false;
1477 }
1478
1479 function wck_sanitize_associative_array( $associative_array ){
1480 $sanitized_associative_array = array();
1481
1482 foreach ( $associative_array as $meta_name => $value) {
1483 $sanitized_associative_array[$meta_name] = $this->wck_sanitize_value($value, $meta_name);
1484 }
1485
1486 return $sanitized_associative_array;
1487 }
1488
1489 function wck_sanitize_value( $value, $meta_name = false ){
1490
1491 if( apply_filters( 'wck_pre_sanitize_value', false, $meta_name ) ){
1492 return apply_filters( 'wck_sanitize_value', $value, $meta_name );
1493 }
1494
1495 $is_wysiwyg_field = false;
1496 $is_textarea_field = false;
1497 $is_query_compare = false;
1498
1499 if( !empty( $meta_name ) && !empty( $this->args['meta_array'] ) ){
1500
1501 foreach( $this->args['meta_array'] as $field ){
1502
1503 if( $field['slug'] === $meta_name && $field['type'] === 'wysiwyg editor' )
1504 $is_wysiwyg_field = true;
1505
1506 if( $field['slug'] === $meta_name && $field['type'] === 'textarea' )
1507 $is_textarea_field = true;
1508
1509 if( $meta_name === 'query-compare' && $field['slug'] === $meta_name )
1510 $is_query_compare = true;
1511
1512 }
1513
1514 }
1515
1516 if( is_array( $value ) ) {
1517 $sanitized_array = array();
1518
1519 foreach ($value as $element) {
1520 if( $is_wysiwyg_field )
1521 $sanitized_array[] = wp_kses_post( $element );
1522 elseif( $is_textarea_field )
1523 $sanitized_array[] = wp_kses_post( $element );
1524 else
1525 $sanitized_array[] = sanitize_text_field( $element );
1526 }
1527
1528 return $sanitized_array;
1529 }
1530 else{
1531 if( $is_wysiwyg_field )
1532 return wp_kses_post( $value );
1533 elseif( $is_textarea_field )
1534 return wp_kses_post( $value );
1535 elseif( $is_query_compare )
1536 return in_array( $value, array( '=', '!=', '>', '>=', '<', '<=', 'LIKE', 'NOT LIKE', 'IN', 'NOT IN', 'BETWEEN', 'NOT BETWEEN', 'EXISTS', 'NOT EXISTS' ), true ) ? $value : '=';
1537 else
1538 return sanitize_text_field( $value );
1539 }
1540 }
1541 }
1542
1543
1544 /*
1545 Helper class that creates admin menu pages ( both top level menu pages and submenu pages )
1546 Default Usage:
1547
1548 $args = array(
1549 'page_type' => 'menu_page',
1550 'page_title' => '',
1551 'menu_title' => '',
1552 'capability' => '',
1553 'menu_slug' => '',
1554 'icon_url' => '',
1555 'position' => '',
1556 'parent_slug' => ''
1557 );
1558
1559 'page_type' (string) (required) The type of page you want to add. Possible values: 'menu_page', 'submenu_page'
1560 'page_title' (string) (required) The text to be displayed in the title tags and header of
1561 the page when the menu is selected
1562 'menu_title' (string) (required) The on-screen name text for the menu
1563 'capability' (string) (required) The capability required for this menu to be displayed to
1564 the user.
1565 'menu_slug' (string) (required) The slug name to refer to this menu by (should be unique
1566 for this menu).
1567 'icon_url' (string) (optional for 'page_type' => 'menu_page') The url to the icon to be used for this menu.
1568 This parameter is optional. Icons should be fairly small, around 16 x 16 pixels
1569 for best results.
1570 'position' (integer) (optional for 'page_type' => 'menu_page') The position in the menu order this menu
1571 should appear.
1572 By default, if this parameter is omitted, the menu will appear at the bottom
1573 of the menu structure. The higher the number, the lower its position in the menu.
1574 WARNING: if 2 menu items use the same position attribute, one of the items may be
1575 overwritten so that only one item displays!
1576 'parent_slug' (string) (required for 'page_type' => 'submenu_page' ) The slug name for the parent menu
1577 (or the file name of a standard WordPress admin page) For examples see http://codex.wordpress.org/Function_Reference/add_submenu_page $parent_slug parameter
1578 'priority' (int) (optional) How important your function is. Alter this to make your function
1579 be called before or after other functions. The default is 10, so (for example) setting it to 5 would make it run earlier and setting it to 12 would make it run later.
1580
1581 public $hookname ( for required for 'page_type' => 'menu_page' ) string used internally to
1582 track menu page callbacks for outputting the page inside the global $menu array
1583 ( for required for 'page_type' => 'submenu_page' ) The resulting page's hook_suffix,
1584 or false if the user does not have the capability required.
1585 */
1586
1587 class WCK_Page_Creator_PB{
1588
1589 private $defaults = array(
1590 'page_type' => 'menu_page',
1591 'page_title' => '',
1592 'menu_title' => '',
1593 'capability' => '',
1594 'menu_slug' => '',
1595 'icon_url' => '',
1596 'position' => '',
1597 'parent_slug' => '',
1598 'priority' => 10,
1599 'network_page' => false
1600 );
1601 private $args;
1602 public $hookname;
1603
1604
1605 /* Constructor method for the class. */
1606 function __construct( $args ) {
1607
1608 /* Global that will hold all the arguments for all the menu pages */
1609 global $wck_pages;
1610
1611 /* Merge the input arguments and the defaults. */
1612 $this->args = wp_parse_args( $args, $this->defaults );
1613
1614 /* Add the settings for this page to the global object */
1615 $wck_pages[$this->args['page_title']] = $this->args;
1616
1617 if( !$this->args['network_page'] ){
1618 /* Hook the page function to 'admin_menu'. */
1619 add_action( 'admin_menu', array( &$this, 'wck_page_init' ), $this->args['priority'] );
1620 }
1621 else{
1622 /* Hook the page function to 'admin_menu'. */
1623 add_action( 'network_admin_menu', array( &$this, 'wck_page_init' ), $this->args['priority'] );
1624 }
1625 }
1626
1627 /**
1628 * Function that creates the admin page
1629 */
1630 function wck_page_init(){
1631 global $pb_wck_pages_hooknames;
1632
1633 /* don't add the page at all if the user doesn't meet the capabilities */
1634 if( !empty( $this->args['capability'] ) ){
1635 if( !current_user_can( $this->args['capability'] ) )
1636 return;
1637 }
1638
1639 /* Create the page using either add_menu_page or add_submenu_page functions depending on the 'page_type' parameter. */
1640 if( $this->args['page_type'] == 'menu_page' ){
1641 $this->hookname = add_menu_page( $this->args['page_title'], $this->args['menu_title'], $this->args['capability'], $this->args['menu_slug'], array( &$this, 'wck_page_template' ), $this->args['icon_url'], $this->args['position'] );
1642
1643 $pb_wck_pages_hooknames[$this->args['menu_slug']] = $this->hookname;
1644 }
1645 else if( $this->args['page_type'] == 'submenu_page' ){
1646 $this->hookname = add_submenu_page( $this->args['parent_slug'], $this->args['page_title'], $this->args['menu_title'], $this->args['capability'], $this->args['menu_slug'], array( &$this, 'wck_page_template' ) );
1647
1648 $pb_wck_pages_hooknames[$this->args['menu_slug']] = $this->hookname;
1649 }
1650
1651 do_action( 'WCK_Page_Creator_PB_after_init', $this->hookname );
1652
1653 /* Create a hook for adding meta boxes. */
1654 add_action( "load-{$this->hookname}", array( &$this, 'wck_settings_page_add_meta_boxes' ) );
1655 /* Load the JavaScript needed for the screen. */
1656 add_action( 'admin_enqueue_scripts', array( &$this, 'wck_page_enqueue_scripts' ) );
1657 add_action( "admin_head-{$this->hookname}", array( &$this, 'wck_page_load_scripts' ) );
1658 }
1659
1660 /**
1661 * Do action 'add_meta_boxes'. This hook isn't executed by default on a admin page so we have to add it.
1662 */
1663 function wck_settings_page_add_meta_boxes() {
1664 global $post;
1665
1666 if( empty( $post ) || empty( $post->ID ) )
1667 do_action( 'wck_add_meta_boxes', $this->hookname, $post );
1668 else
1669 do_action( 'add_meta_boxes', $this->hookname, $post );
1670 }
1671
1672 /**
1673 * Loads the JavaScript files required for managing the meta boxes on the theme settings
1674 * page, which allows users to arrange the boxes to their liking.
1675 *
1676 * @global string $bareskin_settings_page. The global setting page (returned by add_theme_page in function
1677 * bareskin_settings_page_init ).
1678 * @since 1.0.0
1679 * @param string $hook The current page being viewed.
1680 */
1681 function wck_page_enqueue_scripts( $hook ) {
1682 if ( $hook == $this->hookname ) {
1683 wp_enqueue_script( 'common' );
1684 wp_enqueue_script( 'wp-lists' );
1685 wp_enqueue_script( 'postbox' );
1686 }
1687 }
1688
1689 /**
1690 * Loads the JavaScript required for toggling the meta boxes on the theme settings page.
1691 *
1692 * @global string $bareskin_settings_page. The global setting page (returned by add_theme_page in function
1693 * bareskin_settings_page_init ).
1694 * @since 1.0.0
1695 */
1696 function wck_page_load_scripts() {
1697 ?>
1698 <script type="text/javascript">
1699 //<![CDATA[
1700 jQuery(document).ready( function($) {
1701 $('.if-js-closed').removeClass('if-js-closed').addClass('closed');
1702 postboxes.add_postbox_toggles( '<?php echo esc_js( $this->hookname ); ?>' );
1703 });
1704 //]]>
1705 </script><?php
1706 }
1707
1708 /**
1709 * Outputs default template for the page. It contains placeholders for metaboxes. It also
1710 * provides two action hooks 'wck_before_meta_boxes' and 'wck_after_meta_boxes'.
1711 */
1712 function wck_page_template(){
1713 ?>
1714 <div class="wrap cozmoslabs-wrap">
1715
1716 <?php if( !empty( $this->args['page_icon'] ) ): ?>
1717 <div id="<?php echo esc_attr( $this->args['menu_slug'] );//phpcs:ignore ?>-icon" style="background: url('<?php echo $this->args['page_icon']; ?>') no-repeat;" class="icon32">
1718 <br/>
1719 </div>
1720 <?php endif; ?>
1721
1722 <h1></h1>
1723 <!-- WordPress Notices are added after the h1 tag -->
1724
1725 <div class="cozmoslabs-page-header">
1726 <div class="cozmoslabs-section-title">
1727
1728 <h2 class="cozmoslabs-page-title">
1729 <?php echo esc_html( $this->args['page_title'] ) ?>
1730 </h2>
1731
1732 </div>
1733 </div>
1734
1735 <div id="poststuff">
1736
1737 <?php wp_nonce_field( 'closedpostboxes', 'closedpostboxesnonce', false ); ?>
1738 <?php wp_nonce_field( 'meta-box-order', 'meta-box-order-nonce', false ); ?>
1739
1740 <?php do_action( 'wck_before_meta_boxes', $this->hookname ); ?>
1741
1742 <?php $is_email_customizer_page = $this->hookname === 'profile-builder_page_user-email-customizer' || $this->hookname === 'profile-builder_page_admin-email-customizer'; ?>
1743
1744 <div class="metabox-holder <?php echo $is_email_customizer_page ? 'cozmoslabs-settings-container' : '' ?>">
1745 <div class="wck-post-body <?php echo $is_email_customizer_page ? 'cozmoslabs-email-customizer-section cozmoslabs-settings' : '' ?>">
1746 <div class="post-box-container column-1 normal">
1747 <?php do_action( 'wck_before_column1_metabox_content', $this->hookname ); ?>
1748 <?php do_meta_boxes( $this->hookname, 'normal', null ); ?>
1749 <?php do_action( 'wck_after_column1_metabox_content', $this->hookname ); ?>
1750 </div>
1751 <div class="post-box-container column-3 advanced">
1752 <?php do_action( 'wck_before_column3_metabox_content', $this->hookname ); ?>
1753 <?php do_meta_boxes( $this->hookname, 'advanced', null ); ?>
1754 <?php do_action( 'wck_after_column3_metabox_content', $this->hookname ); ?>
1755 </div>
1756 </div>
1757 <div class="post-box-container column-2 side <?php echo $is_email_customizer_page ? 'cozmoslabs-submit' : '' ?>"><?php do_meta_boxes( $this->hookname, 'side', null ); ?></div>
1758
1759 </div>
1760
1761 <?php do_action( 'wck_after_meta_boxes', $this->hookname ); ?>
1762
1763 </div><!-- #poststuff -->
1764
1765 </div><!-- .wrap -->
1766 <?php
1767 }
1768 }
1769
1770
1771
1772 ?>
1773