Dynamic permalinks when creating a post in WordPress - wordpress

I have a custom post type named houses. Inside my custom post type I have several custom fields which I created using ACF.
What I need to do is to change the permalink when I create a new post.
I would like to use the code and title fields to customize the permalink:
//code + post title
4563312-house-example-1
I'm developing a plugin which controls everything.
Is there a way to intermediate the creation of a post to update its permalink?
Thanks.

After some research, I found an answer related to wp_insert_post_data.
Using wp_insert_post_data, I couldn't get the custom field value, and to achieve that, I had to use another action, save_post instead.
function rci_custom_permalink($post_id) {
$post = get_post($post_id);
if($post->post_type !== 'houses') return;
$code = get_field('code', $post_id);
$post_name = sanitize_title($post->post_title);
$permalink = $code . '-' . $post_name;
// remove the action to not enter in a loop
remove_action('save_post', 'rci_custom_permalink');
// perform the update
wp_update_post(array('ID' => $post_id, 'post_name' => $permalink));
// add the action again
add_action('save_post', 'rci_custom_permalink');
}
add_action('save_post', 'rci_custom_permalink');
PS: Since all these fields are required, I didn't need to check if they are empty or not.
For reference about save_post action:
Plugin API/Action Reference/save post

Related

Woocommerce Product Vendor extension - Loading ACF fields into a vendor's store front

I am using ACF to add fields to my vendors' dashboard profile pages. I currently have a test ACF field loading the field from only the WP Admin profile page on all the vendors' product listing page using this simple hook in my child theme's functions.php:
add_action( 'woocommerce_archive_description', 'vendor_profile', 7 );
function vendor_profile() { ?>
<?php if(get_field('founded_on')) { ?>
<?php the_field('founded_on'); ?>
<?php }
}
Perhaps I'm pulling the wrong hook, but I can't seem to find the right hook in the Product Vendor frontend page.
I need help customizing it so that when you are on a vendor's product page, it pulls the ACF fields from that particular vendor's profile. Currently, it partially works; however it only pulls the WP main admin's data for all the different vendors'.
I know there is a way to pull the vendor's ID for each particular vendor's page and have it load their data for their page, but my php knowledge is very limited. I usually just hunt for existing code and tweak it. Unfortunately I haven't found any solutions that have worked, and this is the closest I've come to getting custom fields to work on a vendor's page.
Or if anyone can point me to a better solution to allow me to create customer fields for a vendor to fill out that will be loaded on their front end page, that would be great. I've tried Nicola Mustone's solution ( here ), which would have been perfect, except I couldn't get it to load the new custom fields on the vendor's store profile form page, nor have it load the fields into that vendor's storefront page. Based on comments, it only shows up for the site's Admin and only they can edit it. There's no visible way to have it load on the storefront, which defeats the purpose.
I imagine that the providers are users with a certain level within the WordPress system?
Considering that this is your case, the ACF fields need some additional parameters to become visible:
$post_id = false; // current post
$post_id = 1; // post ID = 1
$post_id = "user_2"; // user ID = 2
$post_id = "category_3"; // category term ID = 3
$post_id = "event_4"; // event (custom taxonomy) term ID = 4
$post_id = "option"; // options page
$post_id = "options"; // same as above
$value1 = the_field( 'my_field', $post_id );
$value2 = get_field( 'my_field', $post_id );
take some examples found in the ACF documentation, but in your particular case you have to pass the user's ID
the_field('founded_on', 'user_' . $user->ID );
echo get_field('founded_on', 'user_' . $user->ID );
function documentation the_field()
You need to pull the user ID of the user and then use the format user_{$user->ID} for the post ID as the second parameter of the ACF field.
If I understand your question, then this should work.
add_action( 'woocommerce_archive_description', 'vendor_profile', 7 );
function vendor_profile() {
$user = wp_get_current_user();
if ( get_field( 'founded_on', 'user_' . $user->ID ) ) {
the_field( 'founded_on', 'user_' . $user->ID );
}
}

Wordpress how to link Custom Post Type directly to a Custom Field instead of the parent post page

I have a Custom Post type with two custom fields - Description and Attachment (to upload file/PDF).
When I complete this Custom Post I want the link to go directly to the attachment rather than the post page. I am using CPT UI and Custom Fields plugins to manage all this.
Does anyone know how I can create a custom post that will go directly to an attachment rather than the post page? I want to be able to display the title of each post on a page and have the title go to the attachment within the post.
I hope this makes sense and any help greatly appreciated!
This example assumes that you are using ACF to create the fields. And the field with the file gives its ID when requested (when creating a field in ACF there is an option to give ID or link)
add_filter( 'post_type_link', 'custom_post_permalink1', 10, 4 );
function custom_post_permalink1( $permalink, $post, $leavename, $sample ) {
// Change here to your post type name
if ( $post->post_type == 'your_post_type' ) {
$post_current_id = $post->ID;
// Change here 'file' to your custom field slug
if(get_post_meta($post_current_id, "file", true) ):
$PDF_ID = get_post_meta($post_current_id, "file", true);
$PDF_URL = wp_get_attachment_url( $PDF_ID );
$permalink = $PDF_URL;
endif;
}
return $permalink;
}

Woocommerce custom Product slug

