Home › Forums › General Issues › Dynamically create vcard from ACF data and download with button click?
Hello,
Ditto the subject pretty much. I can find a lot of info on how to generate a vcard file with PHP, but nothing really says how to make this happen by clicking a button. I don’t want to store a copy locally, or generate a new file on post save or any nonsense like that. Click the button, it builds the file and downloads with a filename that mirrors the post slug.
So I did end up just creating the vCard upon saving the custom post type by cobbling together a few different methods. I started with this function:
function hj_create_vCard( $post_id ) {
/*
* In production code, $slug should be set only once in the plugin,
* preferably as a class property, rather than in each function that needs it.
*/
$post_type = get_post_type($post_id);
// only update the attorneys custom post type on save
if ( "attorneys" != $post_type ) return;
$vpost = get_post($post->ID);
$filename = $vpost->post_name.".vcf";
header('Content-type: text/x-vcard; charset=utf-8');
header("Content-Disposition: attachment; filename=".$filename);
$data=null;
$data.="BEGIN:VCARD\n";
$data.="VERSION:3.0\n";
$data.="FN:".$vpost->post_title."\n"; // get post title
$data.="ORG:Client Company Name\n";
$data.="EMAIL;TYPE=work:" .get_field('att_email',$vpost->ID)."\n"; // get acf field value
$data.="TEL;WORK;VOICE:" .get_field('att_phone',$vpost->ID)."\n"; // get acf field value
$data.="ADR;WORK;PREF:123 Fake Street;Fake City;MN;55106\n"; // get acf field value
$data.="END:VCARD";
$filePath = get_template_directory()."/vcard/".$filename; // you can specify path here where you want to store file.
$file = fopen($filePath,"w");
fwrite($file,$data);
fclose($file);
}
add_action( 'save_post', 'hj_create_vCard' );
Then for use in my template I just grab the file that is generated on save by looking for the file based on its name, which is generated from the page slug:
<?php
global $post;
$vcfname = $post->post_name;
?>
<a href="<?php echo get_template_directory_uri(); ?>/vcard/<?php echo $vcfname; ?>.vcf"><i class="far fa-address-card"></i> Download Vcard</a>
Hi,
Im trying to do the same. You got this working??
I was try this code put first part in my template functions.php and secound part in post with shortcode snippet.
I get this error
The page can’t be found.
It looks like nothing was found at this location.
@pierrebalian Thanks so much for this, worked a treat and was easily tweaked for it’s intended purpose on a website i’m working on.
@pierrebalian this is awesome and works wonderfully except for one thing: when you attempt to add a new post of the specified custom post type the browser attempts to download a .vcf file. No file name, as I assume it’s trying to download a file with “post_name.vcf” but there’s not post_name to reference so it’s just “.vcf”.
Did you or @pixelsandthings figure out a workaround for this glitch?
Thanks!
Hi @shawnrosspeters
Just unset the two header lines in the main function. That is the cause of the problem.
//header('Content-type: text/x-vcard; charset=utf-8');
//header("Content-Disposition: attachment; filename=".$filename);
Hi! I’m trying to use with my site and have no luck added the code to the functions.php, have I missed something?? My code looks:
function hj_create_vCard( $post_id ) {
/*
* In production code, $slug should be set only once in the plugin,
* preferably as a class property, rather than in each function that needs it.
*/
$post_type = get_post_type($post_id);
// only update the agremiados custom post type on save
if ( "Agremiados" != $post_type ) return;
$vpost = get_post($post->ID);
$filename = $vpost->post_name.".vcf";
//header('Content-type: text/x-vcard; charset=utf-8');
//header("Content-Disposition: attachment; filename=".$filename);
$data=null;
$data.="BEGIN:VCARD\n";
$data.="VERSION:3.0\n";
$data.="FN:".$vpost->post_title."\n"; // get post title
$data.="ORG:" .get_field('nombre_de_la_empresa',$vpost->ID)."\n"; // get acf field value
$data.="EMAIL;TYPE=work:" .get_field('correo_electronico',$vpost->ID)."\n"; // get acf field value
$data.="TEL;WORK;VOICE:" .get_field('telefono_celular',$vpost->ID)."\n"; // get acf field value
$data.="ADR;WORK;PREF:" .get_field('direccion_de_la_empresa',$vpost->ID)."\n"; // get acf field value; // get acf field value
$data.="END:VCARD";
$filePath = "/vcard/".$filename; // you can specify path here where you want to store file.
$file = fopen($filePath,"w");
fwrite($file,$data);
fclose($file);
}
add_action( 'save_post', 'hj_create_vCard' );
I’ve gotten this to work perfectly with the information above, however I also want to have the image as a vcard item. so.. the image has to be set to BASE64 format, after some googling I also got that to work.. so finally I updated my profile and yess! the image is in the vcard after updating the page. But.. one big problem; I’m not able to create new pages, I get the error: Path cannot be empty in function $image = file_get_contents($path);
This is what I got:
function imageEncode($path)
{
$path = __DIR__."/".$path;
$image = file_get_contents($path);
$finfo = new finfo(FILEINFO_MIME_TYPE);
$type = $finfo->buffer($image);
return "data:".$type.";charset=utf-8;base64,".base64_encode($image);
}
function imageEncodePath($path)
{
$image = file_get_contents($path);
$finfo = new finfo(FILEINFO_MIME_TYPE);
$type = $finfo->buffer($image);
return "data:".$type.";charset=utf-8;base64,".base64_encode($image);
}
function imageEncodeURL($path)
{
$image = file_get_contents($path);
$finfo = new finfo(FILEINFO_MIME_TYPE);
$type = $finfo->buffer($image);
return "PHOTO;TYPE=".$type.";ENCODING=BASE64:".base64_encode($image);
}
function hj_create_vCard( $post_id ) {
/*
* In production code, $slug should be set only once in the plugin,
* preferably as a class property, rather than in each function that needs it.
*/
$post_type = get_post_type($post_id);
// only update the attorneys custom post type on save
if ( "page" != $post_type ) return;
$vpost = get_post($post_id);
$filename = $vpost->post_name.".vcf";
$today = date('Y-m-d');
$data=null;
$data.="BEGIN:VCARD\n";
$data.="VERSION:3.0\n";
$data.="REV:".$today."T00:00:00Z\n";
$data.="N:" .get_field('achternaam',$vpost->ID).";" .get_field('voornaam',$vpost->ID).";;;\n";
$data.="ORG:" .get_field('bedrijf',$vpost->ID)."\n";
$data.="TITLE:" .get_field('functie',$vpost->ID)."\n";
$data.="EMAIL;INTERNET;WORK:" .get_field('email_adres',$vpost->ID)."\n";
$data.="TEL;WORK:" .get_field('telefoonnummer',$vpost->ID)."\n";
$data.="ADR;WORK:" .get_field('adres',$vpost->ID)."\n";
$data.="URL;WORK:" .get_field('website',$vpost->ID)."\n";
$data.="URL;OTHER:" .get_field('linkedin',$vpost->ID)."\n";
$data.="URL;OTHER:" .get_field('facebook',$vpost->ID)."\n";
$data.="URL;OTHER:" .get_field('twitter',$vpost->ID)."\n";
$data.="URL;OTHER:" .get_field('instagram',$vpost->ID)."\n";
$data.="URL;OTHER:" .get_field('snapchat',$vpost->ID)."\n";
$data.="" .imageEncodeURL(get_field('foto',$vpost->ID))."\n";
$data.="END:VCARD";
$filePath = get_template_directory()."/vcard/".$filename; // you can specify path here where you want to store file.
$file = fopen($filePath,"w");
fwrite($file,$data);
fclose($file);
}
add_action( 'save_post', 'hj_create_vCard' );
I suppose its quiet an easy fix for someone with a little bit php knowledge, seems I can only copy paste ;(
Hope someone is willing to help me out!
You issue probably comes down to the issue of using the ‘save_post’ hook. ACF fields are saved on this hook with a priority of 10. Your filter also runs on the same hook with a priority of 10. If your action is called before the acf action is called then the acf fields have not been saved yet. This will cause errors on new posts because all of the get_field() calls will return NULL.
Increase the priority or your add_action() call to > 10
The topic ‘Dynamically create vcard from ACF data and download with button click?’ is closed to new replies.
Welcome to the Advanced Custom Fields community forum.
Browse through ideas, snippets of code, questions and answers between fellow ACF users
Helping others is a great way to earn karma, gain badges and help ACF development!
We use cookies to offer you a better browsing experience, analyze site traffic and personalize content. Read about how we use cookies and how you can control them in our Privacy Policy. If you continue to use this site, you consent to our use of cookies.