farinspace / wpalchemy

Thin framework for wordpress
http://wpalchemy.com/
Other
416 stars 110 forks source link

A way to convert wpalchemy fields to acf fields? #122

Open stratboy opened 1 year ago

stratboy commented 1 year ago

Hi, since this plugin is no more maintained, since years ago, and since the way it stores meta values is not standard/flat, I'm starting having A LOT of problems with websites built with wpalchemy and no more usable with php 8, and having to convert all the wpalchemy fields to acf fields, preserving their values. Not that simple. It would be great if the developer could give us a function, or a simple way, to accomplish this task. It it possible please?

Thank you, regards

gluoksnis commented 1 year ago

Hi, @stratboy, any luck with the fields migration to ACF?

stratboy commented 1 year ago

Yes. If you create new records in the postmeta table that are called like the acf ones, acf will properly recognize them. But forget about complex things like acf groups or similar.

First, backup your DB. Very important. Second, take a look to the postmeta table and understand how it works and how wpalchemy saves fields. It's quite easy: it always serializes arrays. Third, create the new fields in ACF. Basically, I called them like the oldies but with acf_ in front. Fourth, fully understand the following two functions. And keep in mind that you'll want to run them once. Also, always carefully check the postmeta table after running them, see if it's all ok and as expected. It's easy to make some error. It's also easy to fix it, though. As long as you constantly keep an eye on that table.

The following functions are good for string data (should be the vast majority). They don't work for images. for images, I solved making acf text fields containing copy of old wpalchemy image data, meant to be used only for existing data, and creating new acf fields meant to be used for new data. Then it's quite easy to rapidly check for new||old data in your php templates.

Hope it helps.

// To convert fields:

function lr_migrate_meta_fields($field, $custom_key = false, $unique = true, $check = false, $delete_old = false){
  if(!is_admin()) return false;

  if($check){
    if(get_option($check)) return false;
  }

  global $wpdb;
  $metas = $wpdb->get_results(
    "
      SELECT *
      FROM $wpdb->postmeta 
      WHERE meta_key = '$field'
    "
  );

  foreach($metas as $meta){
    $fields_data = unserialize($meta->meta_value);

    foreach($fields_data as $key => $value){
      // $unique is for avoiding the same field gets written more than once
      $k = ($custom_key) ? $custom_key : $key;
      add_post_meta($meta->post_id, 'acf_' . $k, $value, $unique); 
    }
  }

  if($check) add_option($check, 1);   
}

To delete olds:

function lr_delete_meta_fields($field){
  if(!is_admin()) return false;

  global $wpdb;
  $metas = $wpdb->get_results(
    "
      SELECT *
      FROM $wpdb->postmeta 
      WHERE meta_key = '$field'
    "
  );

  foreach($metas as $meta){
    delete_post_meta($meta->post_id, $meta->meta_key);
  }
}
gluoksnis commented 1 year ago

Thank you @stratboy, it worked like a charm :)