How to get an array of values from $entry - wordpress

In Gravity Form's class GF_Field_Checkbox there is a method called get_value_export() that returns implode( ', ', $selected ) for a bunch of elements created by GFCommon::selection_display()
The class-gf-field-checkbox.php code so you can see what I am referencing.
public function get_value_export( $entry, $input_id = '', $use_text = false, $is_csv = false ) {
if ( empty( $input_id ) || absint( $input_id ) == $input_id ) {
$selected = array();
foreach ( $this->inputs as $input ) {
$index = (string) $input['id'];
if ( ! rgempty( $index, $entry ) ) {
$selected[] = GFCommon::selection_display( rgar( $entry, $index ), $this, rgar( $entry, 'currency' ), $use_text );
}
}
return implode( ', ', $selected );
...
This is all well and good, however, the problem with this is that I'm exploding the values that are returned from this method.
$answer = explode(', ', $field->get_value_export($entry));
I do not want to do this as there exists an edge case where a potential value could have a comma which gets exploded. For example, say there is an option in my form like below
Label: Are you not entertained?
Value:
[x] Lorem ipsum dolor sit amet, consectetur adipiscing elit
[x] Duis blandit, risus vel rutrum suscipit
[ ] Duis cursus ex risus
As you can see the first two selections are selected, and this will be picked up and will then be exploded as such
['Lorem ipsum dolor sit amet', 'consectetur adipiscing elit', 'Duis blandit', 'risus vel rutrum suscipit']
When it should have been exploded like this
['Lorem ipsum dolor sit amet, consectetur adipiscing elit', 'Duis blandit, risus vel rutrum suscipit']
What method exists in GFAPI, or custom code can I use that could resolve this issue?

You can retrieve the checkbox values in the following way:
$entry = GFAPI::get_entry( **entry id here** );//add your entry id in parenthesis
$field_id = **add field number here**;
$items = array();
$field_keys = array_keys( $entry );
foreach ( $field_keys as $input_id ) {
if ( is_numeric( $input_id ) && absint( $input_id ) == $field_id ) {
$value = rgar( $entry, $input_id );
if ( "" !== $value ) $items[ $input_id ] = str_replace(",",",",$value);
}
}
$answer = implode(",",$items);

Rochelle's answer was useful in producing this solution. Instead of using GF_Field_Checkbox's method, I've created my own function that will pull out the necessary values into an array, while effectively getting rid of the comma issue, due to using explode()
function get_value_export($entry, $input_id)
{
$items = array();
foreach ($entry as $key => $value) {
if ($value == "") continue;
if (!is_numeric($key)) continue;
if (absint($key) !== absint($input_id)) continue;
$items[] = $value;
}
return $items;
}

Related

Selectable recipient with pipes contact form 7 get country name issue

I am using country dropdown in my contact form 7. it look like this [select* country "Canada | team1#website.com,team3#website.com" "Mexico | team2#website.com" "Zimbabwe | team3#website.com"], It is working fine if I am using it to get first value by [_row_country] and second value (after pipe) by [country] in mail section.
But I want to save it in customer database and tryin to get country name by this
$your_country = $form_data['_raw_country'];
$country = implode( ', ', (array) $your_country );
it return only email but not country, So I also try this
$your_country = $form_data['country'];
$country = implode( ', ', (array) $your_country );
It return blank.
This is my Code for reference.
function contactform7_before_send_mail( $contact_form, $abort, $submission ) {
// set your db details.
$mydb = new wpdb( 'user', 'password', 'database', 'localhost' );
if ( $submission ) {
$form_data = $submission->get_posted_data();
$your_country = $form_data['_raw_country'];
$country = implode( ', ', (array) $your_country );
$mydb->insert(
'tableName',
array(
'fullname' => sanitize_text_field( $form_data['FullName'] ),
'country' => $country,
'companyname' => sanitize_text_field( $form_data['CompanyName'] ),
),
array( '%s', '%s', '%s' )
);
}
}
add_action( 'wpcf7_before_send_mail', 'contactform7_before_send_mail', 10, 3 );
this is the reference link https://contactform7.com/selectable-recipient-with-pipes/
To get the information from the pipes, you can't just use the [_raw_field] since it's not stored that way. It's a little more complicated to get the value of the Piped data. To get the value of the pipes, you have to retrieve the form tags, then loop through the pipe values for each.
add_action( 'wpcf7_before_send_mail', 'dd_handle_form_submission', 10, 3 );
function dd_handle_form_submission( $contact_form, $abort, $submission ) {
if ( $submission ) {
$form_data = $submission->get_posted_data();
// Get the tags.
$tags = $submission->get_contact_form()->scan_form_tags();
// Get the country field submission.
$country = $submission->get_posted_data( 'country' );
foreach ( $tags as $tag ) {
if ( 'country' === $tag->name ) {
// Get the Pipes.
$pipe_array = $tag->pipes->to_array();
foreach ( $pipe_array as $value ) {
if ( $country[0] === $value[1] ) {
// $value[0] is Left of Pipe - $value[1] is right of pipe.
$country_name = $value[0];
}
}
}
}
if ( isset( $country_name ) ) {
$mydb = new wpdb( 'user', 'password', 'database', 'localhost' );
$mydb->insert(
'tableName',
array(
'fullname' => sanitize_text_field( $form_data['FullName'] ),
'country' => $country_name,
'companyname' => sanitize_text_field( $form_data['CompanyName'] ),
),
array( '%s', '%s', '%s' )
);
}
}
}
New Answer / Solution to Specific Problem
In your case, the values after the pipes are not unique. This poses another issue all together, which makes pipes less than awesome. In this case, I would use jQuery and a hidden form field.
Make the contact form something like this:
<p>[select* country id:country include_blank "Canada | team1#website.com,team3#website.com" "Mexico | team2#website.com" "Serbia | team2#website.com" "Zimbabwe | team3#website.com"]</p>
<p>[text FullName]</p>
<p>[email your-email]</p>
[hidden hidden_country id:hidden_country]
[submit]
<script>
jQuery(function($){
$('#country').on( 'change', function() {
$('#hidden_country').val($(this).val());
});
});
</script>
Then since you're just capturing the country value on change, you can easily push that value to your database, and your email to (the right of the pipes) is used, and that's that.
add_action( 'wpcf7_before_send_mail', 'dd_handle_form_submission', 10, 3 );
function dd_handle_form_submission( $contact_form, $abort, $submission ) {
if ( $submission ) {
$form_data = $submission->get_posted_data();
$country_name = sanitize_text_field( $form_data['hidden_country'] );
if ( ! empty( $country_name ) ) {
$mydb = new wpdb( 'user', 'password', 'database', 'localhost' );
$mydb->insert(
'tableName',
array(
'fullname' => sanitize_text_field( $form_data['FullName'] ),
'country' => $country_name,
'companyname' => sanitize_text_field( $form_data['CompanyName'] ),
),
array( '%s', '%s', '%s' )
);
}
}
}

Cannot get custom taxonomy filter in media list view to work

I have created a filter dropdown in Media list view to filter media files based on selected term. The dropdown rendered OK with the custom taxonomy item. But the filter is not working at all. Irrespective of the term I select from this dropdown, all media items are being listed. No filtration is happening.
Here is my code to create the filter dropdown (in functions.php):
function media_add_content_category_filter_dropdown()
{
$scr = get_current_screen();
if ( $scr->base !== 'upload' ) return;
$terms = get_terms('media_content_category', array('hide_empty' => false));
if ( $terms ) {
printf( '<select name="%s" class="postform">', esc_attr( 'mcfdd' ) );
print( '<option value="">All Categories</option>');
foreach ( $terms as $term ) {
printf( '<option value="%s">%s</option>', esc_attr( $term->term_id ), esc_html( $term->name ) );
}
print( '</select>' );
}
}
add_action('restrict_manage_posts', 'media_add_content_category_filter_dropdown');
And this is the code I am using to for filtration purpose:
function media_content_filter($query) {
if ( is_admin() && $query->is_main_query() ) {
if (isset($_GET['mcfdd']) && $_GET['mcfdd'] == -1) {
$query->set('mcfdd', '');
}
}
}
add_action('pre_get_posts','media_content_filter');
Working solution to display taxonomy filters on media library and filter:
//[[START] - Add custom taxonomy dropdown to media library
function media_add_content_category_filter_dropdown()
{
global $wp_query;
// check we're in the right place, otherwise return
if ( 'upload.php' != $pagenow )
return;
$tax_slug = 'media_content_category';
$tax_obj = get_taxonomy( $tax_slug );
// check if anything has been selected, else set selected to null
$selected = isset($wp_query->query[$tax_slug]) ? $wp_query->query[$tax_slug] : null;
wp_dropdown_categories( array(
'show_option_all' => __($tax_obj->label . ' - All'),
'taxonomy' => $tax_slug,
'name' => $tax_obj->name,
'orderby' => 'name',
'selected' => $selected,
'hierarchical' => true,
// 'show_count' => true,
'hide_empty' => false
) );
}
add_action('restrict_manage_posts', 'media_add_content_category_filter_dropdown');
To filter posts by custom taxonomy
function media_tsm_post_convert_id_to_term_in_query($query)
{
global $pagenow, $typenow;
// check we're in the right place, otherwise return
if ( 'upload.php' != $pagenow )
return;
$filters = get_object_taxonomies( $typenow );
foreach ( $filters as $tax_slug ) {
$var = &$query->query_vars[$tax_slug];
if ( $var != 0 ) {
$term = get_term_by( 'id', $var, $tax_slug );
$var = $term->slug;
}
}
}
add_filter('parse_query', 'media_tsm_post_convert_id_to_term_in_query');
//[END] - Add custom taxonomy dropdown to media library

WordPress REST API - hide field for non logged users

With this example I manage to add custom post type and custom meta data in WordPress REST API.
Right now I'm trying to hide some of the data for non logged users and I'm trying like this:
add_filter( 'rest_prepare_the_event', 'add_meta_to_json', 10, 3 );
function add_meta_to_json($data, $post, $request){
$response_data = $data->get_data();
if ( $request['context'] !== 'view' || is_wp_error( $data ) ) {
return $data;
}
$start = get_post_meta( $post->ID, '_the_event_start', true );
if(empty($start)){
$start = '';
}
$end = get_post_meta( $post->ID, '_the_event_end', true );
if(empty($end)){
$end = '';
}
$location = get_post_meta( $post->ID, '_the_event_location', true );
if(empty($location)){
$location = '';
}
if($post->post_type == 'the_event'){
$response_data['event_meta'] = array(
'start' => $start,
'end' => $end,
'location' => $location,
);
if ( !is_user_logged_in() ) {
unset($response_data['event_meta']['location']);
}
}
$data->set_data( $response_data );
return $data;
}
In above example code I'm trying to hide location field to non logged users but this is not working.
How to hide that field for non logged users?
I see your code fine... but you can to try:
if($post->post_type == 'the_event'){
$response_data['event_meta'] = array(
'start' => $start,
'end' => $end
);
if ( is_user_logged_in() ) {
$response_data['event_meta']['location'] = $location;
}
}

Wordpress - radio button checkout woocommerce show/hide required field

I'm Italian (sorry for my english) and I'm not a programmer.
I need to insert in my checkout woocommerce site, a radio button with two options to answer this question: "Sei un privato cittadino, un'azienda o un libero professionista?".
These are the options:
1) Privato cittadino
2) Azienda o libero professionista
When users click on the first option, it has to show a required field: "codice fiscale". When users click on the second option, it has to show two required fields: "P.Iva" and "Ragione sociale". I've created the radio field with this code in form-billing.php:
<div class="woocommerce-billing-fields">
<?php if ( wc_ship_to_billing_address_only() && WC()->cart->needs_shipping() ) : ?>
<h3><?php _e( 'Billing & Shipping', 'woocommerce' ); ?></h3>
<?php else : ?>
<h3><?php _e( 'Billing Details', 'woocommerce' ); ?></h3>
<?
if($key=='billing_first_name')
{
?>
<p>Sei un privato cittadino, un'azienda o un libero professionista?</p>
<input type="radio" name="choice" value="privato_cittadino">Privato cittadino
<input type="radio" name="choice" value="azienda_professionista">Azienda o libero professionista<br>
<?
}
?>
<?php endif; ?>
It works properly, but now I don't know how can I create the required fields like I described.
Can you help me step by step? Please, consider I'm not a programmer.
To answer the question, it will need to be done in 4 steps.
Add 4 custom fields to the woocommerce checkout page. The way you have done it is not best practice and should be done through use of actions/filters.
Validate the data when the request is made to the back-end, this is to make sure the user actually selected and entered what is required.
Save the data to the order as post meta so it can be accessed later.
Implement javascript toggle feature so that based on what the user selects for the first question, the related fields are then shown.
Adding custom fields to woocommerce checkout
You will need to find a suitable action for where you would like to add the fields. I would recommend using the action woocommerce_after_checkout_billing_form as it will display fields after all the personal/billing information.
if( !function_exists( 'custom_checkout_question_field' ) ) {
/**
* Add custom question field after the billing form fields
*
* #param Integer $order_id New order id
*/
function custom_checkout_question_field( $checkout ) {
echo "<div class='custom-question-field-wrapper custom-question-1'>";
echo sprintf( '<p>%s</p>', __( "Sei un privato cittadino, un'azienda o un libero professionista?" ) );
woocommerce_form_field( 'custom_question_field', array(
'type' => 'radio',
'required' => true,
'class' => array('custom-question-field', 'form-row-wide'),
'options' => array(
'privato_cittadino' => 'Privato cittadino',
'azienda_professionista' => 'Azienda o libero professionista',
),
), $checkout->get_value( 'custom_question_field' ) );
woocommerce_form_field( 'custom_question_text_codice_fiscale', array(
'type' => 'text',
'label' => 'Codice Fiscale',
'required' => true,
'class' => array('custom-question-codice-fiscale-field', 'form-row-wide'),
), $checkout->get_value( 'custom_question_text_codice_fiscale' ) );
woocommerce_form_field( 'custom_question_text_p_iva', array(
'type' => 'text',
'label' => 'P.Iva',
'required' => true,
'class' => array('custom-question-p-iva-field', 'form-row-wide'),
), $checkout->get_value( 'custom_question_text_p_iva' ) );
woocommerce_form_field( 'custom_question_text_ragione_sociale', array(
'type' => 'text',
'label' => 'Ragione sociale',
'required' => true,
'class' => array('custom-question-ragione-sociale-field', 'form-row-wide'),
), $checkout->get_value( 'custom_question_text_ragione_sociale' ) );
echo "</div>";
}
add_action( 'woocommerce_after_checkout_billing_form', 'custom_checkout_question_field' );
}
Javascript front-end toggle
You will need to add custom javascript in order to toggle the 3 additional fields depending on the question. I have created a php function which will output a html script tag with some javascript. This is then attached to the wp_footer action.
This is not recommended method and you should really separate it into a new file js and enqueue the file when needed.
See: https://codex.wordpress.org/Plugin_API/Action_Reference/wp_enqueue_scripts
if( !function_exists( 'custom_question_conditional_javascript' ) ) {
function custom_question_conditional_javascript() {
?>
<script type="text/javascript">
(function() {
// Check if jquery exists
if(!window.jQuery) {
return;
};
var $ = window.jQuery;
$(document).ready(function() {
var questionField = $('.custom-question-field'),
codiceFiscaleField = $('.custom-question-codice-fiscale-field'),
pIvaField = $('.custom-question-p-iva-field'),
ragioneSocialeField = $('.custom-question-ragione-sociale-field ');
// Check that all fields exist
if(
!questionField.length ||
!codiceFiscaleField.length ||
!pIvaField.length ||
!ragioneSocialeField.length
) {
return;
}
function toggleVisibleFields() {
var selectedAnswer = questionField.find('input:checked').val();
if(selectedAnswer === 'privato_cittadino') {
codiceFiscaleField.show();
pIvaField.hide();
ragioneSocialeField.hide();
} else if(selectedAnswer === 'azienda_professionista') {
codiceFiscaleField.hide();
pIvaField.show();
ragioneSocialeField.show();
} else {
codiceFiscaleField.hide();
pIvaField.hide();
ragioneSocialeField.hide();
}
}
$(document).on('change', 'input[name=custom_question_field]', toggleVisibleFields);
$(document).on('updated_checkout', toggleVisibleFields);
toggleVisibleFields();
});
})();
</script>
<?php
}
add_action( 'wp_footer', 'custom_question_conditional_javascript', 1000 );
}
Getting fields from submitted post request
You will need to get the data from php $_POST array and also sanitise it to prevent sql injection or other malicious code. I have created a helper function which will grab all the fields by keys provided in an array and sanitise them using wordpress sanitize_text_field helper function.
This helper can then be used when validating and also adding post meta.
if( !function_exists( 'custom_checkout_question_get_field_values' ) ) {
/**
* Get all form field values based on user submitted post data
*
* #return Array Key/value pair of field values based on $_POST data
*/
function custom_checkout_question_get_field_values() {
$fields = [
'custom_question_field' => '',
'custom_question_text_codice_fiscale' => '',
'custom_question_text_p_iva' => '',
'custom_question_text_ragione_sociale' => '',
];
foreach( $fields as $field_name => $value ) {
if( !empty( $_POST[ $field_name ] ) ) {
$fields[ $field_name ] = sanitize_text_field( $_POST[ $field_name ] );
} else {
unset( $fields[ $field_name ] );
}
}
return $fields;
}
}
Validating fields on the back-end
Validation is important because front-end cannot be trusted, it is very easy for users to modify required fields on the front-end. You can use Woocommerce woocommerce_checkout_process action in order to validate the fields and add error messages if it does not meet what is required.
if( !function_exists( 'custom_checkout_question_field_validate' ) ) {
/**
* Custom woocommerce field validation to prevent user for completing checkout
*
* #param Integer $order_id New order id
*/
function custom_checkout_question_field_validate() {
$field_values = custom_checkout_question_get_field_values();
if ( empty( $field_values['custom_question_field'] ) ) {
wc_add_notice( 'Please select an answer for the question.', 'error' );
}
if (
$field_values['custom_question_field'] === 'privato_cittadino' &&
empty( $field_values['custom_question_text_codice_fiscale'] )
) {
wc_add_notice( 'Please enter codice fiscale.', 'error' );
}
if (
$field_values['custom_question_field'] === 'azienda_professionista' &&
empty( $field_values['custom_question_text_p_iva'] )
) {
wc_add_notice( 'Please enter p iva.', 'error' );
}
if (
$field_values['custom_question_field'] === 'azienda_professionista' &&
empty( $field_values['custom_question_text_ragione_sociale'] )
) {
wc_add_notice( 'Please enter ragione sociale.', 'error' );
}
}
add_action( 'woocommerce_checkout_process', 'custom_checkout_question_field_validate' );
}
Saving custom post meta to the order
You can use the woocommerce woocommerce_checkout_update_order_meta action in order to save additional post meta to the order post type. Here we will use the helper function custom_checkout_question_get_field_values created above to get all fields from php $_POST array and also sanitize them before saving each one to the post meta.
if( !function_exists( 'custom_checkout_question_field_save' ) ) {
/**
* Update order post meta based on submitted form values
*
* #param Integer $order_id New order id
*/
function custom_checkout_question_field_save( $order_id ) {
$field_values = custom_checkout_question_get_field_values();
foreach( $field_values as $field_name => $value ) {
if( !empty( $field_values[ $field_name ] ) ) {
update_post_meta( $order_id, $field_name, $value );
}
}
}
add_action( 'woocommerce_checkout_update_order_meta', 'custom_checkout_question_field_save' );
}

