Wordpress specific order of echo post meta checkboxes - php

I'm a php newbie and a first time poster.
I am working on a wordpress site where I need a discography.
I have successfully:
Created my custom post type : Albums
Added custom meta boxes and custom fields to admin post edit page
Made an archive page and echoed all the custom field meta.
http://squarerecording.com/albums/
One of my custom fields is a series of 5 checkboxes: the last line of each album on that archive page
array(
'name' => 'Services Rendered',
'desc' => 'field description (optional)',
'id' => $prefix . 'services',
'type' => 'multicheck',
'options' => array(
'R' => 'Recorded',
'Mi' => 'Mixed',
'Ma' => 'Mastered',
'P' => 'Produced',
'RMV' => 'Re-mastered for vinyl',
),
),
although I have successfully echoed the "Services Rendered" in a comma separated format, the order is different for each post (P,RMV,R,Mi,Ma-for the first one, P,Ma,Mi,R,RMV-for the second, etc.)
Here is the code for the archive page that outputs "Services Rendered":
<?php $key="sqr_services"; get_post_meta($post->ID, $key);
$sqr_services = get_post_meta( $post->ID, $key );
$comma_sep_services = implode(",", $sqr_services );
echo $comma_sep_services;
?>
My question is: What do I need to do so that they are listed in the same order that they appear on the edit page ( R,Mi,Ma,P,RMV)? Bearing in mind that they will not always ALL be checked.
I have tried messing around with unserializing but i don't know enough about it.
Any help or a point in the right direction would be greatly appreciated!
Thanks

This post might be of interest. It's one of the few solutions I've seen that doesn't involve editing Wordpress core files.
You could also try this modified get_post_custom function that orders the key/value pairs by meta id instead of the "date modified" order returned by get_post_custom.
A third option would be to sift through this answer.
Update: Silly Me! PHP can sort arrays any darn way you want, and it just gets a teeny bit tricky when that's not numerical or alphabetical. If alphabetization works for you, attempt the following:
$key="sqr_services";
get_post_meta($post->ID, $key);
$sqr_services = get_post_meta( $post->ID, $key );
asort($sqr_services);
foreach ($sqr_services as $key => $val) {
echo "$val\n";
}
If you want to learn yourself more complex array sorting, be my guest. Me? I'll stick to ABCs.
Update: Silly You!
In response to your comment about checking for and displaying individual values in your $sqr_services array, alls you needs to do is check in_array():
if (in_array('Recorded', $sqr_services)){echo 'Recorded';}
if (in_array('Mixed',$sqr_services)){echo 'Mixed';}
if (in_array('Mastered',$sqr_services)){echo 'Mastered';}
if (in_array('Produced',$sqr_services)){echo 'Produced';}
if (in_array('Re-mastered for vinyl',$sqr_services)){echo 'Re-mastered for vinyl';}
It's less flexible in that if you add a value to the array (add a new tax term), it won't start showing up until you check for it in your loop. I'm guessing that's not gonna be a problem, though, as this seems like a pretty finite set of options.

Related

Prepopulating gravityforms fields based on logged in users latest form entry

