PluginProbe
User Profile Builder – Beautiful User Registration Forms, User Profiles & User Role Editor / 3.9.9
User Profile Builder – Beautiful User Registration Forms, User Profiles & User Role Editor v3.9.9
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.9.9, at assets/lib/wck-api/wordpress-creation-kit.php

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