PluginProbe
User Profile Builder – Beautiful User Registration Forms, User Profiles & User Role Editor / 4.0.3
User Profile Builder – Beautiful User Registration Forms, User Profiles & User Role Editor v4.0.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
← All changes | assets/lib/wck-api/wordpress-creation-kit.php +1772 -1449 2.0.6 → 4.0.3 View file →
@@ -1,1449 +1,1772 @@
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' ));
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_refresh_entry".$this->args['meta_name'], array( &$this, 'wck_refresh_entry') );
96 - add_action("wp_ajax_wck_add_form".$this->args['meta_name'], array( &$this, 'wck_add_form') );
97 - add_action("wp_ajax_wck_remove_meta".$this->args['meta_name'], array( &$this, 'wck_remove_meta') );
98 - add_action("wp_ajax_wck_reorder_meta".$this->args['meta_name'], array( &$this, 'wck_reorder_meta') );
99 -
100 - /* modify Insert into post button */
101 - add_action('admin_head-media-upload-popup', array( &$this, 'wck_media_upload_popup_head') );
102 -
103 - /* custom functionality for upload video */
104 - add_filter('media_send_to_editor', array( &$this, 'wck_media_send_to_editor' ), 15, 2 );
105 -
106 - add_action('add_meta_boxes', array( &$this, 'wck_add_metabox') );
107 -
108 - /* hook to add a side metabox with the Syncronize translation button */
109 - add_action('add_meta_boxes', array( &$this, 'wck_add_sync_translation_metabox' ) );
110 -
111 - /* ajax hook the syncronization function */
112 - add_action("wp_ajax_wck_sync_translation", array( &$this, 'wck_sync_translation_ajax' ) );
113 -
114 - }
115 -
116 -
117 - //add metabox using wordpress api
118 -
119 - function wck_add_metabox() {
120 -
121 - global $pb_wck_pages_hooknames;
122 -
123 - if( $this->args['context'] == 'post_meta' ){
124 - if( $this->args['post_id'] == '' && $this->args['page_template'] == '' ){
125 - 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']) );
126 - /* add class to meta box */
127 - add_filter( "postbox_classes_".$this->args['post_type']."_".$this->args['metabox_id'], array( &$this, 'wck_add_metabox_classes' ) );
128 - }
129 - else{
130 - if( !empty( $_GET['post'] ) )
131 - $post_id = $_GET['post'];
132 - else if( !empty( $_POST['post_ID'] ) )
133 - $post_id = $_POST['post_ID'];
134 - else
135 - $post_id = '';
136 -
137 -
138 - if( $this->args['post_id'] != '' && $this->args['page_template'] != '' ){
139 - $template_file = get_post_meta($post_id,'_wp_page_template',TRUE);
140 - if( $this->args['post_id'] == $post_id && $template_file == $this->args['page_template'] )
141 - 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'] ) );
142 -
143 - /* add class to meta box */
144 - add_filter( "postbox_classes_page_".$this->args['metabox_id'], array( &$this, 'wck_add_metabox_classes' ) );
145 - }
146 - else{
147 -
148 - if( $this->args['post_id'] != '' ){
149 - if( $this->args['post_id'] == $post_id ){
150 - $post_type = get_post_type( $post_id );
151 - 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'] ) );
152 - /* add class to meta box */
153 - add_filter( "postbox_classes_".$post_type."_".$this->args['metabox_id'], array( &$this, 'wck_add_metabox_classes' ) );
154 - }
155 - }
156 -
157 - if( $this->args['page_template'] != '' ){
158 - $template_file = get_post_meta($post_id,'_wp_page_template',TRUE);
159 - if ( $template_file == $this->args['page_template'] ){
160 - 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']) );
161 - /* add class to meta box */
162 - add_filter( "postbox_classes_page_".$this->args['metabox_id'], array( &$this, 'wck_add_metabox_classes' ) );
163 - }
164 - }
165 -
166 - }
167 -
168 - }
169 - }
170 - else if( $this->args['context'] == 'option' ){
171 - 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']) );
172 - /* add class to meta box */
173 - add_filter( "postbox_classes_".$pb_wck_pages_hooknames[$this->args['post_type']]."_".$this->args['metabox_id'], array( &$this, 'wck_add_metabox_classes' ) );
174 - }
175 - }
176 -
177 - /* Function used to add classes to the wck meta boxes */
178 - function wck_add_metabox_classes( $classes ){
179 - array_push($classes,'wck-post-box');
180 - return $classes;
181 - }
182 -
183 - function wck_content($post, $metabox){
184 - if( !empty( $post->ID ) )
185 - $post_id = $post->ID;
186 - else
187 - $post_id = '';
188 -
189 - //output the add form
190 - if( $this->args['single'] ){
191 -
192 - if( $this->args['context'] == 'post_meta' )
193 - $meta_val = get_post_meta( $post_id, $metabox['args']['meta_name'], true );
194 - else if ( $this->args['context'] == 'option' )
195 - $meta_val = get_option( $metabox['args']['meta_name'] );
196 -
197 - if( empty( $meta_val ) )
198 - self::create_add_form($metabox['args']['meta_array'], $metabox['args']['meta_name'], $post);
199 - }
200 - else
201 - self::create_add_form($metabox['args']['meta_array'], $metabox['args']['meta_name'], $post);
202 -
203 - //output the entries
204 - echo self::wck_output_meta_content($metabox['args']['meta_name'], $post_id, $metabox['args']['meta_array']);
205 - }
206 -
207 - /**
208 - * The function used to create a form element
209 - *
210 - * @since 1.0.0
211 - *
212 - * @param string $meta Meta name.
213 - * @param array $details Contains the details for the field.
214 - * @param string $value Contains input value;
215 - * @param string $context Context where the function is used. Depending on it some actions are preformed.;
216 - * @param int $post_id The post ID;
217 - * @return string $element input element html string.
218 - */
219 -
220 - function wck_output_form_field( $meta, $details, $value = '', $context = '', $post_id = '' ){
221 - $element = '';
222 -
223 - if( $context == 'edit_form' ){
224 - $edit_class = '.mb-table-container ';
225 - $var_prefix = 'edit';
226 - }
227 - else if( $context == 'fep' ){
228 - /* id prefix for frontend posting */
229 - $frontend_prefix = 'fep-';
230 - }
231 - else{
232 - if( !empty( $details['default'] ) )
233 - $value = apply_filters( "wck_default_value_{$meta}_". Wordpress_Creation_Kit_PB::wck_generate_slug( $details['title'], $details ) , $details['default'] );
234 - }
235 -
236 - $element .= '<label for="'. esc_attr( Wordpress_Creation_Kit_PB::wck_generate_slug( $details['title'], $details ) ) .'" class="field-label">'. apply_filters( "wck_label_{$meta}_". Wordpress_Creation_Kit_PB::wck_generate_slug( $details['title'], $details ), ucfirst($details['title']) ) .':';
237 - if( !empty( $details['required'] ) && $details['required'] )
238 - $element .= '<span class="required">*</span>';
239 - $element .= '</label>';
240 -
241 - $element .= '<div class="mb-right-column">';
242 -
243 - /*
244 - include actual field type
245 - possible field types: text, textarea, select, checkbox, radio, upload, wysiwyg editor, datepicker, country select, user select, cpt select
246 - */
247 -
248 - if( function_exists( 'wck_nr_get_repeater_boxes' ) ){
249 - $cfc_titles = wck_nr_get_repeater_boxes();
250 - if( in_array( $details['type'], $cfc_titles ) ){
251 - $details['type'] = 'nested repeater';
252 - }
253 - }
254 -
255 -
256 - if( file_exists( dirname( __FILE__ ).'/fields/'.$details['type'].'.php' ) ){
257 - require( dirname( __FILE__ ).'/fields/'.$details['type'].'.php' );
258 - }
259 -
260 - if( !empty( $details['description'] ) ){
261 - $element .= '<p class="description">'. $details['description'].'</p>';
262 - }
263 -
264 - $element .= '</div><!-- .mb-right-column -->';
265 -
266 - $element = apply_filters( "wck_output_form_field_{$meta}_" . Wordpress_Creation_Kit_PB::wck_generate_slug( $details['title'], $details ), $element );
267 -
268 - return $element;
269 -
270 - }
271 -
272 -
273 - /**
274 - * The function used to create the form for adding records
275 - *
276 - * @since 1.0.0
277 - *
278 - * @param array $fields Contains the desired inputs in the repeater field. Must be like: array('Key:type').
279 - * Key is used for the name attribute of the field, label of the field and as the meta_key.
280 - * Supported types: input, textarea, upload
281 - * @param string $meta It is used in update_post_meta($id, $meta, $results);. Use '_' prefix if you don't want
282 - * the meta to apear in custom fields box.
283 - * @param object $post Post object
284 - */
285 - function create_add_form($fields, $meta, $post){
286 - $nonce = wp_create_nonce( 'wck-add-meta' );
287 - if( !empty( $post->ID ) )
288 - $post_id = $post->ID;
289 - else
290 - $post_id = '';
291 -
292 - ?>
293 - <div id="<?php echo $meta ?>" style="padding:10px 0;" class="wck-add-form<?php if( $this->args['single'] ) echo ' single' ?>">
294 - <ul class="mb-list-entry-fields">
295 - <?php
296 - $element_id = 0;
297 - if( !empty( $fields ) ){
298 - foreach( $fields as $details ){
299 -
300 - do_action( "wck_before_add_form_{$meta}_element_{$element_id}" );
301 -
302 - ?>
303 - <li class="row-<?php echo esc_attr( Wordpress_Creation_Kit_PB::wck_generate_slug( $details['title'], $details ) ) ?>">
304 - <?php echo self::wck_output_form_field( $meta, $details, '', '', $post_id ); ?>
305 - </li>
306 - <?php
307 -
308 - do_action( "wck_after_add_form_{$meta}_element_{$element_id}" );
309 -
310 - $element_id++;
311 - }
312 - }
313 - ?>
314 - <li style="overflow:visible;" class="add-entry-button">
315 - <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 _e( apply_filters( 'wck_add_entry_button', 'Add Entry', $meta, $post ), 'wck' ); ?></span></a>
316 - </li>
317 - </ul>
318 - </div>
319 - <?php
320 - }
321 -
322 - /**
323 - * The function used to display a form to update a reccord from meta
324 - *
325 - * @since 1.0.0
326 - *
327 - * @param string $meta It is used in get_post_meta($id, $meta, $results);. Use '_' prefix if you don't want
328 - * the meta to apear in custom fields box.
329 - * @param int $id Post id
330 - * @param int $element_id The id of the reccord. The meta is stored as array(array());
331 - */
332 - function mb_update_form($fields, $meta, $id, $element_id){
333 -
334 - $update_nonce = wp_create_nonce( 'wck-update-entry' );
335 -
336 - if( $this->args['context'] == 'post_meta' )
337 - $results = get_post_meta($id, $meta, true);
338 - else if ( $this->args['context'] == 'option' )
339 - $results = get_option( $meta );
340 -
341 - /* Filter primary used for CFC/OPC fields in order to show/hide fields based on type */
342 - $wck_update_container_css_class = " class='update_container_$meta'";
343 - $wck_update_container_css_class = apply_filters("wck_update_container_class_{$meta}", $wck_update_container_css_class, $meta, $results, $element_id );
344 -
345 - $form = '';
346 - $form .= '<tr id="update_container_'.$meta.'_'.$element_id.'" ' . $wck_update_container_css_class . '><td colspan="4">';
347 - if($results != null){
348 - $i = 0;
349 - $form .= '<ul class="mb-list-entry-fields">';
350 -
351 - if( !empty( $fields ) ){
352 - foreach( $fields as $field ){
353 - $details = $field;
354 - if( !empty( $results[$element_id][Wordpress_Creation_Kit_PB::wck_generate_slug( $details['title'], $details )] ) )
355 - $value = $results[$element_id][Wordpress_Creation_Kit_PB::wck_generate_slug( $details['title'], $details )];
356 - else
357 - $value = '';
358 -
359 - $form = apply_filters( "wck_before_update_form_{$meta}_element_{$i}", $form, $element_id, $value );
360 -
361 - $form .= '<li class="row-'. esc_attr( Wordpress_Creation_Kit_PB::wck_generate_slug( $details['title'], $details ) ) .'">';
362 -
363 - $form .= self::wck_output_form_field( $meta, $details, $value, 'edit_form', $id );
364 -
365 - $form .= '</li>';
366 -
367 - $form = apply_filters( "wck_after_update_form_{$meta}_element_{$i}", $form, $element_id, $value );
368 -
369 - $i++;
370 - }
371 - }
372 - $form .= '<li style="overflow:visible;">';
373 - $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', $meta ), 'wck' ) .'</span></a>';
374 - $form .= '<a href="javascript:void(0)" class="button-secondary" style="margin-left:10px;" onclick=\'removeUpdateForm("'. esc_js( 'update_container_'.$meta.'_'.$element_id ). '" )\'><span>'. __( apply_filters( 'wck_cancel_button', 'Cancel', $meta ), 'wck' ) .'</span></a>';
375 - $form .= '</li>';
376 -
377 - $form .= '</ul>';
378 - }
379 - $form .= '</td></tr>';
380 -
381 - return $form;
382 - }
383 -
384 -
385 - /**
386 - * The function used to output the content of a meta
387 - *
388 - * @since 1.0.0
389 - *
390 - * @param string $meta It is used in get_post_meta($id, $meta, $results);. Use '_' prefix if you don't want
391 - * the meta to apear in custom fields box.
392 - * @param int $id Post id
393 - */
394 - function wck_output_meta_content($meta, $id, $fields, $box_args = '' ){
395 - /* in fep $this->args is empty so we need it as a parameter */
396 - if( !empty( $box_args ) )
397 - $this->args = wp_parse_args( $box_args, $this->defaults );
398 -
399 -
400 - if( $this->args['context'] == 'post_meta' || $this->args['context'] == '' )
401 - $results = get_post_meta($id, $meta, true);
402 - else if ( $this->args['context'] == 'option' )
403 - $results = get_option( $meta );
404 -
405 - $list = '';
406 - $list .= '<table id="container_'.esc_attr($meta).'" class="mb-table-container widefat';
407 -
408 - if( $this->args['single'] ) $list .= ' single';
409 - if( !$this->args['sortable'] ) $list .= ' not-sortable';
410 -
411 - $list .= '" post="'.esc_attr($id).'">';
412 -
413 -
414 - if( !empty( $results ) ){
415 - $list .= apply_filters( 'wck_metabox_content_header_'.$meta , '<thead><tr><th class="wck-number">#</th><th class="wck-content">'. __( 'Content', 'wck' ) .'</th><th class="wck-edit">'. __( 'Edit', 'wck' ) .'</th><th class="wck-delete">'. __( 'Delete', 'wck' ) .'</th></tr></thead>' );
416 - $i=0;
417 - foreach ($results as $result){
418 -
419 - $list .= self::wck_output_entry_content( $meta, $id, $fields, $results, $i );
420 -
421 - $i++;
422 - }
423 - }
424 - $list .= apply_filters( 'wck_metabox_content_footer_'.$meta , '', $id );
425 - $list .= '</table>';
426 -
427 - $list = apply_filters('wck_metabox_content_'.$meta, $list, $id);
428 - return $list;
429 - }
430 -
431 - function wck_output_entry_content( $meta, $id, $fields, $results, $element_id ){
432 - $edit_nonce = wp_create_nonce( 'wck-edit-entry' );
433 - $delete_nonce = wp_create_nonce( 'wck-delete-entry' );
434 - $entry_nr = $element_id +1;
435 -
436 - $wck_element_class = '';
437 - $wck_element_class = apply_filters( "wck_element_class_{$meta}", $wck_element_class, $meta, $results, $element_id );
438 -
439 - $list = '';
440 - $list .= '<tr id="element_'.$element_id.'" ' . $wck_element_class . '>';
441 - $list .= '<td style="text-align:center;vertical-align:middle;" class="wck-number">'. $entry_nr .'</td>';
442 - $list .= '<td class="wck-content"><ul>' . "\r\n";
443 -
444 - $j = 0;
445 -
446 - if( !empty( $fields ) ){
447 - foreach( $fields as $field ){
448 - $details = $field;
449 -
450 - if( !empty( $results[$element_id][Wordpress_Creation_Kit_PB::wck_generate_slug( $details['title'], $details )] ) )
451 - $value = $results[$element_id][Wordpress_Creation_Kit_PB::wck_generate_slug( $details['title'], $details )];
452 - else
453 - $value ='';
454 -
455 - /* filter display value */
456 - $value = apply_filters( "wck_displayed_value_{$meta}_element_{$j}", $value );
457 -
458 - /* display it differently based on field type*/
459 - if( $details['type'] == 'upload' ){
460 - $display_value = self::wck_get_entry_field_upload($value);
461 - } elseif ( $details['type'] == 'user select' ) {
462 - $display_value = self::wck_get_entry_field_user_select( $value ) . '</pre>';
463 - } elseif ( $details['type'] == 'cpt select' ){
464 - $display_value = self::wck_get_entry_field_cpt_select( $value ) . '</pre>';
465 - } else {
466 - $display_value = '<pre>'.htmlspecialchars( $value ) . '</pre>';
467 - }
468 -
469 -
470 - $list = apply_filters( "wck_before_listed_{$meta}_element_{$j}", $list, $element_id, $value );
471 - /*check for nested repeater type and set it acordingly */
472 - if( strpos( $details['type'], 'CFC-') === 0 )
473 - $details['type'] = 'nested-repeater';
474 -
475 - $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";
476 -
477 - $list = apply_filters( "wck_after_listed_{$meta}_element_{$j}", $list, $element_id, $value );
478 -
479 - $j++;
480 -
481 - /* In CFC/OPC we need the field title. Find it out and output it if found */
482 - if ($meta == 'wck_cfc_fields') {
483 - if( !empty( $results[$element_id][Wordpress_Creation_Kit_PB::wck_generate_slug( $details['title'], $details )] ) ){
484 - $field_title = $results[$element_id][Wordpress_Creation_Kit_PB::wck_generate_slug( $details['title'], $details )];
485 - if ($field_title == "Field Type")
486 - $cfc_field_type = $value;
487 - }
488 - }
489 - }
490 - }
491 - $list .= '</ul>';
492 -
493 - /* check if we have nested repeaters */
494 - if( function_exists( 'wck_nr_check_for_nested_repeaters' ) ){
495 - if( wck_nr_check_for_nested_repeaters( $fields ) === true ){
496 - $list .= wck_nr_handle_repeaters( $meta, $id, $fields, $results, $element_id );
497 - }
498 - }
499 -
500 - $list .= '</td>';
501 - $list .= '<td style="text-align:center;vertical-align:middle;" class="wck-edit"><a href="javascript:void(0)" class="button-secondary" onclick=\'showUpdateFormMeta("'.esc_js($meta).'", "'.esc_js($id).'", "'.esc_js($element_id).'", "'.esc_js($edit_nonce).'")\' title="'. __( 'Edit this item', 'wck' ) .'">'. apply_filters( 'wck_edit_button', __('Edit','wck'), $meta ) .'</a></td>';
502 - $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', 'wck' ) .'">'. apply_filters( 'wck_delete_button', __( 'Delete', 'wck' ), $meta) .'</a></td>';
503 -
504 - $list .= "</tr> \r\n";
505 -
506 - return $list;
507 - }
508 -
509 - /* function to generate output for upload field */
510 - function wck_get_entry_field_upload($id){
511 - if( !empty ( $id ) && is_numeric( $id ) ){
512 - $file_src = wp_get_attachment_url($id);
513 - $thumbnail = wp_get_attachment_image( $id, array( 80, 60 ), true );
514 - $file_name = get_the_title( $id );
515 -
516 - if ( preg_match( '/^.*?\.(\w+)$/', get_attached_file( $id ), $matches ) )
517 - $file_type = esc_html( strtoupper( $matches[1] ) );
518 - else
519 - $file_type = strtoupper( str_replace( 'image/', '', get_post_mime_type( $id ) ) );
520 -
521 - 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>';
522 - } else {
523 - return '';
524 - }
525 - }
526 -
527 - /* function to generate output for user select */
528 - function wck_get_entry_field_user_select($id){
529 - if( !empty ( $id ) && is_numeric( $id ) ){
530 - $user = get_user_by( 'id', $id );
531 - if ( $user )
532 - return '<pre>'.htmlspecialchars( $user->display_name );
533 - else
534 - return 'Error - User ID not found in database';
535 -
536 - } else {
537 - return '';
538 - }
539 - }
540 -
541 - /* function to generate output for cpt select */
542 - function wck_get_entry_field_cpt_select($id){
543 - if( !empty ( $id ) && is_numeric( $id ) ){
544 - $post = get_post( $id );
545 -
546 - if ( $post != null ){
547 - if ( $post->post_title == '' )
548 - $post->post_title = 'No title. ID: ' . $id;
549 -
550 - return '<pre>'.htmlspecialchars( $post->post_title );
551 - }
552 - else
553 - return 'Error - Post ID not found in database';
554 -
555 - } else {
556 - return '';
557 - }
558 - }
559 -
560 - /* enque the js/css */
561 - function wck_print_scripts($hook){
562 - global $pb_wck_pages_hooknames;
563 -
564 - if( $this->args['context'] == 'post_meta' ) {
565 - if( 'post.php' == $hook || 'post-new.php' == $hook){
566 -
567 - /* only add on profile builder custom post types */
568 - if( !empty( $_GET['post'] ) )
569 - $post_id = $_GET['post'];
570 - else if( !empty( $_POST['post_ID'] ) )
571 - $post_id = $_POST['post_ID'];
572 - else
573 - $post_id = '';
574 - if( !empty( $post_id ) ){
575 - $current_post_type = get_post_type( $post_id );
576 - if( strpos( $current_post_type, 'wppb-' ) === false )
577 - return '';
578 - }
579 -
580 - self::wck_enqueue();
581 - }
582 - }
583 - elseif( $this->args['context'] == 'option' ){
584 - if( $pb_wck_pages_hooknames[$this->args['post_type']] == $hook ){
585 - self::wck_enqueue( 'options' );
586 - }
587 - }
588 - }
589 -
590 - /* our own ajaxurl */
591 - function wck_print_ajax_url(){
592 - echo '<script type="text/javascript">var wckAjaxurl = "'. admin_url('admin-ajax.php') .'";</script>';
593 - }
594 -
595 -
596 - /* Helper function for enqueueing scripts and styles */
597 - private static function wck_enqueue( $context = '' ){
598 -
599 - wp_enqueue_script( 'jquery-ui-draggable' );
600 - wp_enqueue_script( 'jquery-ui-droppable' );
601 - wp_enqueue_script( 'jquery-ui-sortable' );
602 -
603 - if( $context == 'options' ){
604 - wp_enqueue_script( 'thickbox' );
605 - wp_enqueue_style( 'thickbox' );
606 - }
607 -
608 - wp_enqueue_script('wordpress-creation-kit', plugins_url('/wordpress-creation-kit.js', __FILE__), array('jquery', 'jquery-ui-draggable', 'jquery-ui-droppable', 'jquery-ui-sortable' ) );
609 - wp_register_style('wordpress-creation-kit-css', plugins_url('/wordpress-creation-kit.css', __FILE__));
610 - wp_enqueue_style('wordpress-creation-kit-css');
611 -
612 - // wysiwyg
613 -// wp_register_script( 'wck-tinymce', plugins_url( '/assets/js/tiny_mce/tiny_mce.js', __FILE__ ), array(), '1.0', true );
614 -// wp_enqueue_script( 'wck-tinymce' );
615 -// wp_register_script( 'wck-tinymce-init', plugins_url( '/assets/js/tiny_mce/wck_tiny_mce_init.js', __FILE__ ), array(), '1.0', true );
616 -// wp_enqueue_script( 'wck-tinymce-init' );
617 -
618 - //datepicker
619 - wp_enqueue_script('jquery-ui-datepicker');
620 - wp_enqueue_style( 'jquery-style', plugins_url( '/assets/datepicker/datepicker.css', __FILE__ ) );
621 -
622 - }
623 -
624 - /* Helper function for required fields */
625 - function wck_test_required( $meta_array, $meta, $values, $id ){
626 - $fields = $meta_array;
627 - $required_fields = array();
628 - $required_fields_with_errors = array();
629 - $required_message = '';
630 -
631 - $errors = '';
632 -
633 - if( !empty( $fields ) ){
634 - foreach( $fields as $field ){
635 - if( !empty( $field['required'] ) && $field['required'] )
636 - $required_fields[Wordpress_Creation_Kit_PB::wck_generate_slug( $field['title'], $field )] = $field['title'];
637 - }
638 - }
639 -
640 - if( !empty( $values ) ){
641 - foreach( $values as $key => $value ){
642 - if( array_key_exists( $key, $required_fields ) && apply_filters( "wck_required_test_{$meta}_{$key}", empty( $value ), $value, $id ) ){
643 - $required_message .= apply_filters( "wck_required_message_{$meta}_{$key}", __( "Please enter a value for the required field ", "wck" ) . "$required_fields[$key] \n", $value );
644 - $required_fields_with_errors[] = $key;
645 - }
646 - }
647 - }
648 -
649 - $required_message .= apply_filters( "wck_extra_message", "", $fields, $required_fields, $meta, $values, $id );
650 - $required_fields_with_errors = apply_filters( "wck_required_fields_with_errors", $required_fields_with_errors, $fields, $required_fields, $meta, $value, $id );
651 -
652 - if( $required_message != '' ){
653 - $errors = array( 'error' => $required_message, 'errorfields' => $required_fields_with_errors );
654 - }
655 -
656 - return $errors;
657 - }
658 -
659 -
660 - /* ajax add a reccord to the meta */
661 - function wck_add_meta(){
662 - check_ajax_referer( "wck-add-meta" );
663 - if( !empty( $_POST['meta'] ) )
664 - $meta = $_POST['meta'];
665 - else
666 - $meta = '';
667 - if( !empty( $_POST['id'] ) )
668 - $id = absint($_POST['id']);
669 - else
670 - $id = '';
671 - if( !empty( $_POST['values'] ) )
672 - $values = $_POST['values'];
673 - else
674 - $values = array();
675 -
676 - $values = apply_filters( "wck_add_meta_filter_values_{$meta}", $values );
677 -
678 - /* check required fields */
679 - $errors = self::wck_test_required( $this->args['meta_array'], $meta, $values, $id );
680 - if( $errors != '' ){
681 - header( 'Content-type: application/json' );
682 - die( json_encode( $errors ) );
683 - }
684 -
685 -
686 - if( $this->args['context'] == 'post_meta' )
687 - $results = get_post_meta($id, $meta, true);
688 - else if ( $this->args['context'] == 'option' )
689 - $results = get_option( $meta );
690 -
691 - $results[] = $values;
692 -
693 - do_action( 'wck_before_add_meta', $meta, $id, $values );
694 -
695 - if( $this->args['context'] == 'post_meta' )
696 - update_post_meta($id, $meta, $results);
697 - else if ( $this->args['context'] == 'option' )
698 - update_option( $meta, wp_unslash( $results ) );
699 -
700 - /* if unserialize_fields is true add for each entry separate post meta for every element of the form */
701 - if( $this->args['unserialize_fields'] && $this->args['context'] == 'post_meta' ){
702 -
703 - $meta_suffix = count( $results );
704 - if( !empty( $values ) ){
705 - foreach( $values as $name => $value ){
706 - update_post_meta($id, $meta.'_'.$name.'_'.$meta_suffix, $value);
707 - }
708 - }
709 - }
710 -
711 - exit;
712 - }
713 -
714 - /* ajax update a reccord in the meta */
715 - function wck_update_meta(){
716 - check_ajax_referer( "wck-update-entry" );
717 - if( !empty( $_POST['meta'] ) )
718 - $meta = $_POST['meta'];
719 - else
720 - $meta = '';
721 - if( !empty( $_POST['id'] ) )
722 - $id = absint($_POST['id']);
723 - else
724 - $id = '';
725 - if( isset( $_POST['element_id'] ) )
726 - $element_id = $_POST['element_id'];
727 - else
728 - $element_id = 0;
729 - if( !empty( $_POST['values'] ) )
730 - $values = $_POST['values'];
731 -
732 -
733 - $values = apply_filters( "wck_update_meta_filter_values_{$meta}", $values, $element_id );
734 -
735 - /* check required fields */
736 - $errors = self::wck_test_required( $this->args['meta_array'], $meta, $values, $id );
737 - if( $errors != '' ){
738 - header( 'Content-type: application/json' );
739 - die( json_encode( $errors ) );
740 - }
741 -
742 - if( $this->args['context'] == 'post_meta' )
743 - $results = get_post_meta($id, $meta, true);
744 - else if ( $this->args['context'] == 'option' )
745 - $results = get_option( $meta );
746 -
747 - $results[$element_id] = $values;
748 -
749 - do_action( 'wck_before_update_meta', $meta, $id, $values, $element_id );
750 -
751 - if( $this->args['context'] == 'post_meta' )
752 - update_post_meta($id, $meta, $results);
753 - else if ( $this->args['context'] == 'option' )
754 - update_option( $meta, wp_unslash( $results ) );
755 -
756 - /* if unserialize_fields is true update the coresponding post metas for every element of the form */
757 - if( $this->args['unserialize_fields'] && $this->args['context'] == 'post_meta' ){
758 -
759 - $meta_suffix = $element_id + 1;
760 - if( !empty( $values ) ){
761 - foreach( $values as $name => $value ){
762 - update_post_meta($id, $meta.'_'.$name.'_'.$meta_suffix, $value);
763 - }
764 - }
765 - }
766 -
767 - exit;
768 - }
769 -
770 - /* ajax to refresh the meta content */
771 - function wck_refresh_list(){
772 - if( isset( $_POST['meta'] ) )
773 - $meta = $_POST['meta'];
774 - else
775 - $meta = '';
776 - if( isset( $_POST['id'] ) )
777 - $id = absint($_POST['id']);
778 - else
779 - $id = '';
780 - echo self::wck_output_meta_content($meta, $id, $this->args['meta_array']);
781 -
782 - do_action( "wck_refresh_list_{$meta}", $id );
783 -
784 - exit;
785 - }
786 -
787 - /* ajax to refresh an entry content */
788 - function wck_refresh_entry(){
789 - if( isset( $_POST['meta'] ) )
790 - $meta = $_POST['meta'];
791 - else
792 - $meta = '';
793 - if( isset( $_POST['id'] ) )
794 - $id = absint( $_POST['id'] );
795 - else
796 - $id = '';
797 - if( isset( $_POST['element_id'] ) )
798 - $element_id = $_POST['element_id'];
799 - else
800 - $element_id = '';
801 -
802 - if( $this->args['context'] == 'post_meta' )
803 - $results = get_post_meta($id, $meta, true);
804 - else if ( $this->args['context'] == 'option' )
805 - $results = get_option( $meta );
806 -
807 - echo self::wck_output_entry_content( $meta, $id, $this->args['meta_array'], $results, $element_id );
808 -
809 - do_action( "wck_refresh_entry_{$meta}", $id );
810 -
811 - exit;
812 - }
813 -
814 - /* ajax to add the form for single */
815 - function wck_add_form(){
816 - if( !empty( $_POST['meta'] ) )
817 - $meta = $_POST['meta'];
818 - else
819 - $meta = '';
820 - if( !empty( $_POST['id'] ) )
821 - $id = absint( $_POST['id'] );
822 - else
823 - $id = '';
824 - $post = get_post($id);
825 - self::create_add_form($this->args['meta_array'], $meta, $post );
826 - do_action( "wck_ajax_add_form_{$meta}", $id );
827 -
828 - exit;
829 - }
830 -
831 -
832 - /* ajax to show the update form */
833 - function wck_show_update_form(){
834 - check_ajax_referer( "wck-edit-entry" );
835 - $meta = $_POST['meta'];
836 - $id = absint($_POST['id']);
837 - $element_id = $_POST['element_id'];
838 -
839 - do_action( "wck_before_adding_form_{$meta}", $id, $element_id );
840 -
841 - echo self::mb_update_form($this->args['meta_array'], $meta, $id, $element_id);
842 -
843 - do_action( "wck_after_adding_form", $meta, $id, $element_id );
844 - do_action( "wck_after_adding_form_{$meta}", $id, $element_id );
845 -
846 - exit;
847 - }
848 -
849 - /* ajax to remove a reccord from the meta */
850 - function wck_remove_meta(){
851 - check_ajax_referer( "wck-delete-entry" );
852 - if( !empty( $_POST['meta'] ) )
853 - $meta = $_POST['meta'];
854 - else
855 - $meta = '';
856 - if( !empty( $_POST['id'] ) )
857 - $id = absint( $_POST['id'] );
858 - else
859 - $id = '';
860 - if( isset( $_POST['element_id'] ) )
861 - $element_id = absint( $_POST['element_id'] );
862 - else
863 - $element_id = '';
864 -
865 - if( $this->args['context'] == 'post_meta' )
866 - $results = get_post_meta($id, $meta, true);
867 - else if ( $this->args['context'] == 'option' )
868 - $results = get_option( $meta );
869 -
870 - $old_results = $results;
871 - unset($results[$element_id]);
872 - /* reset the keys for the array */
873 - $results = array_values($results);
874 -
875 - do_action( 'wck_before_remove_meta', $meta, $id, $element_id );
876 -
877 - if( $this->args['context'] == 'post_meta' )
878 - update_post_meta($id, $meta, $results);
879 - else if ( $this->args['context'] == 'option' )
880 - update_option( $meta, wp_unslash( $results ) );
881 -
882 -
883 -
884 - /* TODO: optimize so that it updates from the deleted element forward */
885 - /* if unserialize_fields is true delete the coresponding post metas */
886 - if( $this->args['unserialize_fields'] && $this->args['context'] == 'post_meta' ){
887 -
888 - $meta_suffix = 1;
889 -
890 - if( !empty( $results ) ){
891 - foreach( $results as $result ){
892 - foreach ( $result as $name => $value){
893 - update_post_meta($id, $meta.'_'.$name.'_'.$meta_suffix, $value);
894 - }
895 - $meta_suffix++;
896 - }
897 - }
898 -
899 - if( count( $results ) == 0 )
900 - $results = $old_results;
901 -
902 - if( !empty( $results ) ){
903 - foreach( $results as $result ){
904 - foreach ( $result as $name => $value){
905 - delete_post_meta( $id, $meta.'_'.$name.'_'.$meta_suffix );
906 - }
907 - break;
908 - }
909 - }
910 - }
911 -
912 - exit;
913 - }
914 -
915 -
916 - /* ajax to reorder records */
917 - function wck_reorder_meta(){
918 - if( !empty( $_POST['meta'] ) )
919 - $meta = $_POST['meta'];
920 - else
921 - $meta = '';
922 - if( !empty( $_POST['id'] ) )
923 - $id = absint($_POST['id']);
924 - else
925 - $id = '';
926 - if( !empty( $_POST['values'] ) )
927 - $elements_id = $_POST['values'];
928 - else
929 - $elements_id = array();
930 -
931 - do_action( 'wck_before_reorder_meta', $meta, $id, $elements_id );
932 -
933 - if( $this->args['context'] == 'post_meta' )
934 - $results = get_post_meta($id, $meta, true);
935 - else if ( $this->args['context'] == 'option' )
936 - $results = get_option( $meta );
937 -
938 - $new_results = array();
939 - if( !empty( $elements_id ) ){
940 - foreach($elements_id as $element_id){
941 - $new_results[] = $results[$element_id];
942 - }
943 - }
944 -
945 - $results = $new_results;
946 -
947 - if( $this->args['context'] == 'post_meta' )
948 - update_post_meta($id, $meta, $results);
949 - else if ( $this->args['context'] == 'option' )
950 - update_option( $meta, wp_unslash( $results ) );
951 -
952 -
953 - /* if unserialize_fields is true reorder all the coresponding post metas */
954 - if( $this->args['unserialize_fields'] && $this->args['context'] == 'post_meta' ){
955 -
956 - $meta_suffix = 1;
957 - if( !empty( $new_results ) ){
958 - foreach( $new_results as $result ){
959 - foreach ( $result as $name => $value){
960 - update_post_meta($id, $meta.'_'.$name.'_'.$meta_suffix, $value);
961 - }
962 - $meta_suffix++;
963 - }
964 - }
965 -
966 - }
967 -
968 - exit;
969 - }
970 -
971 - /* modify Insert into post button */
972 - function wck_media_upload_popup_head()
973 - {
974 - if( isset( $_GET["meta_name"] ) ){
975 - if( $this->args['meta_name'] == $_GET["meta_name"] ){
976 - if( ( isset( $_GET["mb_type"] ) ) ){
977 - ?>
978 - <style type="text/css">
979 - #media-upload-header #sidemenu li#tab-type_url,
980 - #media-upload-header #sidemenu li#tab-gallery {
981 - display: none;
982 - }
983 -
984 - #media-items tr.url,
985 - #media-items tr.align,
986 - #media-items tr.image_alt,
987 - #media-items tr.image-size,
988 - #media-items tr.post_excerpt,
989 - #media-items tr.post_content,
990 - #media-items tr.image_alt p,
991 - #media-items table thead input.button,
992 - #media-items table thead img.imgedit-wait-spin,
993 - #media-items tr.submit a.wp-post-thumbnail {
994 - display: none;
995 - }
996 -
997 - .media-item table thead img {
998 - border: #DFDFDF solid 1px;
999 - margin-right: 10px;
1000 - }
1001 -
1002 - </style>
1003 - <script type="text/javascript">
1004 - (function($){
1005 -
1006 - $(document).ready(function(){
1007 -
1008 - $('#media-items').bind('DOMNodeInserted',function(){
1009 - $('input[value="Insert into Post"]').each(function(){
1010 - $(this).attr('value','<?php _e("Select File")?>');
1011 - });
1012 - }).trigger('DOMNodeInserted');
1013 -
1014 - $('form#filter').each(function(){
1015 -
1016 - $(this).append('<input type="hidden" name="mb_type" value="<?php echo $_GET['mb_type']; ?>" />');
1017 - $(this).append('<input type="hidden" name="mb_info_div" value="<?php echo $_GET['mb_info_div']; ?>" />');
1018 -
1019 - });
1020 - });
1021 -
1022 - })(jQuery);
1023 - </script>
1024 - <?php
1025 - }
1026 - }
1027 - }
1028 - }
1029 -
1030 - /* custom functionality for upload button */
1031 -
1032 - function wck_media_send_to_editor($html, $id)
1033 - {
1034 - if( !empty( $_POST["_wp_http_referer"] ) ) {
1035 - parse_str($_POST["_wp_http_referer"], $arr_postinfo);
1036 - if (isset($arr_postinfo["mb_type"])) {
1037 - $file_src = wp_get_attachment_url($id);
1038 - $thumbnail = wp_get_attachment_image($id, array(80, 60), true);
1039 - $file_name = get_the_title($id);
1040 -
1041 - if (preg_match('/^.*?\.(\w+)$/', get_attached_file($id), $matches))
1042 - $file_type = esc_html(strtoupper($matches[1]));
1043 - else
1044 - $file_type = strtoupper(str_replace('image/', '', get_post_mime_type($id)));
1045 -
1046 - ?>
1047 - <script type="text/javascript">
1048 -
1049 - self.parent.window.<?php echo $arr_postinfo["mb_type"];?>.val('<?php echo $id; ?>');
1050 - self.parent.window.<?php echo $arr_postinfo["mb_info_div"];?>.html('<?php echo $thumbnail ?><p><span class="file-name"><?php echo $file_name; ?></span><span class="file-type"><?php echo $file_type; ?></span><span class="wck-remove-upload"><?php _e( 'Remove', 'wck' )?></span></p>');
1051 -
1052 - self.parent.tb_remove();
1053 -
1054 - </script>
1055 - <?php
1056 - exit;
1057 - }
1058 - }
1059 - else{
1060 - return $html;
1061 - }
1062 -
1063 - }
1064 -
1065 - /* WPML Compatibility */
1066 -
1067 - /**
1068 - * Function that ads the side metabox with the Syncronize translation button.
1069 - * The meta box is only added if the lang attribute is set and
1070 - * if any of the custom fields has the 'wckwpml' prefix.
1071 - */
1072 - function wck_add_sync_translation_metabox(){
1073 - global $post;
1074 -
1075 - if( isset( $_GET['lang'] ) ){
1076 -
1077 - $has_wck_with_unserialize_fields = false;
1078 - $custom_field_keys = get_post_custom_keys( $post->ID );
1079 - if( !empty( $custom_field_keys ) ){
1080 - foreach( $custom_field_keys as $custom_field_key ){
1081 - $custom_field_key = explode( '_', $custom_field_key );
1082 - if( $custom_field_key[0] == 'wckwpml' ){
1083 - $has_wck_with_unserialize_fields = true;
1084 - break;
1085 - }
1086 - }
1087 - }
1088 -
1089 - if($has_wck_with_unserialize_fields){
1090 - add_meta_box( 'wck_sync_translation', __( 'Syncronize WCK', 'wck' ), array( &$this, 'wck_add_sync_box' ), $post->post_type, 'side', 'low' );
1091 - }
1092 -
1093 - }
1094 - }
1095 -
1096 - /**
1097 - * Callback for the add_meta_box function that ads the "Syncronize WCK Translation" button.
1098 - */
1099 - function wck_add_sync_box(){
1100 - global $post;
1101 - ?>
1102 - <span id="wck_sync" class="button" onclick="wckSyncTranslation(<?php echo $post->ID; ?>)"><?php _e( 'Syncronize WCK Translation', 'wck' ) ?></span>
1103 - <?php
1104 - }
1105 -
1106 -
1107 -
1108 - /**
1109 - * Function that recreates the serialized metas from the individual meta fields.
1110 - */
1111 - function wck_sync_translation_ajax(){
1112 - if( !empty( $_POST['id'] ) )
1113 - $post_id = $_POST['id'];
1114 - else
1115 - $post_id = '';
1116 -
1117 - /* get all the custom fields keys for the post */
1118 - $custom_field_keys = (array)get_post_custom_keys( $post_id );
1119 -
1120 - /* initialize an array that will hold all the arrays for all the wck boxes */
1121 - $wck_array = array();
1122 -
1123 - /* go through all the custom fields and if it is a custom field created automaticaly for the translation add it to the $wck_array array*/
1124 - if( !empty( $custom_field_keys ) ){
1125 - foreach( $custom_field_keys as $cf ){
1126 -
1127 - $cf_name_array = explode( '_', $cf );
1128 -
1129 - /* a custom field added for the translation will have this form
1130 - 'wckwpml_{meta name}_{field name}_{entry position}_{field position}'
1131 - */
1132 - if( count( $cf_name_array ) >= 5 ){
1133 -
1134 - $cf_name = implode( '_', array_slice( $cf_name_array, 1, -3 ) );
1135 -
1136 - if( $cf_name_array[0] == 'wckwpml' ){
1137 -
1138 - $wck_key = $cf_name_array[ count($cf_name_array) -3 ];
1139 - $wck_position = $cf_name_array[ count($cf_name_array) -2 ];
1140 - $wck_field_position = $cf_name_array[ count($cf_name_array) -1 ];
1141 -
1142 - /* "$wck_position - 1" is required because fields in wck by default start at 0 and the additional
1143 - translation fields start at 1 */
1144 - $wck_array[$cf_name][$wck_position - 1][$wck_field_position][$wck_key] = get_post_meta($post_id,$cf,true);
1145 -
1146 - }
1147 - }
1148 - }
1149 - }
1150 -
1151 -
1152 -
1153 - if( !empty( $wck_array ) ){
1154 - /* sort the array so that the entry order and fields order are synced */
1155 - self::deep_ksort( $wck_array );
1156 -
1157 - /* remove the field position level in the array because it was added just so we could keep the field
1158 - order in place */
1159 - $wck_array = self::wck_reconstruct_array($wck_array);
1160 -
1161 - /* add the translated meta to the post */
1162 - foreach( $wck_array as $wck_key => $wck_meta ){
1163 - update_post_meta( $post_id, $wck_key, $wck_meta );
1164 - }
1165 - echo('syncsuccess');
1166 - }
1167 -
1168 - exit;
1169 - }
1170 -
1171 - /**
1172 - * Function that deep sorts a multy array by numeric key
1173 - */
1174 - function deep_ksort(&$arr) {
1175 - ksort($arr);
1176 - if( !empty( $arr ) ){
1177 - foreach ($arr as &$a) {
1178 - if (is_array($a) && !empty($a)) {
1179 - self::deep_ksort($a);
1180 - }
1181 - }
1182 - }
1183 - }
1184 -
1185 - /**
1186 - * Function that removes the field position level
1187 - */
1188 - function wck_reconstruct_array($wck_array){
1189 - if( !empty( $wck_array ) ){
1190 - foreach( $wck_array as $wck_array_key => $wck_meta ){
1191 - if( !empty( $wck_meta ) ){
1192 - foreach( $wck_meta as $wck_meta_key => $wck_entry ){
1193 - if( !empty( $wck_entry ) ){
1194 - foreach( $wck_entry as $wck_entry_key => $wck_field ){
1195 - $wck_array[$wck_array_key][$wck_meta_key][key($wck_field)] = current($wck_field);
1196 - unset($wck_array[$wck_array_key][$wck_meta_key][$wck_entry_key]);
1197 - }
1198 - }
1199 - }
1200 - }
1201 - }
1202 - }
1203 - return $wck_array;
1204 - }
1205 -
1206 -
1207 - function wck_get_meta_boxes( $screen = null ){
1208 - global $wp_meta_boxes, $wck_objects;
1209 -
1210 - if ( empty( $screen ) )
1211 - $screen = get_current_screen();
1212 - elseif ( is_string( $screen ) )
1213 - $screen = convert_to_screen( $screen );
1214 -
1215 - $page = $screen->id;
1216 -
1217 - $wck_meta_boxes = array();
1218 -
1219 - if( !empty( $wck_objects ) && !empty( $wp_meta_boxes[$page]['normal']['low'] ) ){
1220 - foreach( $wck_objects as $key => $wck_object ){
1221 - if( array_key_exists( $key, $wp_meta_boxes[$page]['normal']['low'] ) )
1222 - $wck_meta_boxes[] = $key;
1223 - }
1224 - }
1225 -
1226 - return $wck_meta_boxes;
1227 - }
1228 -
1229 -
1230 - /**
1231 - * The function used to generate slugs in WCK
1232 - *
1233 - * @since 1.1.1
1234 - *
1235 - * @param string $string The input string from which we generate the slug
1236 - * @return string $slug The henerated slug
1237 - */
1238 - static function wck_generate_slug( $string, $details = array() ){
1239 - if( !empty( $details['slug'] ) )
1240 - $slug = $details['slug'];
1241 - else
1242 - $slug = rawurldecode( sanitize_title_with_dashes( remove_accents( $string ) ) );
1243 - return $slug;
1244 - }
1245 -}
1246 -
1247 -
1248 -/*
1249 -Helper class that creates admin menu pages ( both top level menu pages and submenu pages )
1250 -Default Usage:
1251 -
1252 -$args = array(
1253 - 'page_type' => 'menu_page',
1254 - 'page_title' => '',
1255 - 'menu_title' => '',
1256 - 'capability' => '',
1257 - 'menu_slug' => '',
1258 - 'icon_url' => '',
1259 - 'position' => '',
1260 - 'parent_slug' => ''
1261 - );
1262 -
1263 -'page_type' (string) (required) The type of page you want to add. Possible values: 'menu_page', 'submenu_page'
1264 -'page_title' (string) (required) The text to be displayed in the title tags and header of
1265 - the page when the menu is selected
1266 -'menu_title' (string) (required) The on-screen name text for the menu
1267 -'capability' (string) (required) The capability required for this menu to be displayed to
1268 - the user.
1269 -'menu_slug' (string) (required) The slug name to refer to this menu by (should be unique
1270 - for this menu).
1271 -'icon_url' (string) (optional for 'page_type' => 'menu_page') The url to the icon to be used for this menu.
1272 - This parameter is optional. Icons should be fairly small, around 16 x 16 pixels
1273 - for best results.
1274 -'position' (integer) (optional for 'page_type' => 'menu_page') The position in the menu order this menu
1275 - should appear.
1276 - By default, if this parameter is omitted, the menu will appear at the bottom
1277 - of the menu structure. The higher the number, the lower its position in the menu.
1278 - WARNING: if 2 menu items use the same position attribute, one of the items may be
1279 - overwritten so that only one item displays!
1280 -'parent_slug' (string) (required for 'page_type' => 'submenu_page' ) The slug name for the parent menu
1281 - (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
1282 -'priority' (int) (optional) How important your function is. Alter this to make your function
1283 - 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.
1284 -
1285 -public $hookname ( for required for 'page_type' => 'menu_page' ) string used internally to
1286 - track menu page callbacks for outputting the page inside the global $menu array
1287 - ( for required for 'page_type' => 'submenu_page' ) The resulting page's hook_suffix,
1288 - or false if the user does not have the capability required.
1289 -*/
1290 -
1291 -class WCK_Page_Creator_PB{
1292 -
1293 - private $defaults = array(
1294 - 'page_type' => 'menu_page',
1295 - 'page_title' => '',
1296 - 'menu_title' => '',
1297 - 'capability' => '',
1298 - 'menu_slug' => '',
1299 - 'icon_url' => '',
1300 - 'position' => '',
1301 - 'parent_slug' => '',
1302 - 'priority' => 10,
1303 - 'network_page' => false
1304 - );
1305 - private $args;
1306 - public $hookname;
1307 -
1308 -
1309 - /* Constructor method for the class. */
1310 - function __construct( $args ) {
1311 -
1312 - /* Global that will hold all the arguments for all the menu pages */
1313 - global $wck_pages;
1314 -
1315 - /* Merge the input arguments and the defaults. */
1316 - $this->args = wp_parse_args( $args, $this->defaults );
1317 -
1318 - /* Add the settings for this page to the global object */
1319 - $wck_pages[$this->args['page_title']] = $this->args;
1320 -
1321 - if( !$this->args['network_page'] ){
1322 - /* Hook the page function to 'admin_menu'. */
1323 - add_action( 'admin_menu', array( &$this, 'wck_page_init' ), $this->args['priority'] );
1324 - }
1325 - else{
1326 - /* Hook the page function to 'admin_menu'. */
1327 - add_action( 'network_admin_menu', array( &$this, 'wck_page_init' ), $this->args['priority'] );
1328 - }
1329 - }
1330 -
1331 - /**
1332 - * Function that creates the admin page
1333 - */
1334 - function wck_page_init(){
1335 - global $pb_wck_pages_hooknames;
1336 -
1337 - /* Create the page using either add_menu_page or add_submenu_page functions depending on the 'page_type' parameter. */
1338 - if( $this->args['page_type'] == 'menu_page' ){
1339 - $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'] );
1340 -
1341 - $pb_wck_pages_hooknames[$this->args['menu_slug']] = $this->hookname;
1342 - }
1343 - else if( $this->args['page_type'] == 'submenu_page' ){
1344 - $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' ) );
1345 -
1346 - $pb_wck_pages_hooknames[$this->args['menu_slug']] = $this->hookname;
1347 - }
1348 -
1349 - do_action( 'WCK_Page_Creator_PB_after_init', $this->hookname );
1350 -
1351 - /* Create a hook for adding meta boxes. */
1352 - add_action( "load-{$this->hookname}", array( &$this, 'wck_settings_page_add_meta_boxes' ) );
1353 - /* Load the JavaScript needed for the screen. */
1354 - add_action( 'admin_enqueue_scripts', array( &$this, 'wck_page_enqueue_scripts' ) );
1355 - add_action( "admin_head-{$this->hookname}", array( &$this, 'wck_page_load_scripts' ) );
1356 - }
1357 -
1358 - /**
1359 - * Do action 'add_meta_boxes'. This hook isn't executed by default on a admin page so we have to add it.
1360 - */
1361 - function wck_settings_page_add_meta_boxes() {
1362 - do_action( 'add_meta_boxes', $this->hookname );
1363 - }
1364 -
1365 - /**
1366 - * Loads the JavaScript files required for managing the meta boxes on the theme settings
1367 - * page, which allows users to arrange the boxes to their liking.
1368 - *
1369 - * @global string $bareskin_settings_page. The global setting page (returned by add_theme_page in function
1370 - * bareskin_settings_page_init ).
1371 - * @since 1.0.0
1372 - * @param string $hook The current page being viewed.
1373 - */
1374 - function wck_page_enqueue_scripts( $hook ) {
1375 - if ( $hook == $this->hookname ) {
1376 - wp_enqueue_script( 'common' );
1377 - wp_enqueue_script( 'wp-lists' );
1378 - wp_enqueue_script( 'postbox' );
1379 - }
1380 - }
1381 -
1382 - /**
1383 - * Loads the JavaScript required for toggling the meta boxes on the theme settings page.
1384 - *
1385 - * @global string $bareskin_settings_page. The global setting page (returned by add_theme_page in function
1386 - * bareskin_settings_page_init ).
1387 - * @since 1.0.0
1388 - */
1389 - function wck_page_load_scripts() {
1390 - ?>
1391 - <script type="text/javascript">
1392 - //<![CDATA[
1393 - jQuery(document).ready( function($) {
1394 - $('.if-js-closed').removeClass('if-js-closed').addClass('closed');
1395 - postboxes.add_postbox_toggles( '<?php echo $this->hookname; ?>' );
1396 - });
1397 - //]]>
1398 - </script><?php
1399 - }
1400 -
1401 - /**
1402 - * Outputs default template for the page. It contains placeholders for metaboxes. It also
1403 - * provides two action hooks 'wck_before_meta_boxes' and 'wck_after_meta_boxes'.
1404 - */
1405 - function wck_page_template(){
1406 - ?>
1407 - <div class="wrap">
1408 -
1409 - <?php if( !empty( $this->args['page_icon'] ) ): ?>
1410 - <div id="<?php echo $this->args['menu_slug'] ?>-icon" style="background: url('<?php echo $this->args['page_icon']; ?>') no-repeat;" class="icon32">
1411 - <br/>
1412 - </div>
1413 - <?php endif; ?>
1414 -
1415 - <h2><?php echo $this->args['page_title'] ?></h2>
1416 -
1417 - <div id="poststuff">
1418 -
1419 - <?php wp_nonce_field( 'closedpostboxes', 'closedpostboxesnonce', false ); ?>
1420 - <?php wp_nonce_field( 'meta-box-order', 'meta-box-order-nonce', false ); ?>
1421 -
1422 - <?php do_action( 'wck_before_meta_boxes', $this->hookname ); ?>
1423 -
1424 - <div class="metabox-holder">
1425 - <div class="wck-post-body">
1426 - <div class="post-box-container column-1 normal">
1427 - <?php do_action( 'wck_before_column1_metabox_content', $this->hookname ); ?>
1428 - <?php do_meta_boxes( $this->hookname, 'normal', null ); ?>
1429 - <?php do_action( 'wck_after_column1_metabox_content', $this->hookname ); ?>
1430 - </div>
1431 - <div class="post-box-container column-3 advanced">
1432 - <?php do_action( 'wck_before_column3_metabox_content', $this->hookname ); ?>
1433 - <?php do_meta_boxes( $this->hookname, 'advanced', null ); ?>
1434 - <?php do_action( 'wck_after_column3_metabox_content', $this->hookname ); ?>
1435 - </div>
1436 - </div>
1437 - <div class="post-box-container column-2 side"><?php do_meta_boxes( $this->hookname, 'side', null ); ?></div>
1438 -
1439 - </div>
1440 -
1441 - <?php do_action( 'wck_after_meta_boxes', $this->hookname ); ?>
1442 -
1443 - </div><!-- #poststuff -->
1444 -
1445 - </div><!-- .wrap -->
1446 - <?php
1447 - }
1448 -}
1449 -?>
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 +?>