Wordpress search function for custom post type only

I've got a function added in functions.php to improve the search functionality in my directory section: http://www.highwaysindustry.com/?post_type=directory_listings&s=king
However, with the following enabled, it overrides the search for the rest of the website also: http://www.highwaysindustry.com
This particular function I would prefer it to be targeted for the directory search only.
Function in functions.php
function __search_by_title_only( $search, $wp_query )
{
global $wpdb;
if ( empty( $search ) )
return $search; // skip processing - no search term in query
$q = $wp_query->query_vars;
$n = ! empty( $q['exact'] ) ? '' : '%';
$search =
$searchand = '';
foreach ( (array) $q['search_terms'] as $term ) {
$term = esc_sql( like_escape( $term ) );
$search .= "{$searchand}($wpdb->posts.post_title REGEXP '[[:<:]]{$term}[[:>:]]')";
$searchand = ' AND ';
}
if ( ! empty( $search ) ) {
$search = " AND ({$search}) ";
if ( ! is_user_logged_in() )
$search .= " AND ($wpdb->posts.post_password = '') ";
}
return $search;
}
add_filter( 'posts_search', '__search_by_title_only', 1000, 2 );
Snippet of my directory-search.php which the form on /Directory uses:
<?php
$args = array(
'post_type'=> 'directory_listings',
's' => $s,
'paged' => $paged,
'meta_query' => array(
array(
'key' => 'membership_type',
'orderby' => 'meta_value',
'order' => "DESC"
,
),
),
);
?>
<div class="row">
<div class="small-12 columns">
<div class="directory-banner">
<img src="<?php echo site_url(); ?>/wp-content/themes/highways/images/directory-banner.jpg" alt="" title="" />
<h1><?php echo $s; ?></h1>
</div>
</div>
</div>
**I currently have the function defined above commented out, when enabled it's a lot more specific, for example, searching "King" would only provide back 2 results. Right now the generic search provides too many unspecific results.
The other 2 answers are also worth investigating. However I'll stick to your solution.
To search only directory_listings post type, tweak the function as shown below
function __search_by_title_only( $search, $wp_query )
{
global $wpdb;
if ( empty( $search ) )
return $search; // skip processing - no search term in query
$q = $wp_query->query_vars;
// post_type query var has other posts types as well, return default search
if( ! 'directory_listings' == $q['post_type'] )
return $search
// We are here, it means post_type var contains only directory_listings
// continue with the rest of the code
........
Answering your 2nd query
There is a company called blakedale, if you search just blake you won't get the result. Any method to increase the method of the returned result(s).
The regexp being used in the code below searches for full words hence "blake" doesn't return any results
$search .= "{$searchand}($wpdb->posts.post_title REGEXP '[[:<:]]{$term}[[:>:]]')";
You need to either change the regexp or use SQL LIKE
$search .= "{$searchand}($wpdb->posts.post_title LIKE '%{$term}%')";
P.S: I haven't tested the line of code above, so it may need polishing.
did you try using pre_get_posts ?
function search_filter($query) {
if ( !is_admin() && $query->is_main_query() ) {
if ($query->is_search && $_GET['post_type'] == 'directory_listings') {
// add custom meta / tax queries
}
}
}
add_action('pre_get_posts','search_filter');
You can try this .
$query_args = array( 'post_type' => 'directory_listings', 'tax_query' => array() );
if ( !empty( $search_terms ) ) {
$query_args['s'] = $search_terms;
}
if ( !empty( $search_terms ) ) {
$query_args['tax_query'][] = array(
array(
'taxonomy' => 'directory_listings',
'field' => 'slug',
'terms' => $news_category
)
);
}
$my_posts = new WP_Query( $query_args );
if ( $my_posts->have_posts() ) { // etc
}

Resources