Can anyone help/have some ideas on how to prepopulate gravityforms fields based on users latest entry of the same form.
I've users, who will "register" to an event every year and fill the same form, so it would be nice to have the same fields already filled and if the client wants, they can refill some of the changed fields themselves.
So far I've found some info from gravityforms docs myself, but this code seems only to be prepopulating only one field? Still haven't gotten it to work.
The code ->
add_filter( 'gform_field_value_previous_value', 'populate_previous_value', 10, 2 );
function populate_previous_value( $value, $field ) {
$entries = GFAPI::get_entries(
$field->formId,
array(
'field_filters' => array(
array(
'key' => 'created_by',
'value' => get_current_user_id(),
),
),
),
array(),
array( 'page_size' => 1 )
);
return rgars( $entries, '0/' . $field->id );
}
I assume, the value between the rgars apostrophes aka the field id needs to be filled?
If anyone else is wondering/struggling to solve this issue - I've come to the realization that the best and easiest way to pre-populate fields values based on logged in user is through gravity forms merge tags.
Best way to use merge tags based on logged in user is next:
{user:[meta_tag}
You can use all the meta fields available, also the billing_address and billing_postcode and so on, as long as you include 'user:' before.
So the fields get populated based on logged in users meta fields. The merge tags need to be placed to form field->advanced->under default value.
For example if you need logged in users first name and last name to be populated you would add {user:first_name} to the first name default value field and {user:last_name} to the last name value field.

Add Advanced Custom Field to existing form on Dokan- Add product & edit product page (WordPress/WooCommerce)

I’m using a multi-vendor (Dokan) plugin, and been customizing it. One thing I want to achieve and been struggling is that I want my advanced custom field(also a plugin) for single product to actually appear on the front-end, in one of the Dokan’s seller dashboard form (Edit product section).
I want my seller to be able to select a brand (my acf field) on the fron-end page.
Normally when we add a new acf field group, and assign to the archive, the field will appear on the backend.
I found this to be pretty hard to achieve, especially adding the custom field onto an existing front-end form.
I have trying to customize it and I finally get the field to appear on the form I want to, but then another problem came up, which is the save button from the original form isn’t clickable anymore.
Please see screenshot: https://gyazo.com/dfb20ed90e773723658979c515581730
and here is the code I attempted to add into my Dokan’s single-product-new.php:
<?php acf_form_head(); ?>
<div class=”dokan-form-group”>
<?php
$product_brand = -1;
$term = array();
$term = wp_get_post_terms( $post_id, ‘brand’, array( ‘fields’ => ‘ids’) );
if ( $term ) {
$product_brand = reset( $term );
}
include_once DOKAN_LIB_DIR.’/class.category-walker.php’;
include_once DOKAN_LIB_DIR. ‘acf.php’;
$brand_args = array(
‘hierarchical’ => 1,
‘hide_empty’ => 0,
‘fields’ => array(‘brand’),
‘name’ => ‘brand’,
‘id’ => ‘brand’,
‘taxonomy’ => ‘brand’,
‘title_li’ => ”,
‘class’ => ‘product_brand dokan-form-control dokan-select2’,
‘exclude’ => ”,
‘selected’ => $product_brand,
‘walker’ => new DokanCategoryWalker( $post_id )
);
acf_form($brand_args);
?>
<div class=”dokan-product-cat-alert dokan-hide”>
<?php esc_html_e(‘Please choose a brand!’, ‘dokan-lite’ ); ?>
</div>
</div>
I know this is wrong, but somehow these code helped me to pull the advanced custom field onto the form I want, and it’s actually saving the field data to the product when you click update.
I was thinking maybe should of work around this under child-theme's function.php...
Any help will be really appreciated!
Luke
You can use a free plugin named ACF Frontend Form for Elementor to add / edit products from front end for your sellers / vendors.
https://wordpress.org/plugins/acf-frontend-form-element/
For this you also need to use elementor plugin and create a product page through elementor

Wordpress: Custom Post Type query not finding advanced custom field meta_query

I have a custom post type in Wordpress called People (each post in people is a person with some bio details etc).
Inside each People post I've created a custom field called 'tags' which has a series of checkboxes.
If someone clicks on the System Manager checkbox I want to be able to only pull through all the system managers on a particular page.
The most success I've had is using the wp_get_recent_posts instead of new wp_query .. this will output everybody UNTIL I add my extra meta query search. Then nothing appears.
$people_args = array(
'post_type' => 'people',
'post_status'=>'publish',
'meta_query' => array(
array(
'key' => 'tags', // name of custom field
'value' => 'systemmanager',
'compare' => 'LIKE'
)
)
);
$people_posts = wp_get_recent_posts($people_args);
foreach( $people_posts as $people ){
$fields = get_fields($people["ID"]);
if (get_post_thumbnail_id( $people["ID"] )>0) {
$myimgsp = wp_get_attachment_image_src(get_post_thumbnail_id($people["ID"]),'full');
echo '
<li class="item">
<img src="'.$myimgsp[0].'" alt="'.$people["post_title"].'" class="img-responsive" />
<div class="profile">
<h3>'.$people["post_title"].'</h3>
<p>'.$fields["job_title"].'</p>
View Profile
</div>
</li>';
}
}
wp_reset_query();
I've been stuck on this for hours trying out all the different types of loops but I've had no luck. Has anyone come across this problem before?
If you got stuck on the query maybe try different approach and use the post_id from the query and make small loop inside your code there use get_post_meta(post_id) to check the meta key and get the tags value... something like this...
$meta = get_post_meta($post_ID);
foreach($meta as $key=>$val)
{
if ($key == 'tags')
echo $val;
}
So I'm feeling a little silly! In my functions.php I had forgotten to set that the custom post type should support custom fields. So even though my Advanced Custom Fields were showing .. it wasn't getting pulled through when I was calling it.
To rectify I added to my custom post type config:
'supports' => array('title','thumbnail','custom-fields')

Check for duplicate Wordpress Post with Custom Meta Data on Publish

I have a site that uses a custom meta-box with the following fields using Meta-Box plugin. Code is as follows
`
$meta_boxes[] = array(
'title' => 'MLS ID',
'pages' => array('property'),
'fields' => array(
array(
'name' => 'MLS ID',
'id' => "IntegratorPropertyID",
'desc' => 'MLS: e.g. 240091025-217',
'type' => 'text',
),
array(
'name' => 'Test MLS',
'id' => "mlsTest",
'desc' => 'Test MLS for Duplicate',
'type' => 'button',
),
),
'validation' => array(
'rules' => array(
"IntegratorPropertyID" => array(
'required' => true
),
),
'messages' => array(
"IntegratorPropertyID" => array(
'required' => 'MLS is required',
),
)
)
);
Now what im looking for is to add an 'add_action( 'save_post', 'checkMLS' );' function that checks all previous CPT property for MLS number to make sure it hasn't been input before. The code I used was:
function checkMLS( $post_id ) {
$slug = 'property';
if ( $slug != $_POST['post_type'] ) {
return;
}
$mls2 = rwmb_meta('IntegratorPropertyID', 'type=text', $post_id);
$args = array( 'post_type' => 'property' );
$loop = new WP_Query( $args );
while ( $loop->have_posts() ) : $loop->the_post();
$this1 = get_the_ID();
$mls1 = rwmb_meta('IntegratorPropertyID', 'type=text', $this1);
if ( $mls2 == $mls1 ) {
$my_post = array(
'ID' => $post_id,
'IntegratorPropertyID' => 'DUPLICATE!'
);
wp_update_post($my_post);
return;
}
endwhile;
}
add_action( 'save_post', 'checkMLS' );
That code is found in the functions.php and when I try to post the screen goes white. Debugging mode does not offer any help either. :/
I'm sure I'm making some programming Major mistake somewhere. Can someone point it out? or maybe point me in the right direction? or suggest something completely different?
Thanks
Keith
OK. Firstly, your white page with no indication of why, is probably either an 'out of memory' error, or a php 'max execution time' error. This stims from one major flaw in the way the checkMLS() function works. The flaw is that you are literally cycling through ALL 'property' posts in your database. Depending on the size of your dataset, this can be a LOT, especially considering you are dealing with MLS lists.
MY RECOMMENDATION:
Figure out how the rwmb_meta() function is grabbing it's information. It is probably just a wrapper function for the get_post_meta() function, but maybe not. Assuming that it is, I propose doing the following, which I will explain the details of after as well as in the comments:
// the save_post action runs after a post has been saved/created, and has two parameters
// param 1: the id of the post
// param 2: the post object
function checkMLS($post_id, $post) {
// use the post object post_type to determine if this is a property or not.
// it will be a lot more reliable
if ($post->post_type != 'property') return;
// meta_key should be equal to the 'meta_key' field in the wp_postmeta table, for the
// id you are trying to check against. your example used IntegratorPropertyID.
// again you may want to check rwmb_meta() function to figure out if there is a
// 'prefix' or 'suffix' added to this. despite that, it is almost certainly going to
// be looking in the wp_postmeta table, so this should work nicely
$meta_key = 'IntegratorPropertyID';
// look up the current mls id for this post, which you just saved/created
$mls_id = get_post_meta($post_id, $meta_key, true);
// lookup in the actual database table for any matching row, that has the same MLS id
// that is not this post.
global $wpdb;
$q = $wpdb->prepare('select post_id from '.$wpdb->postmeta.' where meta_key = %s and meta_value = %s and post_id != %d limit 1', $meta_key, $mls_id, $post_id);
$exists = $wpdb->get_var($q);
// if it already exists, mark the value as a duplicate
if ($exists) update_post_meta($post_id, $meta_key, 'DUPLICATE!');
}
// add your check function late in the actions, at priority 10000
add_action('save_post', 'checkMLS', 10000, 2);
From the top, we create a callback with two params, because the save_post action sends two, $post_id and $post. Since save_post runs after the post has been saved, you already have an object ($post) which has all the post info in it. We can then use that $post object to determine the type of the post, which is more reliable than looking at a $_REQUEST value, mainly because $post is pulled directly from the database and passed to you.
Now, as stated before I assume that rwmb_meta() is just a kinda wrapper function for get_post_meta(). It probably adds a prefix or suffix to the $meta_key, but a little research into the rwmb_meta() function should tell you how the $meta_key is changed when passing it to the get_post_meta() function, and you can modify $meta_key from there. With the correct $meta_key, we can now get the MLS id of the property you just saved.
With that MLS id, we need to do a direct lookup in the database, to determine if there is another property with that id already. While the way in your demo function does work on small sets of data, there is no way it would work on any appreciable amount of properties. Thus the direct approach is needed. Simply we craft some special SQL to look in the wp_postmeta table for any post_id that has an MLS id that is equal to the one entered for this property, that is not this property. If we find one match that is not this property, then it is a dupe. If it is a dupe, we need to mark it as a dupe.
Notice that this solution does not do any looping at all. There is no potential for it to loop over 10000 records to find a dup id. This is streamlined. It looks up the id directly in the db, to see if there are dups.
Hopefully this is helpful to you, and hopefully others find it helpful as well. My company does WordPress work, almost exclusively. Through our years of working with WordPress we have encountered problems from the super simple to the overly complex. This same problem, in different settings, has manifested with many of our clients. This solution is simple and to the point, though highly custom. It will however, work.

Drupal 7 API + Taxonomy

I'm attempting to build a small tool with PHP to import content from my current CMS into Drupal 7 because I have about 10k+ articles to bring in. So far I've gotten the title, summary, body, author and published date to come through, but when it comes to categories (tags), I am completely baffled.
Each of my current categories/tags are stored in a database table, each having their own ID, name and description. I can pull this out per article and sort it however I'd like (string, array, etc).
During my import, I'm guessing I should do something like this:
$node->field_tags = array(
'und' => array(
array(
'Update',
'News',
'Report'
)
)
);
I've also tried:
$node->field_tags = array(
'Update',
'News',
'Report'
);
But these nor feeding in a comma separated string of words doesn't work. The Drupal 7 API documentation doesn't seem to explain this anywhere that I've found.
What's the format for sending tags through or what's the documentation page I haven't been able to locate? Thank you in advance!
Term fields in Drupal 7 are related to physical taxonomy terms, so you'll need to create a term for each category, and then add that reference as the field's value.
This code might help:
// Load the tags vocabulary
$vocab = taxonomy_vocabulary_machine_name_load('tags');
$term = new stdClass;
$term->vid = $vocab->vid; // Attach the vocab id to the new term
$term->name = 'Category Name'; // Give the term a name
taxonomy_term_save($term); // Save it
// Add the tags field
$node->field_tags = array(
LANGUAGE_NONE => array(
'tid' => $term->tid // Relate the field to the new category term using it's tid (term id)
)
);

Categories