Commit 86df505b authored by Kevin Stover's avatar Kevin Stover

Merge branch 'develop'

parents 4a408c7b 0d6a638d
......@@ -4,7 +4,7 @@
Tags: form, forms, contact form, custom form, form builder, form creator, form manager, form creation, contact forms, custom forms, forms builder, forms creator, forms manager, forms creation, form administration,
Requires at least: 4.5
Tested up to: 4.7.1
Stable tag: 3.0.24
Stable tag: 3.0.25
License: GPLv2 or later
With a simple drag and drop interface you can create contact forms, email subscription forms, order forms, payment forms, and any other type of form for your WordPress site.
......
......@@ -69,7 +69,7 @@ define( ['models/fields/fieldCollection', 'models/fields/fieldModel'], function(
* @param string action action context - are we performing a higher level action? i.e. duplicate
*/
addField: function( data, silent, renderTrigger, action ) {
/*
* Set our fields 'adding' value to true. This enables our add field animation.
*/
......@@ -88,6 +88,8 @@ define( ['models/fields/fieldCollection', 'models/fields/fieldModel'], function(
var model = data;
}
// console.log( model );
/*
* TODO: Add an nfRadio message filter for the model variable.
* Currently, we manually replace for saved fields; this should be moved to a separate controller.
......
......@@ -2,7 +2,7 @@
* When we add a new field, update its key.
*
* When we change the key, update any refs to the key.
*
*
* @package Ninja Forms builder
* @subpackage Fields
* @copyright (c) 2015 WP Ninjas
......@@ -26,7 +26,7 @@ define( [], function() {
/**
* Add a key to our new field model.
*
*
* @since 3.0
* @param backbone.model model new field model
* @return void
......@@ -52,17 +52,17 @@ define( [], function() {
* When we're editing settings, we expect the edits to fire one at a time.
* Since we're calling this in the middle of our label update, anything that inquires about what has changed after we set our key will see both label and key.
* We need to remove the label from our model.changed property so that all that has changed is the key.
*
*
*/
delete model.changed.label;
var key = this.keyExists( model.get( 'label' ) );
model.set( 'key', key );
model.set( 'key', key );
}
},
/**
* When a field key is updated, find any merge tags using the key and update them.
*
*
* @since 3.0
* @param backbone.model model field model
* @return void
......@@ -84,6 +84,14 @@ define( [], function() {
var error = false;
if ( '' == jQuery.trim( key ) ) {
error = 'Field keys can\'t be empty. Please enter a key.';
} else if ( key != key.toLowerCase() ) {
error = 'Field keys must be lowercase.';
} else if ( key != key.replace( ' ', '_' ) ) {
error = 'Field keys must cannot use spaces. Separate with "_" instead.';
} else if ( '_' == key.slice( -1 ) ) {
error = 'Field keys cannot end with a "_"';
} else if ( key != this.slugify( key ) ) {
error = 'Invalid Format.';
} else if ( key != this.keyExists( key, dataModel ) ) {
error = 'Field keys must be unique. Please enter another key.'
}
......@@ -97,7 +105,7 @@ define( [], function() {
},
keyExists: function( key, dataModel ) {
var newKey = jQuery.slugify( key, { separator: '_' } );
var newKey = this.slugify( key );
if ( 0 != newKey.length ) {
key = newKey;
}
......@@ -110,12 +118,16 @@ define( [], function() {
x++;
}
} );
key = testKey;
return key;
},
slugify: function( string ){
return jQuery.slugify( string, { separator: '_' } )
}
});
return controller;
} );
\ No newline at end of file
} );
......@@ -75,7 +75,7 @@ define( [
* @return void
*/
addField: function( e ) {
var type = jQuery( e.target ).data( 'id' );
var type = jQuery( e.target ).data( 'id' );
if( e.shiftKey ){
nfRadio.channel( 'fields' ).request( 'add:stagedField', type );
......@@ -121,7 +121,6 @@ define( [
* @return backbone.collection
*/
getSavedFields: function() {
console.log( this.sections.get( 'saved' ) );
this.sections.get( 'saved' );
}
});
......
/**
* Collection that holds our field models.
* Collection that holds our field models.
* This is the actual field data created by the user.
*
* We listen to the add and remove events so that we can push the new id to either the new fields or removed fields property.
*
*
* @package Ninja Forms builder
* @subpackage Fields
* @copyright (c) 2015 WP Ninjas
......@@ -12,7 +12,9 @@
define( ['models/fields/fieldModel'], function( fieldModel ) {
var collection = Backbone.Collection.extend( {
model: fieldModel,
comparator: 'order',
comparator: function( model ){
return parseInt( model.get( 'order' ) );
},
tmpNum: 1,
initialize: function() {
......@@ -28,7 +30,7 @@ define( ['models/fields/fieldModel'], function( fieldModel ) {
/**
* When we add a field, push the id onto our new fields property.
* This lets us tell the server that this is a new field to be added rather than a field to be updated.
*
*
* @since 3.0
* @param void
*/
......@@ -38,7 +40,7 @@ define( ['models/fields/fieldModel'], function( fieldModel ) {
/**
* When we remove a field, push the id onto our removed fields property.
*
*
* @since 3.0
* @param void
*/
......@@ -55,9 +57,9 @@ define( ['models/fields/fieldModel'], function( fieldModel ) {
if ( 0 == this.length ) {
var order = 0;
} else {
var order = this.at( this.length -1 ).get( 'order' ) + 1;
var order = this.at( this.length -1 ).get( 'order' ) + 1;
}
model.set( 'order', order, { silent: true } );
this.add( model );
},
......@@ -71,4 +73,4 @@ define( ['models/fields/fieldModel'], function( fieldModel ) {
}
} );
return collection;
} );
\ No newline at end of file
} );
......@@ -32,6 +32,13 @@ define( [], function() {
}
}, this );
/*
* If our field type is a saved field, set our field type to the actual field type
*/
if ( 'saved' == fieldType.get( 'section' ) ) {
this.set( 'type', fieldType.get( 'type' ) );
}
/*
* Trigger an init event on three channels:
*
......
......@@ -2,7 +2,20 @@ define( [], function() {
var view = Marionette.ItemView.extend({
tagName: 'div',
className: 'nf-error',
template: '#tmpl-nf-edit-setting-option-repeater-error'
template: '#tmpl-nf-edit-setting-option-repeater-error',
templateHelpers: function() {
var that = this;
return {
renderErrors: function() {
if ( 'undefined' != typeof that.errors ) {
return that.errors[ Object.keys( errors )[0] ];
} else {
return '';
}
}
}
}
});
return view;
......
......@@ -28,7 +28,7 @@ define([], function() {
var selected = _.filter( model.get( 'options' ), function( opt ) { return 1 == opt.selected } );
selected = _.map( selected, function( opt ) { return opt.value } );
var value = selected;
} else {
} else if ( 'listradio' !== model.get( 'type' ) ) {
/*
* Check to see if we have a selected value.
*/
......
......@@ -64,6 +64,13 @@ define([], function() {
return false;
}
/*
* Send out a radio message saying that we're about to begin submitting.
* First we send on the generic forms channel, and then on the form-specific channel.
*/
nfRadio.channel( 'forms' ).trigger( 'after:submitValidation', formModel );
nfRadio.channel( 'form-' + formModel.get( 'id' ) ).trigger( 'after:submitValidation', formModel );
/*
* Actually submit our form, and send out a message with our response.
*/
......
......@@ -19,6 +19,15 @@ define([], function() {
} );
}
if ( 'undefined' != typeof response.errors.last ) {
if( 'undefined' != typeof response.errors.last.message ) {
var style = 'background: rgba( 255, 207, 115, .5 ); color: #FFA700; display: block;';
console.log( '%c NINJA FORMS SUPPORT: SERVER ERROR', style );
console.log( response.errors.last.message );
console.log( '%c END SERVER ERROR MESSAGE', style );
}
}
/**
* TODO: This needs to be re-worked for backbone. It's not dynamic enough.
*/
......@@ -31,4 +40,4 @@ define([], function() {
});
return controller;
} );
\ No newline at end of file
} );
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -265,7 +265,7 @@ class Ninja_Forms {
// Plugin version
if ( ! defined( 'NF_PLUGIN_VERSION' ) )
define( 'NF_PLUGIN_VERSION', '3.0.24' );
define( 'NF_PLUGIN_VERSION', '3.0.25' );
// Plugin Folder Path
if ( ! defined( 'NF_PLUGIN_DIR' ) )
......
......@@ -363,7 +363,13 @@ class NF_AJAX_Controllers_Submission extends NF_Abstracts_Controller
{
$error = error_get_last();
if( $error !== NULL && in_array( $error[ 'type' ], array( E_ERROR, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR ) ) ) {
$this->_errors[ 'form' ][ 'last' ] = __( 'The server encountered an error during processing.', 'ninja-forms' );
if( current_user_can( 'manage_options' ) && isset( $error[ 'message' ] ) ){
$this->_errors[ 'form' ][ 'last_admin' ] = '<pre>' . $error[ 'message' ] . '</pre>';
}
$this->_errors[ 'last' ] = $error;
$this->_respond();
}
......@@ -389,4 +395,4 @@ class NF_AJAX_Controllers_Submission extends NF_Abstracts_Controller
if( ! isset( $this->_form_data[ 'settings' ][ 'is_preview' ] ) ) return false;
return $this->_form_data[ 'settings' ][ 'is_preview' ];
}
}
\ No newline at end of file
}
......@@ -287,7 +287,7 @@ abstract class NF_Abstracts_Field
public static function sort_by_order( $a, $b )
{
return strcmp( $a->get_setting( 'order' ), $b->get_setting( 'order' ) );
return $a->get_setting( 'order' ) - $b->get_setting( 'order' );
}
public function localize_settings( $settings, $form_id ) {
......
......@@ -38,9 +38,11 @@ abstract class NF_Abstracts_List extends NF_Abstracts_Field
$field = Ninja_Forms()->form()->get_field( $id );
$options = '<option>--</option>';
foreach( $field->get_setting( 'options' ) as $option ){
$selected = ( $value == $option[ 'value' ] ) ? "selected" : '';
$options .= "<option value='{$option[ 'value' ]}' $selected>{$option[ 'label' ]}</option>";
if ( is_array( $field->get_setting( 'options' ) ) ) {
foreach( $field->get_setting( 'options' ) as $option ){
$selected = ( $value == $option[ 'value' ] ) ? "selected" : '';
$options .= "<option value='{$option[ 'value' ]}' $selected>{$option[ 'label' ]}</option>";
}
}
return "<select class='widefat' name='fields[$id]' id=''>$options</select>";
......
......@@ -20,6 +20,11 @@ class NF_Abstracts_ModelFactory
*/
protected $_object;
/**
* Form
*/
protected $_form;
/**
* Fields
*
......@@ -60,7 +65,7 @@ class NF_Abstracts_ModelFactory
{
$this->_db = $db;
$this->_object = new NF_Database_Models_Form( $this->_db, $id );
$this->_object = $this->_form = new NF_Database_Models_Form( $this->_db, $id );
$form_cache = get_option( 'nf_form_' . $id, false );
......@@ -78,7 +83,9 @@ class NF_Abstracts_ModelFactory
*/
public function get()
{
return $this->_object;
$object = $this->_object;
$this->_object = $this->_form;
return $object;
}
/**
......@@ -121,6 +128,7 @@ class NF_Abstracts_ModelFactory
public function import_form( $import, $id = FALSE, $is_conversion = FALSE )
{
if( ! is_array( $import ) ){
$data = WPN_Helper::utf8_decode( json_decode( html_entity_decode( $import ), true ) );
if( ! is_array( $data ) ) {
......@@ -128,7 +136,7 @@ class NF_Abstracts_ModelFactory
}
if( ! is_array( $data ) ){
$data = maybe_unserialize( $import );
$data = WPN_Helper::maybe_unserialize( $import );
if( ! is_array( $data ) ){
return false;
......@@ -181,9 +189,12 @@ class NF_Abstracts_ModelFactory
*/
public function get_fields( $where = array(), $fresh = FALSE)
{
if( $where || $fresh || ! $this->_fields ){
$form_id = $this->_object->get_id();
$field_by_key = array();
$form_id = $this->_object->get_id();
if( $where || $fresh || ! $this->_fields ){
$form_cache = get_option( 'nf_form_' . $form_id, false );
......@@ -194,17 +205,32 @@ class NF_Abstracts_ModelFactory
foreach ($fields as $field) {
$this->_fields[$field->get_id()] = $field;
$field_by_key[ $field->get_setting( 'key' ) ] = $field;
}
} else {
foreach( $form_cache[ 'fields' ] as $cached_field ){
$field = Ninja_Forms()->form( $form_id )->get_field( $cached_field[ 'id' ] );
$field->update_settings( $cached_field[ 'settings' ] );
$this->_fields[$field->get_id()] = $field;
$field_by_key[ $field->get_setting( 'key' ) ] = $field;
}
}
/*
* If a filter is registered to modify field order, then use that filter.
* If not, then usort??.
*/
$order = apply_filters( 'ninja_forms_get_fields_sorted', array(), $this->_fields, $field_by_key, $form_id );
if ( ! empty( $order ) ) {
$this->_fields = $order;
}
}
usort( $this->_fields, "NF_Abstracts_Field::sort_by_order" );
/*
* Broke the sub edit screen order when I have this enabled.
*/
// usort( $this->_fields, "NF_Abstracts_Field::sort_by_order" );
return $this->_fields;
}
......@@ -385,15 +411,15 @@ class NF_Abstracts_ModelFactory
* @param bool|FALSE $fresh
* @return array
*/
public function get_subs( $where = array(), $fresh = FALSE )
public function get_subs( $where = array(), $fresh = FALSE, $sub_ids = array() )
{
if( $where || $fresh || ! $this->_objects ){
if( $where || $fresh || $sub_ids || ! $this->_objects ){
$form_id = $this->_object->get_id();
$model_shell = new NF_Database_Models_Submission( 0 );
$objects = $model_shell->find( $form_id, $where );
$objects = $model_shell->find( $form_id, $where, $sub_ids );
foreach( $objects as $object ){
$this->_objects[ $object->get_id() ] = $object;
......
......@@ -17,6 +17,7 @@ class NF_Admin_CPT_DownloadAllSubmissions extends NF_Step_Processing {
}
public function loading() {
$subs_per_step = apply_filters( 'ninja_forms_export_subs_per_step', 10 );
$form_id = isset( $this->args['form_id'] ) ? absint( $this->args['form_id'] ) : 0;
if ( empty( $form_id ) ) {
......@@ -27,7 +28,7 @@ class NF_Admin_CPT_DownloadAllSubmissions extends NF_Step_Processing {
$sub_count = $this->get_sub_count( $form_id );
if( empty( $this->total_steps ) || $this->total_steps <= 1 ) {
$this->total_steps = round( ( $sub_count / 250 ), 0 ) + 2;
$this->total_steps = round( ( $sub_count / $subs_per_step ), 0 ) + 2;
}
$args = array(
......@@ -47,6 +48,8 @@ class NF_Admin_CPT_DownloadAllSubmissions extends NF_Step_Processing {
wp_die( __( 'Invalid form id', 'ninja-forms' ) );
}
$subs_per_step = apply_filters( 'ninja_forms_export_subs_per_step', 10 );
$this->args[ 'filename' ] = wp_kses_post( $this->args[ 'filename' ] );
$exported_subs = get_user_option( get_current_user_id(), 'nf_download_all_subs_ids' );
......@@ -60,7 +63,7 @@ class NF_Admin_CPT_DownloadAllSubmissions extends NF_Step_Processing {
}
$args = array(
'posts_per_page' => 250,
'posts_per_page' => $subs_per_step,
'paged' => $this->step,
'post_type' => 'nf_sub',
'meta_query' => array(
......
......@@ -142,8 +142,7 @@ class NF_Admin_CPT_Submission
$form_cache = get_option( 'nf_form_' . $form_id );
$form_fields = $form_cache[ 'fields' ];
if( empty( $form_fields ) ) $form_fields = Ninja_Forms()->form( $form_id )->get_fields();
$form_fields = Ninja_Forms()->form( $form_id )->get_fields();
foreach( $form_fields as $field ) {
......@@ -264,8 +263,6 @@ class NF_Admin_CPT_Submission
$fields = Ninja_Forms()->form( $form_id )->get_fields();
usort( $fields, array( $this, 'sort_fields' ) );
$hidden_field_types = apply_filters( 'nf_sub_hidden_field_types', array() );
Ninja_Forms::template( 'admin-metabox-sub-fields.html.php', compact( 'fields', 'sub', 'hidden_field_types' ) );
......
......@@ -217,8 +217,9 @@ final class NF_Database_Models_Submission
* @param array $where
* @return array
*/
public function find( $form_id, array $where = array() )
public function find( $form_id, array $where = array(), array $ids = array() )
{
$this->_form_id = $form_id;
$args = array(
......@@ -227,6 +228,10 @@ final class NF_Database_Models_Submission
'meta_query' => $this->format_meta_query( $where )
);
if ( ! empty ( $ids ) ) {
$args[ 'post__in' ] = $ids;
}
$subs = get_posts( $args );
$class = get_class( $this );
......@@ -283,7 +288,6 @@ final class NF_Database_Models_Submission
{
$date_format = Ninja_Forms()->get_setting( 'date_format' );
/*
* Labels
*/
......@@ -298,7 +302,14 @@ final class NF_Database_Models_Submission
$fields = Ninja_Forms()->form( $form_id )->get_fields();
usort( $fields, array( 'NF_Database_Models_Submission', 'sort_fields' ) );
/*
* If we are using an add-on that filters our field order, we don't want to call sort again.
*
* TODO: This is probably not the most effecient way to handle this. It should be re-thought.
*/
if ( ! has_filter( 'ninja_forms_get_fields_sorted' ) ) {
usort( $fields, array( 'NF_Database_Models_Submission', 'sort_fields' ) );
}
$hidden_field_types = apply_filters( 'nf_sub_hidden_field_types', array() );
......@@ -313,8 +324,7 @@ final class NF_Database_Models_Submission
} else {
$field_labels[ $field->get_id() ] = $field->get_setting( 'label' );
}
$fields_order_by[] = "'_field_{$field->get_id()}'";
$fields_order_by[] = $field->get_id();
if( has_filter( 'ninja_forms_subs_export_field_value_' . $field->get_setting( 'type' ) ) ){
// $i represents the relative field order for later reference when running filters on a specific value.
$field_type_filters[ $i ] = $field->get_setting( 'type' );
......@@ -326,14 +336,10 @@ final class NF_Database_Models_Submission
* Submissions
*/
$value_array = array();
$subs = Ninja_Forms()->form( $form_id )->get_subs();
$subs = Ninja_Forms()->form( $form_id )->get_subs( array(), FALSE, $sub_ids );
foreach( $subs as $sub ){
if( ! in_array( $sub->get_id(), $sub_ids ) ) continue;
$value[ '_seq_num' ] = $sub->get_seq_num();
$value[ '_date_submitted' ] = $sub->get_sub_date( $date_format );
......@@ -355,7 +361,7 @@ final class NF_Database_Models_Submission
$field_value = implode(' | ', $field_value);
}
$value[$field_id] = $field_value;
$value[$field_id] = maybe_unserialize( $field_value );
}
$value_array[] = $value;
......@@ -366,15 +372,17 @@ final class NF_Database_Models_Submission
*/
global $wpdb;
$field_values = $wpdb->get_col( $wpdb->prepare("
SELECT `meta_value`
FROM `" . $wpdb->postmeta . "`
WHERE post_id = %d
ORDER BY FIELD( meta_key, " . implode( ',', $fields_order_by ) . " )
", $sub->get_id() ) );
array_shift( $field_values ); // Remove form ID value from array.
array_shift( $field_values ); // Remove duplicate sequence number value from array.
$field_values = $wpdb->get_col( "
SELECT IFNULL( meta_value, '' )
FROM ". $wpdb->postmeta . " as postmeta
RIGHT JOIN (
SELECT id FROM wp_nf3_fields
WHERE id IN ( " . implode( ',', $fields_order_by ) . " )
ORDER BY FIELD( id, " . implode( ',', $fields_order_by ) . " )
) as fields
ON postmeta.meta_key LIKE CONCAT( '%', fields.id, '%' )
AND postmeta.post_id = " . $sub->get_id()
);
if( is_array( $field_type_filters ) && ! empty( $field_type_filters ) ){
foreach( $field_type_filters as $i => $type ){
......
......@@ -118,9 +118,7 @@ final class NF_Display_Render
$after_form = apply_filters( 'ninja_forms_display_after_form', '', $form_id );
$form->update_setting( 'afterForm', $after_form );
$form_cache = get_option( 'nf_form_' . $form_id, false );
$form_fields = $form_cache[ 'fields' ];
if( empty( $form_fields ) ) $form_fields = Ninja_Forms()->form( $form_id )->get_fields();
$form_fields = Ninja_Forms()->form( $form_id )->get_fields();
$fields = array();
if( empty( $form_fields ) ){
......@@ -259,12 +257,12 @@ final class NF_Display_Render
$thousands_sep = $wp_locale->number_format[ 'thousands_sep'];
$decimal_point = $wp_locale->number_format[ 'decimal_point' ];
// TODO: Find a better way to do this.
if ('shipping' == $settings['type']) {
$settings[ 'shipping_cost' ] = preg_replace ('/[^\d,\.]/', '', $settings[ 'shipping_cost' ] );
$settings[ 'shipping_cost' ] = str_replace( Ninja_Forms()->get_setting( 'currency_symbol' ), '', $settings[ 'shipping_cost' ] );
$settings[ 'shipping_cost' ] = str_replace( $decimal_point, '||', $settings[ 'shipping_cost' ] );
$settings[ 'shipping_cost' ] = str_replace( $thousands_sep, '', $settings[ 'shipping_cost' ] );
$settings[ 'shipping_cost' ] = str_replace( '||', '.', $settings[ 'shipping_cost' ] );
......@@ -325,17 +323,17 @@ final class NF_Display_Render
<script>
var formDisplay = 1;
// Maybe initialize nfForms object
/* Maybe initialize nfForms object */
var nfForms = nfForms || [];
// Build Form Data
/* Build Form Data */
var form = [];
form.id = '<?php echo $form_id; ?>';
form.settings = <?php echo wp_json_encode( $form->get_settings() ); ?>;
form.fields = <?php echo wp_json_encode( $fields ); ?>;
// Add Form Data to nfForms object
/* Add Form Data to nfForms object */
nfForms.push( form );
</script>
......
......@@ -35,6 +35,7 @@ class NF_Fields_Checkbox extends NF_Abstracts_Input
add_filter( 'ninja_forms_merge_tag_value_' . $this->_name, array( $this, 'filter_merge_tag_value' ), 10, 2 );
add_filter( 'ninja_forms_merge_tag_calc_value_' . $this->_name, array( $this, 'filter_merge_tag_value_calc' ), 10, 2 );
add_filter( 'ninja_forms_subs_export_field_value_' . $this->_type, array( $this, 'export_value' ), 10 );
}
public function admin_form_element( $id, $value )
......@@ -77,4 +78,12 @@ class NF_Fields_Checkbox extends NF_Abstracts_Input
{
return ( 1 == $value ) ? $field[ 'checked_calc_value' ] : $field[ 'unchecked_calc_value' ];
}
public function export_value( $value ) {
if ( 1 == $value ) {
return __( 'checked', 'ninja-forms' );
} else {
return __( 'unchecked', 'ninja-forms' );
}
}
}
......@@ -26,6 +26,7 @@ class NF_Fields_ListCheckbox extends NF_Abstracts_List
$this->_nicename = __( 'Checkbox List', 'ninja-forms' );
add_filter( 'ninja_forms_merge_tag_calc_value_' . $this->_type, array( $this, 'get_calc_value' ), 10, 2 );
add_filter( 'ninja_forms_subs_export_field_value_' . $this->_type, array( $this, 'export_value' ), 10 );
}
public function admin_form_element( $id, $value )
......@@ -53,4 +54,8 @@ class NF_Fields_ListCheckbox extends NF_Abstracts_List
}
return $value;
}
public function export_value( $value ) {
return implode( ',', maybe_unserialize( $value ) );
}
}
......@@ -24,6 +24,7 @@ class NF_Fields_ListMultiselect extends NF_Abstracts_List
$this->_nicename = __( 'Multi-Select', 'ninja-forms' );
add_filter( 'ninja_forms_merge_tag_calc_value_' . $this->_type, array( $this, 'get_calc_value' ), 10, 2 );
add_filter( 'ninja_forms_subs_export_field_value_' . $this->_type, array( $this, 'export_value' ), 10 );
}
public function admin_form_element( $id, $value )
......@@ -51,4 +52,8 @@ class NF_Fields_ListMultiselect extends NF_Abstracts_List
}
return $value;
}
}
public function export_value( $value ) {
return implode( ',', maybe_unserialize( $value ) );
}
}
\ No newline at end of file
......@@ -227,4 +227,22 @@ final class WPN_Helper
return in_array( $function, $disabled );
}
public static function maybe_unserialize( $original )
{
// Repalcement for https://codex.wordpress.org/Function_Reference/maybe_unserialize
if ( is_serialized( $original ) ){
// Ported with php5.2 support from https://magp.ie/2014/08/13/php-unserialize-string-after-non-utf8-characters-stripped-out/