Is there a way to create custom product URL based on the product attributes, I have a product sunglasses which has a couple of attributes tied to it: metal, blue and round, so the current URL is:
website.com/glasses/sunglasses/abram-widana-629/
What I am trying to get is a URL which has those attributes included:
website.com/glasses/sunglasses/abram-widana-meta-blue-round-629/
I would really appreciate if someone would even just point me to the right direction on how to tackle this.
There are two ways to do this, either Manually or Programmatically.
Manually adjusting permalinks:
In your example, you are simply adjusting the product URL to include attributes. This can be achieved manually by editing the permalink on the product itself.
Once the product has been added/saved, you will see the permalink showing directly under the title field like this:
Simply click the Edit button next to it and change it from abram-widana-629 to abram-widana-meta-blue-round-629
Programmatically adding attributes to permalinks:
If you want to try to achieve this permanently for all products you will have to work through the "save_post" filter/hook to add all the attributes to the permalink. The only downfall from this is that you will no longer be able to adjust your individual permalinks for your products as they will simply revert back once you click save.
Below is a code example of how to achieve that:
add_action( 'save_post', 'add_custom_attributes_to_permalink', 10, 3 );
function add_custom_attributes_to_permalink( $post_id, $post, $update ) {
//make sure we are only working with Products
if ($post->post_type != 'product' || $post->post_status == 'auto-draft') {
return;
}
//get the product
$_product = wc_get_product($post_id);
//get the "clean" permalink based on the post title
$clean_permalink = sanitize_title( $post->post_title, $post_id );
//next we get all of the attribute slugs, and separate them with a "-"
$attribute_slugs = array(); //we will be added all the attribute slugs to this array
foreach ($_product->get_attributes(); as $attribute_slug => $attribute_value) {
$attribute_slugs[] = $attribute_value;
}
$attribute_suffix = implode('-', $attribute_slugs);
//then add the attributes to the clean permalink
$full_permalink = $clean_permalink.$attribute_suffix;
// unhook the save post action to avoid a broken loop
remove_action( 'save_post', 'add_custom_attributes_to_permalink', 10, 3 );
// update the post_name (which becomes the permalink)
wp_update_post( array(
'ID' => $post_id,
'post_name' => $full_permalink
));
// re-hook the save_post action
add_action( 'save_post', 'add_custom_attributes_to_permalink', 10, 3 );
}

Show different page templates for custom post types

I am using the Custom Post Type UI plugin for worpdress and have created custom "pages". I have set these pages to be able to use the page template dropdown but would like to know if anyone knows of a way to show separate page templates for different post types?
You will need the theme_page_templates filter hook to remove the templates that you do not want to see for each post type. When the templates are loaded, including for display in the edit screen the templates that are returned are first passed to this function:
apply_filters ( 'theme_page_templates', array $page_templates, WP_Theme $this, WP_Post|null $post )
To implement you will use something like the following code:
function filter_theme_page_templates( $templates, $theme, $post ){
// make sure we have a post so we know what to filter
if ( !empty( $post ) ){
// get the post type for the current post
$post_type = get_post_type( $post->ID );
// switch on the post type
switch( $post_type ){
case 'custom-post-type':
// remove anything we don't want shown for the custom post type
// array is keyed on the template filename
unset( $templates['page-template-filename.php'] );
break;
default:
// if there is no match it will return everything
break;
}
}
// return the (maybe) filtered array of templates
return $templates;
}
add_filter( 'theme_page_templates', 'filter_theme_page_templates', 10, 3 );

Syncing custom fields between 2 languages (with WPML)

I'm using WPML (Wordpress multilanguage plugin) with custom post and fields (with Advanced Custom Fields plugin) and I have this "issue":
I've a custom post with a custom field (text), I enter text in the field and save. Now I go to the translated post and see that the same custom field is empty. Then the fields ar not synched. Notice that instead the Tag field is well synched between the languages.
Someone can help? Thanks
I don´t think the saved value of a custom field is synced by default. Only the name of the variable etc.
So if you have a custom field and wan´t it to have the same value on all languages, simply don´t add that custom field to other languages. Just have it on the main language.
Then in the template you can use this, to allways get the value from main language:
<?php the_field('fieldname',lang_page_original_id($post->ID));?>
Then add this to functions.php
function lang_page_original_id($id){
if(function_exists('icl_object_id')) {
return icl_object_id($id,'page', false, "MAIN LANGUAGE CODE EX: SV");
} else {
return $id;
}
}
Here are ACF docs: http://www.advancedcustomfields.com/resources/multilingual-custom-fields/
But it doesn't work as well as you may expect. Syncing is only "one way" from original to translated versions. See: https://wordpress.stackexchange.com/questions/181338/fixed-values-for-same-post-translations/214120#214120 for more details.
You will need WPML Multilingual CMS in order to use sync feature.
Hi use this in your function.php works 100%:
function sync_field_meta( $post_id, $post, $update ) {
$post_type = get_post_type($post_id);
// use this if u have muti custom post type
$posts_type = array('your_custom_post_type1', 'your_custom_post_type2', 'your_custom_post_type3', 'your_custom_post_type4');
if( ! in_array($post_type, $posts_type)) return;
$en = apply_filters( 'wpml_object_id', $post_id, 'any', FALSE, 'en' );
$fr = apply_filters( 'wpml_object_id', $post_id, 'any', FALSE, 'fr' );
// your acf key like (field_58136c9dc9963) you can check documention
$field = get_field('acf_key',$post_id);
if($en){
update_field('acf_key',$field,$en);
}
if($fr){
update_field('acf_key',$field,$fr);
}
}
add_action( 'save_post', 'sync_field_meta', 10, 3 );

Resources